Skip to content

Commit 4d98eb5

Browse files
committed
SMB: Implement encryption, cleanup RequireSignature
1 parent 92925da commit 4d98eb5

File tree

9 files changed

+527
-134
lines changed

9 files changed

+527
-134
lines changed

.config/codespell_ignore.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ browseable
77
byteorder
88
cace
99
cas
10+
ciph
1011
componet
1112
comversion
1213
cros

doc/scapy/layers/smb.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ Scapy provides pretty good support for SMB 2/3 and very partial support of SMB1.
55

66
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.
77

8-
.. warning:: Encryption is currently not supported in neither the client nor server.
9-
108
.. _client:
119

1210
SMB 2/3 client
@@ -94,6 +92,12 @@ You might be wondering if you can pass the ``HashNT`` of the password of the use
9492
9593
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)])``.
9694

95+
**smbclient forcing encryption**:
96+
97+
.. code:: python
98+
99+
>>> smbclient("server1.domain.local", "admin", REQUIRE_ENCRYPTION=True)
100+
97101
.. note::
98102

99103
It is also possible to start the :class:`~scapy.layers.smbclient.smbclient` directly from the OS, using the following::

scapy/layers/ntlm.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,9 +1680,7 @@ def GSS_Accept_sec_context(self, Context: CONTEXT, val=None):
16801680
EncryptedRandomSessionKey = b"\x00" * 16
16811681
else:
16821682
EncryptedRandomSessionKey = auth_tok.EncryptedRandomSessionKey
1683-
ExportedSessionKey = RC4K(
1684-
KeyExchangeKey, EncryptedRandomSessionKey
1685-
)
1683+
ExportedSessionKey = RC4K(KeyExchangeKey, EncryptedRandomSessionKey)
16861684
else:
16871685
ExportedSessionKey = KeyExchangeKey
16881686
Context.ExportedSessionKey = ExportedSessionKey
@@ -1800,6 +1798,7 @@ def _getSessionBaseKey(self, Context, auth_tok):
18001798
return NTLMv2_ComputeSessionBaseKey(
18011799
ResponseKeyNT, auth_tok.NtChallengeResponse.NTProofStr
18021800
)
1801+
log_runtime.debug("NTLMSSP: Bad credentials for %s" % username)
18031802
return None
18041803

18051804
def _checkLogin(self, Context, auth_tok):

scapy/layers/smb.py

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@
6767
)
6868
from scapy.layers.smb2 import (
6969
STATUS_ERREF,
70+
SMB2_Compression_Transform_Header,
7071
SMB2_Header,
72+
SMB2_Transform_Header,
7173
)
7274

7375

@@ -919,11 +921,9 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs):
919921
elif _pkt[0] == 0x13: # LOGON_SAM_USER_RESPONSE
920922
try:
921923
i = _pkt.index(b"\xff\xff\xff\xff")
922-
NtVersion = (
923-
NETLOGON_SAM_LOGON_RESPONSE_NT40.fields_desc[-3].getfield(
924-
None, _pkt[i - 4:i]
925-
)[1]
926-
)
924+
NtVersion = NETLOGON_SAM_LOGON_RESPONSE_NT40.fields_desc[
925+
-3
926+
].getfield(None, _pkt[i - 4 : i])[1]
927927
if NtVersion.V1 and not NtVersion.V5:
928928
return NETLOGON_SAM_LOGON_RESPONSE_NT40
929929
except Exception:
@@ -1013,6 +1013,7 @@ class NETLOGON_SAM_LOGON_RESPONSE_NT40(NETLOGON):
10131013

10141014
# [MS-ADTS] sect 6.3.1.8
10151015

1016+
10161017
class NETLOGON_SAM_LOGON_RESPONSE(NETLOGON, DNSCompressedPacket):
10171018
fields_desc = [
10181019
LEShortEnumField("OpCode", 0x17, _NETLOGON_opcodes),
@@ -1085,8 +1086,7 @@ def pre_dissect(self, s):
10851086
try:
10861087
i = s.index(b"\xff\xff\xff\xff")
10871088
self.fields["NtVersion"] = self.fields_desc[-3].getfield(
1088-
self,
1089-
s[i - 4:i]
1089+
self, s[i - 4 : i]
10901090
)[1]
10911091
except Exception:
10921092
self.NtVersion = 0xB
@@ -1098,20 +1098,25 @@ def get_full(self):
10981098

10991099
# [MS-BRWS] sect 2.2
11001100

1101+
11011102
class BRWS(Packet):
11021103
fields_desc = [
1103-
ByteEnumField("OpCode", 0x00, {
1104-
0x01: "HostAnnouncement",
1105-
0x02: "AnnouncementRequest",
1106-
0x08: "RequestElection",
1107-
0x09: "GetBackupListRequest",
1108-
0x0A: "GetBackupListResponse",
1109-
0x0B: "BecomeBackup",
1110-
0x0C: "DomainAnnouncement",
1111-
0x0D: "MasterAnnouncement",
1112-
0x0E: "ResetStateRequest",
1113-
0x0F: "LocalMasterAnnouncement",
1114-
}),
1104+
ByteEnumField(
1105+
"OpCode",
1106+
0x00,
1107+
{
1108+
0x01: "HostAnnouncement",
1109+
0x02: "AnnouncementRequest",
1110+
0x08: "RequestElection",
1111+
0x09: "GetBackupListRequest",
1112+
0x0A: "GetBackupListResponse",
1113+
0x0B: "BecomeBackup",
1114+
0x0C: "DomainAnnouncement",
1115+
0x0D: "MasterAnnouncement",
1116+
0x0E: "ResetStateRequest",
1117+
0x0F: "LocalMasterAnnouncement",
1118+
},
1119+
),
11151120
]
11161121

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

11361141
# [MS-BRWS] sect 2.2.1
11371142

1143+
11381144
class BRWS_HostAnnouncement(BRWS):
11391145
OpCode = 0x01
11401146
fields_desc = [
@@ -1157,6 +1163,7 @@ def mysummary(self):
11571163

11581164
# [MS-BRWS] sect 2.2.6
11591165

1166+
11601167
class BRWS_BecomeBackup(BRWS):
11611168
OpCode = 0x0B
11621169
fields_desc = [
@@ -1170,6 +1177,7 @@ def mysummary(self):
11701177

11711178
# [MS-BRWS] sect 2.2.10
11721179

1180+
11731181
class BRWS_LocalMasterAnnouncement(BRWS_HostAnnouncement):
11741182
OpCode = 0x0F
11751183

@@ -1193,6 +1201,10 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs):
11931201
return SMB_Header
11941202
if _pkt[:4] == b"\xfeSMB":
11951203
return SMB2_Header
1204+
if _pkt[:4] == b"\xfdSMB":
1205+
return SMB2_Transform_Header
1206+
if _pkt[:4] == b"\xfcSMB":
1207+
return SMB2_Compression_Transform_Header
11961208
return cls
11971209

11981210

0 commit comments

Comments
 (0)