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 5 6""" 7SMB (Server Message Block), also known as CIFS - version 2 8 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""" 13 14import collections 15import functools 16import hashlib 17import os 18import re 19import struct 20 21from scapy.automaton import select_objects 22from scapy.config import conf, crypto_validator 23from scapy.error import log_runtime 24from scapy.packet import Packet, bind_layers, bind_top_down 25from scapy.fields import ( 26 ByteEnumField, 27 ByteField, 28 ConditionalField, 29 FieldLenField, 30 FieldListField, 31 FlagValue, 32 FlagsField, 33 IP6Field, 34 IPField, 35 IntField, 36 LEIntField, 37 LEIntEnumField, 38 LELongField, 39 LenField, 40 LEShortEnumField, 41 LEShortField, 42 MultipleTypeField, 43 PadField, 44 PacketField, 45 PacketLenField, 46 PacketListField, 47 ReversePadField, 48 ScalingField, 49 ShortEnumField, 50 ShortField, 51 StrFieldUtf16, 52 StrFixedLenField, 53 StrLenField, 54 StrLenFieldUtf16, 55 StrNullFieldUtf16, 56 ThreeBytesField, 57 UTCTimeField, 58 UUIDField, 59 XLEIntField, 60 XLELongField, 61 XLEShortField, 62 XStrLenField, 63 XStrFixedLenField, 64 YesNoByteField, 65) 66from scapy.sessions import DefaultSession 67from scapy.supersocket import StreamSocket 68 69if conf.crypto_valid: 70 from scapy.libs.rfc3961 import SP800108_KDFCTR 71 72from scapy.layers.gssapi import GSSAPI_BLOB 73from scapy.layers.netbios import NBTSession 74from scapy.layers.ntlm import ( 75 _NTLMPayloadField, 76 _NTLMPayloadPacket, 77 _NTLM_ENUM, 78 _NTLM_post_build, 79) 80 81 82# EnumField 83SMB_DIALECTS = { 84 0x0202: "SMB 2.002", 85 0x0210: "SMB 2.1", 86 0x02FF: "SMB 2.???", 87 0x0300: "SMB 3.0", 88 0x0302: "SMB 3.0.2", 89 0x0311: "SMB 3.1.1", 90} 91 92# SMB2 sect 3.3.5.15 + [MS-ERREF] 93STATUS_ERREF = { 94 0x00000000: "STATUS_SUCCESS", 95 0x00000103: "STATUS_PENDING", 96 0x0000010B: "STATUS_NOTIFY_CLEANUP", 97 0x0000010C: "STATUS_NOTIFY_ENUM_DIR", 98 0x00000532: "ERROR_PASSWORD_EXPIRED", 99 0x00000533: "ERROR_ACCOUNT_DISABLED", 100 0x000006FE: "ERROR_TRUST_FAILURE", 101 0x80000005: "STATUS_BUFFER_OVERFLOW", 102 0x80000006: "STATUS_NO_MORE_FILES", 103 0x8000002D: "STATUS_STOPPED_ON_SYMLINK", 104 0x8009030C: "SEC_E_LOGON_DENIED", 105 0x8009030F: "SEC_E_MESSAGE_ALTERED", 106 0x80090310: "SEC_E_OUT_OF_SEQUENCE", 107 0xC0000003: "STATUS_INVALID_INFO_CLASS", 108 0xC0000004: "STATUS_INFO_LENGTH_MISMATCH", 109 0xC000000D: "STATUS_INVALID_PARAMETER", 110 0xC000000F: "STATUS_NO_SUCH_FILE", 111 0xC0000016: "STATUS_MORE_PROCESSING_REQUIRED", 112 0xC0000022: "STATUS_ACCESS_DENIED", 113 0xC0000033: "STATUS_OBJECT_NAME_INVALID", 114 0xC0000034: "STATUS_OBJECT_NAME_NOT_FOUND", 115 0xC0000043: "STATUS_SHARING_VIOLATION", 116 0xC0000061: "STATUS_PRIVILEGE_NOT_HELD", 117 0xC0000064: "STATUS_NO_SUCH_USER", 118 0xC000006D: "STATUS_LOGON_FAILURE", 119 0xC000006E: "STATUS_ACCOUNT_RESTRICTION", 120 0xC0000071: "STATUS_PASSWORD_EXPIRED", 121 0xC0000072: "STATUS_ACCOUNT_DISABLED", 122 0xC000009A: "STATUS_INSUFFICIENT_RESOURCES", 123 0xC00000BA: "STATUS_FILE_IS_A_DIRECTORY", 124 0xC00000BB: "STATUS_NOT_SUPPORTED", 125 0xC00000C9: "STATUS_NETWORK_NAME_DELETED", 126 0xC00000CC: "STATUS_BAD_NETWORK_NAME", 127 0xC0000120: "STATUS_CANCELLED", 128 0xC0000122: "STATUS_INVALID_COMPUTER_NAME", 129 0xC0000128: "STATUS_FILE_CLOSED", # backup error for older Win versions 130 0xC000015B: "STATUS_LOGON_TYPE_NOT_GRANTED", 131 0xC000018B: "STATUS_NO_TRUST_SAM_ACCOUNT", 132 0xC000019C: "STATUS_FS_DRIVER_REQUIRED", 133 0xC0000203: "STATUS_USER_SESSION_DELETED", 134 0xC000020C: "STATUS_CONNECTION_DISCONNECTED", 135 0xC0000225: "STATUS_NOT_FOUND", 136 0xC0000257: "STATUS_PATH_NOT_COVERED", 137 0xC000035C: "STATUS_NETWORK_SESSION_EXPIRED", 138} 139 140# SMB2 sect 2.1.2.1 141REPARSE_TAGS = { 142 0x00000000: "IO_REPARSE_TAG_RESERVED_ZERO", 143 0x00000001: "IO_REPARSE_TAG_RESERVED_ONE", 144 0x00000002: "IO_REPARSE_TAG_RESERVED_TWO", 145 0xA0000003: "IO_REPARSE_TAG_MOUNT_POINT", 146 0xC0000004: "IO_REPARSE_TAG_HSM", 147 0x80000005: "IO_REPARSE_TAG_DRIVE_EXTENDER", 148 0x80000006: "IO_REPARSE_TAG_HSM2", 149 0x80000007: "IO_REPARSE_TAG_SIS", 150 0x80000008: "IO_REPARSE_TAG_WIM", 151 0x80000009: "IO_REPARSE_TAG_CSV", 152 0x8000000A: "IO_REPARSE_TAG_DFS", 153 0x8000000B: "IO_REPARSE_TAG_FILTER_MANAGER", 154 0xA000000C: "IO_REPARSE_TAG_SYMLINK", 155 0xA0000010: "IO_REPARSE_TAG_IIS_CACHE", 156 0x80000012: "IO_REPARSE_TAG_DFSR", 157 0x80000013: "IO_REPARSE_TAG_DEDUP", 158 0xC0000014: "IO_REPARSE_TAG_APPXSTRM", 159 0x80000014: "IO_REPARSE_TAG_NFS", 160 0x80000015: "IO_REPARSE_TAG_FILE_PLACEHOLDER", 161 0x80000016: "IO_REPARSE_TAG_DFM", 162 0x80000017: "IO_REPARSE_TAG_WOF", 163 0x80000018: "IO_REPARSE_TAG_WCI", 164 0x90001018: "IO_REPARSE_TAG_WCI_1", 165 0xA0000019: "IO_REPARSE_TAG_GLOBAL_REPARSE", 166 0x9000001A: "IO_REPARSE_TAG_CLOUD", 167 0x9000101A: "IO_REPARSE_TAG_CLOUD_1", 168 0x9000201A: "IO_REPARSE_TAG_CLOUD_2", 169 0x9000301A: "IO_REPARSE_TAG_CLOUD_3", 170 0x9000401A: "IO_REPARSE_TAG_CLOUD_4", 171 0x9000501A: "IO_REPARSE_TAG_CLOUD_5", 172 0x9000601A: "IO_REPARSE_TAG_CLOUD_6", 173 0x9000701A: "IO_REPARSE_TAG_CLOUD_7", 174 0x9000801A: "IO_REPARSE_TAG_CLOUD_8", 175 0x9000901A: "IO_REPARSE_TAG_CLOUD_9", 176 0x9000A01A: "IO_REPARSE_TAG_CLOUD_A", 177 0x9000B01A: "IO_REPARSE_TAG_CLOUD_B", 178 0x9000C01A: "IO_REPARSE_TAG_CLOUD_C", 179 0x9000D01A: "IO_REPARSE_TAG_CLOUD_D", 180 0x9000E01A: "IO_REPARSE_TAG_CLOUD_E", 181 0x9000F01A: "IO_REPARSE_TAG_CLOUD_F", 182 0x8000001B: "IO_REPARSE_TAG_APPEXECLINK", 183 0x9000001C: "IO_REPARSE_TAG_PROJFS", 184 0xA000001D: "IO_REPARSE_TAG_LX_SYMLINK", 185 0x8000001E: "IO_REPARSE_TAG_STORAGE_SYNC", 186 0xA000001F: "IO_REPARSE_TAG_WCI_TOMBSTONE", 187 0x80000020: "IO_REPARSE_TAG_UNHANDLED", 188 0x80000021: "IO_REPARSE_TAG_ONEDRIVE", 189 0xA0000022: "IO_REPARSE_TAG_PROJFS_TOMBSTONE", 190 0x80000023: "IO_REPARSE_TAG_AF_UNIX", 191 0x80000024: "IO_REPARSE_TAG_LX_FIFO", 192 0x80000025: "IO_REPARSE_TAG_LX_CHR", 193 0x80000026: "IO_REPARSE_TAG_LX_BLK", 194 0xA0000027: "IO_REPARSE_TAG_WCI_LINK", 195 0xA0001027: "IO_REPARSE_TAG_WCI_LINK_1", 196} 197 198# SMB2 sect 2.2.1.1 199SMB2_COM = { 200 0x0000: "SMB2_NEGOTIATE", 201 0x0001: "SMB2_SESSION_SETUP", 202 0x0002: "SMB2_LOGOFF", 203 0x0003: "SMB2_TREE_CONNECT", 204 0x0004: "SMB2_TREE_DISCONNECT", 205 0x0005: "SMB2_CREATE", 206 0x0006: "SMB2_CLOSE", 207 0x0007: "SMB2_FLUSH", 208 0x0008: "SMB2_READ", 209 0x0009: "SMB2_WRITE", 210 0x000A: "SMB2_LOCK", 211 0x000B: "SMB2_IOCTL", 212 0x000C: "SMB2_CANCEL", 213 0x000D: "SMB2_ECHO", 214 0x000E: "SMB2_QUERY_DIRECTORY", 215 0x000F: "SMB2_CHANGE_NOTIFY", 216 0x0010: "SMB2_QUERY_INFO", 217 0x0011: "SMB2_SET_INFO", 218 0x0012: "SMB2_OPLOCK_BREAK", 219} 220 221# EnumField 222SMB2_NEGOTIATE_CONTEXT_TYPES = { 223 0x0001: "SMB2_PREAUTH_INTEGRITY_CAPABILITIES", 224 0x0002: "SMB2_ENCRYPTION_CAPABILITIES", 225 0x0003: "SMB2_COMPRESSION_CAPABILITIES", 226 0x0005: "SMB2_NETNAME_NEGOTIATE_CONTEXT_ID", 227 0x0006: "SMB2_TRANSPORT_CAPABILITIES", 228 0x0007: "SMB2_RDMA_TRANSFORM_CAPABILITIES", 229 0x0008: "SMB2_SIGNING_CAPABILITIES", 230} 231 232# FlagField 233SMB2_CAPABILITIES = { 234 0x00000001: "DFS", 235 0x00000002: "LEASING", 236 0x00000004: "LARGE_MTU", 237 0x00000008: "MULTI_CHANNEL", 238 0x00000010: "PERSISTENT_HANDLES", 239 0x00000020: "DIRECTORY_LEASING", 240 0x00000040: "ENCRYPTION", 241} 242SMB2_SECURITY_MODE = { 243 0x01: "SIGNING_ENABLED", 244 0x02: "SIGNING_REQUIRED", 245} 246 247# [MS-SMB2] 2.2.3.1.3 248SMB2_COMPRESSION_ALGORITHMS = { 249 0x0000: "None", 250 0x0001: "LZNT1", 251 0x0002: "LZ77", 252 0x0003: "LZ77 + Huffman", 253 0x0004: "Pattern_V1", 254} 255 256# [MS-SMB2] sect 2.2.3.1.2 257SMB2_ENCRYPTION_CIPHERS = { 258 0x0001: "AES-128-CCM", 259 0x0002: "AES-128-GCM", 260 0x0003: "AES-256-CCM", 261 0x0004: "AES-256-GCM", 262} 263 264# [MS-SMB2] sect 2.2.3.1.7 265SMB2_SIGNING_ALGORITHMS = { 266 0x0000: "HMAC-SHA256", 267 0x0001: "AES-CMAC", 268 0x0002: "AES-GMAC", 269} 270 271# sect [MS-SMB2] 2.2.13.1.1 272SMB2_ACCESS_FLAGS_FILE = { 273 0x00000001: "FILE_READ_DATA", 274 0x00000002: "FILE_WRITE_DATA", 275 0x00000004: "FILE_APPEND_DATA", 276 0x00000008: "FILE_READ_EA", 277 0x00000010: "FILE_WRITE_EA", 278 0x00000040: "FILE_DELETE_CHILD", 279 0x00000020: "FILE_EXECUTE", 280 0x00000080: "FILE_READ_ATTRIBUTES", 281 0x00000100: "FILE_WRITE_ATTRIBUTES", 282 0x00010000: "DELETE", 283 0x00020000: "READ_CONTROL", 284 0x00040000: "WRITE_DAC", 285 0x00080000: "WRITE_OWNER", 286 0x00100000: "SYNCHRONIZE", 287 0x01000000: "ACCESS_SYSTEM_SECURITY", 288 0x02000000: "MAXIMUM_ALLOWED", 289 0x10000000: "GENERIC_ALL", 290 0x20000000: "GENERIC_EXECUTE", 291 0x40000000: "GENERIC_WRITE", 292 0x80000000: "GENERIC_READ", 293} 294 295# sect [MS-SMB2] 2.2.13.1.2 296SMB2_ACCESS_FLAGS_DIRECTORY = { 297 0x00000001: "FILE_LIST_DIRECTORY", 298 0x00000002: "FILE_ADD_FILE", 299 0x00000004: "FILE_ADD_SUBDIRECTORY", 300 0x00000008: "FILE_READ_EA", 301 0x00000010: "FILE_WRITE_EA", 302 0x00000020: "FILE_TRAVERSE", 303 0x00000040: "FILE_DELETE_CHILD", 304 0x00000080: "FILE_READ_ATTRIBUTES", 305 0x00000100: "FILE_WRITE_ATTRIBUTES", 306 0x00010000: "DELETE", 307 0x00020000: "READ_CONTROL", 308 0x00040000: "WRITE_DAC", 309 0x00080000: "WRITE_OWNER", 310 0x00100000: "SYNCHRONIZE", 311 0x01000000: "ACCESS_SYSTEM_SECURITY", 312 0x02000000: "MAXIMUM_ALLOWED", 313 0x10000000: "GENERIC_ALL", 314 0x20000000: "GENERIC_EXECUTE", 315 0x40000000: "GENERIC_WRITE", 316 0x80000000: "GENERIC_READ", 317} 318 319# [MS-SRVS] sec 2.2.2.4 320SRVSVC_SHARE_TYPES = { 321 0x00000000: "DISKTREE", 322 0x00000001: "PRINTQ", 323 0x00000002: "DEVICE", 324 0x00000003: "IPC", 325 0x02000000: "CLUSTER_FS", 326 0x04000000: "CLUSTER_SOFS", 327 0x08000000: "CLUSTER_DFS", 328} 329 330 331# [MS-FSCC] sec 2.6 332FileAttributes = { 333 0x00000001: "FILE_ATTRIBUTE_READONLY", 334 0x00000002: "FILE_ATTRIBUTE_HIDDEN", 335 0x00000004: "FILE_ATTRIBUTE_SYSTEM", 336 0x00000010: "FILE_ATTRIBUTE_DIRECTORY", 337 0x00000020: "FILE_ATTRIBUTE_ARCHIVE", 338 0x00000080: "FILE_ATTRIBUTE_NORMAL", 339 0x00000100: "FILE_ATTRIBUTE_TEMPORARY", 340 0x00000200: "FILE_ATTRIBUTE_SPARSE_FILE", 341 0x00000400: "FILE_ATTRIBUTE_REPARSE_POINT", 342 0x00000800: "FILE_ATTRIBUTE_COMPRESSED", 343 0x00001000: "FILE_ATTRIBUTE_OFFLINE", 344 0x00002000: "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED", 345 0x00004000: "FILE_ATTRIBUTE_ENCRYPTED", 346 0x00008000: "FILE_ATTRIBUTE_INTEGRITY_STREAM", 347 0x00020000: "FILE_ATTRIBUTE_NO_SCRUB_DATA", 348 0x00040000: "FILE_ATTRIBUTE_RECALL_ON_OPEN", 349 0x00080000: "FILE_ATTRIBUTE_PINNED", 350 0x00100000: "FILE_ATTRIBUTE_UNPINNED", 351 0x00400000: "FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS", 352} 353 354 355# [MS-FSCC] sect 2.4 356FileInformationClasses = { 357 0x01: "FileDirectoryInformation", 358 0x02: "FileFullDirectoryInformation", 359 0x03: "FileBothDirectoryInformation", 360 0x04: "FileBasicInformation", 361 0x05: "FileStandardInformation", 362 0x06: "FileInternalInformation", 363 0x07: "FileEaInformation", 364 0x08: "FileAccessInformation", 365 0x0A: "FileRenameInformation", 366 0x0E: "FilePositionInformation", 367 0x10: "FileModeInformation", 368 0x11: "FileAlignmentInformation", 369 0x12: "FileAllInformation", 370 0x22: "FileNetworkOpenInformation", 371 0x25: "FileIdBothDirectoryInformation", 372 0x26: "FileIdFullDirectoryInformation", 373 0x0C: "FileNamesInformation", 374 0x30: "FileNormalizedNameInformation", 375 0x3C: "FileIdExtdDirectoryInformation", 376} 377_FileInformationClasses = {} 378 379 380# [MS-FSCC] 2.1.7 FILE_NAME_INFORMATION 381 382 383class FILE_NAME_INFORMATION(Packet): 384 fields_desc = [ 385 FieldLenField("FileNameLength", None, length_of="FileName", fmt="<I"), 386 StrLenFieldUtf16("FileName", "", length_from=lambda pkt: pkt.FileNameLength), 387 ] 388 389 def default_payload_class(self, s): 390 return conf.padding_layer 391 392 393# [MS-FSCC] 2.4.1 FileAccessInformation 394 395 396class FileAccessInformation(Packet): 397 fields_desc = [ 398 FlagsField("AccessFlags", 0, -32, SMB2_ACCESS_FLAGS_FILE), 399 ] 400 401 def default_payload_class(self, s): 402 return conf.padding_layer 403 404 405# [MS-FSCC] 2.4.3 FileAlignmentInformation 406 407 408class FileAlignmentInformation(Packet): 409 fields_desc = [ 410 LEIntEnumField( 411 "AccessFlags", 412 0, 413 { 414 0x00000000: "FILE_BYTE_ALIGNMENT", 415 0x00000001: "FILE_WORD_ALIGNMENT", 416 0x00000003: "FILE_LONG_ALIGNMENT", 417 0x00000007: "FILE_QUAD_ALIGNMENT", 418 0x0000000F: "FILE_OCTA_ALIGNMENT", 419 0x0000001F: "FILE_32_BYTE_ALIGNMENT", 420 0x0000003F: "FILE_64_BYTE_ALIGNMENT", 421 0x0000007F: "FILE_128_BYTE_ALIGNMENT", 422 0x000000FF: "FILE_256_BYTE_ALIGNMENT", 423 0x000001FF: "FILE_512_BYTE_ALIGNMENT", 424 }, 425 ), 426 ] 427 428 def default_payload_class(self, s): 429 return conf.padding_layer 430 431 432# [MS-FSCC] 2.4.5 FileAlternateNameInformation 433 434 435class FileAlternateNameInformation(Packet): 436 fields_desc = [ 437 FieldLenField("FileNameLength", None, length_of="FileName", fmt="<I"), 438 StrLenFieldUtf16("FileName", b"", length_from=lambda pkt: pkt.FileNameLength), 439 ] 440 441 442# [MS-FSCC] 2.4.7 FileBasicInformation 443 444 445class FileBasicInformation(Packet): 446 fields_desc = [ 447 UTCTimeField( 448 "CreationTime", 449 None, 450 fmt="<Q", 451 epoch=[1601, 1, 1, 0, 0, 0], 452 custom_scaling=1e7, 453 ), 454 UTCTimeField( 455 "LastAccessTime", 456 None, 457 fmt="<Q", 458 epoch=[1601, 1, 1, 0, 0, 0], 459 custom_scaling=1e7, 460 ), 461 UTCTimeField( 462 "LastWriteTime", 463 None, 464 fmt="<Q", 465 epoch=[1601, 1, 1, 0, 0, 0], 466 custom_scaling=1e7, 467 ), 468 UTCTimeField( 469 "ChangeTime", 470 None, 471 fmt="<Q", 472 epoch=[1601, 1, 1, 0, 0, 0], 473 custom_scaling=1e7, 474 ), 475 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes), 476 IntField("Reserved", 0), 477 ] 478 479 def default_payload_class(self, s): 480 return conf.padding_layer 481 482 483# [MS-FSCC] 2.4.12 FileEaInformation 484 485 486class FileEaInformation(Packet): 487 fields_desc = [ 488 LEIntField("EaSize", 0), 489 ] 490 491 def default_payload_class(self, s): 492 return conf.padding_layer 493 494 495# [MS-FSCC] 2.4.29 FileNetworkOpenInformation 496 497 498class FileNetworkOpenInformation(Packet): 499 fields_desc = [ 500 UTCTimeField( 501 "CreationTime", 502 None, 503 fmt="<Q", 504 epoch=[1601, 1, 1, 0, 0, 0], 505 custom_scaling=1e7, 506 ), 507 UTCTimeField( 508 "LastAccessTime", 509 None, 510 fmt="<Q", 511 epoch=[1601, 1, 1, 0, 0, 0], 512 custom_scaling=1e7, 513 ), 514 UTCTimeField( 515 "LastWriteTime", 516 None, 517 fmt="<Q", 518 epoch=[1601, 1, 1, 0, 0, 0], 519 custom_scaling=1e7, 520 ), 521 UTCTimeField( 522 "ChangeTime", 523 None, 524 fmt="<Q", 525 epoch=[1601, 1, 1, 0, 0, 0], 526 custom_scaling=1e7, 527 ), 528 LELongField("AllocationSize", 4096), 529 LELongField("EndOfFile", 0), 530 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes), 531 IntField("Reserved2", 0), 532 ] 533 534 def default_payload_class(self, s): 535 return conf.padding_layer 536 537 538# [MS-FSCC] 2.4.8 FileBothDirectoryInformation 539 540 541class FILE_BOTH_DIR_INFORMATION(Packet): 542 fields_desc = ( 543 [ 544 LEIntField("Next", None), # 0 = no next entry 545 LEIntField("FileIndex", 0), 546 ] 547 + ( 548 FileNetworkOpenInformation.fields_desc[:4] 549 + FileNetworkOpenInformation.fields_desc[4:6][::-1] 550 + [FileNetworkOpenInformation.fields_desc[6]] 551 ) 552 + [ 553 FieldLenField("FileNameLength", None, fmt="<I", length_of="FileName"), 554 MultipleTypeField( 555 # "If FILE_ATTRIBUTE_REPARSE_POINT is set in the FileAttributes field, 556 # this field MUST contain a reparse tag as specified in section 557 # 2.1.2.1." 558 [ 559 ( 560 LEIntEnumField("EaSize", 0, REPARSE_TAGS), 561 lambda pkt: pkt.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT, 562 ) 563 ], 564 LEIntField("EaSize", 0), 565 ), 566 ByteField("ShortNameLength", 0), 567 ByteField("Reserved1", 0), 568 StrFixedLenField("ShortName", b"", length=24), 569 PadField( 570 StrLenFieldUtf16( 571 "FileName", b".", length_from=lambda pkt: pkt.FileNameLength 572 ), 573 align=8, 574 ), 575 ] 576 ) 577 578 def default_payload_class(self, s): 579 return conf.padding_layer 580 581 582class _NextPacketListField(PacketListField): 583 def addfield(self, pkt, s, val): 584 # we use this field to set NextEntryOffset 585 res = b"" 586 for i, v in enumerate(val): 587 x = self.i2m(pkt, v) 588 if v.Next is None and i != len(val) - 1: 589 x = struct.pack("<I", len(x)) + x[4:] 590 res += x 591 return s + res 592 593 594class FileBothDirectoryInformation(Packet): 595 fields_desc = [ 596 _NextPacketListField( 597 "files", 598 [], 599 FILE_BOTH_DIR_INFORMATION, 600 max_count=1000, 601 ), 602 ] 603 604 605# [MS-FSCC] 2.4.14 FileFullDirectoryInformation 606 607 608class FILE_FULL_DIR_INFORMATION(Packet): 609 fields_desc = FILE_BOTH_DIR_INFORMATION.fields_desc[:11] + [ 610 FILE_BOTH_DIR_INFORMATION.fields_desc[-1] 611 ] 612 613 614class FileFullDirectoryInformation(Packet): 615 fields_desc = [ 616 _NextPacketListField( 617 "files", 618 [], 619 FILE_FULL_DIR_INFORMATION, 620 max_count=1000, 621 ), 622 ] 623 624 625# [MS-FSCC] 2.4.17 FileIdBothDirectoryInformation 626 627 628class FILE_ID_BOTH_DIR_INFORMATION(Packet): 629 fields_desc = FILE_BOTH_DIR_INFORMATION.fields_desc[:14] + [ 630 LEShortField("Reserved2", 0), 631 LELongField("FileId", 0), 632 FILE_BOTH_DIR_INFORMATION.fields_desc[-1], 633 ] 634 635 def default_payload_class(self, s): 636 return conf.padding_layer 637 638 639class FileIdBothDirectoryInformation(Packet): 640 fields_desc = [ 641 _NextPacketListField( 642 "files", 643 [], 644 FILE_ID_BOTH_DIR_INFORMATION, 645 max_count=1000, # > 65535 / len(FILE_ID_BOTH_DIR_INFORMATION()) 646 ), 647 ] 648 649 650# [MS-FSCC] 2.4.22 FileInternalInformation 651 652 653class FileInternalInformation(Packet): 654 fields_desc = [ 655 LELongField("IndexNumber", 0), 656 ] 657 658 def default_payload_class(self, s): 659 return conf.padding_layer 660 661 662# [MS-FSCC] 2.4.26 FileModeInformation 663 664 665class FileModeInformation(Packet): 666 fields_desc = [ 667 FlagsField( 668 "Mode", 669 0, 670 -32, 671 { 672 0x00000002: "FILE_WRITE_TROUGH", 673 0x00000004: "FILE_SEQUENTIAL_ONLY", 674 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING", 675 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT", 676 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT", 677 0x00001000: "FILE_DELETE_ON_CLOSE", 678 }, 679 ) 680 ] 681 682 def default_payload_class(self, s): 683 return conf.padding_layer 684 685 686# [MS-FSCC] 2.4.35 FilePositionInformation 687 688 689class FilePositionInformation(Packet): 690 fields_desc = [ 691 LELongField("CurrentByteOffset", 0), 692 ] 693 694 def default_payload_class(self, s): 695 return conf.padding_layer 696 697 698# [MS-FSCC] 2.4.37 FileRenameInformation 699 700 701class FileRenameInformation(Packet): 702 fields_desc = [ 703 YesNoByteField("ReplaceIfExists", False), 704 XStrFixedLenField("Reserved", b"", length=7), 705 LELongField("RootDirectory", 0), 706 FieldLenField("FileNameLength", 0, length_of="FileName", fmt="<I"), 707 StrLenFieldUtf16("FileName", b"", length_from=lambda pkt: pkt.FileNameLength), 708 ] 709 710 def post_build(self, pkt, pay): 711 # type: (bytes, bytes) -> bytes 712 if len(pkt) < 24: 713 # 'Length of this field MUST be the number of bytes required to make the 714 # size of this structure at least 24.' 715 pkt += (24 - len(pkt)) * b"\x00" 716 return pkt + pay 717 718 def default_payload_class(self, s): 719 return conf.padding_layer 720 721 722_FileInformationClasses[0x0A] = FileRenameInformation 723 724 725# [MS-FSCC] 2.4.41 FileStandardInformation 726 727 728class FileStandardInformation(Packet): 729 fields_desc = [ 730 LELongField("AllocationSize", 4096), 731 LELongField("EndOfFile", 0), 732 LEIntField("NumberOfLinks", 1), 733 ByteField("DeletePending", 0), 734 ByteField("Directory", 0), 735 ShortField("Reserved", 0), 736 ] 737 738 def default_payload_class(self, s): 739 return conf.padding_layer 740 741 742# [MS-FSCC] 2.4.43 FileStreamInformation 743 744 745class FileStreamInformation(Packet): 746 fields_desc = [ 747 LEIntField("Next", 0), 748 FieldLenField("StreamNameLength", None, length_of="StreamName", fmt="<I"), 749 LELongField("StreamSize", 0), 750 LELongField("StreamAllocationSize", 4096), 751 StrLenFieldUtf16( 752 "StreamName", b"::$DATA", length_from=lambda pkt: pkt.StreamNameLength 753 ), 754 ] 755 756 757# [MS-DTYP] sect 2.4.1 758 759 760class WINNT_SID_IDENTIFIER_AUTHORITY(Packet): 761 fields_desc = [ 762 StrFixedLenField("Value", b"\x00\x00\x00\x00\x00\x01", length=6), 763 ] 764 765 def default_payload_class(self, payload): 766 return conf.padding_layer 767 768 769# [MS-DTYP] sect 2.4.2 770 771 772class WINNT_SID(Packet): 773 fields_desc = [ 774 ByteField("Revision", 1), 775 FieldLenField("SubAuthorityCount", None, count_of="SubAuthority", fmt="B"), 776 PacketField( 777 "IdentifierAuthority", 778 WINNT_SID_IDENTIFIER_AUTHORITY(), 779 WINNT_SID_IDENTIFIER_AUTHORITY, 780 ), 781 FieldListField( 782 "SubAuthority", 783 [0], 784 LEIntField("", 0), 785 count_from=lambda pkt: pkt.SubAuthorityCount, 786 ), 787 ] 788 789 def default_payload_class(self, payload): 790 return conf.padding_layer 791 792 _SID_REG = re.compile(r"^S-(\d)-(\d+)((?:-\d+)*)$") 793 794 @staticmethod 795 def fromstr(x): 796 m = WINNT_SID._SID_REG.match(x) 797 if not m: 798 raise ValueError("Invalid SID format !") 799 rev, authority, subauthority = m.groups() 800 return WINNT_SID( 801 Revision=int(rev), 802 IdentifierAuthority=WINNT_SID_IDENTIFIER_AUTHORITY( 803 Value=struct.pack(">Q", int(authority))[2:] 804 ), 805 SubAuthority=[int(x) for x in subauthority[1:].split("-")], 806 ) 807 808 def summary(self): 809 return "S-%s-%s%s" % ( 810 self.Revision, 811 struct.unpack(">Q", b"\x00\x00" + self.IdentifierAuthority.Value)[0], 812 ("-%s" % "-".join(str(x) for x in self.SubAuthority)) 813 if self.SubAuthority 814 else "", 815 ) 816 817 818# https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers 819 820WELL_KNOWN_SIDS = { 821 # Universal well-known SID 822 "S-1-0-0": "Null SID", 823 "S-1-1-0": "Everyone", 824 "S-1-2-0": "Local", 825 "S-1-2-1": "Console Logon", 826 "S-1-3-0": "Creator Owner ID", 827 "S-1-3-1": "Creator Group ID", 828 "S-1-3-2": "Owner Server", 829 "S-1-3-3": "Group Server", 830 "S-1-3-4": "Owner Rights", 831 "S-1-4": "Non-unique Authority", 832 "S-1-5": "NT Authority", 833 "S-1-5-80-0": "All Services", 834 # NT well-known SIDs 835 "S-1-5-1": "Dialup", 836 "S-1-5-113": "Local account", 837 "S-1-5-114": "Local account and member of Administrators group", 838 "S-1-5-2": "Network", 839 "S-1-5-3": "Batch", 840 "S-1-5-4": "Interactive", 841 "S-1-5-6": "Service", 842 "S-1-5-7": "Anonymous Logon", 843 "S-1-5-8": "Proxy", 844 "S-1-5-9": "Enterprise Domain Controllers", 845 "S-1-5-10": "Self", 846 "S-1-5-11": "Authenticated Users", 847 "S-1-5-12": "Restricted Code", 848 "S-1-5-13": "Terminal Server User", 849 "S-1-5-14": "Remote Interactive Logon", 850 "S-1-5-15": "This Organization", 851 "S-1-5-17": "IUSR", 852 "S-1-5-18": "System (or LocalSystem)", 853 "S-1-5-19": "NT Authority (LocalService)", 854 "S-1-5-20": "Network Service", 855 "S-1-5-32-544": "Administrators", 856 "S-1-5-32-545": "Users", 857 "S-1-5-32-546": "Guests", 858 "S-1-5-32-547": "Power Users", 859 "S-1-5-32-548": "Account Operators", 860 "S-1-5-32-549": "Server Operators", 861 "S-1-5-32-550": "Print Operators", 862 "S-1-5-32-551": "Backup Operators", 863 "S-1-5-32-552": "Replicators", 864 "S-1-5-32-554": r"Builtin\Pre-Windows 2000 Compatible Access", 865 "S-1-5-32-555": r"Builtin\Remote Desktop Users", 866 "S-1-5-32-556": r"Builtin\Network Configuration Operators", 867 "S-1-5-32-557": r"Builtin\Incoming Forest Trust Builders", 868 "S-1-5-32-558": r"Builtin\Performance Monitor Users", 869 "S-1-5-32-559": r"Builtin\Performance Log Users", 870 "S-1-5-32-560": r"Builtin\Windows Authorization Access Group", 871 "S-1-5-32-561": r"Builtin\Terminal Server License Servers", 872 "S-1-5-32-562": r"Builtin\Distributed COM Users", 873 "S-1-5-32-568": r"Builtin\IIS_IUSRS", 874 "S-1-5-32-569": r"Builtin\Cryptographic Operators", 875 "S-1-5-32-573": r"Builtin\Event Log Readers", 876 "S-1-5-32-574": r"Builtin\Certificate Service DCOM Access", 877 "S-1-5-32-575": r"Builtin\RDS Remote Access Servers", 878 "S-1-5-32-576": r"Builtin\RDS Endpoint Servers", 879 "S-1-5-32-577": r"Builtin\RDS Management Servers", 880 "S-1-5-32-578": r"Builtin\Hyper-V Administrators", 881 "S-1-5-32-579": r"Builtin\Access Control Assistance Operators", 882 "S-1-5-32-580": r"Builtin\Remote Management Users", 883 "S-1-5-32-581": r"Builtin\Default Account", 884 "S-1-5-32-582": r"Builtin\Storage Replica Admins", 885 "S-1-5-32-583": r"Builtin\Device Owners", 886 "S-1-5-64-10": "NTLM Authentication", 887 "S-1-5-64-14": "SChannel Authentication", 888 "S-1-5-64-21": "Digest Authentication", 889 "S-1-5-80": "NT Service", 890 "S-1-5-80-0": "All Services", 891 "S-1-5-83-0": r"NT VIRTUAL MACHINE\Virtual Machines", 892} 893 894 895# [MS-DTYP] sect 2.4.3 896 897_WINNT_ACCESS_MASK = { 898 0x80000000: "GENERIC_READ", 899 0x40000000: "GENERIC_WRITE", 900 0x20000000: "GENERIC_EXECUTE", 901 0x10000000: "GENERIC_ALL", 902 0x02000000: "MAXIMUM_ALLOWED", 903 0x01000000: "ACCESS_SYSTEM_SECURITY", 904 0x00100000: "SYNCHRONIZE", 905 0x00080000: "WRITE_OWNER", 906 0x00040000: "WRITE_DACL", 907 0x00020000: "READ_CONTROL", 908 0x00010000: "DELETE", 909} 910 911 912# [MS-DTYP] sect 2.4.4.1 913 914 915WINNT_ACE_FLAGS = { 916 0x01: "OBJECT_INHERIT", 917 0x02: "CONTAINER_INHERIT", 918 0x04: "NO_PROPAGATE_INHERIT", 919 0x08: "INHERIT_ONLY", 920 0x10: "INHERITED_ACE", 921 0x40: "SUCCESSFUL_ACCESS", 922 0x80: "FAILED_ACCESS", 923} 924 925 926class WINNT_ACE_HEADER(Packet): 927 fields_desc = [ 928 ByteEnumField( 929 "AceType", 930 0, 931 { 932 0x00: "ACCESS_ALLOWED", 933 0x01: "ACCESS_DENIED", 934 0x02: "SYSTEM_AUDIT", 935 0x03: "SYSTEM_ALARM", 936 0x04: "ACCESS_ALLOWED_COMPOUND", 937 0x05: "ACCESS_ALLOWED_OBJECT", 938 0x06: "ACCESS_DENIED_OBJECT", 939 0x07: "SYSTEM_AUDIT_OBJECT", 940 0x08: "SYSTEM_ALARM_OBJECT", 941 0x09: "ACCESS_ALLOWED_CALLBACK", 942 0x0A: "ACCESS_DENIED_CALLBACK", 943 0x0B: "ACCESS_ALLOWED_CALLBACK_OBJECT", 944 0x0C: "ACCESS_DENIED_CALLBACK_OBJECT", 945 0x0D: "SYSTEM_AUDIT_CALLBACK", 946 0x0E: "SYSTEM_ALARM_CALLBACK", 947 0x0F: "SYSTEM_AUDIT_CALLBACK_OBJECT", 948 0x10: "SYSTEM_ALARM_CALLBACK_OBJECT", 949 0x11: "SYSTEM_MANDATORY_LABEL", 950 0x12: "SYSTEM_RESOURCE_ATTRIBUTE", 951 0x13: "SYSTEM_SCOPED_POLICY_ID", 952 }, 953 ), 954 FlagsField( 955 "AceFlags", 956 0, 957 8, 958 WINNT_ACE_FLAGS, 959 ), 960 LenField("AceSize", None, fmt="<H", adjust=lambda x: x + 4), 961 ] 962 963 def extract_padding(self, p): 964 return p[: self.AceSize - 4], p[self.AceSize - 4 :] 965 966 # fmt: off 967 def extractData(self, accessMask=None): 968 """ 969 Return the ACE data as usable data. 970 971 :param accessMask: context-specific flags for the ACE Mask. 972 """ 973 sid_string = self.payload.Sid.summary() 974 mask = self.payload.Mask 975 if accessMask is not None: 976 mask = FlagValue(mask, FlagsField("", 0, 32, accessMask).names) 977 ace_flag_string = str( 978 FlagValue(self.AceFlags, ["OI", "CI", "NP", "IO", "ID", "SA", "FA"]) 979 ) 980 object_guid = getattr(self.payload, "ObjectType", "") 981 inherit_object_guid = getattr(self.payload, "InheritedObjectType", "") 982 # ApplicationData -> conditional expression 983 cond_expr = None 984 if hasattr(self.payload, "ApplicationData"): 985 # Parse tokens 986 res = [] 987 for ct in self.payload.ApplicationData.Tokens: 988 if ct.TokenType in [ 989 # binary operators 990 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x88, 0x8e, 0x8f, 991 0xa0, 0xa1 992 ]: 993 t1 = res.pop(-1) 994 t0 = res.pop(-1) 995 tt = ct.sprintf("%TokenType%") 996 if ct.TokenType in [0xa0, 0xa1]: # && and || 997 res.append(f"({t0}) {tt} ({t1})") 998 else: 999 res.append(f"{t0} {tt} {t1}") 1000 elif ct.TokenType in [ 1001 # unary operators 1002 0x87, 0x8d, 0xa2, 0x89, 0x8a, 0x8b, 0x8c, 0x91, 0x92, 0x93 1003 ]: 1004 t0 = res.pop(-1) 1005 tt = ct.sprintf("%TokenType%") 1006 res.append(f"{tt}{t0}") 1007 elif ct.TokenType in [ 1008 # values 1009 0x01, 0x02, 0x03, 0x04, 0x10, 0x18, 0x50, 0x51, 0xf8, 0xf9, 1010 0xfa, 0xfb 1011 ]: 1012 def lit(ct): 1013 if ct.TokenType in [0x10, 0x18]: # literal strings 1014 return '"%s"' % ct.value 1015 elif ct.TokenType == 0x50: # composite 1016 return "({%s})" % ",".join(lit(x) for x in ct.value) 1017 else: 1018 return str(ct.value) 1019 res.append(lit(ct)) 1020 elif ct.TokenType == 0x00: # padding 1021 pass 1022 else: 1023 raise ValueError("Unhandled token type %s" % ct.TokenType) 1024 if len(res) != 1: 1025 raise ValueError("Incomplete SDDL !") 1026 cond_expr = "(%s)" % res[0] 1027 return { 1028 "ace-flags-string": ace_flag_string, 1029 "sid-string": sid_string, 1030 "mask": mask, 1031 "object-guid": object_guid, 1032 "inherited-object-guid": inherit_object_guid, 1033 "cond-expr": cond_expr, 1034 } 1035 # fmt: on 1036 1037 def toSDDL(self, accessMask=None): 1038 """ 1039 Return SDDL 1040 """ 1041 data = self.extractData(accessMask=accessMask) 1042 ace_rights = "" # TODO 1043 if self.AceType in [0x9, 0xA, 0xB, 0xD]: # Conditional ACE 1044 conditional_ace_type = { 1045 0x09: "XA", 1046 0x0A: "XD", 1047 0x0B: "XU", 1048 0x0D: "ZA", 1049 }[self.AceType] 1050 return "D:(%s)" % ( 1051 ";".join( 1052 x 1053 for x in [ 1054 conditional_ace_type, 1055 data["ace-flags-string"], 1056 ace_rights, 1057 str(data["object-guid"]), 1058 str(data["inherited-object-guid"]), 1059 data["sid-string"], 1060 data["cond-expr"], 1061 ] 1062 if x is not None 1063 ) 1064 ) 1065 else: 1066 ace_type = { 1067 0x00: "A", 1068 0x01: "D", 1069 0x02: "AU", 1070 0x05: "OA", 1071 0x06: "OD", 1072 0x07: "OU", 1073 0x11: "ML", 1074 0x13: "SP", 1075 }[self.AceType] 1076 return "(%s)" % ( 1077 ";".join( 1078 x 1079 for x in [ 1080 ace_type, 1081 data["ace-flags-string"], 1082 ace_rights, 1083 str(data["object-guid"]), 1084 str(data["inherited-object-guid"]), 1085 data["sid-string"], 1086 data["cond-expr"], 1087 ] 1088 if x is not None 1089 ) 1090 ) 1091 1092 1093# [MS-DTYP] sect 2.4.4.2 1094 1095 1096class WINNT_ACCESS_ALLOWED_ACE(Packet): 1097 fields_desc = [ 1098 FlagsField("Mask", 0, -32, _WINNT_ACCESS_MASK), 1099 PacketField("Sid", WINNT_SID(), WINNT_SID), 1100 ] 1101 1102 1103bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_ACE, AceType=0x00) 1104 1105 1106# [MS-DTYP] sect 2.4.4.3 1107 1108 1109class WINNT_ACCESS_ALLOWED_OBJECT_ACE(Packet): 1110 fields_desc = [ 1111 FlagsField("Mask", 0, -32, _WINNT_ACCESS_MASK), 1112 FlagsField( 1113 "Flags", 1114 0, 1115 -32, 1116 { 1117 0x00000001: "OBJECT_TYPE_PRESENT", 1118 0x00000002: "INHERITED_OBJECT_TYPE_PRESENT", 1119 }, 1120 ), 1121 ConditionalField( 1122 UUIDField("ObjectType", None, uuid_fmt=UUIDField.FORMAT_LE), 1123 lambda pkt: pkt.Flags.OBJECT_TYPE_PRESENT, 1124 ), 1125 ConditionalField( 1126 UUIDField("InheritedObjectType", None, uuid_fmt=UUIDField.FORMAT_LE), 1127 lambda pkt: pkt.Flags.INHERITED_OBJECT_TYPE_PRESENT, 1128 ), 1129 PacketField("Sid", WINNT_SID(), WINNT_SID), 1130 ] 1131 1132 1133bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_OBJECT_ACE, AceType=0x05) 1134 1135 1136# [MS-DTYP] sect 2.4.4.4 1137 1138 1139class WINNT_ACCESS_DENIED_ACE(Packet): 1140 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 1141 1142 1143bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_ACE, AceType=0x01) 1144 1145 1146# [MS-DTYP] sect 2.4.4.5 1147 1148 1149class WINNT_ACCESS_DENIED_OBJECT_ACE(Packet): 1150 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc 1151 1152 1153bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_OBJECT_ACE, AceType=0x06) 1154 1155 1156# [MS-DTYP] sect 2.4.4.17.4+ 1157 1158 1159class WINNT_APPLICATION_DATA_LITERAL_TOKEN(Packet): 1160 def default_payload_class(self, payload): 1161 return conf.padding_layer 1162 1163 1164# fmt: off 1165WINNT_APPLICATION_DATA_LITERAL_TOKEN.fields_desc = [ 1166 ByteEnumField( 1167 "TokenType", 1168 0, 1169 { 1170 # [MS-DTYP] sect 2.4.4.17.5 1171 0x00: "Padding token", 1172 0x01: "Signed int8", 1173 0x02: "Signed int16", 1174 0x03: "Signed int32", 1175 0x04: "Signed int64", 1176 0x10: "Unicode", 1177 0x18: "Octet String", 1178 0x50: "Composite", 1179 0x51: "SID", 1180 # [MS-DTYP] sect 2.4.4.17.6 1181 0x80: "==", 1182 0x81: "!=", 1183 0x82: "<", 1184 0x83: "<=", 1185 0x84: ">", 1186 0x85: ">=", 1187 0x86: "Contains", 1188 0x88: "Any_of", 1189 0x8e: "Not_Contains", 1190 0x8f: "Not_Any_of", 1191 0x89: "Member_of", 1192 0x8a: "Device_Member_of", 1193 0x8b: "Member_of_Any", 1194 0x8c: "Device_Member_of_Any", 1195 0x90: "Not_Member_of", 1196 0x91: "Not_Device_Member_of", 1197 0x92: "Not_Member_of_Any", 1198 0x93: "Not_Device_Member_of_Any", 1199 # [MS-DTYP] sect 2.4.4.17.7 1200 0x87: "Exists", 1201 0x8d: "Not_Exists", 1202 0xa0: "&&", 1203 0xa1: "||", 1204 0xa2: "!", 1205 # [MS-DTYP] sect 2.4.4.17.8 1206 0xf8: "Local attribute", 1207 0xf9: "User Attribute", 1208 0xfa: "Resource Attribute", 1209 0xfb: "Device Attribute", 1210 } 1211 ), 1212 ConditionalField( 1213 # Strings 1214 LEIntField("length", 0), 1215 lambda pkt: pkt.TokenType in [ 1216 0x10, # Unicode string 1217 0x18, # Octet string 1218 0xf8, 0xf9, 0xfa, 0xfb, # Attribute tokens 1219 0x50, # Composite 1220 ] 1221 ), 1222 ConditionalField( 1223 MultipleTypeField( 1224 [ 1225 ( 1226 LELongField("value", 0), 1227 lambda pkt: pkt.TokenType in [ 1228 0x01, # signed int8 1229 0x02, # signed int16 1230 0x03, # signed int32 1231 0x04, # signed int64 1232 ] 1233 ), 1234 ( 1235 StrLenFieldUtf16("value", b"", length_from=lambda pkt: pkt.length), 1236 lambda pkt: pkt.TokenType in [ 1237 0x10, # Unicode string 1238 0xf8, 0xf9, 0xfa, 0xfb, # Attribute tokens 1239 ] 1240 ), 1241 ( 1242 StrLenField("value", b"", length_from=lambda pkt: pkt.length), 1243 lambda pkt: pkt.TokenType == 0x18, # Octet string 1244 ), 1245 ( 1246 PacketListField("value", [], WINNT_APPLICATION_DATA_LITERAL_TOKEN, 1247 length_from=lambda pkt: pkt.length), 1248 lambda pkt: pkt.TokenType == 0x50, # Composite 1249 ), 1250 1251 ], 1252 StrFixedLenField("value", b"", length=0), 1253 ), 1254 lambda pkt: pkt.TokenType in [ 1255 0x01, 0x02, 0x03, 0x04, 0x10, 0x18, 0xf8, 0xf9, 0xfa, 0xfb, 0x50 1256 ] 1257 ), 1258 ConditionalField( 1259 # Literal 1260 ByteEnumField("sign", 0, { 1261 0x01: "+", 1262 0x02: "-", 1263 0x03: "None", 1264 }), 1265 lambda pkt: pkt.TokenType in [ 1266 0x01, # signed int8 1267 0x02, # signed int16 1268 0x03, # signed int32 1269 0x04, # signed int64 1270 ] 1271 ), 1272 ConditionalField( 1273 # Literal 1274 ByteEnumField("base", 0, { 1275 0x01: "Octal", 1276 0x02: "Decimal", 1277 0x03: "Hexadecimal", 1278 }), 1279 lambda pkt: pkt.TokenType in [ 1280 0x01, # signed int8 1281 0x02, # signed int16 1282 0x03, # signed int32 1283 0x04, # signed int64 1284 ] 1285 ), 1286] 1287# fmt: on 1288 1289 1290class WINNT_APPLICATION_DATA(Packet): 1291 fields_desc = [ 1292 StrFixedLenField("Magic", b"\x61\x72\x74\x78", length=4), 1293 PacketListField( 1294 "Tokens", 1295 [], 1296 WINNT_APPLICATION_DATA_LITERAL_TOKEN, 1297 ), 1298 ] 1299 1300 def default_payload_class(self, payload): 1301 return conf.padding_layer 1302 1303 1304# [MS-DTYP] sect 2.4.4.6 1305 1306 1307class WINNT_ACCESS_ALLOWED_CALLBACK_ACE(Packet): 1308 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [ 1309 PacketField( 1310 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 1311 ), 1312 ] 1313 1314 1315bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_CALLBACK_ACE, AceType=0x09) 1316 1317 1318# [MS-DTYP] sect 2.4.4.7 1319 1320 1321class WINNT_ACCESS_DENIED_CALLBACK_ACE(Packet): 1322 fields_desc = WINNT_ACCESS_ALLOWED_CALLBACK_ACE.fields_desc 1323 1324 1325bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_CALLBACK_ACE, AceType=0x0A) 1326 1327 1328# [MS-DTYP] sect 2.4.4.8 1329 1330 1331class WINNT_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE(Packet): 1332 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc + [ 1333 PacketField( 1334 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 1335 ), 1336 ] 1337 1338 1339bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE, AceType=0x0B) 1340 1341 1342# [MS-DTYP] sect 2.4.4.9 1343 1344 1345class WINNT_ACCESS_DENIED_CALLBACK_OBJECT_ACE(Packet): 1346 fields_desc = WINNT_ACCESS_DENIED_OBJECT_ACE.fields_desc + [ 1347 PacketField( 1348 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 1349 ), 1350 ] 1351 1352 1353bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_CALLBACK_OBJECT_ACE, AceType=0x0C) 1354 1355 1356# [MS-DTYP] sect 2.4.4.10 1357 1358 1359class WINNT_SYSTEM_AUDIT_ACE(Packet): 1360 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 1361 1362 1363bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_ACE, AceType=0x02) 1364 1365 1366# [MS-DTYP] sect 2.4.4.11 1367 1368 1369class WINNT_SYSTEM_AUDIT_OBJECT_ACE(Packet): 1370 # doc is wrong. 1371 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc 1372 1373 1374bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_OBJECT_ACE, AceType=0x07) 1375 1376 1377# [MS-DTYP] sect 2.4.4.12 1378 1379 1380class WINNT_SYSTEM_AUDIT_CALLBACK_ACE(Packet): 1381 fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc + [ 1382 PacketField( 1383 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 1384 ), 1385 ] 1386 1387 1388bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_CALLBACK_ACE, AceType=0x0D) 1389 1390 1391# [MS-DTYP] sect 2.4.4.13 1392 1393 1394class WINNT_SYSTEM_MANDATORY_LABEL_ACE(Packet): 1395 fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc 1396 1397 1398bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_MANDATORY_LABEL_ACE, AceType=0x11) 1399 1400 1401# [MS-DTYP] sect 2.4.4.14 1402 1403 1404class WINNT_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE(Packet): 1405 fields_desc = WINNT_SYSTEM_AUDIT_OBJECT_ACE.fields_desc 1406 1407 1408bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE, AceType=0x0F) 1409 1410# [MS-DTYP] sect 2.4.10.1 1411 1412 1413class CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(_NTLMPayloadPacket): 1414 _NTLM_PAYLOAD_FIELD_NAME = "Data" 1415 fields_desc = [ 1416 LEIntField("NameOffset", 0), 1417 LEShortEnumField( 1418 "ValueType", 1419 0, 1420 { 1421 0x0001: "CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64", 1422 0x0002: "CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64", 1423 0x0003: "CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING", 1424 0x0005: "CLAIM_SECURITY_ATTRIBUTE_TYPE_SID", 1425 0x0006: "CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN", 1426 0x0010: "CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING", 1427 }, 1428 ), 1429 LEShortField("Reserved", 0), 1430 FlagsField( 1431 "Flags", 1432 0, 1433 -32, 1434 { 1435 0x0001: "CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE", 1436 0x0002: "CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE", 1437 0x0004: "CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY", 1438 0x0008: "CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT", 1439 0x0010: "CLAIM_SECURITY_ATTRIBUTE_DISABLED", 1440 0x0020: "CLAIM_SECURITY_ATTRIBUTE_MANDATORY", 1441 }, 1442 ), 1443 LEIntField("ValueCount", 0), 1444 FieldListField( 1445 "ValueOffsets", [], LEIntField("", 0), count_from=lambda pkt: pkt.ValueCount 1446 ), 1447 _NTLMPayloadField( 1448 "Data", 1449 lambda pkt: 16 + pkt.ValueCount * 4, 1450 [ 1451 ConditionalField( 1452 StrFieldUtf16("Name", b""), 1453 lambda pkt: pkt.NameOffset, 1454 ), 1455 # TODO: Values 1456 ], 1457 offset_name="Offset", 1458 ), 1459 ] 1460 1461 1462# [MS-DTYP] sect 2.4.4.15 1463 1464 1465class WINNT_SYSTEM_RESOURCE_ATTRIBUTE_ACE(Packet): 1466 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [ 1467 PacketField( 1468 "AttributeData", 1469 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(), 1470 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1, 1471 ) 1472 ] 1473 1474 1475bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_RESOURCE_ATTRIBUTE_ACE, AceType=0x12) 1476 1477# [MS-DTYP] sect 2.4.4.16 1478 1479 1480class WINNT_SYSTEM_SCOPED_POLICY_ID_ACE(Packet): 1481 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 1482 1483 1484bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_SCOPED_POLICY_ID_ACE, AceType=0x13) 1485 1486# [MS-DTYP] sect 2.4.5 1487 1488 1489class WINNT_ACL(Packet): 1490 fields_desc = [ 1491 ByteField("AclRevision", 2), 1492 ByteField("Sbz1", 0x00), 1493 FieldLenField( 1494 "AclSize", None, length_of="Aces", adjust=lambda _, x: x + 14, fmt="<H" 1495 ), 1496 FieldLenField("AceCount", None, count_of="Aces", fmt="<H"), 1497 ShortField("Sbz2", 0), 1498 PacketListField( 1499 "Aces", 1500 [], 1501 WINNT_ACE_HEADER, 1502 count_from=lambda pkt: pkt.AceCount, 1503 ), 1504 ] 1505 1506 def toSDDL(self): 1507 return [x.toSDDL() for x in self.Aces] 1508 1509 1510# [MS-DTYP] 2.4.6 SECURITY_DESCRIPTOR 1511 1512 1513class SECURITY_DESCRIPTOR(_NTLMPayloadPacket): 1514 OFFSET = 20 1515 _NTLM_PAYLOAD_FIELD_NAME = "Data" 1516 fields_desc = [ 1517 ByteField("Revision", 0x01), 1518 ByteField("Sbz1", 0x00), 1519 FlagsField( 1520 "Control", 1521 0x00, 1522 -16, 1523 [ 1524 "OWNER_DEFAULTED", 1525 "GROUP_DEFAULTED", 1526 "DACL_PRESENT", 1527 "DACL_DEFAULTED", 1528 "SACL_PRESENT", 1529 "SACL_DEFAULTED", 1530 "DACL_TRUSTED", 1531 "SERVER_SECURITY", 1532 "DACL_COMPUTED", 1533 "SACL_COMPUTED", 1534 "DACL_AUTO_INHERITED", 1535 "SACL_AUTO_INHERITED", 1536 "DACL_PROTECTED", 1537 "SACL_PROTECTED", 1538 "RM_CONTROL_VALID", 1539 "SELF_RELATIVE", 1540 ], 1541 ), 1542 LEIntField("OwnerSidOffset", 0), 1543 LEIntField("GroupSidOffset", 0), 1544 LEIntField("SACLOffset", 0), 1545 LEIntField("DACLOffset", 0), 1546 _NTLMPayloadField( 1547 "Data", 1548 OFFSET, 1549 [ 1550 ConditionalField( 1551 PacketField("OwnerSid", WINNT_SID(), WINNT_SID), 1552 lambda pkt: pkt.OwnerSidOffset, 1553 ), 1554 ConditionalField( 1555 PacketField("GroupSid", WINNT_SID(), WINNT_SID), 1556 lambda pkt: pkt.GroupSidOffset, 1557 ), 1558 ConditionalField( 1559 PacketField("SACL", WINNT_ACL(), WINNT_ACL), 1560 lambda pkt: pkt.Control.SACL_PRESENT, 1561 ), 1562 ConditionalField( 1563 PacketField("DACL", WINNT_ACL(), WINNT_ACL), 1564 lambda pkt: pkt.Control.DACL_PRESENT, 1565 ), 1566 ], 1567 offset_name="Offset", 1568 ), 1569 ] 1570 1571 1572# [MS-FSCC] 2.4.2 FileAllInformation 1573 1574 1575class FileAllInformation(Packet): 1576 fields_desc = [ 1577 PacketField("BasicInformation", FileBasicInformation(), FileBasicInformation), 1578 PacketField( 1579 "StandardInformation", FileStandardInformation(), FileStandardInformation 1580 ), 1581 PacketField( 1582 "InternalInformation", FileInternalInformation(), FileInternalInformation 1583 ), 1584 PacketField("EaInformation", FileEaInformation(), FileEaInformation), 1585 PacketField( 1586 "AccessInformation", FileAccessInformation(), FileAccessInformation 1587 ), 1588 PacketField( 1589 "PositionInformation", FilePositionInformation(), FilePositionInformation 1590 ), 1591 PacketField("ModeInformation", FileModeInformation(), FileModeInformation), 1592 PacketField( 1593 "AlignmentInformation", FileAlignmentInformation(), FileAlignmentInformation 1594 ), 1595 PacketField("NameInformation", FILE_NAME_INFORMATION(), FILE_NAME_INFORMATION), 1596 ] 1597 1598 1599# [MS-FSCC] 2.5.1 FileFsAttributeInformation 1600 1601 1602class FileFsAttributeInformation(Packet): 1603 fields_desc = [ 1604 FlagsField( 1605 "FileSystemAttributes", 1606 0x00C706FF, 1607 -32, 1608 { 1609 0x02000000: "FILE_SUPPORTS_USN_JOURNAL", 1610 0x01000000: "FILE_SUPPORTS_OPEN_BY_FILE_ID", 1611 0x00800000: "FILE_SUPPORTS_EXTENDED_ATTRIBUTES", 1612 0x00400000: "FILE_SUPPORTS_HARD_LINKS", 1613 0x00200000: "FILE_SUPPORTS_TRANSACTIONS", 1614 0x00100000: "FILE_SEQUENTIAL_WRITE_ONCE", 1615 0x00080000: "FILE_READ_ONLY_VOLUME", 1616 0x00040000: "FILE_NAMED_STREAMS", 1617 0x00020000: "FILE_SUPPORTS_ENCRYPTION", 1618 0x00010000: "FILE_SUPPORTS_OBJECT_IDS", 1619 0x00008000: "FILE_VOLUME_IS_COMPRESSED", 1620 0x00000100: "FILE_SUPPORTS_REMOTE_STORAGE", 1621 0x00000080: "FILE_SUPPORTS_REPARSE_POINTS", 1622 0x00000040: "FILE_SUPPORTS_SPARSE_FILES", 1623 0x00000020: "FILE_VOLUME_QUOTAS", 1624 0x00000010: "FILE_FILE_COMPRESSION", 1625 0x00000008: "FILE_PERSISTENT_ACLS", 1626 0x00000004: "FILE_UNICODE_ON_DISK", 1627 0x00000002: "FILE_CASE_PRESERVED_NAMES", 1628 0x00000001: "FILE_CASE_SENSITIVE_SEARCH", 1629 0x04000000: "FILE_SUPPORT_INTEGRITY_STREAMS", 1630 0x08000000: "FILE_SUPPORTS_BLOCK_REFCOUNTING", 1631 0x10000000: "FILE_SUPPORTS_SPARSE_VDL", 1632 }, 1633 ), 1634 LEIntField("MaximumComponentNameLength", 255), 1635 FieldLenField( 1636 "FileSystemNameLength", None, length_of="FileSystemName", fmt="<I" 1637 ), 1638 StrLenFieldUtf16( 1639 "FileSystemName", b"NTFS", length_from=lambda pkt: pkt.FileSystemNameLength 1640 ), 1641 ] 1642 1643 1644# [MS-FSCC] 2.5.8 FileFsSizeInformation 1645 1646 1647class FileFsSizeInformation(Packet): 1648 fields_desc = [ 1649 LELongField("TotalAllocationUnits", 10485760), 1650 LELongField("AvailableAllocationUnits", 1048576), 1651 LEIntField("SectorsPerAllocationUnit", 8), 1652 LEIntField("BytesPerSector", 512), 1653 ] 1654 1655 1656# [MS-FSCC] 2.5.9 FileFsVolumeInformation 1657 1658 1659class FileFsVolumeInformation(Packet): 1660 fields_desc = [ 1661 UTCTimeField( 1662 "VolumeCreationTime", 1663 None, 1664 fmt="<Q", 1665 epoch=[1601, 1, 1, 0, 0, 0], 1666 custom_scaling=1e7, 1667 ), 1668 LEIntField("VolumeSerialNumber", 0), 1669 LEIntField("VolumeLabelLength", 0), 1670 ByteField("SupportsObjects", 1), 1671 ByteField("Reserved", 0), 1672 StrNullFieldUtf16("VolumeLabel", b"C"), 1673 ] 1674 1675 1676# [MS-FSCC] 2.7.1 FILE_NOTIFY_INFORMATION 1677 1678 1679class FILE_NOTIFY_INFORMATION(Packet): 1680 fields_desc = [ 1681 IntField("NextEntryOffset", 0), 1682 LEIntEnumField( 1683 "Action", 1684 0, 1685 { 1686 0x00000001: "FILE_ACTION_ADDED", 1687 0x00000002: "FILE_ACTION_REMOVED", 1688 0x00000003: "FILE_ACTION_MODIFIED", 1689 0x00000004: "FILE_ACTION_RENAMED_OLD_NAME", 1690 0x00000005: "FILE_ACTION_RENAMED_NEW_NAME", 1691 0x00000006: "FILE_ACTION_ADDED_STREAM", 1692 0x00000007: "FILE_ACTION_REMOVED_STREAM", 1693 0x00000008: "FILE_ACTION_MODIFIED_STREAM", 1694 0x00000009: "FILE_ACTION_REMOVED_BY_DELETE", 1695 0x0000000A: "FILE_ACTION_ID_NOT_TUNNELLED", 1696 0x0000000B: "FILE_ACTION_TUNNELLED_ID_COLLISION", 1697 }, 1698 ), 1699 FieldLenField( 1700 "FileNameLength", 1701 None, 1702 length_of="FileName", 1703 fmt="<I", 1704 ), 1705 StrLenFieldUtf16("FileName", b"", length_from=lambda x: x.FileNameLength), 1706 StrLenField( 1707 "pad", 1708 b"", 1709 length_from=lambda x: ( 1710 (x.NextEntryOffset - x.FileNameLength) if x.NextEntryOffset else 0 1711 ), 1712 ), 1713 ] 1714 1715 def default_payload_class(self, s): 1716 return conf.padding_layer 1717 1718 1719_SMB2_CONFIG = [ 1720 ("BufferOffset", _NTLM_ENUM.OFFSET), 1721 ("Len", _NTLM_ENUM.LEN), 1722] 1723 1724 1725def _SMB2_post_build(self, p, pay_offset, fields): 1726 """Util function to build the offset and populate the lengths""" 1727 return _NTLM_post_build(self, p, pay_offset, fields, config=_SMB2_CONFIG) 1728 1729 1730# SMB2 sect 2.1 1731 1732 1733class DirectTCP(NBTSession): 1734 name = "Direct TCP" 1735 MAXLENGTH = 0xFFFFFF 1736 fields_desc = [ByteField("zero", 0), ThreeBytesField("LENGTH", None)] 1737 1738 1739# SMB2 sect 2.2.1.1 1740 1741 1742class SMB2_Header(Packet): 1743 name = "SMB2 Header" 1744 fields_desc = [ 1745 StrFixedLenField("Start", b"\xfeSMB", 4), 1746 LEShortField("StructureSize", 64), 1747 LEShortField("CreditCharge", 0), 1748 LEIntEnumField("Status", 0, STATUS_ERREF), 1749 LEShortEnumField("Command", 0, SMB2_COM), 1750 LEShortField("CreditRequest", 0), 1751 FlagsField( 1752 "Flags", 1753 0, 1754 -32, 1755 { 1756 0x00000001: "SMB2_FLAGS_SERVER_TO_REDIR", 1757 0x00000002: "SMB2_FLAGS_ASYNC_COMMAND", 1758 0x00000004: "SMB2_FLAGS_RELATED_OPERATIONS", 1759 0x00000008: "SMB2_FLAGS_SIGNED", 1760 0x10000000: "SMB2_FLAGS_DFS_OPERATIONS", 1761 0x20000000: "SMB2_FLAGS_REPLAY_OPERATION", 1762 }, 1763 ), 1764 XLEIntField("NextCommand", 0), 1765 LELongField("MID", 0), # MessageID 1766 # ASYNC 1767 ConditionalField( 1768 LELongField("AsyncId", 0), lambda pkt: pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND 1769 ), 1770 # SYNC 1771 ConditionalField( 1772 LEIntField("PID", 0), # Reserved, but PID per wireshark 1773 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND, 1774 ), 1775 ConditionalField( 1776 LEIntField("TID", 0), # TreeID 1777 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND, 1778 ), 1779 # COMMON 1780 LELongField("SessionId", 0), 1781 XStrFixedLenField("SecuritySignature", 0, length=16), 1782 ] 1783 1784 _SMB2_OK_RETURNCODES = ( 1785 # sect 3.3.4.4 1786 (0xC0000016, 0x0001), # STATUS_MORE_PROCESSING_REQUIRED 1787 (0x80000005, 0x0008), # STATUS_BUFFER_OVERFLOW (Read) 1788 (0x80000005, 0x0010), # STATUS_BUFFER_OVERFLOW (QueryInfo) 1789 (0x80000005, 0x000B), # STATUS_BUFFER_OVERFLOW (IOCTL) 1790 (0xC000000D, 0x000B), # STATUS_INVALID_PARAMETER 1791 (0x0000010C, 0x000F), # STATUS_NOTIFY_ENUM_DIR 1792 ) 1793 1794 def guess_payload_class(self, payload): 1795 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR and self.Status != 0x00000000: 1796 # Check status for responses 1797 if (self.Status, self.Command) not in SMB2_Header._SMB2_OK_RETURNCODES: 1798 return SMB2_Error_Response 1799 if self.Command == 0x0000: # Negotiate 1800 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1801 return SMB2_Negotiate_Protocol_Response 1802 return SMB2_Negotiate_Protocol_Request 1803 elif self.Command == 0x0001: # Setup 1804 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1805 return SMB2_Session_Setup_Response 1806 return SMB2_Session_Setup_Request 1807 elif self.Command == 0x0002: # Logoff 1808 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1809 return SMB2_Session_Logoff_Response 1810 return SMB2_Session_Logoff_Request 1811 elif self.Command == 0x0003: # TREE connect 1812 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1813 return SMB2_Tree_Connect_Response 1814 return SMB2_Tree_Connect_Request 1815 elif self.Command == 0x0004: # TREE disconnect 1816 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1817 return SMB2_Tree_Disconnect_Response 1818 return SMB2_Tree_Disconnect_Request 1819 elif self.Command == 0x0005: # Create 1820 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1821 return SMB2_Create_Response 1822 return SMB2_Create_Request 1823 elif self.Command == 0x0006: # Close 1824 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1825 return SMB2_Close_Response 1826 return SMB2_Close_Request 1827 elif self.Command == 0x0008: # Read 1828 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1829 return SMB2_Read_Response 1830 return SMB2_Read_Request 1831 elif self.Command == 0x0009: # Write 1832 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1833 return SMB2_Write_Response 1834 return SMB2_Write_Request 1835 elif self.Command == 0x000C: # Cancel 1836 return SMB2_Cancel_Request 1837 elif self.Command == 0x000D: # Echo 1838 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1839 return SMB2_Echo_Response 1840 return SMB2_Echo_Request 1841 elif self.Command == 0x000E: # Query directory 1842 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1843 return SMB2_Query_Directory_Response 1844 return SMB2_Query_Directory_Request 1845 elif self.Command == 0x000F: # Change Notify 1846 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1847 return SMB2_Change_Notify_Response 1848 return SMB2_Change_Notify_Request 1849 elif self.Command == 0x0010: # Query info 1850 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1851 return SMB2_Query_Info_Response 1852 return SMB2_Query_Info_Request 1853 elif self.Command == 0x0011: # Set info 1854 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1855 return SMB2_Set_Info_Response 1856 return SMB2_Set_Info_Request 1857 elif self.Command == 0x000B: # IOCTL 1858 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 1859 return SMB2_IOCTL_Response 1860 return SMB2_IOCTL_Request 1861 return super(SMB2_Header, self).guess_payload_class(payload) 1862 1863 def sign(self, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None): 1864 # [MS-SMB2] 3.1.4.1 1865 self.SecuritySignature = b"\x00" * 16 1866 s = bytes(self) 1867 if len(s) <= 64: 1868 log_runtime.warning("Cannot sign invalid SMB packet !") 1869 return s 1870 if dialect in [0x0300, 0x0302, 0x0311]: # SMB 3 1871 if dialect == 0x0311: # SMB 3.1.1 1872 if SigningAlgorithmId is None or IsClient is None: 1873 raise Exception("SMB 3.1.1 needs a SigningAlgorithmId and IsClient") 1874 else: 1875 SigningAlgorithmId = "AES-CMAC" # AES-128-CMAC 1876 if "GMAC" in SigningAlgorithmId: 1877 from cryptography.hazmat.primitives.ciphers.aead import AESGCM 1878 1879 aesgcm = AESGCM(SigningSessionKey) 1880 nonce = struct.pack("<Q", self.MID) + struct.pack( 1881 "<I", 1882 (0 if IsClient else 1) | (0x8000000 if self.Command == 9 else 0), 1883 ) 1884 sig = aesgcm.encrypt(nonce, b"", s) 1885 elif "CMAC" in SigningAlgorithmId: 1886 from cryptography.hazmat.primitives import cmac 1887 from cryptography.hazmat.primitives.ciphers import algorithms 1888 1889 c = cmac.CMAC(algorithms.AES(SigningSessionKey)) 1890 c.update(s) 1891 sig = c.finalize() 1892 elif "HMAC" in SigningAlgorithmId: 1893 from scapy.layers.tls.crypto.h_mac import Hmac_SHA256 1894 1895 sig = Hmac_SHA256(SigningSessionKey).digest(s) 1896 sig = sig[:16] 1897 else: 1898 raise ValueError("Unknown SigningAlgorithmId") 1899 elif dialect in [0x0210, 0x0202]: # SMB 2.1 or SMB 2.0.2 1900 from scapy.layers.tls.crypto.h_mac import Hmac_SHA256 1901 1902 sig = Hmac_SHA256(SigningSessionKey).digest(s) 1903 sig = sig[:16] 1904 else: 1905 log_runtime.warning("Unknown SMB Version %s ! Cannot sign." % dialect) 1906 sig = s[:-16] + b"\x00" * 16 1907 self.SecuritySignature = sig 1908 # we make sure the payload is static 1909 self.payload = conf.raw_layer(load=s[64:]) 1910 1911 1912class _SMB2_Payload(Packet): 1913 def do_dissect_payload(self, s): 1914 # There can be padding between this layer and the next one 1915 if self.underlayer and isinstance(self.underlayer, SMB2_Header): 1916 if self.underlayer.NextCommand: 1917 padlen = self.underlayer.NextCommand - (64 + len(self.raw_packet_cache)) 1918 if padlen: 1919 self.add_payload(s[:padlen]) 1920 s = s[padlen:] 1921 super(_SMB2_Payload, self).do_dissect_payload(s) 1922 1923 def answers(self, other): 1924 return ( 1925 isinstance(other, _SMB2_Payload) 1926 and self.__class__ != other.__class__ 1927 and (self.Command == other.Command or self.Command == -1) 1928 ) 1929 1930 def guess_payload_class(self, s): 1931 if self.underlayer and isinstance(self.underlayer, SMB2_Header): 1932 if self.underlayer.NextCommand: 1933 return SMB2_Header 1934 return super(_SMB2_Payload, self).guess_payload_class(s) 1935 1936 1937# sect 2.2.2 1938 1939 1940class SMB2_Error_Response(_SMB2_Payload): 1941 Command = -1 1942 __slots__ = ["NTStatus"] # extra info 1943 name = "SMB2 Error Response" 1944 fields_desc = [ 1945 XLEShortField("StructureSize", 0x09), 1946 ByteField("ErrorContextCount", 0), 1947 ByteField("Reserved", 0), 1948 FieldLenField("ByteCount", None, fmt="<I", length_of="ErrorData"), 1949 XStrLenField("ErrorData", b"", length_from=lambda pkt: pkt.ByteCount), 1950 ] 1951 1952 1953bind_top_down(SMB2_Header, SMB2_Error_Response, Flags=1) # SMB2_FLAGS_SERVER_TO_REDIR 1954 1955# sect 2.2.2.2.2 1956 1957 1958class MOVE_DST_IPADDR(Packet): 1959 fields_desc = [ 1960 # Wireshark appears to get this wrong 1961 LEIntEnumField("Type", 1, {1: "IPv4", 2: "IPv6"}), 1962 IntField("Reserved", 0), 1963 MultipleTypeField( 1964 [(IP6Field("IPAddress", None), lambda pkt: pkt.Type == 2)], 1965 IPField("IPAddress", None), 1966 ), 1967 ConditionalField( 1968 # For IPv4 1969 StrFixedLenField("Reserved2", b"", length=12), 1970 lambda pkt: pkt.Type == 1, 1971 ), 1972 ] 1973 1974 def default_payload_class(self, payload): 1975 return conf.padding_layer 1976 1977 1978class SMB2_Error_Share_Redirect_Context_Response(_NTLMPayloadPacket): 1979 name = "Share Redirect Error Context Response" 1980 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 1981 fields_desc = [ 1982 XLEIntField("StructureSize", 0x30), 1983 LEIntEnumField("NotificationType", 3, {3: "SHARE_MOVE_NOTIFICATION"}), 1984 XLEIntField("ResourceNameBufferOffset", None), 1985 LEIntField("ResourceNameLen", None), 1986 ShortField("Reserved", 0), 1987 ShortEnumField("TargetType", 0, {0: "IP"}), 1988 FieldLenField("IPAddrCount", None, fmt="<I", count_of="IPAddrMoveList"), 1989 PacketListField( 1990 "IPAddrMoveList", 1991 [], 1992 MOVE_DST_IPADDR, 1993 count_from=lambda pkt: pkt.IPAddrCount, 1994 ), 1995 _NTLMPayloadField( 1996 "Buffer", 1997 lambda pkt: 24 + len(pkt.IPAddrMoveList) * 24, 1998 [ 1999 StrLenFieldUtf16( 2000 "ResourceName", b"", length_from=lambda pkt: pkt.ResourceNameLen 2001 ), 2002 ], 2003 ), 2004 ] 2005 2006 def post_build(self, pkt, pay): 2007 # type: (bytes, bytes) -> bytes 2008 return ( 2009 _SMB2_post_build( 2010 self, 2011 pkt, 2012 24 + len(self.IPAddrMoveList) * 24, 2013 { 2014 "ResourceName": 8, 2015 }, 2016 ) 2017 + pay 2018 ) 2019 2020 2021# sect 2.2.2.1 2022 2023 2024class SMB2_Error_ContextResponse(Packet): 2025 fields_desc = [ 2026 FieldLenField("ErrorDatalength", None, fmt="<I", length_of="ErrorContextData"), 2027 LEIntEnumField("ErrorId", 0, {0: "DEFAULT", 0x72645253: "SHARE_REDIRECT"}), 2028 MultipleTypeField( 2029 [ 2030 ( 2031 PacketField( 2032 "ErrorContextData", 2033 SMB2_Error_Share_Redirect_Context_Response(), 2034 SMB2_Error_Share_Redirect_Context_Response, 2035 ), 2036 lambda pkt: pkt.ErrorId == 0x72645253, 2037 ) 2038 ], 2039 XStrLenField( 2040 "ErrorContextData", b"", length_from=lambda pkt: pkt.ErrorDatalength 2041 ), 2042 ), 2043 ] 2044 2045 2046# sect 2.2.3 2047 2048 2049class SMB2_Negotiate_Context(Packet): 2050 name = "SMB2 Negotiate Context" 2051 fields_desc = [ 2052 LEShortEnumField("ContextType", 0x0, SMB2_NEGOTIATE_CONTEXT_TYPES), 2053 LenField("DataLength", None, fmt="<H"), 2054 IntField("Reserved", 0), 2055 ] 2056 2057 def default_payload_class(self, payload): 2058 return conf.padding_layer 2059 2060 2061class SMB2_Negotiate_Protocol_Request(_SMB2_Payload, _NTLMPayloadPacket): 2062 name = "SMB2 Negotiate Protocol Request" 2063 Command = 0x0000 2064 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 2065 fields_desc = [ 2066 XLEShortField("StructureSize", 0x24), 2067 FieldLenField("DialectCount", None, fmt="<H", count_of="Dialects"), 2068 # SecurityMode 2069 FlagsField("SecurityMode", 0, -16, SMB2_SECURITY_MODE), 2070 LEShortField("Reserved", 0), 2071 # Capabilities 2072 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES), 2073 UUIDField("ClientGUID", 0x0, uuid_fmt=UUIDField.FORMAT_LE), 2074 XLEIntField("NegotiateContextsBufferOffset", None), 2075 LEShortField("NegotiateContextsCount", None), 2076 ShortField("Reserved2", 0), 2077 FieldListField( 2078 "Dialects", 2079 [0x0202], 2080 LEShortEnumField("", 0x0, SMB_DIALECTS), 2081 count_from=lambda pkt: pkt.DialectCount, 2082 ), 2083 _NTLMPayloadField( 2084 "Buffer", 2085 lambda pkt: 64 + 36 + len(pkt.Dialects) * 2, 2086 [ 2087 # Field only exists if Dialects contains 0x0311 2088 FieldListField( 2089 "NegotiateContexts", 2090 [], 2091 ReversePadField( 2092 PacketField("Context", None, SMB2_Negotiate_Context), 2093 8, 2094 ), 2095 count_from=lambda pkt: pkt.NegotiateContextsCount, 2096 ), 2097 ], 2098 ), 2099 ] 2100 2101 def post_build(self, pkt, pay): 2102 # type: (bytes, bytes) -> bytes 2103 return ( 2104 _NTLM_post_build( 2105 self, 2106 pkt, 2107 64 + 36 + len(self.Dialects) * 2, 2108 { 2109 "NegotiateContexts": 28, 2110 }, 2111 config=[ 2112 ("BufferOffset", _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8), 2113 ("Count", _NTLM_ENUM.COUNT), 2114 ], 2115 ) 2116 + pay 2117 ) 2118 2119 2120bind_top_down( 2121 SMB2_Header, 2122 SMB2_Negotiate_Protocol_Request, 2123 Command=0x0000, 2124) 2125 2126# sect 2.2.3.1.1 2127 2128 2129class SMB2_Preauth_Integrity_Capabilities(Packet): 2130 name = "SMB2 Preauth Integrity Capabilities" 2131 fields_desc = [ 2132 # According to the spec, this field value must be greater than 0 2133 # (cf Section 2.2.3.1.1 of MS-SMB2.pdf) 2134 FieldLenField("HashAlgorithmCount", None, fmt="<H", count_of="HashAlgorithms"), 2135 FieldLenField("SaltLength", None, fmt="<H", length_of="Salt"), 2136 FieldListField( 2137 "HashAlgorithms", 2138 [0x0001], 2139 LEShortEnumField( 2140 "", 2141 0x0, 2142 { 2143 # As for today, no other hash algorithm is described by the spec 2144 0x0001: "SHA-512", 2145 }, 2146 ), 2147 count_from=lambda pkt: pkt.HashAlgorithmCount, 2148 ), 2149 XStrLenField("Salt", "", length_from=lambda pkt: pkt.SaltLength), 2150 ] 2151 2152 def default_payload_class(self, payload): 2153 return conf.padding_layer 2154 2155 2156bind_layers( 2157 SMB2_Negotiate_Context, SMB2_Preauth_Integrity_Capabilities, ContextType=0x0001 2158) 2159 2160# sect 2.2.3.1.2 2161 2162 2163class SMB2_Encryption_Capabilities(Packet): 2164 name = "SMB2 Encryption Capabilities" 2165 fields_desc = [ 2166 # According to the spec, this field value must be greater than 0 2167 # (cf Section 2.2.3.1.2 of MS-SMB2.pdf) 2168 FieldLenField("CipherCount", None, fmt="<H", count_of="Ciphers"), 2169 FieldListField( 2170 "Ciphers", 2171 [0x0001], 2172 LEShortEnumField( 2173 "", 2174 0x0, 2175 SMB2_ENCRYPTION_CIPHERS, 2176 ), 2177 count_from=lambda pkt: pkt.CipherCount, 2178 ), 2179 ] 2180 2181 def default_payload_class(self, payload): 2182 return conf.padding_layer 2183 2184 2185bind_layers(SMB2_Negotiate_Context, SMB2_Encryption_Capabilities, ContextType=0x0002) 2186 2187# sect 2.2.3.1.3 2188 2189 2190class SMB2_Compression_Capabilities(Packet): 2191 name = "SMB2 Compression Capabilities" 2192 fields_desc = [ 2193 FieldLenField( 2194 "CompressionAlgorithmCount", 2195 None, 2196 fmt="<H", 2197 count_of="CompressionAlgorithms", 2198 ), 2199 ShortField("Padding", 0x0), 2200 LEIntEnumField( 2201 "Flags", 2202 0x0, 2203 { 2204 0x00000000: "SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE", 2205 0x00000001: "SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED", 2206 }, 2207 ), 2208 FieldListField( 2209 "CompressionAlgorithms", 2210 None, 2211 LEShortEnumField("", 0x0, SMB2_COMPRESSION_ALGORITHMS), 2212 count_from=lambda pkt: pkt.CompressionAlgorithmCount, 2213 ), 2214 ] 2215 2216 def default_payload_class(self, payload): 2217 return conf.padding_layer 2218 2219 2220bind_layers(SMB2_Negotiate_Context, SMB2_Compression_Capabilities, ContextType=0x0003) 2221 2222# sect 2.2.3.1.4 2223 2224 2225class SMB2_Netname_Negotiate_Context_ID(Packet): 2226 name = "SMB2 Netname Negotiate Context ID" 2227 fields_desc = [StrFieldUtf16("NetName", "")] 2228 2229 def default_payload_class(self, payload): 2230 return conf.padding_layer 2231 2232 2233bind_layers( 2234 SMB2_Negotiate_Context, SMB2_Netname_Negotiate_Context_ID, ContextType=0x0005 2235) 2236 2237# sect 2.2.3.1.5 2238 2239 2240class SMB2_Transport_Capabilities(Packet): 2241 name = "SMB2 Transport Capabilities" 2242 fields_desc = [ 2243 FlagsField( 2244 "Flags", 2245 0x0, 2246 -32, 2247 { 2248 0x00000001: "SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY", 2249 }, 2250 ), 2251 ] 2252 2253 def default_payload_class(self, payload): 2254 return conf.padding_layer 2255 2256 2257bind_layers(SMB2_Negotiate_Context, SMB2_Transport_Capabilities, ContextType=0x0006) 2258 2259# sect 2.2.3.1.6 2260 2261 2262class SMB2_RDMA_Transform_Capabilities(Packet): 2263 name = "SMB2 RDMA Transform Capabilities" 2264 fields_desc = [ 2265 FieldLenField("TransformCount", None, fmt="<H", count_of="RDMATransformIds"), 2266 LEShortField("Reserved1", 0), 2267 LEIntField("Reserved2", 0), 2268 FieldListField( 2269 "RDMATransformIds", 2270 None, 2271 LEShortEnumField( 2272 "", 2273 0x0, 2274 { 2275 0x0000: "SMB2_RDMA_TRANSFORM_NONE", 2276 0x0001: "SMB2_RDMA_TRANSFORM_ENCRYPTION", 2277 0x0002: "SMB2_RDMA_TRANSFORM_SIGNING", 2278 }, 2279 ), 2280 count_from=lambda pkt: pkt.TransformCount, 2281 ), 2282 ] 2283 2284 def default_payload_class(self, payload): 2285 return conf.padding_layer 2286 2287 2288bind_layers( 2289 SMB2_Negotiate_Context, SMB2_RDMA_Transform_Capabilities, ContextType=0x0007 2290) 2291 2292# sect 2.2.3.1.7 2293 2294 2295class SMB2_Signing_Capabilities(Packet): 2296 name = "SMB2 Signing Capabilities" 2297 fields_desc = [ 2298 FieldLenField( 2299 "SigningAlgorithmCount", None, fmt="<H", count_of="SigningAlgorithms" 2300 ), 2301 FieldListField( 2302 "SigningAlgorithms", 2303 None, 2304 LEShortEnumField( 2305 "", 2306 0x0, 2307 SMB2_SIGNING_ALGORITHMS, 2308 ), 2309 count_from=lambda pkt: pkt.SigningAlgorithmCount, 2310 ), 2311 ] 2312 2313 def default_payload_class(self, payload): 2314 return conf.padding_layer 2315 2316 2317bind_layers(SMB2_Negotiate_Context, SMB2_Signing_Capabilities, ContextType=0x0008) 2318 2319# sect 2.2.4 2320 2321 2322class SMB2_Negotiate_Protocol_Response(_SMB2_Payload, _NTLMPayloadPacket): 2323 name = "SMB2 Negotiate Protocol Response" 2324 Command = 0x0000 2325 OFFSET = 64 + 64 2326 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 2327 fields_desc = [ 2328 XLEShortField("StructureSize", 0x41), 2329 FlagsField("SecurityMode", 0, -16, SMB2_SECURITY_MODE), 2330 LEShortEnumField("DialectRevision", 0x0, SMB_DIALECTS), 2331 LEShortField("NegotiateContextsCount", None), 2332 UUIDField("GUID", 0x0, uuid_fmt=UUIDField.FORMAT_LE), 2333 # Capabilities 2334 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES), 2335 LEIntField("MaxTransactionSize", 65536), 2336 LEIntField("MaxReadSize", 65536), 2337 LEIntField("MaxWriteSize", 65536), 2338 UTCTimeField( 2339 "ServerTime", 2340 None, 2341 fmt="<Q", 2342 epoch=[1601, 1, 1, 0, 0, 0], 2343 custom_scaling=1e7, 2344 ), 2345 UTCTimeField( 2346 "ServerStartTime", 2347 None, 2348 fmt="<Q", 2349 epoch=[1601, 1, 1, 0, 0, 0], 2350 custom_scaling=1e7, 2351 ), 2352 XLEShortField("SecurityBlobBufferOffset", None), 2353 LEShortField("SecurityBlobLen", None), 2354 XLEIntField("NegotiateContextsBufferOffset", None), 2355 _NTLMPayloadField( 2356 "Buffer", 2357 OFFSET, 2358 [ 2359 PacketLenField( 2360 "SecurityBlob", 2361 None, 2362 GSSAPI_BLOB, 2363 length_from=lambda x: x.SecurityBlobLen, 2364 ), 2365 # Field only exists if Dialect is 0x0311 2366 FieldListField( 2367 "NegotiateContexts", 2368 [], 2369 ReversePadField( 2370 PacketField("Context", None, SMB2_Negotiate_Context), 2371 8, 2372 ), 2373 count_from=lambda pkt: pkt.NegotiateContextsCount, 2374 ), 2375 ], 2376 force_order=["SecurityBlob", "NegotiateContexts"], 2377 ), 2378 ] 2379 2380 def post_build(self, pkt, pay): 2381 # type: (bytes, bytes) -> bytes 2382 pkt = _NTLM_post_build( 2383 self, 2384 pkt, 2385 self.OFFSET, 2386 { 2387 "SecurityBlob": 56, 2388 "NegotiateContexts": 60, 2389 }, 2390 config=[ 2391 ( 2392 "BufferOffset", 2393 { 2394 "SecurityBlob": _NTLM_ENUM.OFFSET, 2395 "NegotiateContexts": _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8, 2396 }, 2397 ), 2398 ], 2399 ) 2400 if getattr(self, "SecurityBlob", None): 2401 if self.SecurityBlobLen is None: 2402 pkt = pkt[:58] + struct.pack("<H", len(self.SecurityBlob)) + pkt[60:] 2403 if getattr(self, "NegotiateContexts", None): 2404 if self.NegotiateContextsCount is None: 2405 pkt = pkt[:6] + struct.pack("<H", len(self.NegotiateContexts)) + pkt[8:] 2406 return pkt + pay 2407 2408 2409bind_top_down( 2410 SMB2_Header, 2411 SMB2_Negotiate_Protocol_Response, 2412 Command=0x0000, 2413 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 2414) 2415 2416# sect 2.2.5 2417 2418 2419class SMB2_Session_Setup_Request(_SMB2_Payload, _NTLMPayloadPacket): 2420 name = "SMB2 Session Setup Request" 2421 Command = 0x0001 2422 OFFSET = 24 + 64 2423 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 2424 fields_desc = [ 2425 XLEShortField("StructureSize", 0x19), 2426 FlagsField("Flags", 0, -8, ["SMB2_SESSION_FLAG_BINDING"]), 2427 FlagsField("SecurityMode", 0, -8, SMB2_SECURITY_MODE), 2428 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES), 2429 LEIntField("Channel", 0), 2430 XLEShortField("SecurityBlobBufferOffset", None), 2431 LEShortField("SecurityBlobLen", None), 2432 XLELongField("PreviousSessionId", 0), 2433 _NTLMPayloadField( 2434 "Buffer", 2435 OFFSET, 2436 [ 2437 PacketField("SecurityBlob", None, GSSAPI_BLOB), 2438 ], 2439 ), 2440 ] 2441 2442 def post_build(self, pkt, pay): 2443 # type: (bytes, bytes) -> bytes 2444 return ( 2445 _SMB2_post_build( 2446 self, 2447 pkt, 2448 self.OFFSET, 2449 { 2450 "SecurityBlob": 12, 2451 }, 2452 ) 2453 + pay 2454 ) 2455 2456 2457bind_top_down( 2458 SMB2_Header, 2459 SMB2_Session_Setup_Request, 2460 Command=0x0001, 2461) 2462 2463# sect 2.2.6 2464 2465 2466class SMB2_Session_Setup_Response(_SMB2_Payload, _NTLMPayloadPacket): 2467 name = "SMB2 Session Setup Response" 2468 Command = 0x0001 2469 OFFSET = 8 + 64 2470 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 2471 fields_desc = [ 2472 XLEShortField("StructureSize", 0x9), 2473 FlagsField( 2474 "SessionFlags", 2475 0, 2476 -16, 2477 { 2478 0x0001: "IS_GUEST", 2479 0x0002: "IS_NULL", 2480 0x0004: "ENCRYPT_DATE", 2481 }, 2482 ), 2483 XLEShortField("SecurityBufferOffset", None), 2484 LEShortField("SecurityLen", None), 2485 _NTLMPayloadField( 2486 "Buffer", 2487 OFFSET, 2488 [ 2489 PacketField("Security", None, GSSAPI_BLOB), 2490 ], 2491 ), 2492 ] 2493 2494 def __getattr__(self, attr): 2495 # Ease SMB1 backward compatibility 2496 if attr == "SecurityBlob": 2497 return ( 2498 super(SMB2_Session_Setup_Response, self).__getattr__("Buffer") 2499 or [(None, None)] 2500 )[0][1] 2501 return super(SMB2_Session_Setup_Response, self).__getattr__(attr) 2502 2503 def setfieldval(self, attr, val): 2504 if attr == "SecurityBlob": 2505 return super(SMB2_Session_Setup_Response, self).setfieldval( 2506 "Buffer", [("Security", val)] 2507 ) 2508 return super(SMB2_Session_Setup_Response, self).setfieldval(attr, val) 2509 2510 def post_build(self, pkt, pay): 2511 # type: (bytes, bytes) -> bytes 2512 return ( 2513 _SMB2_post_build( 2514 self, 2515 pkt, 2516 self.OFFSET, 2517 { 2518 "Security": 4, 2519 }, 2520 ) 2521 + pay 2522 ) 2523 2524 2525bind_top_down( 2526 SMB2_Header, 2527 SMB2_Session_Setup_Response, 2528 Command=0x0001, 2529 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 2530) 2531 2532# sect 2.2.7 2533 2534 2535class SMB2_Session_Logoff_Request(_SMB2_Payload): 2536 name = "SMB2 LOGOFF Request" 2537 Command = 0x0002 2538 fields_desc = [ 2539 XLEShortField("StructureSize", 0x4), 2540 ShortField("reserved", 0), 2541 ] 2542 2543 2544bind_top_down( 2545 SMB2_Header, 2546 SMB2_Session_Logoff_Request, 2547 Command=0x0002, 2548) 2549 2550# sect 2.2.8 2551 2552 2553class SMB2_Session_Logoff_Response(_SMB2_Payload): 2554 name = "SMB2 LOGOFF Request" 2555 Command = 0x0002 2556 fields_desc = [ 2557 XLEShortField("StructureSize", 0x4), 2558 ShortField("reserved", 0), 2559 ] 2560 2561 2562bind_top_down( 2563 SMB2_Header, 2564 SMB2_Session_Logoff_Response, 2565 Command=0x0002, 2566 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 2567) 2568 2569# sect 2.2.9 2570 2571 2572class SMB2_Tree_Connect_Request(_SMB2_Payload, _NTLMPayloadPacket): 2573 name = "SMB2 TREE_CONNECT Request" 2574 Command = 0x0003 2575 OFFSET = 8 + 64 2576 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 2577 fields_desc = [ 2578 XLEShortField("StructureSize", 0x9), 2579 FlagsField( 2580 "Flags", 2581 0, 2582 -16, 2583 ["CLUSTER_RECONNECT", "REDIRECT_TO_OWNER", "EXTENSION_PRESENT"], 2584 ), 2585 XLEShortField("PathBufferOffset", None), 2586 LEShortField("PathLen", None), 2587 _NTLMPayloadField( 2588 "Buffer", 2589 OFFSET, 2590 [ 2591 StrFieldUtf16("Path", b""), 2592 ], 2593 ), 2594 ] 2595 2596 def post_build(self, pkt, pay): 2597 # type: (bytes, bytes) -> bytes 2598 return ( 2599 _SMB2_post_build( 2600 self, 2601 pkt, 2602 self.OFFSET, 2603 { 2604 "Path": 4, 2605 }, 2606 ) 2607 + pay 2608 ) 2609 2610 2611bind_top_down( 2612 SMB2_Header, 2613 SMB2_Tree_Connect_Request, 2614 Command=0x0003, 2615) 2616 2617# sect 2.2.10 2618 2619 2620class SMB2_Tree_Connect_Response(_SMB2_Payload): 2621 name = "SMB2 TREE_CONNECT Response" 2622 Command = 0x0003 2623 fields_desc = [ 2624 XLEShortField("StructureSize", 0x10), 2625 ByteEnumField("ShareType", 0, {0x01: "DISK", 0x02: "PIPE", 0x03: "PRINT"}), 2626 ByteField("Reserved", 0), 2627 FlagsField( 2628 "ShareFlags", 2629 0x30, 2630 -32, 2631 { 2632 0x00000010: "AUTO_CACHING", 2633 0x00000020: "VDO_CACHING", 2634 0x00000030: "NO_CACHING", 2635 0x00000001: "DFS", 2636 0x00000002: "DFS_ROOT", 2637 0x00000100: "RESTRICT_EXCLUSIVE_OPENS", 2638 0x00000200: "FORCE_SHARED_DELETE", 2639 0x00000400: "ALLOW_NAMESPACE_CACHING", 2640 0x00000800: "ACCESS_BASED_DIRECTORY_ENUM", 2641 0x00001000: "FORCE_LEVELII_OPLOCK", 2642 0x00002000: "ENABLE_HASH_V1", 2643 0x00004000: "ENABLE_HASH_V2", 2644 0x00008000: "ENCRYPT_DATA", 2645 0x00040000: "IDENTITY_REMOTING", 2646 0x00100000: "COMPRESS_DATA", 2647 }, 2648 ), 2649 FlagsField( 2650 "Capabilities", 2651 0, 2652 -32, 2653 { 2654 0x00000008: "DFS", 2655 0x00000010: "CONTINUOUS_AVAILABILITY", 2656 0x00000020: "SCALEOUT", 2657 0x00000040: "CLUSTER", 2658 0x00000080: "ASYMMETRIC", 2659 0x00000100: "REDIRECT_TO_OWNER", 2660 }, 2661 ), 2662 FlagsField("MaximalAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE), 2663 ] 2664 2665 2666bind_top_down(SMB2_Header, SMB2_Tree_Connect_Response, Command=0x0003, Flags=1) 2667 2668# sect 2.2.11 2669 2670 2671class SMB2_Tree_Disconnect_Request(_SMB2_Payload): 2672 name = "SMB2 TREE_DISCONNECT Request" 2673 Command = 0x0004 2674 fields_desc = [ 2675 XLEShortField("StructureSize", 0x4), 2676 XLEShortField("Reserved", 0), 2677 ] 2678 2679 2680bind_top_down(SMB2_Header, SMB2_Tree_Disconnect_Request, Command=0x0004) 2681 2682# sect 2.2.12 2683 2684 2685class SMB2_Tree_Disconnect_Response(_SMB2_Payload): 2686 name = "SMB2 TREE_DISCONNECT Response" 2687 Command = 0x0004 2688 fields_desc = [ 2689 XLEShortField("StructureSize", 0x4), 2690 XLEShortField("Reserved", 0), 2691 ] 2692 2693 2694bind_top_down(SMB2_Header, SMB2_Tree_Disconnect_Response, Command=0x0004, Flags=1) 2695 2696 2697# sect 2.2.14.1 2698 2699 2700class SMB2_FILEID(Packet): 2701 fields_desc = [XLELongField("Persistent", 0), XLELongField("Volatile", 0)] 2702 2703 def __hash__(self): 2704 return self.Persistent + self.Volatile << 64 2705 2706 def default_payload_class(self, payload): 2707 return conf.padding_layer 2708 2709 2710# sect 2.2.14.2 2711 2712 2713class SMB2_CREATE_DURABLE_HANDLE_RESPONSE(Packet): 2714 fields_desc = [ 2715 XStrFixedLenField("Reserved", b"\x00" * 8, length=8), 2716 ] 2717 2718 2719class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE(Packet): 2720 fields_desc = [ 2721 LEIntEnumField("QueryStatus", 0, STATUS_ERREF), 2722 FlagsField("MaximalAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE), 2723 ] 2724 2725 2726class SMB2_CREATE_QUERY_ON_DISK_ID(Packet): 2727 fields_desc = [ 2728 XLELongField("DiskFileId", 0), 2729 XLELongField("VolumeId", 0), 2730 XStrFixedLenField("Reserved", b"", length=16), 2731 ] 2732 2733 2734class SMB2_CREATE_RESPONSE_LEASE(Packet): 2735 fields_desc = [ 2736 UUIDField("LeaseKey", None), 2737 FlagsField( 2738 "LeaseState", 2739 0x7, 2740 -32, 2741 { 2742 0x01: "SMB2_LEASE_READ_CACHING", 2743 0x02: "SMB2_LEASE_HANDLE_CACHING", 2744 0x04: "SMB2_LEASE_WRITE_CACHING", 2745 }, 2746 ), 2747 FlagsField( 2748 "LeaseFlags", 2749 0, 2750 -32, 2751 { 2752 0x02: "SMB2_LEASE_FLAG_BREAK_IN_PROGRESS", 2753 0x04: "SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET", 2754 }, 2755 ), 2756 LELongField("LeaseDuration", 0), 2757 ] 2758 2759 2760class SMB2_CREATE_RESPONSE_LEASE_V2(Packet): 2761 fields_desc = [ 2762 SMB2_CREATE_RESPONSE_LEASE, 2763 UUIDField("ParentLeaseKey", None), 2764 LEShortField("Epoch", 0), 2765 LEShortField("Reserved", 0), 2766 ] 2767 2768 2769class SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2(Packet): 2770 fields_desc = [ 2771 LEIntField("Timeout", 0), 2772 FlagsField( 2773 "Flags", 2774 0, 2775 -32, 2776 { 2777 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT", 2778 }, 2779 ), 2780 ] 2781 2782 2783# sect 2.2.13 2784 2785 2786class SMB2_CREATE_DURABLE_HANDLE_REQUEST(Packet): 2787 fields_desc = [ 2788 XStrFixedLenField("DurableRequest", b"", length=16), 2789 ] 2790 2791 2792class SMB2_CREATE_DURABLE_HANDLE_RECONNECT(Packet): 2793 fields_desc = [ 2794 PacketField("Data", SMB2_FILEID(), SMB2_FILEID), 2795 ] 2796 2797 2798class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST(Packet): 2799 fields_desc = [ 2800 LELongField("Timestamp", 0), 2801 ] 2802 2803 2804class SMB2_CREATE_ALLOCATION_SIZE(Packet): 2805 fields_desc = [ 2806 LELongField("AllocationSize", 0), 2807 ] 2808 2809 2810class SMB2_CREATE_TIMEWARP_TOKEN(Packet): 2811 fields_desc = [ 2812 LELongField("Timestamp", 0), 2813 ] 2814 2815 2816class SMB2_CREATE_REQUEST_LEASE(Packet): 2817 fields_desc = [ 2818 SMB2_CREATE_RESPONSE_LEASE, 2819 ] 2820 2821 2822class SMB2_CREATE_REQUEST_LEASE_V2(Packet): 2823 fields_desc = [ 2824 SMB2_CREATE_RESPONSE_LEASE_V2, 2825 ] 2826 2827 2828class SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2(Packet): 2829 fields_desc = [ 2830 SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2, 2831 XStrFixedLenField("Reserved", b"", length=8), 2832 UUIDField("CreateGuid", 0x0, uuid_fmt=UUIDField.FORMAT_LE), 2833 ] 2834 2835 2836class SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2(Packet): 2837 fields_desc = [ 2838 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 2839 UUIDField("CreateGuid", 0x0, uuid_fmt=UUIDField.FORMAT_LE), 2840 FlagsField( 2841 "Flags", 2842 0, 2843 -32, 2844 { 2845 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT", 2846 }, 2847 ), 2848 ] 2849 2850 2851class SMB2_CREATE_APP_INSTANCE_ID(Packet): 2852 fields_desc = [ 2853 XLEShortField("StructureSize", 0x14), 2854 LEShortField("Reserved", 0), 2855 XStrFixedLenField("AppInstanceId", b"", length=16), 2856 ] 2857 2858 2859class SMB2_CREATE_APP_INSTANCE_VERSION(Packet): 2860 fields_desc = [ 2861 XLEShortField("StructureSize", 0x18), 2862 LEShortField("Reserved", 0), 2863 LEIntField("Padding", 0), 2864 LELongField("AppInstanceVersionHigh", 0), 2865 LELongField("AppInstanceVersionLow", 0), 2866 ] 2867 2868 2869class SMB2_Create_Context(_NTLMPayloadPacket): 2870 name = "SMB2 CREATE CONTEXT" 2871 OFFSET = 16 2872 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 2873 fields_desc = [ 2874 LEIntField("Next", None), 2875 XLEShortField("NameBufferOffset", None), 2876 LEShortField("NameLen", None), 2877 ShortField("Reserved", 0), 2878 XLEShortField("DataBufferOffset", None), 2879 LEIntField("DataLen", None), 2880 _NTLMPayloadField( 2881 "Buffer", 2882 OFFSET, 2883 [ 2884 PadField( 2885 StrLenField("Name", b"", length_from=lambda pkt: pkt.NameLen), 2886 8, 2887 ), 2888 # Must be padded on 8-octet alignment 2889 PacketLenField( 2890 "Data", None, conf.raw_layer, length_from=lambda pkt: pkt.DataLen 2891 ), 2892 ], 2893 force_order=["Name", "Data"], 2894 ), 2895 StrLenField( 2896 "pad", 2897 b"", 2898 length_from=lambda x: ( 2899 x.Next 2900 - max(x.DataBufferOffset + x.DataLen, x.NameBufferOffset + x.NameLen) 2901 ) 2902 if x.Next 2903 else 0, 2904 ), 2905 ] 2906 2907 def post_dissect(self, s): 2908 if not self.DataLen: 2909 return s 2910 try: 2911 if isinstance(self.parent, SMB2_Create_Request): 2912 data_cls = { 2913 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_REQUEST, 2914 b"DHnC": SMB2_CREATE_DURABLE_HANDLE_RECONNECT, 2915 b"AISi": SMB2_CREATE_ALLOCATION_SIZE, 2916 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 2917 b"TWrp": SMB2_CREATE_TIMEWARP_TOKEN, 2918 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID, 2919 b"RqLs": SMB2_CREATE_REQUEST_LEASE, 2920 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, 2921 b"DH2C": SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, 2922 # 3.1.1 only 2923 b"E\xbc\xa6j\xef\xa7\xf7J\x90\x08\xfaF.\x14Mt": SMB2_CREATE_APP_INSTANCE_ID, # noqa: E501 2924 b"\xb9\x82\xd0\xb7;V\x07O\xa0{RJ\x81\x16\xa0\x10": SMB2_CREATE_APP_INSTANCE_VERSION, # noqa: E501 2925 }[self.Name] 2926 if self.Name == b"RqLs" and self.DataLen > 32: 2927 data_cls = SMB2_CREATE_REQUEST_LEASE_V2 2928 elif isinstance(self.parent, SMB2_Create_Response): 2929 data_cls = { 2930 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_RESPONSE, 2931 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE, 2932 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID, 2933 b"RqLs": SMB2_CREATE_RESPONSE_LEASE, 2934 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2, 2935 }[self.Name] 2936 if self.Name == b"RqLs" and self.DataLen > 32: 2937 data_cls = SMB2_CREATE_RESPONSE_LEASE_V2 2938 else: 2939 return s 2940 except KeyError: 2941 return s 2942 self.Data = data_cls(self.Data.load) 2943 return s 2944 2945 def default_payload_class(self, _): 2946 return conf.padding_layer 2947 2948 def post_build(self, pkt, pay): 2949 # type: (bytes, bytes) -> bytes 2950 return ( 2951 _NTLM_post_build( 2952 self, 2953 pkt, 2954 self.OFFSET, 2955 { 2956 "Name": 4, 2957 "Data": 10, 2958 }, 2959 config=[ 2960 ( 2961 "BufferOffset", 2962 { 2963 "Name": _NTLM_ENUM.OFFSET, 2964 "Data": _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8, 2965 }, 2966 ), 2967 ("Len", _NTLM_ENUM.LEN), 2968 ], 2969 ) 2970 + pay 2971 ) 2972 2973 2974# sect 2.2.13 2975 2976SMB2_OPLOCK_LEVELS = { 2977 0x00: "SMB2_OPLOCK_LEVEL_NONE", 2978 0x01: "SMB2_OPLOCK_LEVEL_II", 2979 0x08: "SMB2_OPLOCK_LEVEL_EXCLUSIVE", 2980 0x09: "SMB2_OPLOCK_LEVEL_BATCH", 2981 0xFF: "SMB2_OPLOCK_LEVEL_LEASE", 2982} 2983 2984 2985class SMB2_Create_Request(_SMB2_Payload, _NTLMPayloadPacket): 2986 name = "SMB2 CREATE Request" 2987 Command = 0x0005 2988 OFFSET = 56 + 64 2989 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 2990 fields_desc = [ 2991 XLEShortField("StructureSize", 0x39), 2992 ByteField("ShareType", 0), 2993 ByteEnumField("RequestedOplockLevel", 0, SMB2_OPLOCK_LEVELS), 2994 LEIntEnumField( 2995 "ImpersonationLevel", 2996 0, 2997 { 2998 0x00000000: "Anonymous", 2999 0x00000001: "Identification", 3000 0x00000002: "Impersonation", 3001 0x00000003: "Delegate", 3002 }, 3003 ), 3004 LELongField("SmbCreateFlags", 0), 3005 LELongField("Reserved", 0), 3006 FlagsField("DesiredAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE), 3007 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes), 3008 FlagsField( 3009 "ShareAccess", 3010 0, 3011 -32, 3012 { 3013 0x00000001: "FILE_SHARE_READ", 3014 0x00000002: "FILE_SHARE_WRITE", 3015 0x00000004: "FILE_SHARE_DELETE", 3016 }, 3017 ), 3018 LEIntEnumField( 3019 "CreateDisposition", 3020 1, 3021 { 3022 0x00000000: "FILE_SUPERSEDE", 3023 0x00000001: "FILE_OPEN", 3024 0x00000002: "FILE_CREATE", 3025 0x00000003: "FILE_OPEN_IF", 3026 0x00000004: "FILE_OVERWRITE", 3027 0x00000005: "FILE_OVERWRITE_IF", 3028 }, 3029 ), 3030 FlagsField( 3031 "CreateOptions", 3032 0, 3033 -32, 3034 { 3035 0x00000001: "FILE_DIRECTORY_FILE", 3036 0x00000002: "FILE_WRITE_THROUGH", 3037 0x00000004: "FILE_SEQUENTIAL_ONLY", 3038 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING", 3039 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT", 3040 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT", 3041 0x00000040: "FILE_NON_DIRECTORY_FILE", 3042 0x00000100: "FILE_COMPLETE_IF_OPLOCKED", 3043 0x00000200: "FILE_RANDOM_ACCESS", 3044 0x00001000: "FILE_DELETE_ON_CLOSE", 3045 0x00002000: "FILE_OPEN_BY_FILE_ID", 3046 0x00004000: "FILE_OPEN_FOR_BACKUP_INTENT", 3047 0x00008000: "FILE_NO_COMPRESSION", 3048 0x00000400: "FILE_OPEN_REMOTE_INSTANCE", 3049 0x00010000: "FILE_OPEN_REQUIRING_OPLOCK", 3050 0x00020000: "FILE_DISALLOW_EXCLUSIVE", 3051 0x00100000: "FILE_RESERVE_OPFILTER", 3052 0x00200000: "FILE_OPEN_REPARSE_POINT", 3053 0x00400000: "FILE_OPEN_NO_RECALL", 3054 0x00800000: "FILE_OPEN_FOR_FREE_SPACE_QUERY", 3055 }, 3056 ), 3057 XLEShortField("NameBufferOffset", None), 3058 LEShortField("NameLen", None), 3059 XLEIntField("CreateContextsBufferOffset", None), 3060 LEIntField("CreateContextsLen", None), 3061 _NTLMPayloadField( 3062 "Buffer", 3063 OFFSET, 3064 [ 3065 StrFieldUtf16("Name", b""), 3066 _NextPacketListField( 3067 "CreateContexts", 3068 [], 3069 SMB2_Create_Context, 3070 length_from=lambda pkt: pkt.CreateContextsLen, 3071 ), 3072 ], 3073 ), 3074 ] 3075 3076 def post_build(self, pkt, pay): 3077 # type: (bytes, bytes) -> bytes 3078 if len(pkt) == 0x38: 3079 # 'In the request, the Buffer field MUST be at least one byte in length.' 3080 pkt += b"\x00" 3081 return ( 3082 _SMB2_post_build( 3083 self, 3084 pkt, 3085 self.OFFSET, 3086 { 3087 "Name": 44, 3088 "CreateContexts": 48, 3089 }, 3090 ) 3091 + pay 3092 ) 3093 3094 3095bind_top_down(SMB2_Header, SMB2_Create_Request, Command=0x0005) 3096 3097 3098# sect 2.2.14 3099 3100 3101class SMB2_Create_Response(_SMB2_Payload, _NTLMPayloadPacket): 3102 name = "SMB2 CREATE Response" 3103 Command = 0x0005 3104 OFFSET = 88 + 64 3105 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3106 fields_desc = [ 3107 XLEShortField("StructureSize", 0x59), 3108 ByteEnumField("OplockLevel", 0, SMB2_OPLOCK_LEVELS), 3109 FlagsField("Flags", 0, -8, {0x01: "SMB2_CREATE_FLAG_REPARSEPOINT"}), 3110 LEIntEnumField( 3111 "CreateAction", 3112 1, 3113 { 3114 0x00000000: "FILE_SUPERSEDED", 3115 0x00000001: "FILE_OPENED", 3116 0x00000002: "FILE_CREATED", 3117 0x00000003: "FILE_OVERWRITEN", 3118 }, 3119 ), 3120 FileNetworkOpenInformation, 3121 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 3122 XLEIntField("CreateContextsBufferOffset", None), 3123 LEIntField("CreateContextsLen", None), 3124 _NTLMPayloadField( 3125 "Buffer", 3126 OFFSET, 3127 [ 3128 _NextPacketListField( 3129 "CreateContexts", 3130 [], 3131 SMB2_Create_Context, 3132 length_from=lambda pkt: pkt.CreateContextsLen, 3133 ), 3134 ], 3135 ), 3136 ] 3137 3138 def post_build(self, pkt, pay): 3139 # type: (bytes, bytes) -> bytes 3140 return ( 3141 _SMB2_post_build( 3142 self, 3143 pkt, 3144 self.OFFSET, 3145 { 3146 "CreateContexts": 80, 3147 }, 3148 ) 3149 + pay 3150 ) 3151 3152 3153bind_top_down(SMB2_Header, SMB2_Create_Response, Command=0x0005, Flags=1) 3154 3155# sect 2.2.15 3156 3157 3158class SMB2_Close_Request(_SMB2_Payload): 3159 name = "SMB2 CLOSE Request" 3160 Command = 0x0006 3161 fields_desc = [ 3162 XLEShortField("StructureSize", 0x18), 3163 FlagsField("Flags", 0, -16, ["SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB"]), 3164 LEIntField("Reserved", 0), 3165 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 3166 ] 3167 3168 3169bind_top_down( 3170 SMB2_Header, 3171 SMB2_Close_Request, 3172 Command=0x0006, 3173) 3174 3175# sect 2.2.16 3176 3177 3178class SMB2_Close_Response(_SMB2_Payload): 3179 name = "SMB2 CLOSE Response" 3180 Command = 0x0006 3181 FileAttributes = 0 3182 CreationTime = 0 3183 LastAccessTime = 0 3184 LastWriteTime = 0 3185 ChangeTime = 0 3186 fields_desc = [ 3187 XLEShortField("StructureSize", 0x3C), 3188 FlagsField("Flags", 0, -16, ["SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB"]), 3189 LEIntField("Reserved", 0), 3190 ] + FileNetworkOpenInformation.fields_desc[:7] 3191 3192 3193bind_top_down( 3194 SMB2_Header, 3195 SMB2_Close_Response, 3196 Command=0x0006, 3197 Flags=1, 3198) 3199 3200# sect 2.2.19 3201 3202 3203class SMB2_Read_Request(_SMB2_Payload, _NTLMPayloadPacket): 3204 name = "SMB2 READ Request" 3205 Command = 0x0008 3206 OFFSET = 48 + 64 3207 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3208 fields_desc = [ 3209 XLEShortField("StructureSize", 0x31), 3210 ByteField("Padding", 0x00), 3211 FlagsField( 3212 "Flags", 3213 0, 3214 -8, 3215 { 3216 0x01: "SMB2_READFLAG_READ_UNBUFFERED", 3217 0x02: "SMB2_READFLAG_REQUEST_COMPRESSED", 3218 }, 3219 ), 3220 LEIntField("Length", 4280), 3221 LELongField("Offset", 0), 3222 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 3223 LEIntField("MinimumCount", 0), 3224 LEIntEnumField( 3225 "Channel", 3226 0, 3227 { 3228 0x00000000: "SMB2_CHANNEL_NONE", 3229 0x00000001: "SMB2_CHANNEL_RDMA_V1", 3230 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE", 3231 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM", 3232 }, 3233 ), 3234 LEIntField("RemainingBytes", 0), 3235 LEShortField("ReadChannelInfoBufferOffset", None), 3236 LEShortField("ReadChannelInfoLen", None), 3237 _NTLMPayloadField( 3238 "Buffer", 3239 OFFSET, 3240 [ 3241 StrLenField( 3242 "ReadChannelInfo", 3243 b"", 3244 length_from=lambda pkt: pkt.ReadChannelInfoLen, 3245 ) 3246 ], 3247 ), 3248 ] 3249 3250 def post_build(self, pkt, pay): 3251 # type: (bytes, bytes) -> bytes 3252 if len(pkt) == 0x30: 3253 # 'The first byte of the Buffer field MUST be set to 0.' 3254 pkt += b"\x00" 3255 return ( 3256 _SMB2_post_build( 3257 self, 3258 pkt, 3259 self.OFFSET, 3260 { 3261 "ReadChannelInfo": 44, 3262 }, 3263 ) 3264 + pay 3265 ) 3266 3267 3268bind_top_down( 3269 SMB2_Header, 3270 SMB2_Read_Request, 3271 Command=0x0008, 3272) 3273 3274# sect 2.2.20 3275 3276 3277class SMB2_Read_Response(_SMB2_Payload, _NTLMPayloadPacket): 3278 name = "SMB2 READ Response" 3279 Command = 0x0008 3280 OFFSET = 16 + 64 3281 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3282 fields_desc = [ 3283 XLEShortField("StructureSize", 0x11), 3284 LEShortField("DataBufferOffset", None), 3285 LEIntField("DataLen", None), 3286 LEIntField("DataRemaining", 0), 3287 FlagsField( 3288 "Flags", 3289 0, 3290 -32, 3291 { 3292 0x01: "SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM", 3293 }, 3294 ), 3295 _NTLMPayloadField( 3296 "Buffer", 3297 OFFSET, 3298 [StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen)], 3299 ), 3300 ] 3301 3302 def post_build(self, pkt, pay): 3303 # type: (bytes, bytes) -> bytes 3304 return ( 3305 _SMB2_post_build( 3306 self, 3307 pkt, 3308 self.OFFSET, 3309 { 3310 "Data": 2, 3311 }, 3312 ) 3313 + pay 3314 ) 3315 3316 3317bind_top_down( 3318 SMB2_Header, 3319 SMB2_Read_Response, 3320 Command=0x0008, 3321 Flags=1, 3322) 3323 3324 3325# sect 2.2.21 3326 3327 3328class SMB2_Write_Request(_SMB2_Payload, _NTLMPayloadPacket): 3329 name = "SMB2 WRITE Request" 3330 Command = 0x0009 3331 OFFSET = 48 + 64 3332 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3333 fields_desc = [ 3334 XLEShortField("StructureSize", 0x31), 3335 LEShortField("DataBufferOffset", None), 3336 LEIntField("DataLen", None), 3337 LELongField("Offset", 0), 3338 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 3339 LEIntEnumField( 3340 "Channel", 3341 0, 3342 { 3343 0x00000000: "SMB2_CHANNEL_NONE", 3344 0x00000001: "SMB2_CHANNEL_RDMA_V1", 3345 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE", 3346 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM", 3347 }, 3348 ), 3349 LEIntField("RemainingBytes", 0), 3350 LEShortField("WriteChannelInfoBufferOffset", None), 3351 LEShortField("WriteChannelInfoLen", None), 3352 FlagsField( 3353 "Flags", 3354 0, 3355 -32, 3356 { 3357 0x00000001: "SMB2_WRITEFLAG_WRITE_THROUGH", 3358 0x00000002: "SMB2_WRITEFLAG_WRITE_UNBUFFERED", 3359 }, 3360 ), 3361 _NTLMPayloadField( 3362 "Buffer", 3363 OFFSET, 3364 [ 3365 StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen), 3366 StrLenField( 3367 "WriteChannelInfo", 3368 b"", 3369 length_from=lambda pkt: pkt.WriteChannelInfoLen, 3370 ), 3371 ], 3372 ), 3373 ] 3374 3375 def post_build(self, pkt, pay): 3376 # type: (bytes, bytes) -> bytes 3377 return ( 3378 _SMB2_post_build( 3379 self, 3380 pkt, 3381 self.OFFSET, 3382 { 3383 "Data": 2, 3384 "WriteChannelInfo": 40, 3385 }, 3386 ) 3387 + pay 3388 ) 3389 3390 3391bind_top_down( 3392 SMB2_Header, 3393 SMB2_Write_Request, 3394 Command=0x0009, 3395) 3396 3397# sect 2.2.22 3398 3399 3400class SMB2_Write_Response(_SMB2_Payload): 3401 name = "SMB2 WRITE Response" 3402 Command = 0x0009 3403 fields_desc = [ 3404 XLEShortField("StructureSize", 0x11), 3405 LEShortField("Reserved", 0), 3406 LEIntField("Count", 0), 3407 LEIntField("Remaining", 0), 3408 LEShortField("WriteChannelInfoBufferOffset", 0), 3409 LEShortField("WriteChannelInfoLen", 0), 3410 ] 3411 3412 3413bind_top_down(SMB2_Header, SMB2_Write_Response, Command=0x0009, Flags=1) 3414 3415# sect 2.2.28 3416 3417 3418class SMB2_Echo_Request(_SMB2_Payload): 3419 name = "SMB2 ECHO Request" 3420 Command = 0x000D 3421 fields_desc = [ 3422 XLEShortField("StructureSize", 0x4), 3423 LEShortField("Reserved", 0), 3424 ] 3425 3426 3427bind_top_down( 3428 SMB2_Header, 3429 SMB2_Echo_Request, 3430 Command=0x000D, 3431) 3432 3433# sect 2.2.29 3434 3435 3436class SMB2_Echo_Response(_SMB2_Payload): 3437 name = "SMB2 ECHO Response" 3438 Command = 0x000D 3439 fields_desc = [ 3440 XLEShortField("StructureSize", 0x4), 3441 LEShortField("Reserved", 0), 3442 ] 3443 3444 3445bind_top_down( 3446 SMB2_Header, 3447 SMB2_Echo_Response, 3448 Command=0x000D, 3449 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 3450) 3451 3452# sect 2.2.30 3453 3454 3455class SMB2_Cancel_Request(_SMB2_Payload): 3456 name = "SMB2 CANCEL Request" 3457 fields_desc = [ 3458 XLEShortField("StructureSize", 0x4), 3459 LEShortField("Reserved", 0), 3460 ] 3461 3462 3463bind_top_down( 3464 SMB2_Header, 3465 SMB2_Cancel_Request, 3466 Command=0x0009, 3467) 3468 3469# sect 2.2.31.4 3470 3471 3472class SMB2_IOCTL_Validate_Negotiate_Info_Request(Packet): 3473 name = "SMB2 IOCTL Validate Negotiate Info" 3474 fields_desc = ( 3475 SMB2_Negotiate_Protocol_Request.fields_desc[4:6] 3476 + SMB2_Negotiate_Protocol_Request.fields_desc[1:3][::-1] # Cap/GUID 3477 + [SMB2_Negotiate_Protocol_Request.fields_desc[9]] # SecMod/DC # Dialects 3478 ) 3479 3480 3481# sect 2.2.31 3482 3483 3484class _SMB2_IOCTL_Request_PacketLenField(PacketLenField): 3485 def m2i(self, pkt, m): 3486 if pkt.CtlCode == 0x00140204: # FSCTL_VALIDATE_NEGOTIATE_INFO 3487 return SMB2_IOCTL_Validate_Negotiate_Info_Request(m) 3488 elif pkt.CtlCode == 0x00060194: # FSCTL_DFS_GET_REFERRALS 3489 return SMB2_IOCTL_REQ_GET_DFS_Referral(m) 3490 elif pkt.CtlCode == 0x00094264: # FSCTL_OFFLOAD_READ 3491 return SMB2_IOCTL_OFFLOAD_READ_Request(m) 3492 return conf.raw_layer(m) 3493 3494 3495class SMB2_IOCTL_Request(_SMB2_Payload, _NTLMPayloadPacket): 3496 name = "SMB2 IOCTL Request" 3497 Command = 0x000B 3498 OFFSET = 56 + 64 3499 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3500 deprecated_fields = { 3501 "IntputCount": ("InputLen", "alias"), 3502 "OutputCount": ("OutputLen", "alias"), 3503 } 3504 fields_desc = [ 3505 XLEShortField("StructureSize", 0x39), 3506 LEShortField("Reserved", 0), 3507 LEIntEnumField( 3508 "CtlCode", 3509 0, 3510 { 3511 0x00060194: "FSCTL_DFS_GET_REFERRALS", 3512 0x0011400C: "FSCTL_PIPE_PEEK", 3513 0x00110018: "FSCTL_PIPE_WAIT", 3514 0x0011C017: "FSCTL_PIPE_TRANSCEIVE", 3515 0x001440F2: "FSCTL_SRV_COPYCHUNK", 3516 0x00144064: "FSCTL_SRV_ENUMERATE_SNAPSHOTS", 3517 0x00140078: "FSCTL_SRV_REQUEST_RESUME_KEY", 3518 0x001441BB: "FSCTL_SRV_READ_HASH", 3519 0x001480F2: "FSCTL_SRV_COPYCHUNK_WRITE", 3520 0x001401D4: "FSCTL_LMR_REQUEST_RESILIENCY", 3521 0x001401FC: "FSCTL_QUERY_NETWORK_INTERFACE_INFO", 3522 0x000900A4: "FSCTL_SET_REPARSE_POINT", 3523 0x000601B0: "FSCTL_DFS_GET_REFERRALS_EX", 3524 0x00098208: "FSCTL_FILE_LEVEL_TRIM", 3525 0x00140204: "FSCTL_VALIDATE_NEGOTIATE_INFO", 3526 0x00094264: "FSCTL_OFFLOAD_READ", 3527 }, 3528 ), 3529 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 3530 LEIntField("InputBufferOffset", None), 3531 LEIntField("InputLen", None), # Called InputCount but it's a length 3532 LEIntField("MaxInputResponse", 0), 3533 LEIntField("OutputBufferOffset", None), 3534 LEIntField("OutputLen", None), # Called OutputCount. 3535 LEIntField("MaxOutputResponse", 1024), 3536 FlagsField("Flags", 0, -32, {0x00000001: "SMB2_0_IOCTL_IS_FSCTL"}), 3537 LEIntField("Reserved2", 0), 3538 _NTLMPayloadField( 3539 "Buffer", 3540 OFFSET, 3541 [ 3542 _SMB2_IOCTL_Request_PacketLenField( 3543 "Input", None, conf.raw_layer, length_from=lambda pkt: pkt.InputLen 3544 ), 3545 _SMB2_IOCTL_Request_PacketLenField( 3546 "Output", 3547 None, 3548 conf.raw_layer, 3549 length_from=lambda pkt: pkt.OutputLen, 3550 ), 3551 ], 3552 ), 3553 ] 3554 3555 def post_build(self, pkt, pay): 3556 # type: (bytes, bytes) -> bytes 3557 return ( 3558 _SMB2_post_build( 3559 self, 3560 pkt, 3561 self.OFFSET, 3562 { 3563 "Input": 24, 3564 "Output": 36, 3565 }, 3566 ) 3567 + pay 3568 ) 3569 3570 3571bind_top_down( 3572 SMB2_Header, 3573 SMB2_IOCTL_Request, 3574 Command=0x000B, 3575) 3576 3577# sect 2.2.32.5 3578 3579 3580class SOCKADDR_STORAGE(Packet): 3581 fields_desc = [ 3582 LEShortEnumField("Family", 0x0002, {0x0002: "IPv4", 0x0017: "IPv6"}), 3583 ShortField("Port", 0), 3584 # IPv4 3585 ConditionalField( 3586 IPField("IPv4Adddress", None), 3587 lambda pkt: pkt.Family == 0x0002, 3588 ), 3589 ConditionalField( 3590 StrFixedLenField("Reserved", b"", length=8), 3591 lambda pkt: pkt.Family == 0x0002, 3592 ), 3593 # IPv6 3594 ConditionalField( 3595 LEIntField("FlowInfo", 0), 3596 lambda pkt: pkt.Family == 0x00017, 3597 ), 3598 ConditionalField( 3599 IP6Field("IPv6Address", None), 3600 lambda pkt: pkt.Family == 0x00017, 3601 ), 3602 ConditionalField( 3603 LEIntField("ScopeId", 0), 3604 lambda pkt: pkt.Family == 0x00017, 3605 ), 3606 ] 3607 3608 def default_payload_class(self, _): 3609 return conf.padding_layer 3610 3611 3612class NETWORK_INTERFACE_INFO(Packet): 3613 fields_desc = [ 3614 LEIntField("Next", None), # 0 = no next entry 3615 LEIntField("IfIndex", 1), 3616 FlagsField( 3617 "Capability", 3618 1, 3619 -32, 3620 { 3621 0x00000001: "RSS_CAPABLE", 3622 0x00000002: "RDMA_CAPABLE", 3623 }, 3624 ), 3625 LEIntField("Reserved", 0), 3626 ScalingField("LinkSpeed", 10000000000, fmt="<Q", unit="bit/s"), 3627 PacketField("SockAddr_Storage", SOCKADDR_STORAGE(), SOCKADDR_STORAGE), 3628 ] 3629 3630 def default_payload_class(self, _): 3631 return conf.padding_layer 3632 3633 3634class SMB2_IOCTL_Network_Interface_Info(Packet): 3635 name = "SMB2 IOCTL Network Interface Info response" 3636 fields_desc = [ 3637 _NextPacketListField("interfaces", [], NETWORK_INTERFACE_INFO), 3638 ] 3639 3640 3641# sect 2.2.32.6 3642 3643 3644class SMB2_IOCTL_Validate_Negotiate_Info_Response(Packet): 3645 name = "SMB2 IOCTL Validate Negotiate Info" 3646 fields_desc = ( 3647 SMB2_Negotiate_Protocol_Response.fields_desc[4:6][::-1] 3648 + SMB2_Negotiate_Protocol_Response.fields_desc[ # Cap/GUID 3649 1:3 3650 ] # SecMod/DialectRevision 3651 ) 3652 3653 3654# [MS-FSCC] sect 2.3.42 3655 3656 3657class SMB2_IOCTL_OFFLOAD_READ_Request(Packet): 3658 name = "SMB2 IOCTL OFFLOAD_READ Request" 3659 fields_desc = [ 3660 LEIntField("StructureSize", 0x20), 3661 LEIntField("Flags", 0), 3662 LEIntField("TokenTimeToLive", 0), 3663 LEIntField("Reserved", 0), 3664 LELongField("FileOffset", 0), 3665 LELongField("CopyLength", 0), 3666 ] 3667 3668 3669# [MS-FSCC] sect 2.1.11 3670 3671 3672class STORAGE_OFFLOAD_TOKEN(Packet): 3673 fields_desc = [ 3674 LEIntEnumField( 3675 "TokenType", 3676 0xFFFF0001, 3677 { 3678 0xFFFF0001: "STORAGE_OFFLOAD_TOKEN_TYPE_ZERO_DATA", 3679 }, 3680 ), 3681 LEShortField("Reserved", 0), 3682 FieldLenField("TokenIdLength", None, fmt="<H", length_of="TokenId"), 3683 StrFixedLenField("TokenId", b"", length=504), 3684 ] 3685 3686 3687# [MS-FSCC] sect 2.3.42 3688 3689 3690class SMB2_IOCTL_OFFLOAD_READ_Response(Packet): 3691 name = "SMB2 IOCTL OFFLOAD_READ Response" 3692 fields_desc = [ 3693 LEIntField("StructureSize", 0x210), 3694 FlagsField( 3695 "Flags", 3696 0, 3697 -32, 3698 { 3699 0x00000001: "OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE", 3700 }, 3701 ), 3702 LELongField("TransferLength", 0), 3703 PacketField("Token", STORAGE_OFFLOAD_TOKEN(), STORAGE_OFFLOAD_TOKEN), 3704 ] 3705 3706 3707# sect 2.2.32 3708 3709 3710class _SMB2_IOCTL_Response_PacketLenField(PacketLenField): 3711 def m2i(self, pkt, m): 3712 if pkt.CtlCode == 0x00140204: # FSCTL_VALIDATE_NEGOTIATE_INFO 3713 return SMB2_IOCTL_Validate_Negotiate_Info_Response(m) 3714 elif pkt.CtlCode == 0x001401FC: # FSCTL_QUERY_NETWORK_INTERFACE_INFO 3715 return SMB2_IOCTL_Network_Interface_Info(m) 3716 elif pkt.CtlCode == 0x00060194: # FSCTL_DFS_GET_REFERRALS 3717 return SMB2_IOCTL_RESP_GET_DFS_Referral(m) 3718 return conf.raw_layer(m) 3719 3720 3721class SMB2_IOCTL_Response(_SMB2_Payload, _NTLMPayloadPacket): 3722 name = "SMB2 IOCTL Response" 3723 Command = 0x000B 3724 OFFSET = 48 + 64 3725 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3726 StructureSize = 0x31 3727 MaxOutputResponse = 0 3728 fields_desc = ( 3729 SMB2_IOCTL_Request.fields_desc[:6] 3730 + SMB2_IOCTL_Request.fields_desc[7:9] 3731 + SMB2_IOCTL_Request.fields_desc[10:12] 3732 + [ 3733 _NTLMPayloadField( 3734 "Buffer", 3735 OFFSET, 3736 [ 3737 _SMB2_IOCTL_Response_PacketLenField( 3738 "Input", 3739 None, 3740 conf.raw_layer, 3741 length_from=lambda pkt: pkt.InputLen, 3742 ), 3743 _SMB2_IOCTL_Response_PacketLenField( 3744 "Output", 3745 None, 3746 conf.raw_layer, 3747 length_from=lambda pkt: pkt.OutputLen, 3748 ), 3749 ], 3750 ), 3751 ] 3752 ) 3753 3754 def post_build(self, pkt, pay): 3755 # type: (bytes, bytes) -> bytes 3756 return ( 3757 _SMB2_post_build( 3758 self, 3759 pkt, 3760 self.OFFSET, 3761 { 3762 "Input": 24, 3763 "Output": 32, 3764 }, 3765 ) 3766 + pay 3767 ) 3768 3769 3770bind_top_down( 3771 SMB2_Header, 3772 SMB2_IOCTL_Response, 3773 Command=0x000B, 3774 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 3775) 3776 3777# sect 2.2.33 3778 3779 3780class SMB2_Query_Directory_Request(_SMB2_Payload, _NTLMPayloadPacket): 3781 name = "SMB2 QUERY DIRECTORY Request" 3782 Command = 0x000E 3783 OFFSET = 32 + 64 3784 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3785 fields_desc = [ 3786 XLEShortField("StructureSize", 0x21), 3787 ByteEnumField("FileInformationClass", 0x1, FileInformationClasses), 3788 FlagsField( 3789 "Flags", 3790 0, 3791 -8, 3792 { 3793 0x01: "SMB2_RESTART_SCANS", 3794 0x02: "SMB2_RETURN_SINGLE_ENTRY", 3795 0x04: "SMB2_INDEX_SPECIFIED", 3796 0x10: "SMB2_REOPEN", 3797 }, 3798 ), 3799 LEIntField("FileIndex", 0), 3800 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 3801 LEShortField("FileNameBufferOffset", None), 3802 LEShortField("FileNameLen", None), 3803 LEIntField("OutputBufferLength", 65535), 3804 _NTLMPayloadField("Buffer", OFFSET, [StrFieldUtf16("FileName", b"")]), 3805 ] 3806 3807 def post_build(self, pkt, pay): 3808 # type: (bytes, bytes) -> bytes 3809 return ( 3810 _SMB2_post_build( 3811 self, 3812 pkt, 3813 self.OFFSET, 3814 { 3815 "FileName": 24, 3816 }, 3817 ) 3818 + pay 3819 ) 3820 3821 3822bind_top_down( 3823 SMB2_Header, 3824 SMB2_Query_Directory_Request, 3825 Command=0x000E, 3826) 3827 3828# sect 2.2.34 3829 3830 3831class SMB2_Query_Directory_Response(_SMB2_Payload, _NTLMPayloadPacket): 3832 name = "SMB2 QUERY DIRECTORY Response" 3833 Command = 0x000E 3834 OFFSET = 8 + 64 3835 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3836 fields_desc = [ 3837 XLEShortField("StructureSize", 0x9), 3838 LEShortField("OutputBufferOffset", None), 3839 LEIntField("OutputLen", None), 3840 _NTLMPayloadField( 3841 "Buffer", 3842 OFFSET, 3843 [ 3844 # TODO 3845 StrFixedLenField("Output", b"", length_from=lambda pkt: pkt.OutputLen) 3846 ], 3847 ), 3848 ] 3849 3850 def post_build(self, pkt, pay): 3851 # type: (bytes, bytes) -> bytes 3852 return ( 3853 _SMB2_post_build( 3854 self, 3855 pkt, 3856 self.OFFSET, 3857 { 3858 "Output": 2, 3859 }, 3860 ) 3861 + pay 3862 ) 3863 3864 3865bind_top_down( 3866 SMB2_Header, 3867 SMB2_Query_Directory_Response, 3868 Command=0x000E, 3869 Flags=1, 3870) 3871 3872# sect 2.2.35 3873 3874 3875class SMB2_Change_Notify_Request(_SMB2_Payload): 3876 name = "SMB2 CHANGE NOTIFY Request" 3877 Command = 0x000F 3878 fields_desc = [ 3879 XLEShortField("StructureSize", 0x20), 3880 FlagsField( 3881 "Flags", 3882 0, 3883 -16, 3884 { 3885 0x0001: "SMB2_WATCH_TREE", 3886 }, 3887 ), 3888 LEIntField("OutputBufferLength", 2048), 3889 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 3890 FlagsField( 3891 "CompletionFilter", 3892 0, 3893 -32, 3894 { 3895 0x00000001: "FILE_NOTIFY_CHANGE_FILE_NAME", 3896 0x00000002: "FILE_NOTIFY_CHANGE_DIR_NAME", 3897 0x00000004: "FILE_NOTIFY_CHANGE_ATTRIBUTES", 3898 0x00000008: "FILE_NOTIFY_CHANGE_SIZE", 3899 0x00000010: "FILE_NOTIFY_CHANGE_LAST_WRITE", 3900 0x00000020: "FILE_NOTIFY_CHANGE_LAST_ACCESS", 3901 0x00000040: "FILE_NOTIFY_CHANGE_CREATION", 3902 0x00000080: "FILE_NOTIFY_CHANGE_EA", 3903 0x00000100: "FILE_NOTIFY_CHANGE_SECURITY", 3904 0x00000200: "FILE_NOTIFY_CHANGE_STREAM_NAME", 3905 0x00000400: "FILE_NOTIFY_CHANGE_STREAM_SIZE", 3906 0x00000800: "FILE_NOTIFY_CHANGE_STREAM_WRITE", 3907 }, 3908 ), 3909 LEIntField("Reserved", 0), 3910 ] 3911 3912 3913bind_top_down( 3914 SMB2_Header, 3915 SMB2_Change_Notify_Request, 3916 Command=0x000F, 3917) 3918 3919# sect 2.2.36 3920 3921 3922class SMB2_Change_Notify_Response(_SMB2_Payload, _NTLMPayloadPacket): 3923 name = "SMB2 CHANGE NOTIFY Response" 3924 Command = 0x000F 3925 OFFSET = 8 + 64 3926 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 3927 fields_desc = [ 3928 XLEShortField("StructureSize", 0x9), 3929 LEShortField("OutputBufferOffset", None), 3930 LEIntField("OutputLen", None), 3931 _NTLMPayloadField( 3932 "Buffer", 3933 OFFSET, 3934 [ 3935 _NextPacketListField( 3936 "Output", 3937 [], 3938 FILE_NOTIFY_INFORMATION, 3939 length_from=lambda pkt: pkt.OutputLen, 3940 max_count=1000, 3941 ) 3942 ], 3943 ), 3944 ] 3945 3946 def post_build(self, pkt, pay): 3947 # type: (bytes, bytes) -> bytes 3948 return ( 3949 _SMB2_post_build( 3950 self, 3951 pkt, 3952 self.OFFSET, 3953 { 3954 "Output": 2, 3955 }, 3956 ) 3957 + pay 3958 ) 3959 3960 3961bind_top_down( 3962 SMB2_Header, 3963 SMB2_Change_Notify_Response, 3964 Command=0x000F, 3965 Flags=1, 3966) 3967 3968# sect 2.2.37 3969 3970 3971class FILE_GET_QUOTA_INFORMATION(Packet): 3972 fields_desc = [ 3973 IntField("NextEntryOffset", 0), 3974 FieldLenField("SidLength", None, length_of="Sid"), 3975 StrLenField("Sid", b"", length_from=lambda x: x.SidLength), 3976 StrLenField( 3977 "pad", 3978 b"", 3979 length_from=lambda x: ( 3980 (x.NextEntryOffset - x.SidLength) if x.NextEntryOffset else 0 3981 ), 3982 ), 3983 ] 3984 3985 3986class SMB2_Query_Quota_Info(Packet): 3987 fields_desc = [ 3988 ByteField("ReturnSingle", 0), 3989 ByteField("ReturnBoolean", 0), 3990 ShortField("Reserved", 0), 3991 LEIntField("SidListLength", 0), 3992 LEIntField("StartSidLength", 0), 3993 LEIntField("StartSidOffset", 0), 3994 StrLenField("pad", b"", length_from=lambda x: x.StartSidOffset), 3995 MultipleTypeField( 3996 [ 3997 ( 3998 PacketListField( 3999 "SidBuffer", 4000 [], 4001 FILE_GET_QUOTA_INFORMATION, 4002 length_from=lambda x: x.SidListLength, 4003 ), 4004 lambda x: x.SidListLength, 4005 ), 4006 ( 4007 StrLenField( 4008 "SidBuffer", b"", length_from=lambda x: x.StartSidLength 4009 ), 4010 lambda x: x.StartSidLength, 4011 ), 4012 ], 4013 StrFixedLenField("SidBuffer", b"", length=0), 4014 ), 4015 ] 4016 4017 4018SMB2_INFO_TYPE = { 4019 0x01: "SMB2_0_INFO_FILE", 4020 0x02: "SMB2_0_INFO_FILESYSTEM", 4021 0x03: "SMB2_0_INFO_SECURITY", 4022 0x04: "SMB2_0_INFO_QUOTA", 4023} 4024 4025SMB2_ADDITIONAL_INFORMATION = { 4026 0x00000001: "OWNER_SECURITY_INFORMATION", 4027 0x00000002: "GROUP_SECURITY_INFORMATION", 4028 0x00000004: "DACL_SECURITY_INFORMATION", 4029 0x00000008: "SACL_SECURITY_INFORMATION", 4030 0x00000010: "LABEL_SECURITY_INFORMATION", 4031 0x00000020: "ATTRIBUTE_SECURITY_INFORMATION", 4032 0x00000040: "SCOPE_SECURITY_INFORMATION", 4033 0x00010000: "BACKUP_SECURITY_INFORMATION", 4034} 4035 4036 4037class SMB2_Query_Info_Request(_SMB2_Payload, _NTLMPayloadPacket): 4038 name = "SMB2 QUERY INFO Request" 4039 Command = 0x0010 4040 OFFSET = 40 + 64 4041 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 4042 fields_desc = [ 4043 XLEShortField("StructureSize", 0x29), 4044 ByteEnumField( 4045 "InfoType", 4046 0, 4047 SMB2_INFO_TYPE, 4048 ), 4049 ByteEnumField("FileInfoClass", 0, FileInformationClasses), 4050 LEIntField("OutputBufferLength", 0), 4051 XLEIntField("InputBufferOffset", None), # Short + Reserved = Int 4052 LEIntField("InputLen", None), 4053 FlagsField( 4054 "AdditionalInformation", 4055 0, 4056 -32, 4057 SMB2_ADDITIONAL_INFORMATION, 4058 ), 4059 FlagsField( 4060 "Flags", 4061 0, 4062 -32, 4063 { 4064 0x00000001: "SL_RESTART_SCAN", 4065 0x00000002: "SL_RETURN_SINGLE_ENTRY", 4066 0x00000004: "SL_INDEX_SPECIFIED", 4067 }, 4068 ), 4069 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 4070 _NTLMPayloadField( 4071 "Buffer", 4072 OFFSET, 4073 [ 4074 MultipleTypeField( 4075 [ 4076 ( 4077 # QUOTA 4078 PacketListField( 4079 "Input", 4080 None, 4081 SMB2_Query_Quota_Info, 4082 length_from=lambda pkt: pkt.InputLen, 4083 ), 4084 lambda pkt: pkt.InfoType == 0x04, 4085 ), 4086 ], 4087 StrLenField("Input", b"", length_from=lambda pkt: pkt.InputLen), 4088 ), 4089 ], 4090 ), 4091 ] 4092 4093 def post_build(self, pkt, pay): 4094 # type: (bytes, bytes) -> bytes 4095 return ( 4096 _SMB2_post_build( 4097 self, 4098 pkt, 4099 self.OFFSET, 4100 { 4101 "Input": 4, 4102 }, 4103 ) 4104 + pay 4105 ) 4106 4107 4108bind_top_down( 4109 SMB2_Header, 4110 SMB2_Query_Info_Request, 4111 Command=0x00010, 4112) 4113 4114 4115class SMB2_Query_Info_Response(_SMB2_Payload, _NTLMPayloadPacket): 4116 name = "SMB2 QUERY INFO Response" 4117 Command = 0x0010 4118 OFFSET = 8 + 64 4119 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 4120 fields_desc = [ 4121 XLEShortField("StructureSize", 0x9), 4122 LEShortField("OutputBufferOffset", None), 4123 LEIntField("OutputLen", None), 4124 _NTLMPayloadField( 4125 "Buffer", 4126 OFFSET, 4127 [ 4128 # TODO 4129 StrFixedLenField("Output", b"", length_from=lambda pkt: pkt.OutputLen) 4130 ], 4131 ), 4132 ] 4133 4134 def post_build(self, pkt, pay): 4135 # type: (bytes, bytes) -> bytes 4136 return ( 4137 _SMB2_post_build( 4138 self, 4139 pkt, 4140 self.OFFSET, 4141 { 4142 "Output": 2, 4143 }, 4144 ) 4145 + pay 4146 ) 4147 4148 4149bind_top_down( 4150 SMB2_Header, 4151 SMB2_Query_Info_Response, 4152 Command=0x00010, 4153 Flags=1, 4154) 4155 4156 4157# sect 2.2.39 4158 4159 4160class SMB2_Set_Info_Request(_SMB2_Payload, _NTLMPayloadPacket): 4161 name = "SMB2 SET INFO Request" 4162 Command = 0x0011 4163 OFFSET = 32 + 64 4164 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 4165 fields_desc = [ 4166 XLEShortField("StructureSize", 0x21), 4167 ByteEnumField( 4168 "InfoType", 4169 0, 4170 SMB2_INFO_TYPE, 4171 ), 4172 ByteEnumField("FileInfoClass", 0, FileInformationClasses), 4173 LEIntField("DataLen", None), 4174 XLEIntField("DataBufferOffset", None), # Short + Reserved = Int 4175 FlagsField( 4176 "AdditionalInformation", 4177 0, 4178 -32, 4179 SMB2_ADDITIONAL_INFORMATION, 4180 ), 4181 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 4182 _NTLMPayloadField( 4183 "Buffer", 4184 OFFSET, 4185 [ 4186 MultipleTypeField( 4187 [ 4188 ( 4189 # FILE 4190 PacketLenField( 4191 "Data", 4192 None, 4193 lambda x, _parent: _FileInformationClasses.get( 4194 _parent.FileInfoClass, conf.raw_layer 4195 )(x), 4196 length_from=lambda pkt: pkt.DataLen, 4197 ), 4198 lambda pkt: pkt.InfoType == 0x01, 4199 ), 4200 ( 4201 # QUOTA 4202 PacketListField( 4203 "Data", 4204 None, 4205 SMB2_Query_Quota_Info, 4206 length_from=lambda pkt: pkt.DataLen, 4207 ), 4208 lambda pkt: pkt.InfoType == 0x04, 4209 ), 4210 ], 4211 StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen), 4212 ), 4213 ], 4214 ), 4215 ] 4216 4217 def post_build(self, pkt, pay): 4218 # type: (bytes, bytes) -> bytes 4219 return ( 4220 _SMB2_post_build( 4221 self, 4222 pkt, 4223 self.OFFSET, 4224 { 4225 "Data": 4, 4226 }, 4227 ) 4228 + pay 4229 ) 4230 4231 4232bind_top_down( 4233 SMB2_Header, 4234 SMB2_Set_Info_Request, 4235 Command=0x00011, 4236) 4237 4238 4239class SMB2_Set_Info_Response(_SMB2_Payload): 4240 name = "SMB2 SET INFO Request" 4241 Command = 0x0011 4242 fields_desc = [ 4243 XLEShortField("StructureSize", 0x02), 4244 ] 4245 4246 4247bind_top_down( 4248 SMB2_Header, 4249 SMB2_Set_Info_Response, 4250 Command=0x00011, 4251 Flags=1, 4252) 4253 4254 4255# sect 2.2.42.1 4256 4257 4258class SMB2_Compression_Transform_Header(Packet): 4259 name = "SMB2 Compression Transform Header" 4260 fields_desc = [ 4261 StrFixedLenField("Start", b"\xfcSMB", 4), 4262 LEIntField("OriginalCompressedSegmentSize", 0x0), 4263 LEShortEnumField("CompressionAlgorithm", 0, SMB2_COMPRESSION_ALGORITHMS), 4264 LEShortEnumField( 4265 "Flags", 4266 0x0, 4267 { 4268 0x0000: "SMB2_COMPRESSION_FLAG_NONE", 4269 0x0001: "SMB2_COMPRESSION_FLAG_CHAINED", 4270 }, 4271 ), 4272 XLEIntField("Offset_or_Length", 0), 4273 ] 4274 4275 4276# [MS-DFSC] sect 2.2 4277 4278 4279class SMB2_IOCTL_REQ_GET_DFS_Referral(Packet): 4280 fields_desc = [ 4281 LEShortField("MaxReferralLevel", 0), 4282 StrNullFieldUtf16("RequestFileName", ""), 4283 ] 4284 4285 4286class DFS_REFERRAL(Packet): 4287 fields_desc = [ 4288 LEShortField("Version", 1), 4289 FieldLenField( 4290 "Size", None, fmt="<H", length_of="ShareName", adjust=lambda pkt, x: x + 9 4291 ), 4292 LEShortEnumField("ServerType", 0, {0: "non-root", 1: "root"}), 4293 LEShortField("ReferralEntryFlags", 0), 4294 StrNullFieldUtf16("ShareName", ""), 4295 ] 4296 4297 @classmethod 4298 def dispatch_hook(cls, _pkt=None, *args, **kargs): 4299 if _pkt and len(_pkt) >= 2: 4300 version = struct.unpack("<H", _pkt[:2])[0] 4301 if version == 1: 4302 return DFS_REFERRAL 4303 elif version == 3: 4304 return DFS_REFERRAL_V3 4305 elif version == 4: 4306 return DFS_REFERRAL_V4 4307 return cls 4308 4309 def default_payload_class(self, s): 4310 return conf.padding_layer 4311 4312 4313class DFS_REFERRAL_V3(DFS_REFERRAL): 4314 fields_desc = [ 4315 LEShortField("Version", 3), 4316 LEShortField("Size", None), 4317 LEShortEnumField("ServerType", 0, {0: "non-root", 1: "root"}), 4318 FlagsField( 4319 "ReferralEntryFlags", 4320 0, 4321 -16, 4322 { 4323 0x0002: "NameListReferral", 4324 0x0004: "TargetSetBoundary", 4325 }, 4326 ), 4327 LEIntField("TimeToLive", 300), 4328 # NameListReferral is 0 4329 ConditionalField( 4330 LEShortField("DFSPathOffset", None), 4331 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 4332 ), 4333 ConditionalField( 4334 LEShortField("DFSAlternatePathOffset", None), 4335 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 4336 ), 4337 ConditionalField( 4338 LEShortField("NetworkAddressOffset", None), 4339 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 4340 ), 4341 ConditionalField( 4342 StrFixedLenField("ServiceSiteGuid", 0, length=16), 4343 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 4344 ), 4345 # NameListReferral is 1 4346 ConditionalField( 4347 LEShortField("SpecialNameOffset", None), 4348 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 4349 ), 4350 ConditionalField( 4351 LEShortField("NumberOfExpandedNames", None), 4352 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 4353 ), 4354 ConditionalField( 4355 LEShortField("ExpandedNameOffset", None), 4356 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 4357 ), 4358 ConditionalField( 4359 StrLenField("Padding", None, length_from=lambda pkt: pkt.Size - 18), 4360 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 4361 ), 4362 ] 4363 4364 def post_build(self, pkt, pay): 4365 # type: (bytes, bytes) -> bytes 4366 if self.Size is None: 4367 pkt = pkt[:2] + struct.pack("<H", len(pkt)) + pkt[4:] 4368 return pkt + pay 4369 4370 4371class DFS_REFERRAL_V4(DFS_REFERRAL_V3): 4372 Version = 4 4373 4374 4375class DFS_REFERRAL_ENTRY0(Packet): 4376 fields_desc = [ 4377 StrNullFieldUtf16("DFSPath", ""), 4378 StrNullFieldUtf16("DFSAlternatePath", ""), 4379 StrNullFieldUtf16("NetworkAddress", ""), 4380 ] 4381 4382 4383class DFS_REFERRAL_ENTRY1(Packet): 4384 fields_desc = [ 4385 StrNullFieldUtf16("SpecialName", ""), 4386 FieldListField( 4387 "ExpandedName", 4388 [], 4389 StrNullFieldUtf16("", ""), 4390 ), 4391 ] 4392 4393 4394class _DFS_Referrals_BufferField(PacketListField): 4395 def getfield(self, pkt, s): 4396 results = [] 4397 offset = sum(x.Size for x in pkt.ReferralEntries) 4398 for ref in pkt.ReferralEntries: 4399 # For every ref 4400 if not ref.ReferralEntryFlags.NameListReferral: 4401 cls = DFS_REFERRAL_ENTRY0 4402 else: 4403 cls = DFS_REFERRAL_ENTRY1 4404 # Build the fields manually 4405 fld = _NTLMPayloadField( 4406 "", 4407 offset, 4408 cls.fields_desc, 4409 force_order=[x.name for x in cls.fields_desc], 4410 offset_name="Offset", 4411 ) 4412 remain, vals = fld.getfield(ref, s) 4413 vals = fld.i2h(ref, vals) 4414 # Append the entry class 4415 results.append(cls(**{x[0]: x[1] for x in vals})) 4416 offset -= ref.Size 4417 return b"", results 4418 4419 def addfield(self, pkt, s, vals): 4420 offset = sum(len(x) for x in pkt.ReferralEntries) 4421 for i, val in enumerate(vals): 4422 try: 4423 ref = pkt.ReferralEntries[i] 4424 except KeyError: 4425 ref = None 4426 fld = _NTLMPayloadField( 4427 "", 4428 offset, 4429 val.fields_desc, 4430 force_order=[x.name for x in val.fields_desc], 4431 offset_name="Offset", 4432 ) 4433 # Append the bytes manually 4434 values = [(fld.name, getattr(val, fld.name)) for fld in val.fields_desc] 4435 values = fld.h2i(ref, values) 4436 s += fld.addfield(ref, b"", values) 4437 offset -= len(ref) 4438 return s 4439 4440 4441class SMB2_IOCTL_RESP_GET_DFS_Referral(Packet): 4442 fields_desc = [ 4443 LEShortField("PathConsumed", 0), 4444 FieldLenField("NumberOfReferrals", None, fmt="<H", count_of="ReferralEntries"), 4445 FlagsField( 4446 "ReferralHeaderFlags", 4447 0, 4448 -32, 4449 { 4450 0x00000001: "ReferralServers", 4451 0x00000002: "StorageServers", 4452 0x00000004: "TargetFailback", 4453 }, 4454 ), 4455 PacketListField( 4456 "ReferralEntries", 4457 [], 4458 DFS_REFERRAL, 4459 count_from=lambda pkt: pkt.NumberOfReferrals, 4460 ), 4461 _DFS_Referrals_BufferField("ReferralBuffer", []), 4462 ] 4463 4464 def post_build(self, pkt, pay): 4465 # type: (bytes, bytes) -> bytes 4466 # Note: Windows is smart and uses some sort of compression in the sense 4467 # that it re-uses fields that are used several times across ReferralBuffer. 4468 # But we just do the dumb thing because it's 'easier', and do no compression. 4469 offsets = { 4470 # DFS_REFERRAL_ENTRY0 4471 "DFSPath": 12, 4472 "DFSAlternatePath": 14, 4473 "NetworkAddress": 16, 4474 # DFS_REFERRAL_ENTRY1 4475 "SpecialName": 12, 4476 "ExpandedName": 16, 4477 } 4478 # dataoffset = pointer in the ReferralBuffer 4479 # entryoffset = pointer in the ReferralEntries 4480 dataoffset = sum(len(x) for x in self.ReferralEntries) 4481 entryoffset = 8 4482 for ref, buf in zip(self.ReferralEntries, self.ReferralBuffer): 4483 for fld in buf.fields_desc: 4484 off = entryoffset + offsets[fld.name] 4485 if ref.getfieldval(fld.name + "Offset") is None and buf.getfieldval( 4486 fld.name 4487 ): 4488 pkt = pkt[:off] + struct.pack("<H", dataoffset) + pkt[off + 2 :] 4489 dataoffset += len(fld.addfield(self, b"", buf.getfieldval(fld.name))) 4490 dataoffset -= len(ref) 4491 entryoffset += len(ref) 4492 return pkt + pay 4493 4494 4495# [MS-SMB2] various usages 4496 4497 4498def SMB2computePreauthIntegrityHashValue( 4499 PreauthIntegrityHashValue, s, HashId="SHA-512" 4500): 4501 """ 4502 Update the PreauthIntegrityHashValue 4503 """ 4504 # get hasher 4505 hasher = {"SHA-512": hashlib.sha512}[HashId] 4506 # compute the hash of concatenation of previous and bytes 4507 return hasher(PreauthIntegrityHashValue + s).digest() 4508 4509 4510# SMB2 socket and session 4511 4512 4513class SMBStreamSocket(StreamSocket): 4514 """ 4515 A modified StreamSocket to dissect SMB compounded requests 4516 [MS-SMB2] 3.3.5.2.7 4517 """ 4518 4519 def __init__(self, *args, **kwargs): 4520 self.queue = collections.deque() 4521 self.session = SMBSession() 4522 super(SMBStreamSocket, self).__init__(*args, **kwargs) 4523 4524 def recv(self, x=None): 4525 # note: normal StreamSocket takes care of NBTSession / DirectTCP fragments. 4526 # this takes care of splitting compounded requests 4527 if self.queue: 4528 return self.queue.popleft() 4529 pkt = super(SMBStreamSocket, self).recv(x) 4530 if pkt is not None and SMB2_Header in pkt: 4531 pay = pkt[SMB2_Header].payload 4532 while SMB2_Header in pay: 4533 pay = pay[SMB2_Header] 4534 pay.underlayer.remove_payload() 4535 self.queue.append(pay) 4536 if not pay.NextCommand: 4537 break 4538 pay = pay.payload 4539 return self.session.in_pkt(pkt) 4540 4541 def send(self, x, Compounded=False, **kwargs): 4542 for pkt in self.session.out_pkt(x, Compounded=Compounded): 4543 return super(SMBStreamSocket, self).send(pkt, **kwargs) 4544 4545 @staticmethod 4546 def select(sockets, remain=conf.recv_poll_rate): 4547 if any(getattr(x, "queue", None) for x in sockets): 4548 return [x for x in sockets if isinstance(x, SMBStreamSocket) and x.queue] 4549 return select_objects(sockets, remain=remain) 4550 4551 4552class SMBSession(DefaultSession): 4553 """ 4554 A SMB session within a TCP socket. 4555 """ 4556 4557 def __init__(self, *args, **kwargs): 4558 self.smb_header = None 4559 self.ssp = kwargs.pop("ssp", None) 4560 self.sspcontext = kwargs.pop("sspcontext", None) 4561 self.sniffsspcontexts = {} # Unfinished contexts for passive 4562 # SMB session parameters 4563 self.CompoundQueue = [] 4564 self.Dialect = 0x0202 # Updated by parent 4565 self.Credits = 0 4566 self.SecurityMode = 0 4567 # Crypto parameters 4568 self.SMBSessionKey = None 4569 self.PreauthIntegrityHashId = "SHA-512" 4570 self.CipherId = "AES-128-CCM" 4571 self.SigningAlgorithmId = "AES-CMAC" 4572 self.Salt = os.urandom(32) 4573 self.ConnectionPreauthIntegrityHashValue = None 4574 self.SessionPreauthIntegrityHashValue = None 4575 # SMB 3.1.1 4576 self.SessionPreauthIntegrityHashValue = None 4577 if conf.winssps_passive: 4578 for ssp in conf.winssps_passive: 4579 self.sniffsspcontexts[ssp] = None 4580 super(SMBSession, self).__init__(*args, **kwargs) 4581 4582 # SMB crypto functions 4583 4584 @crypto_validator 4585 def computeSMBSessionKey(self): 4586 if not getattr(self.sspcontext, "SessionKey", None): 4587 # no signing key, no session key 4588 return 4589 # [MS-SMB2] sect 3.3.5.5.3 4590 if self.Dialect >= 0x0300: 4591 if self.Dialect == 0x0311: 4592 label = b"SMBSigningKey\x00" 4593 preauth_hash = self.SessionPreauthIntegrityHashValue 4594 else: 4595 label = b"SMB2AESCMAC\x00" 4596 preauth_hash = b"SmbSign\x00" 4597 # [MS-SMB2] sect 3.1.4.2 4598 if "256" in self.CipherId: 4599 L = 256 4600 elif "128" in self.CipherId: 4601 L = 128 4602 else: 4603 raise ValueError 4604 self.SMBSessionKey = SP800108_KDFCTR( 4605 self.sspcontext.SessionKey[:16], 4606 label, # label 4607 preauth_hash, # context 4608 L, 4609 ) 4610 elif self.Dialect <= 0x0210: 4611 self.SMBSessionKey = self.sspcontext.SessionKey[:16] 4612 else: 4613 raise ValueError("Hmmm ? >:(") 4614 4615 def computeSMBConnectionPreauth(self, *negopkts): 4616 if self.Dialect and self.Dialect >= 0x0311: # SMB 3.1.1 only 4617 # [MS-SMB2] 3.3.5.4 4618 # TODO: handle SMB2_SESSION_FLAG_BINDING 4619 if self.ConnectionPreauthIntegrityHashValue is None: 4620 # New auth or failure 4621 self.ConnectionPreauthIntegrityHashValue = b"\x00" * 64 4622 # Calculate the *Connection* PreauthIntegrityHashValue 4623 for negopkt in negopkts: 4624 self.ConnectionPreauthIntegrityHashValue = ( 4625 SMB2computePreauthIntegrityHashValue( 4626 self.ConnectionPreauthIntegrityHashValue, 4627 negopkt, 4628 HashId=self.PreauthIntegrityHashId, 4629 ) 4630 ) 4631 4632 def computeSMBSessionPreauth(self, *sesspkts): 4633 if self.Dialect and self.Dialect >= 0x0311: # SMB 3.1.1 only 4634 # [MS-SMB2] 3.3.5.5.3 4635 if self.SessionPreauthIntegrityHashValue is None: 4636 # New auth or failure 4637 self.SessionPreauthIntegrityHashValue = ( 4638 self.ConnectionPreauthIntegrityHashValue 4639 ) 4640 # Calculate the *Session* PreauthIntegrityHashValue 4641 for sesspkt in sesspkts: 4642 self.SessionPreauthIntegrityHashValue = ( 4643 SMB2computePreauthIntegrityHashValue( 4644 self.SessionPreauthIntegrityHashValue, 4645 sesspkt, 4646 HashId=self.PreauthIntegrityHashId, 4647 ) 4648 ) 4649 4650 # I/O 4651 4652 def in_pkt(self, pkt): 4653 """ 4654 Incoming SMB packet 4655 """ 4656 return pkt 4657 4658 def out_pkt(self, pkt, Compounded=False): 4659 """ 4660 Outgoing SMB packet 4661 4662 :param pkt: the packet to send 4663 :param Compound: if True, will be stack to be send with the next 4664 un-compounded packet 4665 4666 Handles: 4667 - handle compounded requests (if any): [MS-SMB2] 3.3.5.2.7 4668 - handles signing (if required) 4669 """ 4670 # Note: impacket and wireshark get crazy on compounded+signature, but 4671 # windows+samba tells we're right :D 4672 if SMB2_Header in pkt: 4673 if self.CompoundQueue: 4674 # this is a subsequent compound: only keep the SMB2 4675 pkt = pkt[SMB2_Header] 4676 if Compounded: 4677 # [MS-SMB2] 3.2.4.1.4 4678 # "Compounded requests MUST be aligned on 8-byte boundaries; the 4679 # last request of the compounded requests does not need to be padded to 4680 # an 8-byte boundary." 4681 # [MS-SMB2] 3.1.4.1 4682 # "If the message is part of a compounded chain, any 4683 # padding at the end of the message MUST be used in the hash 4684 # computation." 4685 length = len(pkt[SMB2_Header]) 4686 padlen = (-length) % 8 4687 if padlen: 4688 pkt.add_payload(b"\x00" * padlen) 4689 pkt[SMB2_Header].NextCommand = length + padlen 4690 if self.Dialect and self.SMBSessionKey and self.SecurityMode != 0: 4691 # Sign SMB2 ! 4692 smb = pkt[SMB2_Header] 4693 smb.Flags += "SMB2_FLAGS_SIGNED" 4694 smb.sign( 4695 self.Dialect, 4696 self.SMBSessionKey, 4697 # SMB 3.1.1 parameters: 4698 SigningAlgorithmId=self.SigningAlgorithmId, 4699 IsClient=False, 4700 ) 4701 if Compounded: 4702 # There IS a next compound. Store in queue 4703 self.CompoundQueue.append(pkt) 4704 return [] 4705 else: 4706 # If there are any compounded responses in store, sum them 4707 if self.CompoundQueue: 4708 pkt = functools.reduce(lambda x, y: x / y, self.CompoundQueue) / pkt 4709 self.CompoundQueue.clear() 4710 return [pkt] 4711 4712 def process(self, pkt: Packet): 4713 # Called when passively sniffing 4714 pkt = super(SMBSession, self).process(pkt) 4715 if pkt is not None and SMB2_Header in pkt: 4716 return self.in_pkt(pkt) 4717 return pkt 4718