From 0fb9108864497be33ea3a1debf02cd5f24360ede Mon Sep 17 00:00:00 2001 From: gpotter2 <10530980+gpotter2@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:58:35 +0100 Subject: [PATCH] SMB: support BUFFER_OVERFLOW and NTLM without TimeStamp --- scapy/layers/ntlm.py | 4 ++-- scapy/layers/smb2.py | 8 +++++--- scapy/layers/smbclient.py | 30 ++++++++++++++++++++++++++---- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/scapy/layers/ntlm.py b/scapy/layers/ntlm.py index 7097d3fd767..094b3e6a5c6 100644 --- a/scapy/layers/ntlm.py +++ b/scapy/layers/ntlm.py @@ -1406,10 +1406,10 @@ def GSS_Init_sec_context(self, Context: CONTEXT, val=None): ChallengeFromClient=os.urandom(8), ) try: - # the client SHOULD set the timestamp in the CHALLENGE_MESSAGE + # the server SHOULD set the timestamp in the CHALLENGE_MESSAGE cr.TimeStamp = chall_tok.getAv(0x0007).Value except IndexError: - pass + cr.TimeStamp = int((time.time() + 11644473600) * 1e7) cr.AvPairs = ( chall_tok.TargetInfo[:-1] + ( diff --git a/scapy/layers/smb2.py b/scapy/layers/smb2.py index 21947dcc862..f2a567bbb54 100644 --- a/scapy/layers/smb2.py +++ b/scapy/layers/smb2.py @@ -1403,7 +1403,9 @@ class SMB2_Header(Packet): _SMB2_OK_RETURNCODES = ( # sect 3.3.4.4 (0xC0000016, 0x0001), # STATUS_MORE_PROCESSING_REQUIRED - (0x80000005, 0x0010), # STATUS_BUFFER_OVERFLOW + (0x80000005, 0x0008), # STATUS_BUFFER_OVERFLOW (Read) + (0x80000005, 0x0010), # STATUS_BUFFER_OVERFLOW (QueryInfo) + (0x80000005, 0x000B), # STATUS_BUFFER_OVERFLOW (IOCTL) (0xC000000D, 0x000B), # STATUS_INVALID_PARAMETER (0x0000010C, 0x000F), # STATUS_NOTIFY_ENUM_DIR ) @@ -2873,7 +2875,7 @@ class SMB2_Read_Request(_SMB2_Payload, _NTLMPayloadPacket): 0x02: "SMB2_READFLAG_REQUEST_COMPRESSED", }, ), - LEIntField("Length", 1024), + LEIntField("Length", 4280), LELongField("Offset", 0), PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), LEIntField("MinimumCount", 0), @@ -3188,7 +3190,7 @@ class SMB2_IOCTL_Request(_SMB2_Payload, _NTLMPayloadPacket): LEIntField("MaxInputResponse", 0), LEIntField("OutputBufferOffset", None), LEIntField("OutputLen", None), # Called OutputCount. - LEIntField("MaxOutputResponse", 4280), + LEIntField("MaxOutputResponse", 1024), FlagsField("Flags", 0, -32, {0x00000001: "SMB2_0_IOCTL_IS_FSCTL"}), LEIntField("Reserved2", 0), _NTLMPayloadField( diff --git a/scapy/layers/smbclient.py b/scapy/layers/smbclient.py index ef9657cf291..90e6c885557 100644 --- a/scapy/layers/smbclient.py +++ b/scapy/layers/smbclient.py @@ -434,8 +434,8 @@ def receive_data_smb(self, pkt): if pkt.Status == 0x0000010B: # STATUS_NOTIFY_CLEANUP # this is a notify cleanup. ignore return - # When an error is returned, add the status to it as metadata - resp.NTStatus = pkt.sprintf("%SMB2_Header.Status%") + # Add the status to the response as metadata + resp.NTStatus = pkt.sprintf("%SMB2_Header.Status%") self.oi.smbpipe.send(resp) @ATMT.ioevent(SOCKET_MODE_SMB, name="smbpipe", as_supersocket="smblink") @@ -757,7 +757,18 @@ def send(self, x): resp = self.ins.sr1(pkt, verbose=0) if SMB2_IOCTL_Response not in resp: raise ValueError("Failed reading IOCTL_Response ! %s" % resp.NTStatus) - super(SMB_RPC_SOCKET, self).send(bytes(resp.Output)) + data = bytes(resp.Output) + # Handle BUFFER_OVERFLOW (big DCE/RPC response) + while resp.NTStatus == "STATUS_BUFFER_OVERFLOW": + # Retrieve DCE/RPC full size + resp = self.ins.sr1( + SMB2_Read_Request( + FileId=self.PipeFileId, + ), + verbose=0 + ) + data += resp.Data + super(SMB_RPC_SOCKET, self).send(data) else: # Use WriteRequest/ReadRequest pkt = SMB2_Write_Request( @@ -777,7 +788,18 @@ def send(self, x): ) if SMB2_Read_Response not in resp: raise ValueError("Failed reading ReadResponse ! %s" % resp.NTStatus) - super(SMB_RPC_SOCKET, self).send(resp.Data) + data = bytes(resp.Data) + # Handle BUFFER_OVERFLOW (big DCE/RPC response) + while resp.NTStatus == "STATUS_BUFFER_OVERFLOW": + # Retrieve DCE/RPC full size + resp = self.ins.sr1( + SMB2_Read_Request( + FileId=self.PipeFileId, + ), + verbose=0 + ) + data += resp.Data + super(SMB_RPC_SOCKET, self).send(data) def close(self): SMB_SOCKET.close(self)