Skip to content

Commit

Permalink
Fix SMB2 compoud response signing (#1834)
Browse files Browse the repository at this point in the history
* Fix SMB2 compoud response signing

Fix the signing the logic when responding with an SMB2 compount
response. The signature will include the padding of each compound
element and include the next offset value before signing the data.

* Pad all SMB2 packets, even the last in a compound response
  • Loading branch information
jborean93 authored Jan 8, 2025
1 parent 2d2e562 commit 72648af
Showing 1 changed file with 17 additions and 21 deletions.
38 changes: 17 additions & 21 deletions impacket/smbserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -4403,10 +4403,11 @@ def signSMBv1(self, connData, packet, signingSessionKey, signingChallengeRespons
packet['SecurityFeatures'] = m.digest()[:8]
connData['SignSequenceNumber'] += 2

def signSMBv2(self, packet, signingSessionKey):
def signSMBv2(self, packet, signingSessionKey, padLength=0):
packet['Signature'] = b'\x00' * 16
packet['Flags'] |= smb2.SMB2_FLAGS_SIGNED
signature = hmac.new(signingSessionKey, packet.getData(), hashlib.sha256).digest()
packetData = packet.getData() + b'\x00' * padLength
signature = hmac.new(signingSessionKey, packetData, hashlib.sha256).digest()
packet['Signature'] = signature[:16]
# print "%s" % packet['Signature'].encode('hex')

Expand Down Expand Up @@ -4624,34 +4625,29 @@ def processRequest(self, connId, data):
else:
respPacket['Data'] = str(respCommand)

if connData['SignatureEnabled']:
self.signSMBv2(respPacket, connData['SigningSessionKey'])

packetsToSend.append(respPacket)
else:
# The SMBCommand took care of building the packet
packetsToSend = respPackets

if isSMB2 is True:
# Let's build a compound answer
finalData = b''
i = 0
for i in range(len(packetsToSend) - 1):
packet = packetsToSend[i]
# Align to 8-bytes
padLen = (8 - (len(packet) % 8)) % 8
packet['NextCommand'] = len(packet) + padLen
# Let's build a compound answer and sign it
finalData = []
totalPackets = len(packetsToSend)
for idx, packet in enumerate(packetsToSend):
padLen = -len(packet) % 8
if idx + 1 < totalPackets:
packet['NextCommand'] = len(packet) + padLen

if connData['SignatureEnabled']:
self.signSMBv2(packet, connData['SigningSessionKey'], padLength=padLen)

if hasattr(packet, 'getData'):
finalData += packet.getData() + padLen * b'\x00'
finalData.append(packet.getData() + padLen * b'\x00')
else:
finalData += packet + padLen * b'\x00'
finalData.append(packet + padLen * b'\x00')

# Last one
if hasattr(packetsToSend[len(packetsToSend) - 1], 'getData'):
finalData += packetsToSend[len(packetsToSend) - 1].getData()
else:
finalData += packetsToSend[len(packetsToSend) - 1]
packetsToSend = [finalData]
packetsToSend = [b"".join(finalData)]

# We clear the compound requests
connData['LastRequest'] = {}
Expand Down

0 comments on commit 72648af

Please sign in to comment.