Skip to content

Commit

Permalink
SMB: Implement encryption, cleanup RequireSignature
Browse files Browse the repository at this point in the history
  • Loading branch information
gpotter2 committed Jan 19, 2025
1 parent 92925da commit 3b2dd19
Show file tree
Hide file tree
Showing 8 changed files with 526 additions and 132 deletions.
1 change: 1 addition & 0 deletions .config/codespell_ignore.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ browseable
byteorder
cace
cas
chip
componet
comversion
cros
Expand Down
8 changes: 6 additions & 2 deletions doc/scapy/layers/smb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ Scapy provides pretty good support for SMB 2/3 and very partial support of SMB1.

You can use the :class:`~scapy.layers.smb2.SMB2_Header` to dissect or build SMB2/3, or :class:`~scapy.layers.smb.SMB_Header` for SMB1.

.. warning:: Encryption is currently not supported in neither the client nor server.

.. _client:

SMB 2/3 client
Expand Down Expand Up @@ -94,6 +92,12 @@ You might be wondering if you can pass the ``HashNT`` of the password of the use
If you pay very close attention, you'll notice that in this case we aren't using the :class:`~scapy.layers.spnego.SPNEGOSSP` wrapper. You could have used ``ssp=SPNEGOSSP([t.ssp(1)])``.

**smbclient forcing encryption**:

.. code:: python
>>> smbclient("server1.domain.local", "admin", REQUIRE_ENCRYPTION=True)
.. note::

It is also possible to start the :class:`~scapy.layers.smbclient.smbclient` directly from the OS, using the following::
Expand Down
5 changes: 2 additions & 3 deletions scapy/layers/ntlm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1680,9 +1680,7 @@ def GSS_Accept_sec_context(self, Context: CONTEXT, val=None):
EncryptedRandomSessionKey = b"\x00" * 16
else:
EncryptedRandomSessionKey = auth_tok.EncryptedRandomSessionKey
ExportedSessionKey = RC4K(
KeyExchangeKey, EncryptedRandomSessionKey
)
ExportedSessionKey = RC4K(KeyExchangeKey, EncryptedRandomSessionKey)
else:
ExportedSessionKey = KeyExchangeKey
Context.ExportedSessionKey = ExportedSessionKey
Expand Down Expand Up @@ -1800,6 +1798,7 @@ def _getSessionBaseKey(self, Context, auth_tok):
return NTLMv2_ComputeSessionBaseKey(
ResponseKeyNT, auth_tok.NtChallengeResponse.NTProofStr
)
log_runtime.debug("NTLMSSP: Bad credentials for %s" % username)
return None

def _checkLogin(self, Context, auth_tok):
Expand Down
50 changes: 31 additions & 19 deletions scapy/layers/smb.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@
)
from scapy.layers.smb2 import (
STATUS_ERREF,
SMB2_Compression_Transform_Header,
SMB2_Header,
SMB2_Transform_Header,
)


Expand Down Expand Up @@ -919,11 +921,9 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs):
elif _pkt[0] == 0x13: # LOGON_SAM_USER_RESPONSE
try:
i = _pkt.index(b"\xff\xff\xff\xff")
NtVersion = (
NETLOGON_SAM_LOGON_RESPONSE_NT40.fields_desc[-3].getfield(
None, _pkt[i - 4:i]
)[1]
)
NtVersion = NETLOGON_SAM_LOGON_RESPONSE_NT40.fields_desc[
-3
].getfield(None, _pkt[i - 4 : i])[1]
if NtVersion.V1 and not NtVersion.V5:
return NETLOGON_SAM_LOGON_RESPONSE_NT40
except Exception:
Expand Down Expand Up @@ -1013,6 +1013,7 @@ class NETLOGON_SAM_LOGON_RESPONSE_NT40(NETLOGON):

# [MS-ADTS] sect 6.3.1.8


class NETLOGON_SAM_LOGON_RESPONSE(NETLOGON, DNSCompressedPacket):
fields_desc = [
LEShortEnumField("OpCode", 0x17, _NETLOGON_opcodes),
Expand Down Expand Up @@ -1085,8 +1086,7 @@ def pre_dissect(self, s):
try:
i = s.index(b"\xff\xff\xff\xff")
self.fields["NtVersion"] = self.fields_desc[-3].getfield(
self,
s[i - 4:i]
self, s[i - 4 : i]
)[1]
except Exception:
self.NtVersion = 0xB
Expand All @@ -1098,20 +1098,25 @@ def get_full(self):

# [MS-BRWS] sect 2.2


class BRWS(Packet):
fields_desc = [
ByteEnumField("OpCode", 0x00, {
0x01: "HostAnnouncement",
0x02: "AnnouncementRequest",
0x08: "RequestElection",
0x09: "GetBackupListRequest",
0x0A: "GetBackupListResponse",
0x0B: "BecomeBackup",
0x0C: "DomainAnnouncement",
0x0D: "MasterAnnouncement",
0x0E: "ResetStateRequest",
0x0F: "LocalMasterAnnouncement",
}),
ByteEnumField(
"OpCode",
0x00,
{
0x01: "HostAnnouncement",
0x02: "AnnouncementRequest",
0x08: "RequestElection",
0x09: "GetBackupListRequest",
0x0A: "GetBackupListResponse",
0x0B: "BecomeBackup",
0x0C: "DomainAnnouncement",
0x0D: "MasterAnnouncement",
0x0E: "ResetStateRequest",
0x0F: "LocalMasterAnnouncement",
},
),
]

def mysummary(self):
Expand All @@ -1135,6 +1140,7 @@ def default_payload_class(self, payload):

# [MS-BRWS] sect 2.2.1


class BRWS_HostAnnouncement(BRWS):
OpCode = 0x01
fields_desc = [
Expand All @@ -1157,6 +1163,7 @@ def mysummary(self):

# [MS-BRWS] sect 2.2.6


class BRWS_BecomeBackup(BRWS):
OpCode = 0x0B
fields_desc = [
Expand All @@ -1170,6 +1177,7 @@ def mysummary(self):

# [MS-BRWS] sect 2.2.10


class BRWS_LocalMasterAnnouncement(BRWS_HostAnnouncement):
OpCode = 0x0F

Expand All @@ -1193,6 +1201,10 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs):
return SMB_Header
if _pkt[:4] == b"\xfeSMB":
return SMB2_Header
if _pkt[:4] == b"\xfdSMB":
return SMB2_Transform_Header
if _pkt[:4] == b"\xfcSMB":
return SMB2_Compression_Transform_Header
return cls


Expand Down
Loading

0 comments on commit 3b2dd19

Please sign in to comment.