A modified StreamSocket to dissect SMB compounded requests [MS-SMB2] 3.3.5.2.7
| 4700 | |
| 4701 | |
| 4702 | class SMBStreamSocket(StreamSocket): |
| 4703 | """ |
| 4704 | A modified StreamSocket to dissect SMB compounded requests |
| 4705 | [MS-SMB2] 3.3.5.2.7 |
| 4706 | """ |
| 4707 | |
| 4708 | def __init__(self, *args, **kwargs): |
| 4709 | self.queue = collections.deque() |
| 4710 | self.session = SMBSession() |
| 4711 | super(SMBStreamSocket, self).__init__(*args, **kwargs) |
| 4712 | |
| 4713 | def recv(self, x=None): |
| 4714 | # note: normal StreamSocket takes care of NBTSession / DirectTCP fragments. |
| 4715 | # this takes care of splitting compounded requests |
| 4716 | if self.queue: |
| 4717 | pkt = self.queue.popleft() |
| 4718 | else: |
| 4719 | pkt = super(SMBStreamSocket, self).recv(x) |
| 4720 | |
| 4721 | # If there are multiple SMB2_Header requests (aka. compounded), |
| 4722 | # take the first and store the rest in a queue. |
| 4723 | if pkt is not None and ( |
| 4724 | SMB2_Header in pkt |
| 4725 | or SMB2_Transform_Header in pkt |
| 4726 | or SMB2_Compression_Transform_Header in pkt |
| 4727 | ): |
| 4728 | pkt = self.session.in_pkt(pkt) |
| 4729 | smbh = pkt[SMB2_Header] |
| 4730 | pay = smbh.payload |
| 4731 | while SMB2_Header in pay: |
| 4732 | pay = pay[SMB2_Header] |
| 4733 | pay._decrypted = smbh._decrypted # Keep the _decrypted flag |
| 4734 | pay.underlayer.remove_payload() |
| 4735 | self.queue.append(pay) |
| 4736 | if not pay.NextCommand: |
| 4737 | break |
| 4738 | pay = pay.payload |
| 4739 | |
| 4740 | # Verify the signature if required. |
| 4741 | # This happens here because we must have split compounded requests first. |
| 4742 | smbh = pkt.getlayer(SMB2_Header) |
| 4743 | if ( |
| 4744 | smbh |
| 4745 | and self.session.Dialect |
| 4746 | and self.session.SigningKey |
| 4747 | and self.session.SigningRequired |
| 4748 | # [MS-SMB2] sect 3.2.5.1.3 Verifying the Signature |
| 4749 | # "The client MUST skip the processing in this section if any of:" |
| 4750 | # - [...] decryption in section 3.2.5.1.1.1 succeeds |
| 4751 | and not smbh._decrypted |
| 4752 | # - MessageId is 0xFFFFFFFFFFFFFFFF |
| 4753 | and smbh.MID != 0xFFFFFFFFFFFFFFFF |
| 4754 | # - Status in the SMB2 header is STATUS_PENDING |
| 4755 | and smbh.Status != 0x00000103 |
| 4756 | ): |
| 4757 | smbh.verify( |
| 4758 | self.session.Dialect, |
| 4759 | self.session.SigningKey, |
no outgoing calls
no test coverage detected
searching dependent graphs…