Skip to content

Commit d8d24da

Browse files
authored
Basic [MS-BRWS] support (#4300)
1 parent 4a86d93 commit d8d24da

File tree

4 files changed

+154
-3
lines changed

4 files changed

+154
-3
lines changed

scapy/layers/ldap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ def is_request(self, req):
573573
req = req.protocolOp
574574
return (
575575
req.attributes
576-
and req.attributes[0].type.val == b"Netlogon"
576+
and req.attributes[0].type.val.lower() == b"netlogon"
577577
and req.filter
578578
and isinstance(req.filter.filter, LDAP_FilterAnd)
579579
and any(

scapy/layers/netbios.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,11 @@ class NBNSRegistrationRequest(Packet):
279279
IPField("NB_ADDRESS", "127.0.0.1")
280280
]
281281

282+
def mysummary(self):
283+
return self.sprintf("Register %G% %QUESTION_NAME% at %NB_ADDRESS%")
284+
282285

286+
bind_bottom_up(NBNSHeader, NBNSRegistrationRequest, OPCODE=0x5)
283287
bind_layers(NBNSHeader, NBNSRegistrationRequest,
284288
OPCODE=0x5, NM_FLAGS=0x11, QDCOUNT=1, ARCOUNT=1)
285289

@@ -312,7 +316,7 @@ class NBTDatagram(Packet):
312316
ShortField("ID", 0),
313317
IPField("SourceIP", "127.0.0.1"),
314318
ShortField("SourcePort", 138),
315-
ShortField("Length", 272),
319+
ShortField("Length", None),
316320
ShortField("Offset", 0),
317321
NetBIOSNameField("SourceName", "windows"),
318322
ShortEnumField("SUFFIX1", 0x4141, _NETBIOS_SUFFIXES),
@@ -321,6 +325,13 @@ class NBTDatagram(Packet):
321325
ShortEnumField("SUFFIX2", 0x4141, _NETBIOS_SUFFIXES),
322326
ByteField("NULL2", 0)]
323327

328+
def post_build(self, pkt, pay):
329+
if self.Length is None:
330+
length = len(pay) + 68
331+
pkt = pkt[:10] + struct.pack("!H", length) + pkt[12:]
332+
return pkt + pay
333+
334+
324335
# SESSION SERVICE PACKETS
325336

326337

scapy/layers/smb.py

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,8 +684,10 @@ class SMBSession_Null(Packet):
684684

685685
class _SMB_TransactionRequest_Data(PacketLenField):
686686
def m2i(self, pkt, m):
687-
if pkt.WordCount == 0x11:
687+
if pkt.Name == b"\\MAILSLOT\\NET\\NETLOGON":
688688
return NETLOGON(m)
689+
elif pkt.Name == b"\\MAILSLOT\\BROWSE" or pkt.name == b"\\MAILSLOT\\LANMAN":
690+
return BRWS(m)
689691
return conf.raw_layer(m)
690692

691693

@@ -780,6 +782,11 @@ def post_build(self, pkt, pay):
780782
+ pay
781783
)
782784

785+
def mysummary(self):
786+
if self.DataLen:
787+
return self.sprintf("Tran %Name% ") + self.Data.mysummary()
788+
return self.sprintf("Tran %Name%")
789+
783790

784791
bind_top_down(SMB_Header, SMBTransaction_Request, Command=0x25)
785792

@@ -1084,6 +1091,84 @@ def get_full(self):
10841091
return self.original
10851092

10861093

1094+
# [MS-BRWS] sect 2.2
1095+
1096+
class BRWS(Packet):
1097+
fields_desc = [
1098+
ByteEnumField("OpCode", 0x00, {
1099+
0x01: "HostAnnouncement",
1100+
0x02: "AnnouncementRequest",
1101+
0x08: "RequestElection",
1102+
0x09: "GetBackupListRequest",
1103+
0x0A: "GetBackupListResponse",
1104+
0x0B: "BecomeBackup",
1105+
0x0C: "DomainAnnouncement",
1106+
0x0D: "MasterAnnouncement",
1107+
0x0E: "ResetStateRequest",
1108+
0x0F: "LocalMasterAnnouncement",
1109+
}),
1110+
]
1111+
1112+
def mysummary(self):
1113+
return self.sprintf("%OpCode%")
1114+
1115+
registered_opcodes = {}
1116+
1117+
@classmethod
1118+
def register_variant(cls):
1119+
cls.registered_opcodes[cls.OpCode.default] = cls
1120+
1121+
@classmethod
1122+
def dispatch_hook(cls, _pkt=None, *args, **kargs):
1123+
if _pkt:
1124+
return cls.registered_opcodes.get(_pkt[0], cls)
1125+
return cls
1126+
1127+
def default_payload_class(self, payload):
1128+
return conf.padding_layer
1129+
1130+
1131+
# [MS-BRWS] sect 2.2.1
1132+
1133+
class BRWS_HostAnnouncement(BRWS):
1134+
OpCode = 0x01
1135+
fields_desc = [
1136+
BRWS,
1137+
ByteField("UpdateCount", 0),
1138+
LEIntField("Periodicity", 128000),
1139+
StrFixedLenField("ServerName", b"", length=16),
1140+
ByteField("OSVersionMajor", 6),
1141+
ByteField("OSVersionMinor", 1),
1142+
LEIntField("ServerType", 4611),
1143+
ByteField("BrowserConfigVersionMajor", 21),
1144+
ByteField("BrowserConfigVersionMinor", 1),
1145+
XLEShortField("Signature", 0xAA55),
1146+
StrNullField("Comment", ""),
1147+
]
1148+
1149+
def mysummary(self):
1150+
return self.sprintf("%OpCode% for %ServerName%")
1151+
1152+
1153+
# [MS-BRWS] sect 2.2.6
1154+
1155+
class BRWS_BecomeBackup(BRWS):
1156+
OpCode = 0x0B
1157+
fields_desc = [
1158+
BRWS,
1159+
StrNullField("BrowserToPromote", b""),
1160+
]
1161+
1162+
def mysummary(self):
1163+
return self.sprintf("%OpCode% from %BrowserToPromote%")
1164+
1165+
1166+
# [MS-BRWS] sect 2.2.10
1167+
1168+
class BRWS_LocalMasterAnnouncement(BRWS_HostAnnouncement):
1169+
OpCode = 0x0F
1170+
1171+
10871172
# SMB dispatcher
10881173

10891174

test/scapy/layers/smb.uts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,58 @@ assert smb_sax_resp_2.SecurityBlob.token.negResult == 0
148148
assert smb_sax_resp_2.SecurityBlob.token.mechListMIC.value.val == b'\x01\x00\x00\x00\xee\t\x91S\xab\x7f]\xe6\x00\x00\x00\x00'
149149
assert smb_sax_resp_2.NativeOS == 'Windows 8.1 9600'
150150
assert smb_sax_resp_2.NativeLanMan == 'Windows 8.1 6.3'
151+
152+
153+
+ Test BRWS
154+
155+
= BRWS BecomeBackup - build
156+
157+
pkt = \
158+
IP(id=3109, ttl=128, src='192.168.1.2', dst='192.168.1.255') / \
159+
UDP(sport=138, dport=138) / \
160+
NBTDatagram(Type=17, Flags=2, ID=37087, SourceIP='192.168.1.2',
161+
SourcePort=138, SourceName=b'VIKRANT-LAPTOP ',
162+
SUFFIX1=16705, DestinationName=b'WORKGROUP',
163+
SUFFIX2=16975) / \
164+
SMB_Header(Flags=0) / \
165+
SMBMailslot_Write(Data=BRWS_BecomeBackup(OpCode=11, BrowserToPromote='LENOVO-NETBOOK'),
166+
Timeout=1000, Name='\\MAILSLOT\\BROWSE')
167+
168+
169+
assert bytes(pkt) == b'E\x00\x00\xd4\x0c%\x00\x00\x80\x11\xa9\xa2\xc0\xa8\x01\x02\xc0\xa8\x01\xff\x00\x8a\x00\x8a\x00\xc0\xca)\x11\x02\x90\xdf\xc0\xa8\x01\x02\x00\x8a\x00\xaa\x00\x00 FGEJELFCEBEOFECNEMEBFAFEEPFACAAA\x00 FHEPFCELEHFCEPFFFACACACACACACABO\x00\xffSMB%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00V\x00\x03\x00\x01\x00\x01\x00\x02\x00!\x00\\MAILSLOT\\BROWSE\x00\x0bLENOVO-NETBOOK\x00'
170+
171+
= BRWS BecomeBackup - dissection
172+
173+
pkt = IP(b'E\x00\x00\xd4\x0c%\x00\x00\x80\x11\xa9\xa2\xc0\xa8\x01\x02\xc0\xa8\x01\xff\x00\x8a\x00\x8a\x00\xc0\xca)\x11\x02\x90\xdf\xc0\xa8\x01\x02\x00\x8a\x00\xaa\x00\x00 FGEJELFCEBEOFECNEMEBFAFEEPFACAAA\x00 FHEPFCELEHFCEPFFFACACACACACACABO\x00\xffSMB%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00V\x00\x03\x00\x01\x00\x01\x00\x02\x00!\x00\\MAILSLOT\\BROWSE\x00\x0bLENOVO-NETBOOK\x00')
174+
175+
assert SMBMailslot_Write in pkt
176+
assert pkt[SMBMailslot_Write].Timeout == 1000
177+
assert pkt[SMBMailslot_Write].Name == b"\\MAILSLOT\\BROWSE"
178+
assert pkt[SMBMailslot_Write].Data.BrowserToPromote == b'LENOVO-NETBOOK'
179+
180+
= BRWS HostAnnouncement - build
181+
182+
pkt = \
183+
IP(id=51657, tos=0x20, src='192.168.1.8', dst='192.168.1.255') / \
184+
UDP(sport=138, dport=138) / \
185+
NBTDatagram(Type=17, Flags=2, ID=18755, SourceIP='192.168.1.8',
186+
SourcePort=0, SourceName='MACBOOKPRO-199C',
187+
SUFFIX1=16705, DestinationName='WORKGROUP',
188+
SUFFIX2=16974) / \
189+
SMB_Header(Flags=0, PIDLow=176, MID=18754) / \
190+
SMBMailslot_Write(Data=BRWS_HostAnnouncement(ServerName="MACBOOKPRO-122A", Comment="Super's MacBook Pro"),
191+
Timeout=0, Flags=2, Name='\\MAILSLOT\\BROWSE')
192+
193+
194+
assert bytes(pkt) == b"E \x00\xf8\xc9\xc9\x00\x00@\x11+\xb4\xc0\xa8\x01\x08\xc0\xa8\x01\xff\x00\x8a\x00\x8a\x00\xe4\xb3\xb0\x11\x02IC\xc0\xa8\x01\x08\x00\x00\x00\xce\x00\x00 ENEBEDECEPEPELFAFCEPCNDBDJDJEDAA\x00 FHEPFCELEHFCEPFFFACACACACACACABN\x00\xffSMB%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb0\x00\x00\x00BI\x11\x00\x004\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004\x00V\x00\x03\x00\x01\x00\x01\x00\x02\x00E\x00\\MAILSLOT\\BROWSE\x00\x01\x00\x00\xf4\x01\x00MACBOOKPRO-122A\x00\x06\x01\x03\x12\x00\x00\x15\x01U\xaaSuper's MacBook Pro\x00"
195+
196+
= BRWS HostAnnouncement - dissection
197+
198+
pkt = IP(b"E \x00\xf8\xc9\xc9\x00\x00@\x11+\xb4\xc0\xa8\x01\x08\xc0\xa8\x01\xff\x00\x8a\x00\x8a\x00\xe4\xb3\xb0\x11\x02IC\xc0\xa8\x01\x08\x00\x00\x00\xce\x00\x00 ENEBEDECEPEPELFAFCEPCNDBDJDJEDAA\x00 FHEPFCELEHFCEPFFFACACACACACACABN\x00\xffSMB%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb0\x00\x00\x00BI\x11\x00\x004\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004\x00V\x00\x03\x00\x01\x00\x01\x00\x02\x00E\x00\\MAILSLOT\\BROWSE\x00\x01\x00\x00\xf4\x01\x00MACBOOKPRO-122A\x00\x06\x01\x03\x12\x00\x00\x15\x01U\xaaSuper's MacBook Pro\x00")
199+
200+
assert SMBMailslot_Write in pkt
201+
assert pkt[SMBMailslot_Write].Name == b"\\MAILSLOT\\BROWSE"
202+
assert pkt[SMBMailslot_Write].Data.OpCode == 1
203+
assert pkt[SMBMailslot_Write].Data.ServerName == b"MACBOOKPRO-122A\x00"
204+
assert pkt[SMBMailslot_Write].Data.Comment == b"Super's MacBook Pro"
205+
assert pkt[SMBMailslot_Write].Data.Signature == 0xAA55

0 commit comments

Comments
 (0)