Skip to content

Commit 42b98a2

Browse files
authored
SMB: support BUFFER_OVERFLOW and NTLM without TimeStamp (#4309)
1 parent 44a0676 commit 42b98a2

File tree

3 files changed

+33
-9
lines changed

3 files changed

+33
-9
lines changed

scapy/layers/ntlm.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,10 +1406,10 @@ def GSS_Init_sec_context(self, Context: CONTEXT, val=None):
14061406
ChallengeFromClient=os.urandom(8),
14071407
)
14081408
try:
1409-
# the client SHOULD set the timestamp in the CHALLENGE_MESSAGE
1409+
# the server SHOULD set the timestamp in the CHALLENGE_MESSAGE
14101410
cr.TimeStamp = chall_tok.getAv(0x0007).Value
14111411
except IndexError:
1412-
pass
1412+
cr.TimeStamp = int((time.time() + 11644473600) * 1e7)
14131413
cr.AvPairs = (
14141414
chall_tok.TargetInfo[:-1]
14151415
+ (

scapy/layers/smb2.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,7 +1403,9 @@ class SMB2_Header(Packet):
14031403
_SMB2_OK_RETURNCODES = (
14041404
# sect 3.3.4.4
14051405
(0xC0000016, 0x0001), # STATUS_MORE_PROCESSING_REQUIRED
1406-
(0x80000005, 0x0010), # STATUS_BUFFER_OVERFLOW
1406+
(0x80000005, 0x0008), # STATUS_BUFFER_OVERFLOW (Read)
1407+
(0x80000005, 0x0010), # STATUS_BUFFER_OVERFLOW (QueryInfo)
1408+
(0x80000005, 0x000B), # STATUS_BUFFER_OVERFLOW (IOCTL)
14071409
(0xC000000D, 0x000B), # STATUS_INVALID_PARAMETER
14081410
(0x0000010C, 0x000F), # STATUS_NOTIFY_ENUM_DIR
14091411
)
@@ -2873,7 +2875,7 @@ class SMB2_Read_Request(_SMB2_Payload, _NTLMPayloadPacket):
28732875
0x02: "SMB2_READFLAG_REQUEST_COMPRESSED",
28742876
},
28752877
),
2876-
LEIntField("Length", 1024),
2878+
LEIntField("Length", 4280),
28772879
LELongField("Offset", 0),
28782880
PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
28792881
LEIntField("MinimumCount", 0),
@@ -3188,7 +3190,7 @@ class SMB2_IOCTL_Request(_SMB2_Payload, _NTLMPayloadPacket):
31883190
LEIntField("MaxInputResponse", 0),
31893191
LEIntField("OutputBufferOffset", None),
31903192
LEIntField("OutputLen", None), # Called OutputCount.
3191-
LEIntField("MaxOutputResponse", 4280),
3193+
LEIntField("MaxOutputResponse", 1024),
31923194
FlagsField("Flags", 0, -32, {0x00000001: "SMB2_0_IOCTL_IS_FSCTL"}),
31933195
LEIntField("Reserved2", 0),
31943196
_NTLMPayloadField(

scapy/layers/smbclient.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,8 @@ def receive_data_smb(self, pkt):
434434
if pkt.Status == 0x0000010B: # STATUS_NOTIFY_CLEANUP
435435
# this is a notify cleanup. ignore
436436
return
437-
# When an error is returned, add the status to it as metadata
438-
resp.NTStatus = pkt.sprintf("%SMB2_Header.Status%")
437+
# Add the status to the response as metadata
438+
resp.NTStatus = pkt.sprintf("%SMB2_Header.Status%")
439439
self.oi.smbpipe.send(resp)
440440

441441
@ATMT.ioevent(SOCKET_MODE_SMB, name="smbpipe", as_supersocket="smblink")
@@ -757,7 +757,18 @@ def send(self, x):
757757
resp = self.ins.sr1(pkt, verbose=0)
758758
if SMB2_IOCTL_Response not in resp:
759759
raise ValueError("Failed reading IOCTL_Response ! %s" % resp.NTStatus)
760-
super(SMB_RPC_SOCKET, self).send(bytes(resp.Output))
760+
data = bytes(resp.Output)
761+
# Handle BUFFER_OVERFLOW (big DCE/RPC response)
762+
while resp.NTStatus == "STATUS_BUFFER_OVERFLOW":
763+
# Retrieve DCE/RPC full size
764+
resp = self.ins.sr1(
765+
SMB2_Read_Request(
766+
FileId=self.PipeFileId,
767+
),
768+
verbose=0
769+
)
770+
data += resp.Data
771+
super(SMB_RPC_SOCKET, self).send(data)
761772
else:
762773
# Use WriteRequest/ReadRequest
763774
pkt = SMB2_Write_Request(
@@ -777,7 +788,18 @@ def send(self, x):
777788
)
778789
if SMB2_Read_Response not in resp:
779790
raise ValueError("Failed reading ReadResponse ! %s" % resp.NTStatus)
780-
super(SMB_RPC_SOCKET, self).send(resp.Data)
791+
data = bytes(resp.Data)
792+
# Handle BUFFER_OVERFLOW (big DCE/RPC response)
793+
while resp.NTStatus == "STATUS_BUFFER_OVERFLOW":
794+
# Retrieve DCE/RPC full size
795+
resp = self.ins.sr1(
796+
SMB2_Read_Request(
797+
FileId=self.PipeFileId,
798+
),
799+
verbose=0
800+
)
801+
data += resp.Data
802+
super(SMB_RPC_SOCKET, self).send(data)
781803

782804
def close(self):
783805
SMB_SOCKET.close(self)

0 commit comments

Comments
 (0)