Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/smb2.py: 68%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Gabriel Potter
6"""
7SMB (Server Message Block), also known as CIFS - version 2
9.. note::
10 You will find more complete documentation for this layer over at
11 `SMB <https://scapy.readthedocs.io/en/latest/layers/smb.html>`_
12"""
14import collections
15import functools
16import hashlib
17import os
18import struct
20from scapy.automaton import select_objects
21from scapy.config import conf, crypto_validator
22from scapy.error import log_runtime
23from scapy.packet import Packet, bind_layers, bind_top_down
24from scapy.fields import (
25 ByteEnumField,
26 ByteField,
27 ConditionalField,
28 FieldLenField,
29 FieldListField,
30 FlagsField,
31 IP6Field,
32 IPField,
33 IntField,
34 LEIntField,
35 LEIntEnumField,
36 LELongField,
37 LenField,
38 LEShortEnumField,
39 LEShortField,
40 MultipleTypeField,
41 PadField,
42 PacketField,
43 PacketLenField,
44 PacketListField,
45 ReversePadField,
46 ScalingField,
47 ShortEnumField,
48 ShortField,
49 StrFieldUtf16,
50 StrFixedLenField,
51 StrLenField,
52 StrLenFieldUtf16,
53 StrNullFieldUtf16,
54 ThreeBytesField,
55 UTCTimeField,
56 UUIDField,
57 XLEIntField,
58 XLELongField,
59 XLEShortField,
60 XStrLenField,
61 XStrFixedLenField,
62 YesNoByteField,
63)
64from scapy.sessions import DefaultSession
65from scapy.supersocket import StreamSocket
67if conf.crypto_valid:
68 from scapy.libs.rfc3961 import SP800108_KDFCTR
70from scapy.layers.gssapi import GSSAPI_BLOB
71from scapy.layers.netbios import NBTSession
72from scapy.layers.ntlm import (
73 _NTLMPayloadField,
74 _NTLMPayloadPacket,
75 _NTLM_ENUM,
76 _NTLM_post_build,
77)
78from scapy.layers.windows.erref import STATUS_ERREF
81# EnumField
82SMB_DIALECTS = {
83 0x0202: "SMB 2.002",
84 0x0210: "SMB 2.1",
85 0x02FF: "SMB 2.???",
86 0x0300: "SMB 3.0",
87 0x0302: "SMB 3.0.2",
88 0x0311: "SMB 3.1.1",
89}
91# SMB2 sect 2.1.2.1
92REPARSE_TAGS = {
93 0x00000000: "IO_REPARSE_TAG_RESERVED_ZERO",
94 0x00000001: "IO_REPARSE_TAG_RESERVED_ONE",
95 0x00000002: "IO_REPARSE_TAG_RESERVED_TWO",
96 0xA0000003: "IO_REPARSE_TAG_MOUNT_POINT",
97 0xC0000004: "IO_REPARSE_TAG_HSM",
98 0x80000005: "IO_REPARSE_TAG_DRIVE_EXTENDER",
99 0x80000006: "IO_REPARSE_TAG_HSM2",
100 0x80000007: "IO_REPARSE_TAG_SIS",
101 0x80000008: "IO_REPARSE_TAG_WIM",
102 0x80000009: "IO_REPARSE_TAG_CSV",
103 0x8000000A: "IO_REPARSE_TAG_DFS",
104 0x8000000B: "IO_REPARSE_TAG_FILTER_MANAGER",
105 0xA000000C: "IO_REPARSE_TAG_SYMLINK",
106 0xA0000010: "IO_REPARSE_TAG_IIS_CACHE",
107 0x80000012: "IO_REPARSE_TAG_DFSR",
108 0x80000013: "IO_REPARSE_TAG_DEDUP",
109 0xC0000014: "IO_REPARSE_TAG_APPXSTRM",
110 0x80000014: "IO_REPARSE_TAG_NFS",
111 0x80000015: "IO_REPARSE_TAG_FILE_PLACEHOLDER",
112 0x80000016: "IO_REPARSE_TAG_DFM",
113 0x80000017: "IO_REPARSE_TAG_WOF",
114 0x80000018: "IO_REPARSE_TAG_WCI",
115 0x90001018: "IO_REPARSE_TAG_WCI_1",
116 0xA0000019: "IO_REPARSE_TAG_GLOBAL_REPARSE",
117 0x9000001A: "IO_REPARSE_TAG_CLOUD",
118 0x9000101A: "IO_REPARSE_TAG_CLOUD_1",
119 0x9000201A: "IO_REPARSE_TAG_CLOUD_2",
120 0x9000301A: "IO_REPARSE_TAG_CLOUD_3",
121 0x9000401A: "IO_REPARSE_TAG_CLOUD_4",
122 0x9000501A: "IO_REPARSE_TAG_CLOUD_5",
123 0x9000601A: "IO_REPARSE_TAG_CLOUD_6",
124 0x9000701A: "IO_REPARSE_TAG_CLOUD_7",
125 0x9000801A: "IO_REPARSE_TAG_CLOUD_8",
126 0x9000901A: "IO_REPARSE_TAG_CLOUD_9",
127 0x9000A01A: "IO_REPARSE_TAG_CLOUD_A",
128 0x9000B01A: "IO_REPARSE_TAG_CLOUD_B",
129 0x9000C01A: "IO_REPARSE_TAG_CLOUD_C",
130 0x9000D01A: "IO_REPARSE_TAG_CLOUD_D",
131 0x9000E01A: "IO_REPARSE_TAG_CLOUD_E",
132 0x9000F01A: "IO_REPARSE_TAG_CLOUD_F",
133 0x8000001B: "IO_REPARSE_TAG_APPEXECLINK",
134 0x9000001C: "IO_REPARSE_TAG_PROJFS",
135 0xA000001D: "IO_REPARSE_TAG_LX_SYMLINK",
136 0x8000001E: "IO_REPARSE_TAG_STORAGE_SYNC",
137 0xA000001F: "IO_REPARSE_TAG_WCI_TOMBSTONE",
138 0x80000020: "IO_REPARSE_TAG_UNHANDLED",
139 0x80000021: "IO_REPARSE_TAG_ONEDRIVE",
140 0xA0000022: "IO_REPARSE_TAG_PROJFS_TOMBSTONE",
141 0x80000023: "IO_REPARSE_TAG_AF_UNIX",
142 0x80000024: "IO_REPARSE_TAG_LX_FIFO",
143 0x80000025: "IO_REPARSE_TAG_LX_CHR",
144 0x80000026: "IO_REPARSE_TAG_LX_BLK",
145 0xA0000027: "IO_REPARSE_TAG_WCI_LINK",
146 0xA0001027: "IO_REPARSE_TAG_WCI_LINK_1",
147}
149# SMB2 sect 2.2.1.1
150SMB2_COM = {
151 0x0000: "SMB2_NEGOTIATE",
152 0x0001: "SMB2_SESSION_SETUP",
153 0x0002: "SMB2_LOGOFF",
154 0x0003: "SMB2_TREE_CONNECT",
155 0x0004: "SMB2_TREE_DISCONNECT",
156 0x0005: "SMB2_CREATE",
157 0x0006: "SMB2_CLOSE",
158 0x0007: "SMB2_FLUSH",
159 0x0008: "SMB2_READ",
160 0x0009: "SMB2_WRITE",
161 0x000A: "SMB2_LOCK",
162 0x000B: "SMB2_IOCTL",
163 0x000C: "SMB2_CANCEL",
164 0x000D: "SMB2_ECHO",
165 0x000E: "SMB2_QUERY_DIRECTORY",
166 0x000F: "SMB2_CHANGE_NOTIFY",
167 0x0010: "SMB2_QUERY_INFO",
168 0x0011: "SMB2_SET_INFO",
169 0x0012: "SMB2_OPLOCK_BREAK",
170}
172# EnumField
173SMB2_NEGOTIATE_CONTEXT_TYPES = {
174 0x0001: "SMB2_PREAUTH_INTEGRITY_CAPABILITIES",
175 0x0002: "SMB2_ENCRYPTION_CAPABILITIES",
176 0x0003: "SMB2_COMPRESSION_CAPABILITIES",
177 0x0005: "SMB2_NETNAME_NEGOTIATE_CONTEXT_ID",
178 0x0006: "SMB2_TRANSPORT_CAPABILITIES",
179 0x0007: "SMB2_RDMA_TRANSFORM_CAPABILITIES",
180 0x0008: "SMB2_SIGNING_CAPABILITIES",
181}
183# FlagField
184SMB2_CAPABILITIES = {
185 0x00000001: "DFS",
186 0x00000002: "LEASING",
187 0x00000004: "LARGE_MTU",
188 0x00000008: "MULTI_CHANNEL",
189 0x00000010: "PERSISTENT_HANDLES",
190 0x00000020: "DIRECTORY_LEASING",
191 0x00000040: "ENCRYPTION",
192}
193SMB2_SECURITY_MODE = {
194 0x01: "SIGNING_ENABLED",
195 0x02: "SIGNING_REQUIRED",
196}
198# [MS-SMB2] 2.2.3.1.3
199SMB2_COMPRESSION_ALGORITHMS = {
200 0x0000: "None",
201 0x0001: "LZNT1",
202 0x0002: "LZ77",
203 0x0003: "LZ77 + Huffman",
204 0x0004: "Pattern_V1",
205}
207# [MS-SMB2] sect 2.2.3.1.2
208SMB2_ENCRYPTION_CIPHERS = {
209 0x0001: "AES-128-CCM",
210 0x0002: "AES-128-GCM",
211 0x0003: "AES-256-CCM",
212 0x0004: "AES-256-GCM",
213}
215# [MS-SMB2] sect 2.2.3.1.7
216SMB2_SIGNING_ALGORITHMS = {
217 0x0000: "HMAC-SHA256",
218 0x0001: "AES-CMAC",
219 0x0002: "AES-GMAC",
220}
222# [MS-SMB2] sect 2.2.3.1.1
223SMB2_HASH_ALGORITHMS = {
224 0x0001: "SHA-512",
225}
227# sect [MS-SMB2] 2.2.13.1.1
228SMB2_ACCESS_FLAGS_FILE = {
229 0x00000001: "FILE_READ_DATA",
230 0x00000002: "FILE_WRITE_DATA",
231 0x00000004: "FILE_APPEND_DATA",
232 0x00000008: "FILE_READ_EA",
233 0x00000010: "FILE_WRITE_EA",
234 0x00000040: "FILE_DELETE_CHILD",
235 0x00000020: "FILE_EXECUTE",
236 0x00000080: "FILE_READ_ATTRIBUTES",
237 0x00000100: "FILE_WRITE_ATTRIBUTES",
238 0x00010000: "DELETE",
239 0x00020000: "READ_CONTROL",
240 0x00040000: "WRITE_DAC",
241 0x00080000: "WRITE_OWNER",
242 0x00100000: "SYNCHRONIZE",
243 0x01000000: "ACCESS_SYSTEM_SECURITY",
244 0x02000000: "MAXIMUM_ALLOWED",
245 0x10000000: "GENERIC_ALL",
246 0x20000000: "GENERIC_EXECUTE",
247 0x40000000: "GENERIC_WRITE",
248 0x80000000: "GENERIC_READ",
249}
251# sect [MS-SMB2] 2.2.13.1.2
252SMB2_ACCESS_FLAGS_DIRECTORY = {
253 0x00000001: "FILE_LIST_DIRECTORY",
254 0x00000002: "FILE_ADD_FILE",
255 0x00000004: "FILE_ADD_SUBDIRECTORY",
256 0x00000008: "FILE_READ_EA",
257 0x00000010: "FILE_WRITE_EA",
258 0x00000020: "FILE_TRAVERSE",
259 0x00000040: "FILE_DELETE_CHILD",
260 0x00000080: "FILE_READ_ATTRIBUTES",
261 0x00000100: "FILE_WRITE_ATTRIBUTES",
262 0x00010000: "DELETE",
263 0x00020000: "READ_CONTROL",
264 0x00040000: "WRITE_DAC",
265 0x00080000: "WRITE_OWNER",
266 0x00100000: "SYNCHRONIZE",
267 0x01000000: "ACCESS_SYSTEM_SECURITY",
268 0x02000000: "MAXIMUM_ALLOWED",
269 0x10000000: "GENERIC_ALL",
270 0x20000000: "GENERIC_EXECUTE",
271 0x40000000: "GENERIC_WRITE",
272 0x80000000: "GENERIC_READ",
273}
275# [MS-SRVS] sec 2.2.2.4
276SRVSVC_SHARE_TYPES = {
277 0x00000000: "DISKTREE",
278 0x00000001: "PRINTQ",
279 0x00000002: "DEVICE",
280 0x00000003: "IPC",
281 0x02000000: "CLUSTER_FS",
282 0x04000000: "CLUSTER_SOFS",
283 0x08000000: "CLUSTER_DFS",
284}
287# [MS-FSCC] sec 2.6
288FileAttributes = {
289 0x00000001: "FILE_ATTRIBUTE_READONLY",
290 0x00000002: "FILE_ATTRIBUTE_HIDDEN",
291 0x00000004: "FILE_ATTRIBUTE_SYSTEM",
292 0x00000010: "FILE_ATTRIBUTE_DIRECTORY",
293 0x00000020: "FILE_ATTRIBUTE_ARCHIVE",
294 0x00000080: "FILE_ATTRIBUTE_NORMAL",
295 0x00000100: "FILE_ATTRIBUTE_TEMPORARY",
296 0x00000200: "FILE_ATTRIBUTE_SPARSE_FILE",
297 0x00000400: "FILE_ATTRIBUTE_REPARSE_POINT",
298 0x00000800: "FILE_ATTRIBUTE_COMPRESSED",
299 0x00001000: "FILE_ATTRIBUTE_OFFLINE",
300 0x00002000: "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED",
301 0x00004000: "FILE_ATTRIBUTE_ENCRYPTED",
302 0x00008000: "FILE_ATTRIBUTE_INTEGRITY_STREAM",
303 0x00020000: "FILE_ATTRIBUTE_NO_SCRUB_DATA",
304 0x00040000: "FILE_ATTRIBUTE_RECALL_ON_OPEN",
305 0x00080000: "FILE_ATTRIBUTE_PINNED",
306 0x00100000: "FILE_ATTRIBUTE_UNPINNED",
307 0x00400000: "FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS",
308}
311# [MS-FSCC] sect 2.4
312FileInformationClasses = {
313 0x01: "FileDirectoryInformation",
314 0x02: "FileFullDirectoryInformation",
315 0x03: "FileBothDirectoryInformation",
316 0x04: "FileBasicInformation",
317 0x05: "FileStandardInformation",
318 0x06: "FileInternalInformation",
319 0x07: "FileEaInformation",
320 0x08: "FileAccessInformation",
321 0x0A: "FileRenameInformation",
322 0x0E: "FilePositionInformation",
323 0x10: "FileModeInformation",
324 0x11: "FileAlignmentInformation",
325 0x12: "FileAllInformation",
326 0x22: "FileNetworkOpenInformation",
327 0x25: "FileIdBothDirectoryInformation",
328 0x26: "FileIdFullDirectoryInformation",
329 0x0C: "FileNamesInformation",
330 0x30: "FileNormalizedNameInformation",
331 0x3C: "FileIdExtdDirectoryInformation",
332}
333_FileInformationClasses = {}
336# [MS-FSCC] 2.1.7 FILE_NAME_INFORMATION
339class FILE_NAME_INFORMATION(Packet):
340 fields_desc = [
341 FieldLenField("FileNameLength", None, length_of="FileName", fmt="<I"),
342 StrLenFieldUtf16("FileName", "", length_from=lambda pkt: pkt.FileNameLength),
343 ]
345 def default_payload_class(self, s):
346 return conf.padding_layer
349# [MS-FSCC] 2.4.1 FileAccessInformation
352class FileAccessInformation(Packet):
353 fields_desc = [
354 FlagsField("AccessFlags", 0, -32, SMB2_ACCESS_FLAGS_FILE),
355 ]
357 def default_payload_class(self, s):
358 return conf.padding_layer
361# [MS-FSCC] 2.4.3 FileAlignmentInformation
364class FileAlignmentInformation(Packet):
365 fields_desc = [
366 LEIntEnumField(
367 "AccessFlags",
368 0,
369 {
370 0x00000000: "FILE_BYTE_ALIGNMENT",
371 0x00000001: "FILE_WORD_ALIGNMENT",
372 0x00000003: "FILE_LONG_ALIGNMENT",
373 0x00000007: "FILE_QUAD_ALIGNMENT",
374 0x0000000F: "FILE_OCTA_ALIGNMENT",
375 0x0000001F: "FILE_32_BYTE_ALIGNMENT",
376 0x0000003F: "FILE_64_BYTE_ALIGNMENT",
377 0x0000007F: "FILE_128_BYTE_ALIGNMENT",
378 0x000000FF: "FILE_256_BYTE_ALIGNMENT",
379 0x000001FF: "FILE_512_BYTE_ALIGNMENT",
380 },
381 ),
382 ]
384 def default_payload_class(self, s):
385 return conf.padding_layer
388# [MS-FSCC] 2.4.5 FileAlternateNameInformation
391class FileAlternateNameInformation(Packet):
392 fields_desc = [
393 FieldLenField("FileNameLength", None, length_of="FileName", fmt="<I"),
394 StrLenFieldUtf16("FileName", b"", length_from=lambda pkt: pkt.FileNameLength),
395 ]
398# [MS-FSCC] 2.4.7 FileBasicInformation
401class FileBasicInformation(Packet):
402 fields_desc = [
403 UTCTimeField(
404 "CreationTime",
405 None,
406 fmt="<Q",
407 epoch=[1601, 1, 1, 0, 0, 0],
408 custom_scaling=1e7,
409 ),
410 UTCTimeField(
411 "LastAccessTime",
412 None,
413 fmt="<Q",
414 epoch=[1601, 1, 1, 0, 0, 0],
415 custom_scaling=1e7,
416 ),
417 UTCTimeField(
418 "LastWriteTime",
419 None,
420 fmt="<Q",
421 epoch=[1601, 1, 1, 0, 0, 0],
422 custom_scaling=1e7,
423 ),
424 UTCTimeField(
425 "ChangeTime",
426 None,
427 fmt="<Q",
428 epoch=[1601, 1, 1, 0, 0, 0],
429 custom_scaling=1e7,
430 ),
431 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes),
432 IntField("Reserved", 0),
433 ]
435 def default_payload_class(self, s):
436 return conf.padding_layer
439# [MS-FSCC] 2.4.12 FileEaInformation
442class FileEaInformation(Packet):
443 fields_desc = [
444 LEIntField("EaSize", 0),
445 ]
447 def default_payload_class(self, s):
448 return conf.padding_layer
451# [MS-FSCC] 2.4.29 FileNetworkOpenInformation
454class FileNetworkOpenInformation(Packet):
455 fields_desc = [
456 UTCTimeField(
457 "CreationTime",
458 None,
459 fmt="<Q",
460 epoch=[1601, 1, 1, 0, 0, 0],
461 custom_scaling=1e7,
462 ),
463 UTCTimeField(
464 "LastAccessTime",
465 None,
466 fmt="<Q",
467 epoch=[1601, 1, 1, 0, 0, 0],
468 custom_scaling=1e7,
469 ),
470 UTCTimeField(
471 "LastWriteTime",
472 None,
473 fmt="<Q",
474 epoch=[1601, 1, 1, 0, 0, 0],
475 custom_scaling=1e7,
476 ),
477 UTCTimeField(
478 "ChangeTime",
479 None,
480 fmt="<Q",
481 epoch=[1601, 1, 1, 0, 0, 0],
482 custom_scaling=1e7,
483 ),
484 LELongField("AllocationSize", 4096),
485 LELongField("EndOfFile", 0),
486 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes),
487 IntField("Reserved2", 0),
488 ]
490 def default_payload_class(self, s):
491 return conf.padding_layer
494# [MS-FSCC] 2.4.8 FileBothDirectoryInformation
497class FILE_BOTH_DIR_INFORMATION(Packet):
498 fields_desc = (
499 [
500 LEIntField("Next", None), # 0 = no next entry
501 LEIntField("FileIndex", 0),
502 ]
503 + (
504 FileNetworkOpenInformation.fields_desc[:4]
505 + FileNetworkOpenInformation.fields_desc[4:6][::-1]
506 + [FileNetworkOpenInformation.fields_desc[6]]
507 )
508 + [
509 FieldLenField("FileNameLength", None, fmt="<I", length_of="FileName"),
510 MultipleTypeField(
511 # "If FILE_ATTRIBUTE_REPARSE_POINT is set in the FileAttributes field,
512 # this field MUST contain a reparse tag as specified in section
513 # 2.1.2.1."
514 [
515 (
516 LEIntEnumField("EaSize", 0, REPARSE_TAGS),
517 lambda pkt: pkt.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT,
518 )
519 ],
520 LEIntField("EaSize", 0),
521 ),
522 ByteField("ShortNameLength", 0),
523 ByteField("Reserved1", 0),
524 StrFixedLenField("ShortName", b"", length=24),
525 PadField(
526 StrLenFieldUtf16(
527 "FileName", b".", length_from=lambda pkt: pkt.FileNameLength
528 ),
529 align=8,
530 ),
531 ]
532 )
534 def default_payload_class(self, s):
535 return conf.padding_layer
538class _NextPacketListField(PacketListField):
539 def addfield(self, pkt, s, val):
540 # we use this field to set NextEntryOffset
541 res = b""
542 for i, v in enumerate(val):
543 x = self.i2m(pkt, v)
544 if v.Next is None and i != len(val) - 1:
545 x = struct.pack("<I", len(x)) + x[4:]
546 res += x
547 return s + res
550class FileBothDirectoryInformation(Packet):
551 fields_desc = [
552 _NextPacketListField(
553 "files",
554 [],
555 FILE_BOTH_DIR_INFORMATION,
556 max_count=1000,
557 ),
558 ]
561# [MS-FSCC] 2.4.14 FileFullDirectoryInformation
564class FILE_FULL_DIR_INFORMATION(Packet):
565 fields_desc = FILE_BOTH_DIR_INFORMATION.fields_desc[:11] + [
566 FILE_BOTH_DIR_INFORMATION.fields_desc[-1]
567 ]
570class FileFullDirectoryInformation(Packet):
571 fields_desc = [
572 _NextPacketListField(
573 "files",
574 [],
575 FILE_FULL_DIR_INFORMATION,
576 max_count=1000,
577 ),
578 ]
581# [MS-FSCC] 2.4.17 FileIdBothDirectoryInformation
584class FILE_ID_BOTH_DIR_INFORMATION(Packet):
585 fields_desc = FILE_BOTH_DIR_INFORMATION.fields_desc[:14] + [
586 LEShortField("Reserved2", 0),
587 LELongField("FileId", 0),
588 FILE_BOTH_DIR_INFORMATION.fields_desc[-1],
589 ]
591 def default_payload_class(self, s):
592 return conf.padding_layer
595class FileIdBothDirectoryInformation(Packet):
596 fields_desc = [
597 _NextPacketListField(
598 "files",
599 [],
600 FILE_ID_BOTH_DIR_INFORMATION,
601 max_count=1000, # > 65535 / len(FILE_ID_BOTH_DIR_INFORMATION())
602 ),
603 ]
606# [MS-FSCC] 2.4.22 FileInternalInformation
609class FileInternalInformation(Packet):
610 fields_desc = [
611 LELongField("IndexNumber", 0),
612 ]
614 def default_payload_class(self, s):
615 return conf.padding_layer
618# [MS-FSCC] 2.4.26 FileModeInformation
621class FileModeInformation(Packet):
622 fields_desc = [
623 FlagsField(
624 "Mode",
625 0,
626 -32,
627 {
628 0x00000002: "FILE_WRITE_TROUGH",
629 0x00000004: "FILE_SEQUENTIAL_ONLY",
630 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING",
631 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT",
632 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT",
633 0x00001000: "FILE_DELETE_ON_CLOSE",
634 },
635 )
636 ]
638 def default_payload_class(self, s):
639 return conf.padding_layer
642# [MS-FSCC] 2.4.35 FilePositionInformation
645class FilePositionInformation(Packet):
646 fields_desc = [
647 LELongField("CurrentByteOffset", 0),
648 ]
650 def default_payload_class(self, s):
651 return conf.padding_layer
654# [MS-FSCC] 2.4.37 FileRenameInformation
657class FileRenameInformation(Packet):
658 fields_desc = [
659 YesNoByteField("ReplaceIfExists", False),
660 XStrFixedLenField("Reserved", b"", length=7),
661 LELongField("RootDirectory", 0),
662 FieldLenField("FileNameLength", 0, length_of="FileName", fmt="<I"),
663 StrLenFieldUtf16("FileName", b"", length_from=lambda pkt: pkt.FileNameLength),
664 ]
666 def post_build(self, pkt, pay):
667 # type: (bytes, bytes) -> bytes
668 if len(pkt) < 24:
669 # 'Length of this field MUST be the number of bytes required to make the
670 # size of this structure at least 24.'
671 pkt += (24 - len(pkt)) * b"\x00"
672 return pkt + pay
674 def default_payload_class(self, s):
675 return conf.padding_layer
678_FileInformationClasses[0x0A] = FileRenameInformation
681# [MS-FSCC] 2.4.41 FileStandardInformation
684class FileStandardInformation(Packet):
685 fields_desc = [
686 LELongField("AllocationSize", 4096),
687 LELongField("EndOfFile", 0),
688 LEIntField("NumberOfLinks", 1),
689 ByteField("DeletePending", 0),
690 ByteField("Directory", 0),
691 ShortField("Reserved", 0),
692 ]
694 def default_payload_class(self, s):
695 return conf.padding_layer
698# [MS-FSCC] 2.4.43 FileStreamInformation
701class FileStreamInformation(Packet):
702 fields_desc = [
703 LEIntField("Next", 0),
704 FieldLenField("StreamNameLength", None, length_of="StreamName", fmt="<I"),
705 LELongField("StreamSize", 0),
706 LELongField("StreamAllocationSize", 4096),
707 StrLenFieldUtf16(
708 "StreamName", b"::$DATA", length_from=lambda pkt: pkt.StreamNameLength
709 ),
710 ]
713# [MS-FSCC] 2.4.2 FileAllInformation
716class FileAllInformation(Packet):
717 fields_desc = [
718 PacketField("BasicInformation", FileBasicInformation(), FileBasicInformation),
719 PacketField(
720 "StandardInformation", FileStandardInformation(), FileStandardInformation
721 ),
722 PacketField(
723 "InternalInformation", FileInternalInformation(), FileInternalInformation
724 ),
725 PacketField("EaInformation", FileEaInformation(), FileEaInformation),
726 PacketField(
727 "AccessInformation", FileAccessInformation(), FileAccessInformation
728 ),
729 PacketField(
730 "PositionInformation", FilePositionInformation(), FilePositionInformation
731 ),
732 PacketField("ModeInformation", FileModeInformation(), FileModeInformation),
733 PacketField(
734 "AlignmentInformation", FileAlignmentInformation(), FileAlignmentInformation
735 ),
736 PacketField("NameInformation", FILE_NAME_INFORMATION(), FILE_NAME_INFORMATION),
737 ]
740# [MS-FSCC] 2.5.1 FileFsAttributeInformation
743class FileFsAttributeInformation(Packet):
744 fields_desc = [
745 FlagsField(
746 "FileSystemAttributes",
747 0x00C706FF,
748 -32,
749 {
750 0x02000000: "FILE_SUPPORTS_USN_JOURNAL",
751 0x01000000: "FILE_SUPPORTS_OPEN_BY_FILE_ID",
752 0x00800000: "FILE_SUPPORTS_EXTENDED_ATTRIBUTES",
753 0x00400000: "FILE_SUPPORTS_HARD_LINKS",
754 0x00200000: "FILE_SUPPORTS_TRANSACTIONS",
755 0x00100000: "FILE_SEQUENTIAL_WRITE_ONCE",
756 0x00080000: "FILE_READ_ONLY_VOLUME",
757 0x00040000: "FILE_NAMED_STREAMS",
758 0x00020000: "FILE_SUPPORTS_ENCRYPTION",
759 0x00010000: "FILE_SUPPORTS_OBJECT_IDS",
760 0x00008000: "FILE_VOLUME_IS_COMPRESSED",
761 0x00000100: "FILE_SUPPORTS_REMOTE_STORAGE",
762 0x00000080: "FILE_SUPPORTS_REPARSE_POINTS",
763 0x00000040: "FILE_SUPPORTS_SPARSE_FILES",
764 0x00000020: "FILE_VOLUME_QUOTAS",
765 0x00000010: "FILE_FILE_COMPRESSION",
766 0x00000008: "FILE_PERSISTENT_ACLS",
767 0x00000004: "FILE_UNICODE_ON_DISK",
768 0x00000002: "FILE_CASE_PRESERVED_NAMES",
769 0x00000001: "FILE_CASE_SENSITIVE_SEARCH",
770 0x04000000: "FILE_SUPPORT_INTEGRITY_STREAMS",
771 0x08000000: "FILE_SUPPORTS_BLOCK_REFCOUNTING",
772 0x10000000: "FILE_SUPPORTS_SPARSE_VDL",
773 },
774 ),
775 LEIntField("MaximumComponentNameLength", 255),
776 FieldLenField(
777 "FileSystemNameLength", None, length_of="FileSystemName", fmt="<I"
778 ),
779 StrLenFieldUtf16(
780 "FileSystemName", b"NTFS", length_from=lambda pkt: pkt.FileSystemNameLength
781 ),
782 ]
785# [MS-FSCC] 2.5.8 FileFsSizeInformation
788class FileFsSizeInformation(Packet):
789 fields_desc = [
790 LELongField("TotalAllocationUnits", 10485760),
791 LELongField("AvailableAllocationUnits", 1048576),
792 LEIntField("SectorsPerAllocationUnit", 8),
793 LEIntField("BytesPerSector", 512),
794 ]
797# [MS-FSCC] 2.5.9 FileFsVolumeInformation
800class FileFsVolumeInformation(Packet):
801 fields_desc = [
802 UTCTimeField(
803 "VolumeCreationTime",
804 None,
805 fmt="<Q",
806 epoch=[1601, 1, 1, 0, 0, 0],
807 custom_scaling=1e7,
808 ),
809 LEIntField("VolumeSerialNumber", 0),
810 LEIntField("VolumeLabelLength", 0),
811 ByteField("SupportsObjects", 1),
812 ByteField("Reserved", 0),
813 StrNullFieldUtf16("VolumeLabel", b"C"),
814 ]
817# [MS-FSCC] 2.7.1 FILE_NOTIFY_INFORMATION
820class FILE_NOTIFY_INFORMATION(Packet):
821 fields_desc = [
822 IntField("NextEntryOffset", 0),
823 LEIntEnumField(
824 "Action",
825 0,
826 {
827 0x00000001: "FILE_ACTION_ADDED",
828 0x00000002: "FILE_ACTION_REMOVED",
829 0x00000003: "FILE_ACTION_MODIFIED",
830 0x00000004: "FILE_ACTION_RENAMED_OLD_NAME",
831 0x00000005: "FILE_ACTION_RENAMED_NEW_NAME",
832 0x00000006: "FILE_ACTION_ADDED_STREAM",
833 0x00000007: "FILE_ACTION_REMOVED_STREAM",
834 0x00000008: "FILE_ACTION_MODIFIED_STREAM",
835 0x00000009: "FILE_ACTION_REMOVED_BY_DELETE",
836 0x0000000A: "FILE_ACTION_ID_NOT_TUNNELLED",
837 0x0000000B: "FILE_ACTION_TUNNELLED_ID_COLLISION",
838 },
839 ),
840 FieldLenField(
841 "FileNameLength",
842 None,
843 length_of="FileName",
844 fmt="<I",
845 ),
846 StrLenFieldUtf16("FileName", b"", length_from=lambda x: x.FileNameLength),
847 StrLenField(
848 "pad",
849 b"",
850 length_from=lambda x: (
851 (x.NextEntryOffset - x.FileNameLength) if x.NextEntryOffset else 0
852 ),
853 ),
854 ]
856 def default_payload_class(self, s):
857 return conf.padding_layer
860_SMB2_CONFIG = [
861 ("BufferOffset", _NTLM_ENUM.OFFSET),
862 ("Len", _NTLM_ENUM.LEN),
863]
866def _SMB2_post_build(self, p, pay_offset, fields):
867 """Util function to build the offset and populate the lengths"""
868 return _NTLM_post_build(self, p, pay_offset, fields, config=_SMB2_CONFIG)
871# SMB2 sect 2.1
874class DirectTCP(NBTSession):
875 name = "Direct TCP"
876 MAXLENGTH = 0xFFFFFF
877 fields_desc = [ByteField("zero", 0), ThreeBytesField("LENGTH", None)]
880# SMB2 sect 2.2.1.1
883class SMB2_Header(Packet):
884 __slots__ = ["_decrypted"]
886 name = "SMB2 Header"
887 fields_desc = [
888 StrFixedLenField("Start", b"\xfeSMB", 4),
889 LEShortField("StructureSize", 64),
890 LEShortField("CreditCharge", 0),
891 LEIntEnumField("Status", 0, STATUS_ERREF),
892 LEShortEnumField("Command", 0, SMB2_COM),
893 LEShortField("CreditRequest", 0),
894 FlagsField(
895 "Flags",
896 0,
897 -32,
898 {
899 0x00000001: "SMB2_FLAGS_SERVER_TO_REDIR",
900 0x00000002: "SMB2_FLAGS_ASYNC_COMMAND",
901 0x00000004: "SMB2_FLAGS_RELATED_OPERATIONS",
902 0x00000008: "SMB2_FLAGS_SIGNED",
903 0x10000000: "SMB2_FLAGS_DFS_OPERATIONS",
904 0x20000000: "SMB2_FLAGS_REPLAY_OPERATION",
905 },
906 ),
907 XLEIntField("NextCommand", 0),
908 LELongField("MID", 0), # MessageID
909 # ASYNC
910 ConditionalField(
911 LELongField("AsyncId", 0), lambda pkt: pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND
912 ),
913 # SYNC
914 ConditionalField(
915 LEIntField("PID", 0), # Reserved, but PID per wireshark
916 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND,
917 ),
918 ConditionalField(
919 LEIntField("TID", 0), # TreeID
920 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND,
921 ),
922 # COMMON
923 LELongField("SessionId", 0),
924 XStrFixedLenField("SecuritySignature", 0, length=16),
925 ]
927 _SMB2_OK_RETURNCODES = (
928 # sect 3.3.4.4
929 (0xC0000016, 0x0001), # STATUS_MORE_PROCESSING_REQUIRED
930 (0x80000005, 0x0008), # STATUS_BUFFER_OVERFLOW (Read)
931 (0x80000005, 0x0010), # STATUS_BUFFER_OVERFLOW (QueryInfo)
932 (0x80000005, 0x000B), # STATUS_BUFFER_OVERFLOW (IOCTL)
933 (0xC000000D, 0x000B), # STATUS_INVALID_PARAMETER
934 (0x0000010C, 0x000F), # STATUS_NOTIFY_ENUM_DIR
935 )
937 def __init__(self, *args, **kwargs):
938 # The parent passes whether this packet was decrypted or not.
939 self._decrypted = kwargs.pop("_decrypted", False)
940 super(SMB2_Header, self).__init__(*args, **kwargs)
942 def guess_payload_class(self, payload):
943 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR and self.Status != 0x00000000:
944 # Check status for responses
945 if (self.Status, self.Command) not in SMB2_Header._SMB2_OK_RETURNCODES:
946 return SMB2_Error_Response
947 if self.Command == 0x0000: # Negotiate
948 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
949 return SMB2_Negotiate_Protocol_Response
950 return SMB2_Negotiate_Protocol_Request
951 elif self.Command == 0x0001: # Setup
952 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
953 return SMB2_Session_Setup_Response
954 return SMB2_Session_Setup_Request
955 elif self.Command == 0x0002: # Logoff
956 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
957 return SMB2_Session_Logoff_Response
958 return SMB2_Session_Logoff_Request
959 elif self.Command == 0x0003: # TREE connect
960 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
961 return SMB2_Tree_Connect_Response
962 return SMB2_Tree_Connect_Request
963 elif self.Command == 0x0004: # TREE disconnect
964 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
965 return SMB2_Tree_Disconnect_Response
966 return SMB2_Tree_Disconnect_Request
967 elif self.Command == 0x0005: # Create
968 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
969 return SMB2_Create_Response
970 return SMB2_Create_Request
971 elif self.Command == 0x0006: # Close
972 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
973 return SMB2_Close_Response
974 return SMB2_Close_Request
975 elif self.Command == 0x0008: # Read
976 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
977 return SMB2_Read_Response
978 return SMB2_Read_Request
979 elif self.Command == 0x0009: # Write
980 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
981 return SMB2_Write_Response
982 return SMB2_Write_Request
983 elif self.Command == 0x000C: # Cancel
984 return SMB2_Cancel_Request
985 elif self.Command == 0x000D: # Echo
986 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
987 return SMB2_Echo_Response
988 return SMB2_Echo_Request
989 elif self.Command == 0x000E: # Query directory
990 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
991 return SMB2_Query_Directory_Response
992 return SMB2_Query_Directory_Request
993 elif self.Command == 0x000F: # Change Notify
994 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
995 return SMB2_Change_Notify_Response
996 return SMB2_Change_Notify_Request
997 elif self.Command == 0x0010: # Query info
998 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
999 return SMB2_Query_Info_Response
1000 return SMB2_Query_Info_Request
1001 elif self.Command == 0x0011: # Set info
1002 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
1003 return SMB2_Set_Info_Response
1004 return SMB2_Set_Info_Request
1005 elif self.Command == 0x000B: # IOCTL
1006 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:
1007 return SMB2_IOCTL_Response
1008 return SMB2_IOCTL_Request
1009 return super(SMB2_Header, self).guess_payload_class(payload)
1011 def _calc_signature(
1012 self, s, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None
1013 ):
1014 """
1015 This function calculates the signature of a SMB2 packet.
1016 Detail is from [MS-SMB2] 3.1.4.1
1017 """
1018 if len(s) <= 64:
1019 log_runtime.warning("Cannot sign invalid SMB packet !")
1020 return s
1021 if dialect in [0x0300, 0x0302, 0x0311]: # SMB 3
1022 if dialect == 0x0311: # SMB 3.1.1
1023 if IsClient is None:
1024 raise Exception("SMB 3.1.1 needs a IsClient")
1025 if SigningAlgorithmId is None:
1026 SigningAlgorithmId = "AES-CMAC" # AES-128-CMAC
1027 else:
1028 SigningAlgorithmId = "AES-CMAC" # AES-128-CMAC
1029 if "GMAC" in SigningAlgorithmId:
1030 from cryptography.hazmat.primitives.ciphers.aead import AESGCM
1032 aesgcm = AESGCM(SigningSessionKey)
1033 nonce = struct.pack("<Q", self.MID) + struct.pack(
1034 "<I",
1035 (0 if IsClient else 1) | (0x8000000 if self.Command == 9 else 0),
1036 )
1037 sig = aesgcm.encrypt(nonce, b"", s)
1038 elif "CMAC" in SigningAlgorithmId:
1039 from cryptography.hazmat.primitives import cmac
1040 from cryptography.hazmat.primitives.ciphers import algorithms
1042 c = cmac.CMAC(algorithms.AES(SigningSessionKey))
1043 c.update(s)
1044 sig = c.finalize()
1045 elif "HMAC" in SigningAlgorithmId:
1046 from scapy.layers.tls.crypto.h_mac import Hmac_SHA256
1048 sig = Hmac_SHA256(SigningSessionKey).digest(s)
1049 sig = sig[:16]
1050 else:
1051 raise ValueError("Unknown SigningAlgorithmId")
1052 elif dialect in [0x0210, 0x0202]: # SMB 2.1 or SMB 2.0.2
1053 from scapy.layers.tls.crypto.h_mac import Hmac_SHA256
1055 sig = Hmac_SHA256(SigningSessionKey).digest(s)
1056 sig = sig[:16]
1057 else:
1058 log_runtime.warning("Unknown SMB Version %s ! Cannot sign." % dialect)
1059 sig = b"\x00" * 16
1060 return sig
1062 def sign(self, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None):
1063 """
1064 [MS-SMB2] 3.1.4.1 - Signing An Outgoing Message
1065 """
1066 # Set the current signature to nul
1067 self.SecuritySignature = b"\x00" * 16
1068 # Calculate the signature
1069 s = bytes(self)
1070 self.SecuritySignature = self._calc_signature(
1071 s,
1072 dialect=dialect,
1073 SigningSessionKey=SigningSessionKey,
1074 SigningAlgorithmId=SigningAlgorithmId,
1075 IsClient=IsClient,
1076 )
1077 # we make sure the payload is static
1078 self.payload = conf.raw_layer(load=s[64:])
1080 def verify(
1081 self, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None
1082 ):
1083 """
1084 [MS-SMB2] sect 3.2.5.1.3 - Verifying the signature
1085 """
1086 s = bytes(self)
1087 # Set SecuritySignature to nul
1088 s = s[:48] + b"\x00" * 16 + s[64:]
1089 # Calculate the signature
1090 sig = self._calc_signature(
1091 s,
1092 dialect=dialect,
1093 SigningSessionKey=SigningSessionKey,
1094 SigningAlgorithmId=SigningAlgorithmId,
1095 IsClient=IsClient,
1096 )
1097 if self.SecuritySignature != sig:
1098 log_runtime.error("SMB signature is invalid !")
1099 raise Exception("ERROR: SMB signature is invalid !")
1101 def encrypt(self, dialect, EncryptionKey, CipherId):
1102 """
1103 [MS-SMB2] sect 3.1.4.3 - Encrypting the Message
1104 """
1105 if dialect < 0x0300:
1106 raise Exception("Encryption is not supported on this SMB dialect !")
1107 elif dialect < 0x0311 and CipherId != "AES-128-CCM":
1108 raise Exception("CipherId is not supported on this SMB dialect !")
1110 data = bytes(self)
1111 smbt = SMB2_Transform_Header(
1112 OriginalMessageSize=len(self),
1113 SessionId=self.SessionId,
1114 Flags=0x0001,
1115 )
1116 if "GCM" in CipherId:
1117 from cryptography.hazmat.primitives.ciphers.aead import AESGCM
1119 nonce = os.urandom(12)
1120 cipher = AESGCM(EncryptionKey)
1121 elif "CCM" in CipherId:
1122 from cryptography.hazmat.primitives.ciphers.aead import AESCCM
1124 nonce = os.urandom(11)
1125 cipher = AESCCM(EncryptionKey)
1126 else:
1127 raise Exception("Unknown CipherId !")
1129 # Add nonce to header and build the auth data
1130 smbt.Nonce = nonce
1131 aad = bytes(smbt)[20:]
1133 # Perform the actual encryption
1134 data = cipher.encrypt(nonce, data, aad)
1136 # Put the auth tag in the Signature field
1137 smbt.Signature, data = data[-16:], data[:-16]
1139 return smbt / data
1142class _SMB2_Payload(Packet):
1143 def do_dissect_payload(self, s):
1144 # There can be padding between this layer and the next one
1145 if self.underlayer and isinstance(self.underlayer, SMB2_Header):
1146 if self.underlayer.NextCommand:
1147 padlen = self.underlayer.NextCommand - (64 + len(self.raw_packet_cache))
1148 if padlen:
1149 self.add_payload(s[:padlen])
1150 s = s[padlen:]
1151 super(_SMB2_Payload, self).do_dissect_payload(s)
1153 def answers(self, other):
1154 return (
1155 isinstance(other, _SMB2_Payload)
1156 and self.__class__ != other.__class__
1157 and (self.Command == other.Command or self.Command == -1)
1158 )
1160 def guess_payload_class(self, s):
1161 if self.underlayer and isinstance(self.underlayer, SMB2_Header):
1162 if self.underlayer.NextCommand:
1163 return SMB2_Header
1164 return super(_SMB2_Payload, self).guess_payload_class(s)
1167# sect 2.2.2
1170class SMB2_Error_Response(_SMB2_Payload):
1171 Command = -1
1172 __slots__ = ["NTStatus"] # extra info
1173 name = "SMB2 Error Response"
1174 fields_desc = [
1175 XLEShortField("StructureSize", 0x09),
1176 ByteField("ErrorContextCount", 0),
1177 ByteField("Reserved", 0),
1178 FieldLenField("ByteCount", None, fmt="<I", length_of="ErrorData"),
1179 XStrLenField("ErrorData", b"", length_from=lambda pkt: pkt.ByteCount),
1180 ]
1183bind_top_down(SMB2_Header, SMB2_Error_Response, Flags=1) # SMB2_FLAGS_SERVER_TO_REDIR
1185# sect 2.2.2.2.2
1188class MOVE_DST_IPADDR(Packet):
1189 fields_desc = [
1190 # Wireshark appears to get this wrong
1191 LEIntEnumField("Type", 1, {1: "IPv4", 2: "IPv6"}),
1192 IntField("Reserved", 0),
1193 MultipleTypeField(
1194 [(IP6Field("IPAddress", None), lambda pkt: pkt.Type == 2)],
1195 IPField("IPAddress", None),
1196 ),
1197 ConditionalField(
1198 # For IPv4
1199 StrFixedLenField("Reserved2", b"", length=12),
1200 lambda pkt: pkt.Type == 1,
1201 ),
1202 ]
1204 def default_payload_class(self, payload):
1205 return conf.padding_layer
1208class SMB2_Error_Share_Redirect_Context_Response(_NTLMPayloadPacket):
1209 name = "Share Redirect Error Context Response"
1210 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
1211 fields_desc = [
1212 XLEIntField("StructureSize", 0x30),
1213 LEIntEnumField("NotificationType", 3, {3: "SHARE_MOVE_NOTIFICATION"}),
1214 XLEIntField("ResourceNameBufferOffset", None),
1215 LEIntField("ResourceNameLen", None),
1216 ShortField("Reserved", 0),
1217 ShortEnumField("TargetType", 0, {0: "IP"}),
1218 FieldLenField("IPAddrCount", None, fmt="<I", count_of="IPAddrMoveList"),
1219 PacketListField(
1220 "IPAddrMoveList",
1221 [],
1222 MOVE_DST_IPADDR,
1223 count_from=lambda pkt: pkt.IPAddrCount,
1224 ),
1225 _NTLMPayloadField(
1226 "Buffer",
1227 lambda pkt: 24 + len(pkt.IPAddrMoveList) * 24,
1228 [
1229 StrLenFieldUtf16(
1230 "ResourceName", b"", length_from=lambda pkt: pkt.ResourceNameLen
1231 ),
1232 ],
1233 ),
1234 ]
1236 def post_build(self, pkt, pay):
1237 # type: (bytes, bytes) -> bytes
1238 return (
1239 _SMB2_post_build(
1240 self,
1241 pkt,
1242 24 + len(self.IPAddrMoveList) * 24,
1243 {
1244 "ResourceName": 8,
1245 },
1246 )
1247 + pay
1248 )
1251# sect 2.2.2.1
1254class SMB2_Error_ContextResponse(Packet):
1255 fields_desc = [
1256 FieldLenField("ErrorDatalength", None, fmt="<I", length_of="ErrorContextData"),
1257 LEIntEnumField("ErrorId", 0, {0: "DEFAULT", 0x72645253: "SHARE_REDIRECT"}),
1258 MultipleTypeField(
1259 [
1260 (
1261 PacketField(
1262 "ErrorContextData",
1263 SMB2_Error_Share_Redirect_Context_Response(),
1264 SMB2_Error_Share_Redirect_Context_Response,
1265 ),
1266 lambda pkt: pkt.ErrorId == 0x72645253,
1267 )
1268 ],
1269 XStrLenField(
1270 "ErrorContextData", b"", length_from=lambda pkt: pkt.ErrorDatalength
1271 ),
1272 ),
1273 ]
1276# sect 2.2.3
1279class SMB2_Negotiate_Context(Packet):
1280 name = "SMB2 Negotiate Context"
1281 fields_desc = [
1282 LEShortEnumField("ContextType", 0x0, SMB2_NEGOTIATE_CONTEXT_TYPES),
1283 LenField("DataLength", None, fmt="<H"),
1284 IntField("Reserved", 0),
1285 ]
1287 def default_payload_class(self, payload):
1288 return conf.padding_layer
1291class SMB2_Negotiate_Protocol_Request(_SMB2_Payload, _NTLMPayloadPacket):
1292 name = "SMB2 Negotiate Protocol Request"
1293 Command = 0x0000
1294 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
1295 fields_desc = [
1296 XLEShortField("StructureSize", 0x24),
1297 FieldLenField("DialectCount", None, fmt="<H", count_of="Dialects"),
1298 # SecurityMode
1299 FlagsField("SecurityMode", 0, -16, SMB2_SECURITY_MODE),
1300 LEShortField("Reserved", 0),
1301 # Capabilities
1302 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES),
1303 UUIDField("ClientGUID", 0x0, uuid_fmt=UUIDField.FORMAT_LE),
1304 XLEIntField("NegotiateContextsBufferOffset", None),
1305 LEShortField("NegotiateContextsCount", None),
1306 ShortField("Reserved2", 0),
1307 FieldListField(
1308 "Dialects",
1309 [0x0202],
1310 LEShortEnumField("", 0x0, SMB_DIALECTS),
1311 count_from=lambda pkt: pkt.DialectCount,
1312 ),
1313 _NTLMPayloadField(
1314 "Buffer",
1315 lambda pkt: 64 + 36 + len(pkt.Dialects) * 2,
1316 [
1317 # Field only exists if Dialects contains 0x0311
1318 FieldListField(
1319 "NegotiateContexts",
1320 [],
1321 ReversePadField(
1322 PacketField("Context", None, SMB2_Negotiate_Context),
1323 8,
1324 ),
1325 count_from=lambda pkt: pkt.NegotiateContextsCount,
1326 ),
1327 ],
1328 ),
1329 ]
1331 def post_build(self, pkt, pay):
1332 # type: (bytes, bytes) -> bytes
1333 return (
1334 _NTLM_post_build(
1335 self,
1336 pkt,
1337 64 + 36 + len(self.Dialects) * 2,
1338 {
1339 "NegotiateContexts": 28,
1340 },
1341 config=[
1342 ("BufferOffset", _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8),
1343 ("Count", _NTLM_ENUM.COUNT),
1344 ],
1345 )
1346 + pay
1347 )
1350bind_top_down(
1351 SMB2_Header,
1352 SMB2_Negotiate_Protocol_Request,
1353 Command=0x0000,
1354)
1356# sect 2.2.3.1.1
1359class SMB2_Preauth_Integrity_Capabilities(Packet):
1360 name = "SMB2 Preauth Integrity Capabilities"
1361 fields_desc = [
1362 # According to the spec, this field value must be greater than 0
1363 # (cf Section 2.2.3.1.1 of MS-SMB2.pdf)
1364 FieldLenField("HashAlgorithmCount", None, fmt="<H", count_of="HashAlgorithms"),
1365 FieldLenField("SaltLength", None, fmt="<H", length_of="Salt"),
1366 FieldListField(
1367 "HashAlgorithms",
1368 [0x0001],
1369 LEShortEnumField(
1370 "",
1371 0x0,
1372 SMB2_HASH_ALGORITHMS,
1373 ),
1374 count_from=lambda pkt: pkt.HashAlgorithmCount,
1375 ),
1376 XStrLenField("Salt", "", length_from=lambda pkt: pkt.SaltLength),
1377 ]
1379 def default_payload_class(self, payload):
1380 return conf.padding_layer
1383bind_layers(
1384 SMB2_Negotiate_Context, SMB2_Preauth_Integrity_Capabilities, ContextType=0x0001
1385)
1387# sect 2.2.3.1.2
1390class SMB2_Encryption_Capabilities(Packet):
1391 name = "SMB2 Encryption Capabilities"
1392 fields_desc = [
1393 # According to the spec, this field value must be greater than 0
1394 # (cf Section 2.2.3.1.2 of MS-SMB2.pdf)
1395 FieldLenField("CipherCount", None, fmt="<H", count_of="Ciphers"),
1396 FieldListField(
1397 "Ciphers",
1398 [0x0001],
1399 LEShortEnumField(
1400 "",
1401 0x0,
1402 SMB2_ENCRYPTION_CIPHERS,
1403 ),
1404 count_from=lambda pkt: pkt.CipherCount,
1405 ),
1406 ]
1408 def default_payload_class(self, payload):
1409 return conf.padding_layer
1412bind_layers(SMB2_Negotiate_Context, SMB2_Encryption_Capabilities, ContextType=0x0002)
1414# sect 2.2.3.1.3
1417class SMB2_Compression_Capabilities(Packet):
1418 name = "SMB2 Compression Capabilities"
1419 fields_desc = [
1420 FieldLenField(
1421 "CompressionAlgorithmCount",
1422 None,
1423 fmt="<H",
1424 count_of="CompressionAlgorithms",
1425 ),
1426 ShortField("Padding", 0x0),
1427 LEIntEnumField(
1428 "Flags",
1429 0x0,
1430 {
1431 0x00000000: "SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE",
1432 0x00000001: "SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED",
1433 },
1434 ),
1435 FieldListField(
1436 "CompressionAlgorithms",
1437 None,
1438 LEShortEnumField("", 0x0, SMB2_COMPRESSION_ALGORITHMS),
1439 count_from=lambda pkt: pkt.CompressionAlgorithmCount,
1440 ),
1441 ]
1443 def default_payload_class(self, payload):
1444 return conf.padding_layer
1447bind_layers(SMB2_Negotiate_Context, SMB2_Compression_Capabilities, ContextType=0x0003)
1449# sect 2.2.3.1.4
1452class SMB2_Netname_Negotiate_Context_ID(Packet):
1453 name = "SMB2 Netname Negotiate Context ID"
1454 fields_desc = [
1455 StrLenFieldUtf16(
1456 "NetName", "", length_from=lambda pkt: pkt.underlayer.DataLength
1457 )
1458 ]
1460 def default_payload_class(self, payload):
1461 return conf.padding_layer
1464bind_layers(
1465 SMB2_Negotiate_Context, SMB2_Netname_Negotiate_Context_ID, ContextType=0x0005
1466)
1468# sect 2.2.3.1.5
1471class SMB2_Transport_Capabilities(Packet):
1472 name = "SMB2 Transport Capabilities"
1473 fields_desc = [
1474 FlagsField(
1475 "Flags",
1476 0x0,
1477 -32,
1478 {
1479 0x00000001: "SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY",
1480 },
1481 ),
1482 ]
1484 def default_payload_class(self, payload):
1485 return conf.padding_layer
1488bind_layers(SMB2_Negotiate_Context, SMB2_Transport_Capabilities, ContextType=0x0006)
1490# sect 2.2.3.1.6
1493class SMB2_RDMA_Transform_Capabilities(Packet):
1494 name = "SMB2 RDMA Transform Capabilities"
1495 fields_desc = [
1496 FieldLenField("TransformCount", None, fmt="<H", count_of="RDMATransformIds"),
1497 LEShortField("Reserved1", 0),
1498 LEIntField("Reserved2", 0),
1499 FieldListField(
1500 "RDMATransformIds",
1501 None,
1502 LEShortEnumField(
1503 "",
1504 0x0,
1505 {
1506 0x0000: "SMB2_RDMA_TRANSFORM_NONE",
1507 0x0001: "SMB2_RDMA_TRANSFORM_ENCRYPTION",
1508 0x0002: "SMB2_RDMA_TRANSFORM_SIGNING",
1509 },
1510 ),
1511 count_from=lambda pkt: pkt.TransformCount,
1512 ),
1513 ]
1515 def default_payload_class(self, payload):
1516 return conf.padding_layer
1519bind_layers(
1520 SMB2_Negotiate_Context, SMB2_RDMA_Transform_Capabilities, ContextType=0x0007
1521)
1523# sect 2.2.3.1.7
1526class SMB2_Signing_Capabilities(Packet):
1527 name = "SMB2 Signing Capabilities"
1528 fields_desc = [
1529 FieldLenField(
1530 "SigningAlgorithmCount", None, fmt="<H", count_of="SigningAlgorithms"
1531 ),
1532 FieldListField(
1533 "SigningAlgorithms",
1534 None,
1535 LEShortEnumField(
1536 "",
1537 0x0,
1538 SMB2_SIGNING_ALGORITHMS,
1539 ),
1540 count_from=lambda pkt: pkt.SigningAlgorithmCount,
1541 ),
1542 ]
1544 def default_payload_class(self, payload):
1545 return conf.padding_layer
1548bind_layers(SMB2_Negotiate_Context, SMB2_Signing_Capabilities, ContextType=0x0008)
1550# sect 2.2.4
1553class SMB2_Negotiate_Protocol_Response(_SMB2_Payload, _NTLMPayloadPacket):
1554 name = "SMB2 Negotiate Protocol Response"
1555 Command = 0x0000
1556 OFFSET = 64 + 64
1557 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
1558 fields_desc = [
1559 XLEShortField("StructureSize", 0x41),
1560 FlagsField("SecurityMode", 0, -16, SMB2_SECURITY_MODE),
1561 LEShortEnumField("DialectRevision", 0x0, SMB_DIALECTS),
1562 LEShortField("NegotiateContextsCount", None),
1563 UUIDField("GUID", 0x0, uuid_fmt=UUIDField.FORMAT_LE),
1564 # Capabilities
1565 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES),
1566 LEIntField("MaxTransactionSize", 65536),
1567 LEIntField("MaxReadSize", 65536),
1568 LEIntField("MaxWriteSize", 65536),
1569 UTCTimeField(
1570 "ServerTime",
1571 None,
1572 fmt="<Q",
1573 epoch=[1601, 1, 1, 0, 0, 0],
1574 custom_scaling=1e7,
1575 ),
1576 UTCTimeField(
1577 "ServerStartTime",
1578 None,
1579 fmt="<Q",
1580 epoch=[1601, 1, 1, 0, 0, 0],
1581 custom_scaling=1e7,
1582 ),
1583 XLEShortField("SecurityBlobBufferOffset", None),
1584 LEShortField("SecurityBlobLen", None),
1585 XLEIntField("NegotiateContextsBufferOffset", None),
1586 _NTLMPayloadField(
1587 "Buffer",
1588 OFFSET,
1589 [
1590 PacketLenField(
1591 "SecurityBlob",
1592 None,
1593 GSSAPI_BLOB,
1594 length_from=lambda x: x.SecurityBlobLen,
1595 ),
1596 # Field only exists if Dialect is 0x0311
1597 FieldListField(
1598 "NegotiateContexts",
1599 [],
1600 ReversePadField(
1601 PacketField("Context", None, SMB2_Negotiate_Context),
1602 8,
1603 ),
1604 count_from=lambda pkt: pkt.NegotiateContextsCount,
1605 ),
1606 ],
1607 force_order=["SecurityBlob", "NegotiateContexts"],
1608 ),
1609 ]
1611 def post_build(self, pkt, pay):
1612 # type: (bytes, bytes) -> bytes
1613 pkt = _NTLM_post_build(
1614 self,
1615 pkt,
1616 self.OFFSET,
1617 {
1618 "SecurityBlob": 56,
1619 "NegotiateContexts": 60,
1620 },
1621 config=[
1622 (
1623 "BufferOffset",
1624 {
1625 "SecurityBlob": _NTLM_ENUM.OFFSET,
1626 "NegotiateContexts": _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8,
1627 },
1628 ),
1629 ],
1630 )
1631 if getattr(self, "SecurityBlob", None):
1632 if self.SecurityBlobLen is None:
1633 pkt = pkt[:58] + struct.pack("<H", len(self.SecurityBlob)) + pkt[60:]
1634 if getattr(self, "NegotiateContexts", None):
1635 if self.NegotiateContextsCount is None:
1636 pkt = pkt[:6] + struct.pack("<H", len(self.NegotiateContexts)) + pkt[8:]
1637 return pkt + pay
1640bind_top_down(
1641 SMB2_Header,
1642 SMB2_Negotiate_Protocol_Response,
1643 Command=0x0000,
1644 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR
1645)
1647# sect 2.2.5
1650class SMB2_Session_Setup_Request(_SMB2_Payload, _NTLMPayloadPacket):
1651 name = "SMB2 Session Setup Request"
1652 Command = 0x0001
1653 OFFSET = 24 + 64
1654 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
1655 fields_desc = [
1656 XLEShortField("StructureSize", 0x19),
1657 FlagsField("Flags", 0, -8, ["SMB2_SESSION_FLAG_BINDING"]),
1658 FlagsField("SecurityMode", 0, -8, SMB2_SECURITY_MODE),
1659 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES),
1660 LEIntField("Channel", 0),
1661 XLEShortField("SecurityBlobBufferOffset", None),
1662 LEShortField("SecurityBlobLen", None),
1663 XLELongField("PreviousSessionId", 0),
1664 _NTLMPayloadField(
1665 "Buffer",
1666 OFFSET,
1667 [
1668 PacketField("SecurityBlob", None, GSSAPI_BLOB),
1669 ],
1670 ),
1671 ]
1673 def post_build(self, pkt, pay):
1674 # type: (bytes, bytes) -> bytes
1675 return (
1676 _SMB2_post_build(
1677 self,
1678 pkt,
1679 self.OFFSET,
1680 {
1681 "SecurityBlob": 12,
1682 },
1683 )
1684 + pay
1685 )
1688bind_top_down(
1689 SMB2_Header,
1690 SMB2_Session_Setup_Request,
1691 Command=0x0001,
1692)
1694# sect 2.2.6
1697class SMB2_Session_Setup_Response(_SMB2_Payload, _NTLMPayloadPacket):
1698 name = "SMB2 Session Setup Response"
1699 Command = 0x0001
1700 OFFSET = 8 + 64
1701 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
1702 fields_desc = [
1703 XLEShortField("StructureSize", 0x9),
1704 FlagsField(
1705 "SessionFlags",
1706 0,
1707 -16,
1708 {
1709 0x0001: "IS_GUEST",
1710 0x0002: "IS_NULL",
1711 0x0004: "ENCRYPT_DATA",
1712 },
1713 ),
1714 XLEShortField("SecurityBufferOffset", None),
1715 LEShortField("SecurityLen", None),
1716 _NTLMPayloadField(
1717 "Buffer",
1718 OFFSET,
1719 [
1720 PacketField("Security", None, GSSAPI_BLOB),
1721 ],
1722 ),
1723 ]
1725 def __getattr__(self, attr):
1726 # Ease SMB1 backward compatibility
1727 if attr == "SecurityBlob":
1728 return (
1729 super(SMB2_Session_Setup_Response, self).__getattr__("Buffer")
1730 or [(None, None)]
1731 )[0][1]
1732 return super(SMB2_Session_Setup_Response, self).__getattr__(attr)
1734 def setfieldval(self, attr, val):
1735 if attr == "SecurityBlob":
1736 return super(SMB2_Session_Setup_Response, self).setfieldval(
1737 "Buffer", [("Security", val)]
1738 )
1739 return super(SMB2_Session_Setup_Response, self).setfieldval(attr, val)
1741 def post_build(self, pkt, pay):
1742 # type: (bytes, bytes) -> bytes
1743 return (
1744 _SMB2_post_build(
1745 self,
1746 pkt,
1747 self.OFFSET,
1748 {
1749 "Security": 4,
1750 },
1751 )
1752 + pay
1753 )
1756bind_top_down(
1757 SMB2_Header,
1758 SMB2_Session_Setup_Response,
1759 Command=0x0001,
1760 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR
1761)
1763# sect 2.2.7
1766class SMB2_Session_Logoff_Request(_SMB2_Payload):
1767 name = "SMB2 LOGOFF Request"
1768 Command = 0x0002
1769 fields_desc = [
1770 XLEShortField("StructureSize", 0x4),
1771 ShortField("reserved", 0),
1772 ]
1775bind_top_down(
1776 SMB2_Header,
1777 SMB2_Session_Logoff_Request,
1778 Command=0x0002,
1779)
1781# sect 2.2.8
1784class SMB2_Session_Logoff_Response(_SMB2_Payload):
1785 name = "SMB2 LOGOFF Request"
1786 Command = 0x0002
1787 fields_desc = [
1788 XLEShortField("StructureSize", 0x4),
1789 ShortField("reserved", 0),
1790 ]
1793bind_top_down(
1794 SMB2_Header,
1795 SMB2_Session_Logoff_Response,
1796 Command=0x0002,
1797 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR
1798)
1800# sect 2.2.9
1803class SMB2_Tree_Connect_Request(_SMB2_Payload, _NTLMPayloadPacket):
1804 name = "SMB2 TREE_CONNECT Request"
1805 Command = 0x0003
1806 OFFSET = 8 + 64
1807 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
1808 fields_desc = [
1809 XLEShortField("StructureSize", 0x9),
1810 FlagsField(
1811 "Flags",
1812 0,
1813 -16,
1814 ["CLUSTER_RECONNECT", "REDIRECT_TO_OWNER", "EXTENSION_PRESENT"],
1815 ),
1816 XLEShortField("PathBufferOffset", None),
1817 LEShortField("PathLen", None),
1818 _NTLMPayloadField(
1819 "Buffer",
1820 OFFSET,
1821 [
1822 StrFieldUtf16("Path", b""),
1823 ],
1824 ),
1825 ]
1827 def post_build(self, pkt, pay):
1828 # type: (bytes, bytes) -> bytes
1829 return (
1830 _SMB2_post_build(
1831 self,
1832 pkt,
1833 self.OFFSET,
1834 {
1835 "Path": 4,
1836 },
1837 )
1838 + pay
1839 )
1842bind_top_down(
1843 SMB2_Header,
1844 SMB2_Tree_Connect_Request,
1845 Command=0x0003,
1846)
1848# sect 2.2.10
1851class SMB2_Tree_Connect_Response(_SMB2_Payload):
1852 name = "SMB2 TREE_CONNECT Response"
1853 Command = 0x0003
1854 fields_desc = [
1855 XLEShortField("StructureSize", 0x10),
1856 ByteEnumField("ShareType", 0, {0x01: "DISK", 0x02: "PIPE", 0x03: "PRINT"}),
1857 ByteField("Reserved", 0),
1858 FlagsField(
1859 "ShareFlags",
1860 0x30,
1861 -32,
1862 {
1863 0x00000010: "AUTO_CACHING",
1864 0x00000020: "VDO_CACHING",
1865 0x00000030: "NO_CACHING",
1866 0x00000001: "DFS",
1867 0x00000002: "DFS_ROOT",
1868 0x00000100: "RESTRICT_EXCLUSIVE_OPENS",
1869 0x00000200: "FORCE_SHARED_DELETE",
1870 0x00000400: "ALLOW_NAMESPACE_CACHING",
1871 0x00000800: "ACCESS_BASED_DIRECTORY_ENUM",
1872 0x00001000: "FORCE_LEVELII_OPLOCK",
1873 0x00002000: "ENABLE_HASH_V1",
1874 0x00004000: "ENABLE_HASH_V2",
1875 0x00008000: "ENCRYPT_DATA",
1876 0x00040000: "IDENTITY_REMOTING",
1877 0x00100000: "COMPRESS_DATA",
1878 },
1879 ),
1880 FlagsField(
1881 "Capabilities",
1882 0,
1883 -32,
1884 {
1885 0x00000008: "DFS",
1886 0x00000010: "CONTINUOUS_AVAILABILITY",
1887 0x00000020: "SCALEOUT",
1888 0x00000040: "CLUSTER",
1889 0x00000080: "ASYMMETRIC",
1890 0x00000100: "REDIRECT_TO_OWNER",
1891 },
1892 ),
1893 FlagsField("MaximalAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE),
1894 ]
1897bind_top_down(SMB2_Header, SMB2_Tree_Connect_Response, Command=0x0003, Flags=1)
1899# sect 2.2.11
1902class SMB2_Tree_Disconnect_Request(_SMB2_Payload):
1903 name = "SMB2 TREE_DISCONNECT Request"
1904 Command = 0x0004
1905 fields_desc = [
1906 XLEShortField("StructureSize", 0x4),
1907 XLEShortField("Reserved", 0),
1908 ]
1911bind_top_down(SMB2_Header, SMB2_Tree_Disconnect_Request, Command=0x0004)
1913# sect 2.2.12
1916class SMB2_Tree_Disconnect_Response(_SMB2_Payload):
1917 name = "SMB2 TREE_DISCONNECT Response"
1918 Command = 0x0004
1919 fields_desc = [
1920 XLEShortField("StructureSize", 0x4),
1921 XLEShortField("Reserved", 0),
1922 ]
1925bind_top_down(SMB2_Header, SMB2_Tree_Disconnect_Response, Command=0x0004, Flags=1)
1928# sect 2.2.14.1
1931class SMB2_FILEID(Packet):
1932 fields_desc = [XLELongField("Persistent", 0), XLELongField("Volatile", 0)]
1934 def __hash__(self):
1935 return self.Persistent + self.Volatile << 64
1937 def default_payload_class(self, payload):
1938 return conf.padding_layer
1941# sect 2.2.14.2
1944class SMB2_CREATE_DURABLE_HANDLE_RESPONSE(Packet):
1945 fields_desc = [
1946 XStrFixedLenField("Reserved", b"\x00" * 8, length=8),
1947 ]
1950class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE(Packet):
1951 fields_desc = [
1952 LEIntEnumField("QueryStatus", 0, STATUS_ERREF),
1953 FlagsField("MaximalAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE),
1954 ]
1957class SMB2_CREATE_QUERY_ON_DISK_ID(Packet):
1958 fields_desc = [
1959 XLELongField("DiskFileId", 0),
1960 XLELongField("VolumeId", 0),
1961 XStrFixedLenField("Reserved", b"", length=16),
1962 ]
1965class SMB2_CREATE_RESPONSE_LEASE(Packet):
1966 fields_desc = [
1967 UUIDField("LeaseKey", None),
1968 FlagsField(
1969 "LeaseState",
1970 0x7,
1971 -32,
1972 {
1973 0x01: "SMB2_LEASE_READ_CACHING",
1974 0x02: "SMB2_LEASE_HANDLE_CACHING",
1975 0x04: "SMB2_LEASE_WRITE_CACHING",
1976 },
1977 ),
1978 FlagsField(
1979 "LeaseFlags",
1980 0,
1981 -32,
1982 {
1983 0x02: "SMB2_LEASE_FLAG_BREAK_IN_PROGRESS",
1984 0x04: "SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET",
1985 },
1986 ),
1987 LELongField("LeaseDuration", 0),
1988 ]
1991class SMB2_CREATE_RESPONSE_LEASE_V2(Packet):
1992 fields_desc = [
1993 SMB2_CREATE_RESPONSE_LEASE,
1994 UUIDField("ParentLeaseKey", None),
1995 LEShortField("Epoch", 0),
1996 LEShortField("Reserved", 0),
1997 ]
2000class SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2(Packet):
2001 fields_desc = [
2002 LEIntField("Timeout", 0),
2003 FlagsField(
2004 "Flags",
2005 0,
2006 -32,
2007 {
2008 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT",
2009 },
2010 ),
2011 ]
2014# sect 2.2.13
2017class SMB2_CREATE_DURABLE_HANDLE_REQUEST(Packet):
2018 fields_desc = [
2019 XStrFixedLenField("DurableRequest", b"", length=16),
2020 ]
2023class SMB2_CREATE_DURABLE_HANDLE_RECONNECT(Packet):
2024 fields_desc = [
2025 PacketField("Data", SMB2_FILEID(), SMB2_FILEID),
2026 ]
2029class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST(Packet):
2030 fields_desc = [
2031 LELongField("Timestamp", 0),
2032 ]
2035class SMB2_CREATE_ALLOCATION_SIZE(Packet):
2036 fields_desc = [
2037 LELongField("AllocationSize", 0),
2038 ]
2041class SMB2_CREATE_TIMEWARP_TOKEN(Packet):
2042 fields_desc = [
2043 LELongField("Timestamp", 0),
2044 ]
2047class SMB2_CREATE_REQUEST_LEASE(Packet):
2048 fields_desc = [
2049 SMB2_CREATE_RESPONSE_LEASE,
2050 ]
2053class SMB2_CREATE_REQUEST_LEASE_V2(Packet):
2054 fields_desc = [
2055 SMB2_CREATE_RESPONSE_LEASE_V2,
2056 ]
2059class SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2(Packet):
2060 fields_desc = [
2061 SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2,
2062 XStrFixedLenField("Reserved", b"", length=8),
2063 UUIDField("CreateGuid", 0x0, uuid_fmt=UUIDField.FORMAT_LE),
2064 ]
2067class SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2(Packet):
2068 fields_desc = [
2069 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
2070 UUIDField("CreateGuid", 0x0, uuid_fmt=UUIDField.FORMAT_LE),
2071 FlagsField(
2072 "Flags",
2073 0,
2074 -32,
2075 {
2076 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT",
2077 },
2078 ),
2079 ]
2082class SMB2_CREATE_APP_INSTANCE_ID(Packet):
2083 fields_desc = [
2084 XLEShortField("StructureSize", 0x14),
2085 LEShortField("Reserved", 0),
2086 XStrFixedLenField("AppInstanceId", b"", length=16),
2087 ]
2090class SMB2_CREATE_APP_INSTANCE_VERSION(Packet):
2091 fields_desc = [
2092 XLEShortField("StructureSize", 0x18),
2093 LEShortField("Reserved", 0),
2094 LEIntField("Padding", 0),
2095 LELongField("AppInstanceVersionHigh", 0),
2096 LELongField("AppInstanceVersionLow", 0),
2097 ]
2100class SMB2_Create_Context(_NTLMPayloadPacket):
2101 name = "SMB2 CREATE CONTEXT"
2102 OFFSET = 16
2103 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
2104 fields_desc = [
2105 LEIntField("Next", None),
2106 XLEShortField("NameBufferOffset", None),
2107 LEShortField("NameLen", None),
2108 ShortField("Reserved", 0),
2109 XLEShortField("DataBufferOffset", None),
2110 LEIntField("DataLen", None),
2111 _NTLMPayloadField(
2112 "Buffer",
2113 OFFSET,
2114 [
2115 PadField(
2116 StrLenField("Name", b"", length_from=lambda pkt: pkt.NameLen),
2117 8,
2118 ),
2119 # Must be padded on 8-octet alignment
2120 PacketLenField(
2121 "Data", None, conf.raw_layer, length_from=lambda pkt: pkt.DataLen
2122 ),
2123 ],
2124 force_order=["Name", "Data"],
2125 ),
2126 StrLenField(
2127 "pad",
2128 b"",
2129 length_from=lambda x: (
2130 (
2131 x.Next
2132 - max(
2133 x.DataBufferOffset + x.DataLen, x.NameBufferOffset + x.NameLen
2134 )
2135 )
2136 if x.Next
2137 else 0
2138 ),
2139 ),
2140 ]
2142 def post_dissect(self, s):
2143 if not self.DataLen:
2144 return s
2145 try:
2146 if isinstance(self.parent, SMB2_Create_Request):
2147 data_cls = {
2148 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_REQUEST,
2149 b"DHnC": SMB2_CREATE_DURABLE_HANDLE_RECONNECT,
2150 b"AISi": SMB2_CREATE_ALLOCATION_SIZE,
2151 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST,
2152 b"TWrp": SMB2_CREATE_TIMEWARP_TOKEN,
2153 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID,
2154 b"RqLs": SMB2_CREATE_REQUEST_LEASE,
2155 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2,
2156 b"DH2C": SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2,
2157 # 3.1.1 only
2158 b"E\xbc\xa6j\xef\xa7\xf7J\x90\x08\xfaF.\x14Mt": SMB2_CREATE_APP_INSTANCE_ID, # noqa: E501
2159 b"\xb9\x82\xd0\xb7;V\x07O\xa0{RJ\x81\x16\xa0\x10": SMB2_CREATE_APP_INSTANCE_VERSION, # noqa: E501
2160 }[self.Name]
2161 if self.Name == b"RqLs" and self.DataLen > 32:
2162 data_cls = SMB2_CREATE_REQUEST_LEASE_V2
2163 elif isinstance(self.parent, SMB2_Create_Response):
2164 data_cls = {
2165 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_RESPONSE,
2166 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE,
2167 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID,
2168 b"RqLs": SMB2_CREATE_RESPONSE_LEASE,
2169 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2,
2170 }[self.Name]
2171 if self.Name == b"RqLs" and self.DataLen > 32:
2172 data_cls = SMB2_CREATE_RESPONSE_LEASE_V2
2173 else:
2174 return s
2175 except KeyError:
2176 return s
2177 self.Data = data_cls(self.Data.load)
2178 return s
2180 def default_payload_class(self, _):
2181 return conf.padding_layer
2183 def post_build(self, pkt, pay):
2184 # type: (bytes, bytes) -> bytes
2185 return (
2186 _NTLM_post_build(
2187 self,
2188 pkt,
2189 self.OFFSET,
2190 {
2191 "Name": 4,
2192 "Data": 10,
2193 },
2194 config=[
2195 (
2196 "BufferOffset",
2197 {
2198 "Name": _NTLM_ENUM.OFFSET,
2199 "Data": _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8,
2200 },
2201 ),
2202 ("Len", _NTLM_ENUM.LEN),
2203 ],
2204 )
2205 + pay
2206 )
2209# sect 2.2.13
2211SMB2_OPLOCK_LEVELS = {
2212 0x00: "SMB2_OPLOCK_LEVEL_NONE",
2213 0x01: "SMB2_OPLOCK_LEVEL_II",
2214 0x08: "SMB2_OPLOCK_LEVEL_EXCLUSIVE",
2215 0x09: "SMB2_OPLOCK_LEVEL_BATCH",
2216 0xFF: "SMB2_OPLOCK_LEVEL_LEASE",
2217}
2220class SMB2_Create_Request(_SMB2_Payload, _NTLMPayloadPacket):
2221 name = "SMB2 CREATE Request"
2222 Command = 0x0005
2223 OFFSET = 56 + 64
2224 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
2225 fields_desc = [
2226 XLEShortField("StructureSize", 0x39),
2227 ByteField("ShareType", 0),
2228 ByteEnumField("RequestedOplockLevel", 0, SMB2_OPLOCK_LEVELS),
2229 LEIntEnumField(
2230 "ImpersonationLevel",
2231 0,
2232 {
2233 0x00000000: "Anonymous",
2234 0x00000001: "Identification",
2235 0x00000002: "Impersonation",
2236 0x00000003: "Delegate",
2237 },
2238 ),
2239 LELongField("SmbCreateFlags", 0),
2240 LELongField("Reserved", 0),
2241 FlagsField("DesiredAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE),
2242 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes),
2243 FlagsField(
2244 "ShareAccess",
2245 0,
2246 -32,
2247 {
2248 0x00000001: "FILE_SHARE_READ",
2249 0x00000002: "FILE_SHARE_WRITE",
2250 0x00000004: "FILE_SHARE_DELETE",
2251 },
2252 ),
2253 LEIntEnumField(
2254 "CreateDisposition",
2255 1,
2256 {
2257 0x00000000: "FILE_SUPERSEDE",
2258 0x00000001: "FILE_OPEN",
2259 0x00000002: "FILE_CREATE",
2260 0x00000003: "FILE_OPEN_IF",
2261 0x00000004: "FILE_OVERWRITE",
2262 0x00000005: "FILE_OVERWRITE_IF",
2263 },
2264 ),
2265 FlagsField(
2266 "CreateOptions",
2267 0,
2268 -32,
2269 {
2270 0x00000001: "FILE_DIRECTORY_FILE",
2271 0x00000002: "FILE_WRITE_THROUGH",
2272 0x00000004: "FILE_SEQUENTIAL_ONLY",
2273 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING",
2274 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT",
2275 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT",
2276 0x00000040: "FILE_NON_DIRECTORY_FILE",
2277 0x00000100: "FILE_COMPLETE_IF_OPLOCKED",
2278 0x00000200: "FILE_RANDOM_ACCESS",
2279 0x00001000: "FILE_DELETE_ON_CLOSE",
2280 0x00002000: "FILE_OPEN_BY_FILE_ID",
2281 0x00004000: "FILE_OPEN_FOR_BACKUP_INTENT",
2282 0x00008000: "FILE_NO_COMPRESSION",
2283 0x00000400: "FILE_OPEN_REMOTE_INSTANCE",
2284 0x00010000: "FILE_OPEN_REQUIRING_OPLOCK",
2285 0x00020000: "FILE_DISALLOW_EXCLUSIVE",
2286 0x00100000: "FILE_RESERVE_OPFILTER",
2287 0x00200000: "FILE_OPEN_REPARSE_POINT",
2288 0x00400000: "FILE_OPEN_NO_RECALL",
2289 0x00800000: "FILE_OPEN_FOR_FREE_SPACE_QUERY",
2290 },
2291 ),
2292 XLEShortField("NameBufferOffset", None),
2293 LEShortField("NameLen", None),
2294 XLEIntField("CreateContextsBufferOffset", None),
2295 LEIntField("CreateContextsLen", None),
2296 _NTLMPayloadField(
2297 "Buffer",
2298 OFFSET,
2299 [
2300 StrFieldUtf16("Name", b""),
2301 _NextPacketListField(
2302 "CreateContexts",
2303 [],
2304 SMB2_Create_Context,
2305 length_from=lambda pkt: pkt.CreateContextsLen,
2306 ),
2307 ],
2308 ),
2309 ]
2311 def post_build(self, pkt, pay):
2312 # type: (bytes, bytes) -> bytes
2313 if len(pkt) == 0x38:
2314 # 'In the request, the Buffer field MUST be at least one byte in length.'
2315 pkt += b"\x00"
2316 return (
2317 _SMB2_post_build(
2318 self,
2319 pkt,
2320 self.OFFSET,
2321 {
2322 "Name": 44,
2323 "CreateContexts": 48,
2324 },
2325 )
2326 + pay
2327 )
2330bind_top_down(SMB2_Header, SMB2_Create_Request, Command=0x0005)
2333# sect 2.2.14
2336class SMB2_Create_Response(_SMB2_Payload, _NTLMPayloadPacket):
2337 name = "SMB2 CREATE Response"
2338 Command = 0x0005
2339 OFFSET = 88 + 64
2340 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
2341 fields_desc = [
2342 XLEShortField("StructureSize", 0x59),
2343 ByteEnumField("OplockLevel", 0, SMB2_OPLOCK_LEVELS),
2344 FlagsField("Flags", 0, -8, {0x01: "SMB2_CREATE_FLAG_REPARSEPOINT"}),
2345 LEIntEnumField(
2346 "CreateAction",
2347 1,
2348 {
2349 0x00000000: "FILE_SUPERSEDED",
2350 0x00000001: "FILE_OPENED",
2351 0x00000002: "FILE_CREATED",
2352 0x00000003: "FILE_OVERWRITEN",
2353 },
2354 ),
2355 FileNetworkOpenInformation,
2356 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
2357 XLEIntField("CreateContextsBufferOffset", None),
2358 LEIntField("CreateContextsLen", None),
2359 _NTLMPayloadField(
2360 "Buffer",
2361 OFFSET,
2362 [
2363 _NextPacketListField(
2364 "CreateContexts",
2365 [],
2366 SMB2_Create_Context,
2367 length_from=lambda pkt: pkt.CreateContextsLen,
2368 ),
2369 ],
2370 ),
2371 ]
2373 def post_build(self, pkt, pay):
2374 # type: (bytes, bytes) -> bytes
2375 return (
2376 _SMB2_post_build(
2377 self,
2378 pkt,
2379 self.OFFSET,
2380 {
2381 "CreateContexts": 80,
2382 },
2383 )
2384 + pay
2385 )
2388bind_top_down(SMB2_Header, SMB2_Create_Response, Command=0x0005, Flags=1)
2390# sect 2.2.15
2393class SMB2_Close_Request(_SMB2_Payload):
2394 name = "SMB2 CLOSE Request"
2395 Command = 0x0006
2396 fields_desc = [
2397 XLEShortField("StructureSize", 0x18),
2398 FlagsField("Flags", 0, -16, ["SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB"]),
2399 LEIntField("Reserved", 0),
2400 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
2401 ]
2404bind_top_down(
2405 SMB2_Header,
2406 SMB2_Close_Request,
2407 Command=0x0006,
2408)
2410# sect 2.2.16
2413class SMB2_Close_Response(_SMB2_Payload):
2414 name = "SMB2 CLOSE Response"
2415 Command = 0x0006
2416 FileAttributes = 0
2417 CreationTime = 0
2418 LastAccessTime = 0
2419 LastWriteTime = 0
2420 ChangeTime = 0
2421 fields_desc = [
2422 XLEShortField("StructureSize", 0x3C),
2423 FlagsField("Flags", 0, -16, ["SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB"]),
2424 LEIntField("Reserved", 0),
2425 ] + FileNetworkOpenInformation.fields_desc[:7]
2428bind_top_down(
2429 SMB2_Header,
2430 SMB2_Close_Response,
2431 Command=0x0006,
2432 Flags=1,
2433)
2435# sect 2.2.19
2438class SMB2_Read_Request(_SMB2_Payload, _NTLMPayloadPacket):
2439 name = "SMB2 READ Request"
2440 Command = 0x0008
2441 OFFSET = 48 + 64
2442 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
2443 fields_desc = [
2444 XLEShortField("StructureSize", 0x31),
2445 ByteField("Padding", 0x00),
2446 FlagsField(
2447 "Flags",
2448 0,
2449 -8,
2450 {
2451 0x01: "SMB2_READFLAG_READ_UNBUFFERED",
2452 0x02: "SMB2_READFLAG_REQUEST_COMPRESSED",
2453 },
2454 ),
2455 LEIntField("Length", 4280),
2456 LELongField("Offset", 0),
2457 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
2458 LEIntField("MinimumCount", 0),
2459 LEIntEnumField(
2460 "Channel",
2461 0,
2462 {
2463 0x00000000: "SMB2_CHANNEL_NONE",
2464 0x00000001: "SMB2_CHANNEL_RDMA_V1",
2465 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE",
2466 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM",
2467 },
2468 ),
2469 LEIntField("RemainingBytes", 0),
2470 LEShortField("ReadChannelInfoBufferOffset", None),
2471 LEShortField("ReadChannelInfoLen", None),
2472 _NTLMPayloadField(
2473 "Buffer",
2474 OFFSET,
2475 [
2476 StrLenField(
2477 "ReadChannelInfo",
2478 b"",
2479 length_from=lambda pkt: pkt.ReadChannelInfoLen,
2480 )
2481 ],
2482 ),
2483 ]
2485 def post_build(self, pkt, pay):
2486 # type: (bytes, bytes) -> bytes
2487 if len(pkt) == 0x30:
2488 # 'The first byte of the Buffer field MUST be set to 0.'
2489 pkt += b"\x00"
2490 return (
2491 _SMB2_post_build(
2492 self,
2493 pkt,
2494 self.OFFSET,
2495 {
2496 "ReadChannelInfo": 44,
2497 },
2498 )
2499 + pay
2500 )
2503bind_top_down(
2504 SMB2_Header,
2505 SMB2_Read_Request,
2506 Command=0x0008,
2507)
2509# sect 2.2.20
2512class SMB2_Read_Response(_SMB2_Payload, _NTLMPayloadPacket):
2513 name = "SMB2 READ Response"
2514 Command = 0x0008
2515 OFFSET = 16 + 64
2516 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
2517 fields_desc = [
2518 XLEShortField("StructureSize", 0x11),
2519 LEShortField("DataBufferOffset", None),
2520 LEIntField("DataLen", None),
2521 LEIntField("DataRemaining", 0),
2522 FlagsField(
2523 "Flags",
2524 0,
2525 -32,
2526 {
2527 0x01: "SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM",
2528 },
2529 ),
2530 _NTLMPayloadField(
2531 "Buffer",
2532 OFFSET,
2533 [StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen)],
2534 ),
2535 ]
2537 def post_build(self, pkt, pay):
2538 # type: (bytes, bytes) -> bytes
2539 return (
2540 _SMB2_post_build(
2541 self,
2542 pkt,
2543 self.OFFSET,
2544 {
2545 "Data": 2,
2546 },
2547 )
2548 + pay
2549 )
2552bind_top_down(
2553 SMB2_Header,
2554 SMB2_Read_Response,
2555 Command=0x0008,
2556 Flags=1,
2557)
2560# sect 2.2.21
2563class SMB2_Write_Request(_SMB2_Payload, _NTLMPayloadPacket):
2564 name = "SMB2 WRITE Request"
2565 Command = 0x0009
2566 OFFSET = 48 + 64
2567 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
2568 fields_desc = [
2569 XLEShortField("StructureSize", 0x31),
2570 LEShortField("DataBufferOffset", None),
2571 LEIntField("DataLen", None),
2572 LELongField("Offset", 0),
2573 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
2574 LEIntEnumField(
2575 "Channel",
2576 0,
2577 {
2578 0x00000000: "SMB2_CHANNEL_NONE",
2579 0x00000001: "SMB2_CHANNEL_RDMA_V1",
2580 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE",
2581 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM",
2582 },
2583 ),
2584 LEIntField("RemainingBytes", 0),
2585 LEShortField("WriteChannelInfoBufferOffset", None),
2586 LEShortField("WriteChannelInfoLen", None),
2587 FlagsField(
2588 "Flags",
2589 0,
2590 -32,
2591 {
2592 0x00000001: "SMB2_WRITEFLAG_WRITE_THROUGH",
2593 0x00000002: "SMB2_WRITEFLAG_WRITE_UNBUFFERED",
2594 },
2595 ),
2596 _NTLMPayloadField(
2597 "Buffer",
2598 OFFSET,
2599 [
2600 StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen),
2601 StrLenField(
2602 "WriteChannelInfo",
2603 b"",
2604 length_from=lambda pkt: pkt.WriteChannelInfoLen,
2605 ),
2606 ],
2607 ),
2608 ]
2610 def post_build(self, pkt, pay):
2611 # type: (bytes, bytes) -> bytes
2612 return (
2613 _SMB2_post_build(
2614 self,
2615 pkt,
2616 self.OFFSET,
2617 {
2618 "Data": 2,
2619 "WriteChannelInfo": 40,
2620 },
2621 )
2622 + pay
2623 )
2626bind_top_down(
2627 SMB2_Header,
2628 SMB2_Write_Request,
2629 Command=0x0009,
2630)
2632# sect 2.2.22
2635class SMB2_Write_Response(_SMB2_Payload):
2636 name = "SMB2 WRITE Response"
2637 Command = 0x0009
2638 fields_desc = [
2639 XLEShortField("StructureSize", 0x11),
2640 LEShortField("Reserved", 0),
2641 LEIntField("Count", 0),
2642 LEIntField("Remaining", 0),
2643 LEShortField("WriteChannelInfoBufferOffset", 0),
2644 LEShortField("WriteChannelInfoLen", 0),
2645 ]
2648bind_top_down(SMB2_Header, SMB2_Write_Response, Command=0x0009, Flags=1)
2650# sect 2.2.28
2653class SMB2_Echo_Request(_SMB2_Payload):
2654 name = "SMB2 ECHO Request"
2655 Command = 0x000D
2656 fields_desc = [
2657 XLEShortField("StructureSize", 0x4),
2658 LEShortField("Reserved", 0),
2659 ]
2662bind_top_down(
2663 SMB2_Header,
2664 SMB2_Echo_Request,
2665 Command=0x000D,
2666)
2668# sect 2.2.29
2671class SMB2_Echo_Response(_SMB2_Payload):
2672 name = "SMB2 ECHO Response"
2673 Command = 0x000D
2674 fields_desc = [
2675 XLEShortField("StructureSize", 0x4),
2676 LEShortField("Reserved", 0),
2677 ]
2680bind_top_down(
2681 SMB2_Header,
2682 SMB2_Echo_Response,
2683 Command=0x000D,
2684 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR
2685)
2687# sect 2.2.30
2690class SMB2_Cancel_Request(_SMB2_Payload):
2691 name = "SMB2 CANCEL Request"
2692 fields_desc = [
2693 XLEShortField("StructureSize", 0x4),
2694 LEShortField("Reserved", 0),
2695 ]
2698bind_top_down(
2699 SMB2_Header,
2700 SMB2_Cancel_Request,
2701 Command=0x0009,
2702)
2704# sect 2.2.31.4
2707class SMB2_IOCTL_Validate_Negotiate_Info_Request(Packet):
2708 name = "SMB2 IOCTL Validate Negotiate Info"
2709 fields_desc = (
2710 SMB2_Negotiate_Protocol_Request.fields_desc[4:6]
2711 + SMB2_Negotiate_Protocol_Request.fields_desc[1:3][::-1] # Cap/GUID
2712 + [SMB2_Negotiate_Protocol_Request.fields_desc[9]] # SecMod/DC # Dialects
2713 )
2716# sect 2.2.31
2719class _SMB2_IOCTL_Request_PacketLenField(PacketLenField):
2720 def m2i(self, pkt, m):
2721 if pkt.CtlCode == 0x00140204: # FSCTL_VALIDATE_NEGOTIATE_INFO
2722 return SMB2_IOCTL_Validate_Negotiate_Info_Request(m)
2723 elif pkt.CtlCode == 0x00060194: # FSCTL_DFS_GET_REFERRALS
2724 return SMB2_IOCTL_REQ_GET_DFS_Referral(m)
2725 elif pkt.CtlCode == 0x00094264: # FSCTL_OFFLOAD_READ
2726 return SMB2_IOCTL_OFFLOAD_READ_Request(m)
2727 return conf.raw_layer(m)
2730class SMB2_IOCTL_Request(_SMB2_Payload, _NTLMPayloadPacket):
2731 name = "SMB2 IOCTL Request"
2732 Command = 0x000B
2733 OFFSET = 56 + 64
2734 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
2735 deprecated_fields = {
2736 "IntputCount": ("InputLen", "alias"),
2737 "OutputCount": ("OutputLen", "alias"),
2738 }
2739 fields_desc = [
2740 XLEShortField("StructureSize", 0x39),
2741 LEShortField("Reserved", 0),
2742 LEIntEnumField(
2743 "CtlCode",
2744 0,
2745 {
2746 0x00060194: "FSCTL_DFS_GET_REFERRALS",
2747 0x0011400C: "FSCTL_PIPE_PEEK",
2748 0x00110018: "FSCTL_PIPE_WAIT",
2749 0x0011C017: "FSCTL_PIPE_TRANSCEIVE",
2750 0x001440F2: "FSCTL_SRV_COPYCHUNK",
2751 0x00144064: "FSCTL_SRV_ENUMERATE_SNAPSHOTS",
2752 0x00140078: "FSCTL_SRV_REQUEST_RESUME_KEY",
2753 0x001441BB: "FSCTL_SRV_READ_HASH",
2754 0x001480F2: "FSCTL_SRV_COPYCHUNK_WRITE",
2755 0x001401D4: "FSCTL_LMR_REQUEST_RESILIENCY",
2756 0x001401FC: "FSCTL_QUERY_NETWORK_INTERFACE_INFO",
2757 0x000900A4: "FSCTL_SET_REPARSE_POINT",
2758 0x000601B0: "FSCTL_DFS_GET_REFERRALS_EX",
2759 0x00098208: "FSCTL_FILE_LEVEL_TRIM",
2760 0x00140204: "FSCTL_VALIDATE_NEGOTIATE_INFO",
2761 0x00094264: "FSCTL_OFFLOAD_READ",
2762 },
2763 ),
2764 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
2765 LEIntField("InputBufferOffset", None),
2766 LEIntField("InputLen", None), # Called InputCount but it's a length
2767 LEIntField("MaxInputResponse", 0),
2768 LEIntField("OutputBufferOffset", None),
2769 LEIntField("OutputLen", None), # Called OutputCount.
2770 LEIntField("MaxOutputResponse", 65535),
2771 FlagsField("Flags", 0, -32, {0x00000001: "SMB2_0_IOCTL_IS_FSCTL"}),
2772 LEIntField("Reserved2", 0),
2773 _NTLMPayloadField(
2774 "Buffer",
2775 OFFSET,
2776 [
2777 _SMB2_IOCTL_Request_PacketLenField(
2778 "Input", None, conf.raw_layer, length_from=lambda pkt: pkt.InputLen
2779 ),
2780 _SMB2_IOCTL_Request_PacketLenField(
2781 "Output",
2782 None,
2783 conf.raw_layer,
2784 length_from=lambda pkt: pkt.OutputLen,
2785 ),
2786 ],
2787 ),
2788 ]
2790 def post_build(self, pkt, pay):
2791 # type: (bytes, bytes) -> bytes
2792 return (
2793 _SMB2_post_build(
2794 self,
2795 pkt,
2796 self.OFFSET,
2797 {
2798 "Input": 24,
2799 "Output": 36,
2800 },
2801 )
2802 + pay
2803 )
2806bind_top_down(
2807 SMB2_Header,
2808 SMB2_IOCTL_Request,
2809 Command=0x000B,
2810)
2812# sect 2.2.32.5
2815class SOCKADDR_STORAGE(Packet):
2816 fields_desc = [
2817 LEShortEnumField("Family", 0x0002, {0x0002: "IPv4", 0x0017: "IPv6"}),
2818 ShortField("Port", 0),
2819 # IPv4
2820 ConditionalField(
2821 IPField("IPv4Adddress", None),
2822 lambda pkt: pkt.Family == 0x0002,
2823 ),
2824 ConditionalField(
2825 StrFixedLenField("Reserved", b"", length=8),
2826 lambda pkt: pkt.Family == 0x0002,
2827 ),
2828 # IPv6
2829 ConditionalField(
2830 LEIntField("FlowInfo", 0),
2831 lambda pkt: pkt.Family == 0x00017,
2832 ),
2833 ConditionalField(
2834 IP6Field("IPv6Address", None),
2835 lambda pkt: pkt.Family == 0x00017,
2836 ),
2837 ConditionalField(
2838 LEIntField("ScopeId", 0),
2839 lambda pkt: pkt.Family == 0x00017,
2840 ),
2841 ]
2843 def default_payload_class(self, _):
2844 return conf.padding_layer
2847class NETWORK_INTERFACE_INFO(Packet):
2848 fields_desc = [
2849 LEIntField("Next", None), # 0 = no next entry
2850 LEIntField("IfIndex", 1),
2851 FlagsField(
2852 "Capability",
2853 1,
2854 -32,
2855 {
2856 0x00000001: "RSS_CAPABLE",
2857 0x00000002: "RDMA_CAPABLE",
2858 },
2859 ),
2860 LEIntField("Reserved", 0),
2861 ScalingField("LinkSpeed", 10000000000, fmt="<Q", unit="bit/s"),
2862 PacketField("SockAddr_Storage", SOCKADDR_STORAGE(), SOCKADDR_STORAGE),
2863 ]
2865 def default_payload_class(self, _):
2866 return conf.padding_layer
2869class SMB2_IOCTL_Network_Interface_Info(Packet):
2870 name = "SMB2 IOCTL Network Interface Info response"
2871 fields_desc = [
2872 _NextPacketListField("interfaces", [], NETWORK_INTERFACE_INFO),
2873 ]
2876# sect 2.2.32.6
2879class SMB2_IOCTL_Validate_Negotiate_Info_Response(Packet):
2880 name = "SMB2 IOCTL Validate Negotiate Info"
2881 fields_desc = (
2882 SMB2_Negotiate_Protocol_Response.fields_desc[4:6][::-1]
2883 + SMB2_Negotiate_Protocol_Response.fields_desc[ # Cap/GUID
2884 1:3
2885 ] # SecMod/DialectRevision
2886 )
2889# [MS-FSCC] sect 2.3.42
2892class SMB2_IOCTL_OFFLOAD_READ_Request(Packet):
2893 name = "SMB2 IOCTL OFFLOAD_READ Request"
2894 fields_desc = [
2895 LEIntField("StructureSize", 0x20),
2896 LEIntField("Flags", 0),
2897 LEIntField("TokenTimeToLive", 0),
2898 LEIntField("Reserved", 0),
2899 LELongField("FileOffset", 0),
2900 LELongField("CopyLength", 0),
2901 ]
2904# [MS-FSCC] sect 2.1.11
2907class STORAGE_OFFLOAD_TOKEN(Packet):
2908 fields_desc = [
2909 LEIntEnumField(
2910 "TokenType",
2911 0xFFFF0001,
2912 {
2913 0xFFFF0001: "STORAGE_OFFLOAD_TOKEN_TYPE_ZERO_DATA",
2914 },
2915 ),
2916 LEShortField("Reserved", 0),
2917 FieldLenField("TokenIdLength", None, fmt="<H", length_of="TokenId"),
2918 StrFixedLenField("TokenId", b"", length=504),
2919 ]
2922# [MS-FSCC] sect 2.3.42
2925class SMB2_IOCTL_OFFLOAD_READ_Response(Packet):
2926 name = "SMB2 IOCTL OFFLOAD_READ Response"
2927 fields_desc = [
2928 LEIntField("StructureSize", 0x210),
2929 FlagsField(
2930 "Flags",
2931 0,
2932 -32,
2933 {
2934 0x00000001: "OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE",
2935 },
2936 ),
2937 LELongField("TransferLength", 0),
2938 PacketField("Token", STORAGE_OFFLOAD_TOKEN(), STORAGE_OFFLOAD_TOKEN),
2939 ]
2942# sect 2.2.32
2945class _SMB2_IOCTL_Response_PacketLenField(PacketLenField):
2946 def m2i(self, pkt, m):
2947 if pkt.CtlCode == 0x00140204: # FSCTL_VALIDATE_NEGOTIATE_INFO
2948 return SMB2_IOCTL_Validate_Negotiate_Info_Response(m)
2949 elif pkt.CtlCode == 0x001401FC: # FSCTL_QUERY_NETWORK_INTERFACE_INFO
2950 return SMB2_IOCTL_Network_Interface_Info(m)
2951 elif pkt.CtlCode == 0x00060194: # FSCTL_DFS_GET_REFERRALS
2952 return SMB2_IOCTL_RESP_GET_DFS_Referral(m)
2953 return conf.raw_layer(m)
2956class SMB2_IOCTL_Response(_SMB2_Payload, _NTLMPayloadPacket):
2957 name = "SMB2 IOCTL Response"
2958 Command = 0x000B
2959 OFFSET = 48 + 64
2960 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
2961 StructureSize = 0x31
2962 MaxOutputResponse = 0
2963 fields_desc = (
2964 SMB2_IOCTL_Request.fields_desc[:6]
2965 + SMB2_IOCTL_Request.fields_desc[7:9]
2966 + SMB2_IOCTL_Request.fields_desc[10:12]
2967 + [
2968 _NTLMPayloadField(
2969 "Buffer",
2970 OFFSET,
2971 [
2972 _SMB2_IOCTL_Response_PacketLenField(
2973 "Input",
2974 None,
2975 conf.raw_layer,
2976 length_from=lambda pkt: pkt.InputLen,
2977 ),
2978 _SMB2_IOCTL_Response_PacketLenField(
2979 "Output",
2980 None,
2981 conf.raw_layer,
2982 length_from=lambda pkt: pkt.OutputLen,
2983 ),
2984 ],
2985 ),
2986 ]
2987 )
2989 def post_build(self, pkt, pay):
2990 # type: (bytes, bytes) -> bytes
2991 return (
2992 _SMB2_post_build(
2993 self,
2994 pkt,
2995 self.OFFSET,
2996 {
2997 "Input": 24,
2998 "Output": 32,
2999 },
3000 )
3001 + pay
3002 )
3005bind_top_down(
3006 SMB2_Header,
3007 SMB2_IOCTL_Response,
3008 Command=0x000B,
3009 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR
3010)
3012# sect 2.2.33
3015class SMB2_Query_Directory_Request(_SMB2_Payload, _NTLMPayloadPacket):
3016 name = "SMB2 QUERY DIRECTORY Request"
3017 Command = 0x000E
3018 OFFSET = 32 + 64
3019 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
3020 fields_desc = [
3021 XLEShortField("StructureSize", 0x21),
3022 ByteEnumField("FileInformationClass", 0x1, FileInformationClasses),
3023 FlagsField(
3024 "Flags",
3025 0,
3026 -8,
3027 {
3028 0x01: "SMB2_RESTART_SCANS",
3029 0x02: "SMB2_RETURN_SINGLE_ENTRY",
3030 0x04: "SMB2_INDEX_SPECIFIED",
3031 0x10: "SMB2_REOPEN",
3032 },
3033 ),
3034 LEIntField("FileIndex", 0),
3035 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
3036 LEShortField("FileNameBufferOffset", None),
3037 LEShortField("FileNameLen", None),
3038 LEIntField("OutputBufferLength", 65535),
3039 _NTLMPayloadField("Buffer", OFFSET, [StrFieldUtf16("FileName", b"")]),
3040 ]
3042 def post_build(self, pkt, pay):
3043 # type: (bytes, bytes) -> bytes
3044 return (
3045 _SMB2_post_build(
3046 self,
3047 pkt,
3048 self.OFFSET,
3049 {
3050 "FileName": 24,
3051 },
3052 )
3053 + pay
3054 )
3057bind_top_down(
3058 SMB2_Header,
3059 SMB2_Query_Directory_Request,
3060 Command=0x000E,
3061)
3063# sect 2.2.34
3066class SMB2_Query_Directory_Response(_SMB2_Payload, _NTLMPayloadPacket):
3067 name = "SMB2 QUERY DIRECTORY Response"
3068 Command = 0x000E
3069 OFFSET = 8 + 64
3070 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
3071 fields_desc = [
3072 XLEShortField("StructureSize", 0x9),
3073 LEShortField("OutputBufferOffset", None),
3074 LEIntField("OutputLen", None),
3075 _NTLMPayloadField(
3076 "Buffer",
3077 OFFSET,
3078 [
3079 # TODO
3080 StrFixedLenField("Output", b"", length_from=lambda pkt: pkt.OutputLen)
3081 ],
3082 ),
3083 ]
3085 def post_build(self, pkt, pay):
3086 # type: (bytes, bytes) -> bytes
3087 return (
3088 _SMB2_post_build(
3089 self,
3090 pkt,
3091 self.OFFSET,
3092 {
3093 "Output": 2,
3094 },
3095 )
3096 + pay
3097 )
3100bind_top_down(
3101 SMB2_Header,
3102 SMB2_Query_Directory_Response,
3103 Command=0x000E,
3104 Flags=1,
3105)
3107# sect 2.2.35
3110class SMB2_Change_Notify_Request(_SMB2_Payload):
3111 name = "SMB2 CHANGE NOTIFY Request"
3112 Command = 0x000F
3113 fields_desc = [
3114 XLEShortField("StructureSize", 0x20),
3115 FlagsField(
3116 "Flags",
3117 0,
3118 -16,
3119 {
3120 0x0001: "SMB2_WATCH_TREE",
3121 },
3122 ),
3123 LEIntField("OutputBufferLength", 2048),
3124 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
3125 FlagsField(
3126 "CompletionFilter",
3127 0,
3128 -32,
3129 {
3130 0x00000001: "FILE_NOTIFY_CHANGE_FILE_NAME",
3131 0x00000002: "FILE_NOTIFY_CHANGE_DIR_NAME",
3132 0x00000004: "FILE_NOTIFY_CHANGE_ATTRIBUTES",
3133 0x00000008: "FILE_NOTIFY_CHANGE_SIZE",
3134 0x00000010: "FILE_NOTIFY_CHANGE_LAST_WRITE",
3135 0x00000020: "FILE_NOTIFY_CHANGE_LAST_ACCESS",
3136 0x00000040: "FILE_NOTIFY_CHANGE_CREATION",
3137 0x00000080: "FILE_NOTIFY_CHANGE_EA",
3138 0x00000100: "FILE_NOTIFY_CHANGE_SECURITY",
3139 0x00000200: "FILE_NOTIFY_CHANGE_STREAM_NAME",
3140 0x00000400: "FILE_NOTIFY_CHANGE_STREAM_SIZE",
3141 0x00000800: "FILE_NOTIFY_CHANGE_STREAM_WRITE",
3142 },
3143 ),
3144 LEIntField("Reserved", 0),
3145 ]
3148bind_top_down(
3149 SMB2_Header,
3150 SMB2_Change_Notify_Request,
3151 Command=0x000F,
3152)
3154# sect 2.2.36
3157class SMB2_Change_Notify_Response(_SMB2_Payload, _NTLMPayloadPacket):
3158 name = "SMB2 CHANGE NOTIFY Response"
3159 Command = 0x000F
3160 OFFSET = 8 + 64
3161 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
3162 fields_desc = [
3163 XLEShortField("StructureSize", 0x9),
3164 LEShortField("OutputBufferOffset", None),
3165 LEIntField("OutputLen", None),
3166 _NTLMPayloadField(
3167 "Buffer",
3168 OFFSET,
3169 [
3170 _NextPacketListField(
3171 "Output",
3172 [],
3173 FILE_NOTIFY_INFORMATION,
3174 length_from=lambda pkt: pkt.OutputLen,
3175 max_count=1000,
3176 )
3177 ],
3178 ),
3179 ]
3181 def post_build(self, pkt, pay):
3182 # type: (bytes, bytes) -> bytes
3183 return (
3184 _SMB2_post_build(
3185 self,
3186 pkt,
3187 self.OFFSET,
3188 {
3189 "Output": 2,
3190 },
3191 )
3192 + pay
3193 )
3196bind_top_down(
3197 SMB2_Header,
3198 SMB2_Change_Notify_Response,
3199 Command=0x000F,
3200 Flags=1,
3201)
3203# sect 2.2.37
3206class FILE_GET_QUOTA_INFORMATION(Packet):
3207 fields_desc = [
3208 IntField("NextEntryOffset", 0),
3209 FieldLenField("SidLength", None, length_of="Sid"),
3210 StrLenField("Sid", b"", length_from=lambda x: x.SidLength),
3211 StrLenField(
3212 "pad",
3213 b"",
3214 length_from=lambda x: (
3215 (x.NextEntryOffset - x.SidLength) if x.NextEntryOffset else 0
3216 ),
3217 ),
3218 ]
3221class SMB2_Query_Quota_Info(Packet):
3222 fields_desc = [
3223 ByteField("ReturnSingle", 0),
3224 ByteField("ReturnBoolean", 0),
3225 ShortField("Reserved", 0),
3226 LEIntField("SidListLength", 0),
3227 LEIntField("StartSidLength", 0),
3228 LEIntField("StartSidOffset", 0),
3229 StrLenField("pad", b"", length_from=lambda x: x.StartSidOffset),
3230 MultipleTypeField(
3231 [
3232 (
3233 PacketListField(
3234 "SidBuffer",
3235 [],
3236 FILE_GET_QUOTA_INFORMATION,
3237 length_from=lambda x: x.SidListLength,
3238 ),
3239 lambda x: x.SidListLength,
3240 ),
3241 (
3242 StrLenField(
3243 "SidBuffer", b"", length_from=lambda x: x.StartSidLength
3244 ),
3245 lambda x: x.StartSidLength,
3246 ),
3247 ],
3248 StrFixedLenField("SidBuffer", b"", length=0),
3249 ),
3250 ]
3253SMB2_INFO_TYPE = {
3254 0x01: "SMB2_0_INFO_FILE",
3255 0x02: "SMB2_0_INFO_FILESYSTEM",
3256 0x03: "SMB2_0_INFO_SECURITY",
3257 0x04: "SMB2_0_INFO_QUOTA",
3258}
3260SMB2_ADDITIONAL_INFORMATION = {
3261 0x00000001: "OWNER_SECURITY_INFORMATION",
3262 0x00000002: "GROUP_SECURITY_INFORMATION",
3263 0x00000004: "DACL_SECURITY_INFORMATION",
3264 0x00000008: "SACL_SECURITY_INFORMATION",
3265 0x00000010: "LABEL_SECURITY_INFORMATION",
3266 0x00000020: "ATTRIBUTE_SECURITY_INFORMATION",
3267 0x00000040: "SCOPE_SECURITY_INFORMATION",
3268 0x00010000: "BACKUP_SECURITY_INFORMATION",
3269}
3272class SMB2_Query_Info_Request(_SMB2_Payload, _NTLMPayloadPacket):
3273 name = "SMB2 QUERY INFO Request"
3274 Command = 0x0010
3275 OFFSET = 40 + 64
3276 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
3277 fields_desc = [
3278 XLEShortField("StructureSize", 0x29),
3279 ByteEnumField(
3280 "InfoType",
3281 0,
3282 SMB2_INFO_TYPE,
3283 ),
3284 ByteEnumField("FileInfoClass", 0, FileInformationClasses),
3285 LEIntField("OutputBufferLength", 0),
3286 XLEIntField("InputBufferOffset", None), # Short + Reserved = Int
3287 LEIntField("InputLen", None),
3288 FlagsField(
3289 "AdditionalInformation",
3290 0,
3291 -32,
3292 SMB2_ADDITIONAL_INFORMATION,
3293 ),
3294 FlagsField(
3295 "Flags",
3296 0,
3297 -32,
3298 {
3299 0x00000001: "SL_RESTART_SCAN",
3300 0x00000002: "SL_RETURN_SINGLE_ENTRY",
3301 0x00000004: "SL_INDEX_SPECIFIED",
3302 },
3303 ),
3304 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
3305 _NTLMPayloadField(
3306 "Buffer",
3307 OFFSET,
3308 [
3309 MultipleTypeField(
3310 [
3311 (
3312 # QUOTA
3313 PacketListField(
3314 "Input",
3315 None,
3316 SMB2_Query_Quota_Info,
3317 length_from=lambda pkt: pkt.InputLen,
3318 ),
3319 lambda pkt: pkt.InfoType == 0x04,
3320 ),
3321 ],
3322 StrLenField("Input", b"", length_from=lambda pkt: pkt.InputLen),
3323 ),
3324 ],
3325 ),
3326 ]
3328 def post_build(self, pkt, pay):
3329 # type: (bytes, bytes) -> bytes
3330 return (
3331 _SMB2_post_build(
3332 self,
3333 pkt,
3334 self.OFFSET,
3335 {
3336 "Input": 4,
3337 },
3338 )
3339 + pay
3340 )
3343bind_top_down(
3344 SMB2_Header,
3345 SMB2_Query_Info_Request,
3346 Command=0x00010,
3347)
3350class SMB2_Query_Info_Response(_SMB2_Payload, _NTLMPayloadPacket):
3351 name = "SMB2 QUERY INFO Response"
3352 Command = 0x0010
3353 OFFSET = 8 + 64
3354 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
3355 fields_desc = [
3356 XLEShortField("StructureSize", 0x9),
3357 LEShortField("OutputBufferOffset", None),
3358 LEIntField("OutputLen", None),
3359 _NTLMPayloadField(
3360 "Buffer",
3361 OFFSET,
3362 [
3363 # TODO
3364 StrFixedLenField("Output", b"", length_from=lambda pkt: pkt.OutputLen)
3365 ],
3366 ),
3367 ]
3369 def post_build(self, pkt, pay):
3370 # type: (bytes, bytes) -> bytes
3371 return (
3372 _SMB2_post_build(
3373 self,
3374 pkt,
3375 self.OFFSET,
3376 {
3377 "Output": 2,
3378 },
3379 )
3380 + pay
3381 )
3384bind_top_down(
3385 SMB2_Header,
3386 SMB2_Query_Info_Response,
3387 Command=0x00010,
3388 Flags=1,
3389)
3392# sect 2.2.39
3395class SMB2_Set_Info_Request(_SMB2_Payload, _NTLMPayloadPacket):
3396 name = "SMB2 SET INFO Request"
3397 Command = 0x0011
3398 OFFSET = 32 + 64
3399 _NTLM_PAYLOAD_FIELD_NAME = "Buffer"
3400 fields_desc = [
3401 XLEShortField("StructureSize", 0x21),
3402 ByteEnumField(
3403 "InfoType",
3404 0,
3405 SMB2_INFO_TYPE,
3406 ),
3407 ByteEnumField("FileInfoClass", 0, FileInformationClasses),
3408 LEIntField("DataLen", None),
3409 XLEIntField("DataBufferOffset", None), # Short + Reserved = Int
3410 FlagsField(
3411 "AdditionalInformation",
3412 0,
3413 -32,
3414 SMB2_ADDITIONAL_INFORMATION,
3415 ),
3416 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID),
3417 _NTLMPayloadField(
3418 "Buffer",
3419 OFFSET,
3420 [
3421 MultipleTypeField(
3422 [
3423 (
3424 # FILE
3425 PacketLenField(
3426 "Data",
3427 None,
3428 lambda x, _parent: _FileInformationClasses.get(
3429 _parent.FileInfoClass, conf.raw_layer
3430 )(x),
3431 length_from=lambda pkt: pkt.DataLen,
3432 ),
3433 lambda pkt: pkt.InfoType == 0x01,
3434 ),
3435 (
3436 # QUOTA
3437 PacketListField(
3438 "Data",
3439 None,
3440 SMB2_Query_Quota_Info,
3441 length_from=lambda pkt: pkt.DataLen,
3442 ),
3443 lambda pkt: pkt.InfoType == 0x04,
3444 ),
3445 ],
3446 StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen),
3447 ),
3448 ],
3449 ),
3450 ]
3452 def post_build(self, pkt, pay):
3453 # type: (bytes, bytes) -> bytes
3454 return (
3455 _SMB2_post_build(
3456 self,
3457 pkt,
3458 self.OFFSET,
3459 {
3460 "Data": 4,
3461 },
3462 )
3463 + pay
3464 )
3467bind_top_down(
3468 SMB2_Header,
3469 SMB2_Set_Info_Request,
3470 Command=0x00011,
3471)
3474class SMB2_Set_Info_Response(_SMB2_Payload):
3475 name = "SMB2 SET INFO Request"
3476 Command = 0x0011
3477 fields_desc = [
3478 XLEShortField("StructureSize", 0x02),
3479 ]
3482bind_top_down(
3483 SMB2_Header,
3484 SMB2_Set_Info_Response,
3485 Command=0x00011,
3486 Flags=1,
3487)
3490# sect 2.2.41
3493class SMB2_Transform_Header(Packet):
3494 name = "SMB2 Transform Header"
3495 fields_desc = [
3496 StrFixedLenField("Start", b"\xfdSMB", 4),
3497 XStrFixedLenField("Signature", 0, length=16),
3498 XStrFixedLenField("Nonce", b"", length=16),
3499 LEIntField("OriginalMessageSize", 0x0),
3500 LEShortField("Reserved", 0),
3501 LEShortEnumField(
3502 "Flags",
3503 0x1,
3504 {
3505 0x0001: "ENCRYPTED",
3506 },
3507 ),
3508 LELongField("SessionId", 0),
3509 ]
3511 def decrypt(self, dialect, DecryptionKey, CipherId):
3512 """
3513 [MS-SMB2] sect 3.2.5.1.1.1 - Decrypting the Message
3514 """
3515 if not isinstance(self.payload, conf.raw_layer):
3516 raise Exception("No payload to decrypt !")
3518 if "GCM" in CipherId:
3519 from cryptography.hazmat.primitives.ciphers.aead import AESGCM
3521 nonce = self.Nonce[:12]
3522 cipher = AESGCM(DecryptionKey)
3523 elif "CCM" in CipherId:
3524 from cryptography.hazmat.primitives.ciphers.aead import AESCCM
3526 nonce = self.Nonce[:11]
3527 cipher = AESCCM(DecryptionKey)
3528 else:
3529 raise Exception("Unknown CipherId !")
3531 # Decrypt the data
3532 aad = self.self_build()[20:]
3533 data = cipher.decrypt(
3534 nonce,
3535 self.payload.load + self.Signature,
3536 aad,
3537 )
3538 return SMB2_Header(data, _decrypted=True)
3541bind_layers(SMB2_Transform_Header, conf.raw_layer)
3544# sect 2.2.42.1
3547class SMB2_Compression_Transform_Header(Packet):
3548 name = "SMB2 Compression Transform Header"
3549 fields_desc = [
3550 StrFixedLenField("Start", b"\xfcSMB", 4),
3551 LEIntField("OriginalCompressedSegmentSize", 0x0),
3552 LEShortEnumField("CompressionAlgorithm", 0, SMB2_COMPRESSION_ALGORITHMS),
3553 LEShortEnumField(
3554 "Flags",
3555 0x0,
3556 {
3557 0x0000: "SMB2_COMPRESSION_FLAG_NONE",
3558 0x0001: "SMB2_COMPRESSION_FLAG_CHAINED",
3559 },
3560 ),
3561 XLEIntField("Offset_or_Length", 0),
3562 ]
3565# [MS-DFSC] sect 2.2
3568class SMB2_IOCTL_REQ_GET_DFS_Referral(Packet):
3569 fields_desc = [
3570 LEShortField("MaxReferralLevel", 0),
3571 StrNullFieldUtf16("RequestFileName", ""),
3572 ]
3575class DFS_REFERRAL(Packet):
3576 fields_desc = [
3577 LEShortField("Version", 1),
3578 FieldLenField(
3579 "Size", None, fmt="<H", length_of="ShareName", adjust=lambda pkt, x: x + 9
3580 ),
3581 LEShortEnumField("ServerType", 0, {0: "non-root", 1: "root"}),
3582 LEShortField("ReferralEntryFlags", 0),
3583 StrNullFieldUtf16("ShareName", ""),
3584 ]
3586 @classmethod
3587 def dispatch_hook(cls, _pkt=None, *args, **kargs):
3588 if _pkt and len(_pkt) >= 2:
3589 version = struct.unpack("<H", _pkt[:2])[0]
3590 if version == 1:
3591 return DFS_REFERRAL
3592 elif version == 3:
3593 return DFS_REFERRAL_V3
3594 elif version == 4:
3595 return DFS_REFERRAL_V4
3596 return cls
3598 def default_payload_class(self, s):
3599 return conf.padding_layer
3602class DFS_REFERRAL_V3(DFS_REFERRAL):
3603 fields_desc = [
3604 LEShortField("Version", 3),
3605 LEShortField("Size", None),
3606 LEShortEnumField("ServerType", 0, {0: "non-root", 1: "root"}),
3607 FlagsField(
3608 "ReferralEntryFlags",
3609 0,
3610 -16,
3611 {
3612 0x0002: "NameListReferral",
3613 0x0004: "TargetSetBoundary",
3614 },
3615 ),
3616 LEIntField("TimeToLive", 300),
3617 # NameListReferral is 0
3618 ConditionalField(
3619 LEShortField("DFSPathOffset", None),
3620 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral,
3621 ),
3622 ConditionalField(
3623 LEShortField("DFSAlternatePathOffset", None),
3624 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral,
3625 ),
3626 ConditionalField(
3627 LEShortField("NetworkAddressOffset", None),
3628 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral,
3629 ),
3630 ConditionalField(
3631 StrFixedLenField("ServiceSiteGuid", 0, length=16),
3632 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral,
3633 ),
3634 # NameListReferral is 1
3635 ConditionalField(
3636 LEShortField("SpecialNameOffset", None),
3637 lambda pkt: pkt.ReferralEntryFlags.NameListReferral,
3638 ),
3639 ConditionalField(
3640 LEShortField("NumberOfExpandedNames", None),
3641 lambda pkt: pkt.ReferralEntryFlags.NameListReferral,
3642 ),
3643 ConditionalField(
3644 LEShortField("ExpandedNameOffset", None),
3645 lambda pkt: pkt.ReferralEntryFlags.NameListReferral,
3646 ),
3647 ConditionalField(
3648 StrLenField("Padding", None, length_from=lambda pkt: pkt.Size - 18),
3649 lambda pkt: pkt.ReferralEntryFlags.NameListReferral,
3650 ),
3651 ]
3653 def post_build(self, pkt, pay):
3654 # type: (bytes, bytes) -> bytes
3655 if self.Size is None:
3656 pkt = pkt[:2] + struct.pack("<H", len(pkt)) + pkt[4:]
3657 return pkt + pay
3660class DFS_REFERRAL_V4(DFS_REFERRAL_V3):
3661 Version = 4
3664class DFS_REFERRAL_ENTRY0(Packet):
3665 fields_desc = [
3666 StrNullFieldUtf16("DFSPath", ""),
3667 StrNullFieldUtf16("DFSAlternatePath", ""),
3668 StrNullFieldUtf16("NetworkAddress", ""),
3669 ]
3672class DFS_REFERRAL_ENTRY1(Packet):
3673 fields_desc = [
3674 StrNullFieldUtf16("SpecialName", ""),
3675 FieldListField(
3676 "ExpandedName",
3677 [],
3678 StrNullFieldUtf16("", ""),
3679 ),
3680 ]
3683class _DFS_Referrals_BufferField(PacketListField):
3684 def getfield(self, pkt, s):
3685 results = []
3686 offset = sum(x.Size for x in pkt.ReferralEntries)
3687 for ref in pkt.ReferralEntries:
3688 # For every ref
3689 if not ref.ReferralEntryFlags.NameListReferral:
3690 cls = DFS_REFERRAL_ENTRY0
3691 else:
3692 cls = DFS_REFERRAL_ENTRY1
3693 # Build the fields manually
3694 fld = _NTLMPayloadField(
3695 "",
3696 offset,
3697 cls.fields_desc,
3698 force_order=[x.name for x in cls.fields_desc],
3699 offset_name="Offset",
3700 )
3701 remain, vals = fld.getfield(ref, s)
3702 vals = fld.i2h(ref, vals)
3703 # Append the entry class
3704 results.append(cls(**{x[0]: x[1] for x in vals}))
3705 offset -= ref.Size
3706 return b"", results
3708 def addfield(self, pkt, s, vals):
3709 offset = sum(len(x) for x in pkt.ReferralEntries)
3710 for i, val in enumerate(vals):
3711 try:
3712 ref = pkt.ReferralEntries[i]
3713 except KeyError:
3714 ref = None
3715 fld = _NTLMPayloadField(
3716 "",
3717 offset,
3718 val.fields_desc,
3719 force_order=[x.name for x in val.fields_desc],
3720 offset_name="Offset",
3721 )
3722 # Append the bytes manually
3723 values = [(fld.name, getattr(val, fld.name)) for fld in val.fields_desc]
3724 values = fld.h2i(ref, values)
3725 s += fld.addfield(ref, b"", values)
3726 offset -= len(ref)
3727 return s
3730class SMB2_IOCTL_RESP_GET_DFS_Referral(Packet):
3731 fields_desc = [
3732 LEShortField("PathConsumed", 0),
3733 FieldLenField("NumberOfReferrals", None, fmt="<H", count_of="ReferralEntries"),
3734 FlagsField(
3735 "ReferralHeaderFlags",
3736 0,
3737 -32,
3738 {
3739 0x00000001: "ReferralServers",
3740 0x00000002: "StorageServers",
3741 0x00000004: "TargetFailback",
3742 },
3743 ),
3744 PacketListField(
3745 "ReferralEntries",
3746 [],
3747 DFS_REFERRAL,
3748 count_from=lambda pkt: pkt.NumberOfReferrals,
3749 ),
3750 _DFS_Referrals_BufferField("ReferralBuffer", []),
3751 ]
3753 def post_build(self, pkt, pay):
3754 # type: (bytes, bytes) -> bytes
3755 # Note: Windows is smart and uses some sort of compression in the sense
3756 # that it reuses fields that are used several times across ReferralBuffer.
3757 # But we just do the dumb thing because it's 'easier', and do no compression.
3758 offsets = {
3759 # DFS_REFERRAL_ENTRY0
3760 "DFSPath": 12,
3761 "DFSAlternatePath": 14,
3762 "NetworkAddress": 16,
3763 # DFS_REFERRAL_ENTRY1
3764 "SpecialName": 12,
3765 "ExpandedName": 16,
3766 }
3767 # dataoffset = pointer in the ReferralBuffer
3768 # entryoffset = pointer in the ReferralEntries
3769 dataoffset = sum(len(x) for x in self.ReferralEntries)
3770 entryoffset = 8
3771 for ref, buf in zip(self.ReferralEntries, self.ReferralBuffer):
3772 for fld in buf.fields_desc:
3773 off = entryoffset + offsets[fld.name]
3774 if ref.getfieldval(fld.name + "Offset") is None and buf.getfieldval(
3775 fld.name
3776 ):
3777 pkt = pkt[:off] + struct.pack("<H", dataoffset) + pkt[off + 2 :]
3778 dataoffset += len(fld.addfield(self, b"", buf.getfieldval(fld.name)))
3779 dataoffset -= len(ref)
3780 entryoffset += len(ref)
3781 return pkt + pay
3784# [MS-SMB2] various usages
3787def SMB2computePreauthIntegrityHashValue(
3788 PreauthIntegrityHashValue, s, HashId="SHA-512"
3789):
3790 """
3791 Update the PreauthIntegrityHashValue
3792 """
3793 # get hasher
3794 hasher = {"SHA-512": hashlib.sha512}[HashId]
3795 # compute the hash of concatenation of previous and bytes
3796 return hasher(PreauthIntegrityHashValue + s).digest()
3799# SMB2 socket and session
3802class SMBStreamSocket(StreamSocket):
3803 """
3804 A modified StreamSocket to dissect SMB compounded requests
3805 [MS-SMB2] 3.3.5.2.7
3806 """
3808 def __init__(self, *args, **kwargs):
3809 self.queue = collections.deque()
3810 self.session = SMBSession()
3811 super(SMBStreamSocket, self).__init__(*args, **kwargs)
3813 def recv(self, x=None):
3814 # note: normal StreamSocket takes care of NBTSession / DirectTCP fragments.
3815 # this takes care of splitting compounded requests
3816 if self.queue:
3817 pkt = self.queue.popleft()
3818 else:
3819 pkt = super(SMBStreamSocket, self).recv(x)
3821 # If there are multiple SMB2_Header requests (aka. compounded),
3822 # take the first and store the rest in a queue.
3823 if pkt is not None and (
3824 SMB2_Header in pkt
3825 or SMB2_Transform_Header in pkt
3826 or SMB2_Compression_Transform_Header in pkt
3827 ):
3828 pkt = self.session.in_pkt(pkt)
3829 smbh = pkt[SMB2_Header]
3830 pay = smbh.payload
3831 while SMB2_Header in pay:
3832 pay = pay[SMB2_Header]
3833 pay._decrypted = smbh._decrypted # Keep the _decrypted flag
3834 pay.underlayer.remove_payload()
3835 self.queue.append(pay)
3836 if not pay.NextCommand:
3837 break
3838 pay = pay.payload
3840 # Verify the signature if required.
3841 # This happens here because we must have split compounded requests first.
3842 smbh = pkt.getlayer(SMB2_Header)
3843 if (
3844 smbh
3845 and self.session.Dialect
3846 and self.session.SigningKey
3847 and self.session.SigningRequired
3848 # [MS-SMB2] sect 3.2.5.1.3 Verifying the Signature
3849 # "The client MUST skip the processing in this section if any of:"
3850 # - [...] decryption in section 3.2.5.1.1.1 succeeds
3851 and not smbh._decrypted
3852 # - MessageId is 0xFFFFFFFFFFFFFFFF
3853 and smbh.MID != 0xFFFFFFFFFFFFFFFF
3854 # - Message is not ECHO request
3855 and smbh.Command != 0x000D
3856 # - Status in the SMB2 header is STATUS_PENDING
3857 and smbh.Status != 0x00000103
3858 ):
3859 smbh.verify(
3860 self.session.Dialect,
3861 self.session.SigningKey,
3862 # SMB 3.1.1 parameters:
3863 SigningAlgorithmId=self.session.SigningAlgorithmId,
3864 IsClient=False,
3865 )
3866 return pkt
3868 def send(self, x, Compounded=False, ForceSign=False, ForceEncrypt=False, **kwargs):
3869 for pkt in self.session.out_pkt(
3870 x, Compounded=Compounded, ForceSign=ForceSign, ForceEncrypt=ForceEncrypt
3871 ):
3872 return super(SMBStreamSocket, self).send(pkt, **kwargs)
3874 @staticmethod
3875 def select(sockets, remain=conf.recv_poll_rate):
3876 if any(getattr(x, "queue", None) for x in sockets):
3877 return [x for x in sockets if isinstance(x, SMBStreamSocket) and x.queue]
3878 return select_objects(sockets, remain=remain)
3881class SMBSession(DefaultSession):
3882 """
3883 A SMB session within a TCP socket.
3884 """
3886 def __init__(self, *args, **kwargs):
3887 self.smb_header = None
3888 self.ssp = kwargs.pop("ssp", None)
3889 self.sspcontext = kwargs.pop("sspcontext", None)
3890 self.sniffsspcontexts = {} # Unfinished contexts for passive
3891 # SMB session parameters
3892 self.CompoundQueue = []
3893 self.Dialect = 0x0202 # Updated by parent
3894 self.Credits = 0
3895 self.IsGuest = False
3896 self.MaxTransactionSize = 0
3897 self.MaxReadSize = 0
3898 self.MaxWriteSize = 0
3899 # Crypto parameters. Go read [MS-SMB2] to understand the names.
3900 self.SigningRequired = True
3901 self.SupportsEncryption = False
3902 self.EncryptData = False
3903 self.TreeEncryptData = False
3904 self.SigningKey = None
3905 self.EncryptionKey = None
3906 self.DecryptionKey = None
3907 self.PreauthIntegrityHashId = "SHA-512"
3908 self.SupportedCipherIds = [
3909 "AES-128-CCM",
3910 "AES-128-GCM",
3911 "AES-256-CCM",
3912 "AES-256-GCM",
3913 ]
3914 self.CipherId = "AES-128-CCM"
3915 self.SupportedSigningAlgorithmIds = [
3916 "AES-CMAC",
3917 "HMAC-SHA256",
3918 ]
3919 self.SigningAlgorithmId = None
3920 self.Salt = os.urandom(32)
3921 self.ConnectionPreauthIntegrityHashValue = None
3922 self.SessionPreauthIntegrityHashValue = None
3923 # SMB 3.1.1
3924 self.SessionPreauthIntegrityHashValue = None
3925 if conf.winssps_passive:
3926 for ssp in conf.winssps_passive:
3927 self.sniffsspcontexts[ssp] = None
3928 super(SMBSession, self).__init__(*args, **kwargs)
3930 # SMB crypto functions
3932 @crypto_validator
3933 def computeSMBSessionKeys(self, IsClient=None):
3934 """
3935 Compute the SigningKey and EncryptionKey (for SMB 3+)
3936 """
3937 if not getattr(self.sspcontext, "SessionKey", None):
3938 # no signing key, no session key
3939 return
3940 # [MS-SMB2] sect 3.3.5.5.3
3941 # SigningKey
3942 if self.Dialect >= 0x0300:
3943 if self.Dialect == 0x0311:
3944 label = b"SMBSigningKey\x00"
3945 context = self.SessionPreauthIntegrityHashValue
3946 else:
3947 label = b"SMB2AESCMAC\x00"
3948 context = b"SmbSign\x00"
3949 # [MS-SMB2] sect 3.1.4.2
3950 if "256" in self.CipherId:
3951 L = 256
3952 elif "128" in self.CipherId:
3953 L = 128
3954 else:
3955 raise ValueError
3956 self.SigningKey = SP800108_KDFCTR(
3957 self.sspcontext.SessionKey[:16],
3958 label,
3959 context,
3960 L,
3961 )
3962 # EncryptionKey / DecryptionKey
3963 if self.Dialect == 0x0311:
3964 if IsClient:
3965 label_out = b"SMBC2SCipherKey\x00"
3966 label_in = b"SMBS2CCipherKey\x00"
3967 else:
3968 label_out = b"SMBS2CCipherKey\x00"
3969 label_in = b"SMBC2SCipherKey\x00"
3970 context_out = context_in = self.SessionPreauthIntegrityHashValue
3971 else:
3972 label_out = label_in = b"SMB2AESCCM\x00"
3973 if IsClient:
3974 context_out = b"ServerIn \x00" # extra space per spec
3975 context_in = b"ServerOut\x00"
3976 else:
3977 context_out = b"ServerOut\x00"
3978 context_in = b"ServerIn \x00"
3979 self.EncryptionKey = SP800108_KDFCTR(
3980 self.sspcontext.SessionKey[: L // 8],
3981 label_out,
3982 context_out,
3983 L,
3984 )
3985 self.DecryptionKey = SP800108_KDFCTR(
3986 self.sspcontext.SessionKey[: L // 8],
3987 label_in,
3988 context_in,
3989 L,
3990 )
3991 elif self.Dialect <= 0x0210:
3992 self.SigningKey = self.sspcontext.SessionKey[:16]
3993 else:
3994 raise ValueError("Hmmm ? >:(")
3996 def computeSMBConnectionPreauth(self, *negopkts):
3997 if self.Dialect and self.Dialect >= 0x0311: # SMB 3.1.1 only
3998 # [MS-SMB2] 3.3.5.4
3999 # TODO: handle SMB2_SESSION_FLAG_BINDING
4000 if self.ConnectionPreauthIntegrityHashValue is None:
4001 # New auth or failure
4002 self.ConnectionPreauthIntegrityHashValue = b"\x00" * 64
4003 # Calculate the *Connection* PreauthIntegrityHashValue
4004 for negopkt in negopkts:
4005 self.ConnectionPreauthIntegrityHashValue = (
4006 SMB2computePreauthIntegrityHashValue(
4007 self.ConnectionPreauthIntegrityHashValue,
4008 negopkt,
4009 HashId=self.PreauthIntegrityHashId,
4010 )
4011 )
4013 def computeSMBSessionPreauth(self, *sesspkts):
4014 if self.Dialect and self.Dialect >= 0x0311: # SMB 3.1.1 only
4015 # [MS-SMB2] 3.3.5.5.3
4016 if self.SessionPreauthIntegrityHashValue is None:
4017 # New auth or failure
4018 self.SessionPreauthIntegrityHashValue = (
4019 self.ConnectionPreauthIntegrityHashValue
4020 )
4021 # Calculate the *Session* PreauthIntegrityHashValue
4022 for sesspkt in sesspkts:
4023 self.SessionPreauthIntegrityHashValue = (
4024 SMB2computePreauthIntegrityHashValue(
4025 self.SessionPreauthIntegrityHashValue,
4026 sesspkt,
4027 HashId=self.PreauthIntegrityHashId,
4028 )
4029 )
4031 # I/O
4033 def in_pkt(self, pkt):
4034 """
4035 Incoming SMB packet
4036 """
4037 if SMB2_Transform_Header in pkt:
4038 # Packet is encrypted
4039 pkt = pkt[SMB2_Transform_Header].decrypt(
4040 self.Dialect,
4041 self.DecryptionKey,
4042 CipherId=self.CipherId,
4043 )
4044 # Signature is verified in SMBStreamSocket
4045 return pkt
4047 def out_pkt(self, pkt, Compounded=False, ForceSign=False, ForceEncrypt=False):
4048 """
4049 Outgoing SMB packet
4051 :param pkt: the packet to send
4052 :param Compound: if True, will be stack to be send with the next
4053 un-compounded packet
4054 :param ForceSign: if True, force to sign the packet.
4055 :param ForceEncrypt: if True, force to encrypt the packet.
4057 Handles:
4058 - handle compounded requests (if any): [MS-SMB2] 3.3.5.2.7
4059 - handles signing and encryption (if required)
4060 """
4061 # Note: impacket and wireshark get crazy on compounded+signature, but
4062 # windows+samba tells we're right :D
4063 if SMB2_Header in pkt:
4064 if self.CompoundQueue:
4065 # this is a subsequent compound: only keep the SMB2
4066 pkt = pkt[SMB2_Header]
4067 if Compounded:
4068 # [MS-SMB2] 3.2.4.1.4
4069 # "Compounded requests MUST be aligned on 8-byte boundaries; the
4070 # last request of the compounded requests does not need to be padded to
4071 # an 8-byte boundary."
4072 # [MS-SMB2] 3.1.4.1
4073 # "If the message is part of a compounded chain, any
4074 # padding at the end of the message MUST be used in the hash
4075 # computation."
4076 length = len(pkt[SMB2_Header])
4077 padlen = (-length) % 8
4078 if padlen:
4079 pkt.add_payload(b"\x00" * padlen)
4080 pkt[SMB2_Header].NextCommand = length + padlen
4081 if (
4082 self.Dialect
4083 and self.SigningKey
4084 and (ForceSign or self.SigningRequired and not ForceEncrypt)
4085 ):
4086 # [MS-SMB2] sect 3.2.4.1.1 - Signing
4087 smb = pkt[SMB2_Header]
4088 smb.Flags += "SMB2_FLAGS_SIGNED"
4089 smb.sign(
4090 self.Dialect,
4091 self.SigningKey,
4092 # SMB 3.1.1 parameters:
4093 SigningAlgorithmId=self.SigningAlgorithmId,
4094 IsClient=False,
4095 )
4096 if Compounded:
4097 # There IS a next compound. Store in queue
4098 self.CompoundQueue.append(pkt)
4099 return []
4100 else:
4101 # If there are any compounded responses in store, sum them
4102 if self.CompoundQueue:
4103 pkt = functools.reduce(lambda x, y: x / y, self.CompoundQueue) / pkt
4104 self.CompoundQueue.clear()
4105 if self.EncryptionKey and (
4106 ForceEncrypt or self.EncryptData or self.TreeEncryptData
4107 ):
4108 # [MS-SMB2] sect 3.1.4.3 - Encrypting the message
4109 smb = pkt[SMB2_Header]
4110 assert not smb.Flags.SMB2_FLAGS_SIGNED
4111 smbt = smb.encrypt(
4112 self.Dialect,
4113 self.EncryptionKey,
4114 CipherId=self.CipherId,
4115 )
4116 if smb.underlayer:
4117 # If there's an underlayer, replace current SMB header
4118 smb.underlayer.payload = smbt
4119 else:
4120 smb = smbt
4121 return [pkt]
4123 def process(self, pkt: Packet):
4124 # Called when passively sniffing
4125 pkt = super(SMBSession, self).process(pkt)
4126 if pkt is not None and SMB2_Header in pkt:
4127 return self.in_pkt(pkt)
4128 return pkt