Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/smb2.py: 68%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

969 statements  

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 struct 

19 

20from scapy.automaton import select_objects 

21from scapy.config import conf, crypto_validator 

22from scapy.error import log_runtime 

23from scapy.packet import Packet, bind_layers, bind_top_down 

24from scapy.fields import ( 

25 ByteEnumField, 

26 ByteField, 

27 ConditionalField, 

28 FieldLenField, 

29 FieldListField, 

30 FlagsField, 

31 IP6Field, 

32 IPField, 

33 IntField, 

34 LEIntField, 

35 LEIntEnumField, 

36 LELongField, 

37 LenField, 

38 LEShortEnumField, 

39 LEShortField, 

40 MultipleTypeField, 

41 PadField, 

42 PacketField, 

43 PacketLenField, 

44 PacketListField, 

45 ReversePadField, 

46 ScalingField, 

47 ShortEnumField, 

48 ShortField, 

49 StrFieldUtf16, 

50 StrFixedLenField, 

51 StrLenField, 

52 StrLenFieldUtf16, 

53 StrNullFieldUtf16, 

54 ThreeBytesField, 

55 UTCTimeField, 

56 UUIDField, 

57 XLEIntField, 

58 XLELongField, 

59 XLEShortField, 

60 XStrLenField, 

61 XStrFixedLenField, 

62 YesNoByteField, 

63) 

64from scapy.sessions import DefaultSession 

65from scapy.supersocket import StreamSocket 

66 

67if conf.crypto_valid: 

68 from scapy.libs.rfc3961 import SP800108_KDFCTR 

69 

70from scapy.layers.gssapi import GSSAPI_BLOB 

71from scapy.layers.netbios import NBTSession 

72from scapy.layers.ntlm import ( 

73 _NTLMPayloadField, 

74 _NTLMPayloadPacket, 

75 _NTLM_ENUM, 

76 _NTLM_post_build, 

77) 

78from scapy.layers.windows.erref import STATUS_ERREF 

79 

80 

81# EnumField 

82SMB_DIALECTS = { 

83 0x0202: "SMB 2.002", 

84 0x0210: "SMB 2.1", 

85 0x02FF: "SMB 2.???", 

86 0x0300: "SMB 3.0", 

87 0x0302: "SMB 3.0.2", 

88 0x0311: "SMB 3.1.1", 

89} 

90 

91# SMB2 sect 2.1.2.1 

92REPARSE_TAGS = { 

93 0x00000000: "IO_REPARSE_TAG_RESERVED_ZERO", 

94 0x00000001: "IO_REPARSE_TAG_RESERVED_ONE", 

95 0x00000002: "IO_REPARSE_TAG_RESERVED_TWO", 

96 0xA0000003: "IO_REPARSE_TAG_MOUNT_POINT", 

97 0xC0000004: "IO_REPARSE_TAG_HSM", 

98 0x80000005: "IO_REPARSE_TAG_DRIVE_EXTENDER", 

99 0x80000006: "IO_REPARSE_TAG_HSM2", 

100 0x80000007: "IO_REPARSE_TAG_SIS", 

101 0x80000008: "IO_REPARSE_TAG_WIM", 

102 0x80000009: "IO_REPARSE_TAG_CSV", 

103 0x8000000A: "IO_REPARSE_TAG_DFS", 

104 0x8000000B: "IO_REPARSE_TAG_FILTER_MANAGER", 

105 0xA000000C: "IO_REPARSE_TAG_SYMLINK", 

106 0xA0000010: "IO_REPARSE_TAG_IIS_CACHE", 

107 0x80000012: "IO_REPARSE_TAG_DFSR", 

108 0x80000013: "IO_REPARSE_TAG_DEDUP", 

109 0xC0000014: "IO_REPARSE_TAG_APPXSTRM", 

110 0x80000014: "IO_REPARSE_TAG_NFS", 

111 0x80000015: "IO_REPARSE_TAG_FILE_PLACEHOLDER", 

112 0x80000016: "IO_REPARSE_TAG_DFM", 

113 0x80000017: "IO_REPARSE_TAG_WOF", 

114 0x80000018: "IO_REPARSE_TAG_WCI", 

115 0x90001018: "IO_REPARSE_TAG_WCI_1", 

116 0xA0000019: "IO_REPARSE_TAG_GLOBAL_REPARSE", 

117 0x9000001A: "IO_REPARSE_TAG_CLOUD", 

118 0x9000101A: "IO_REPARSE_TAG_CLOUD_1", 

119 0x9000201A: "IO_REPARSE_TAG_CLOUD_2", 

120 0x9000301A: "IO_REPARSE_TAG_CLOUD_3", 

121 0x9000401A: "IO_REPARSE_TAG_CLOUD_4", 

122 0x9000501A: "IO_REPARSE_TAG_CLOUD_5", 

123 0x9000601A: "IO_REPARSE_TAG_CLOUD_6", 

124 0x9000701A: "IO_REPARSE_TAG_CLOUD_7", 

125 0x9000801A: "IO_REPARSE_TAG_CLOUD_8", 

126 0x9000901A: "IO_REPARSE_TAG_CLOUD_9", 

127 0x9000A01A: "IO_REPARSE_TAG_CLOUD_A", 

128 0x9000B01A: "IO_REPARSE_TAG_CLOUD_B", 

129 0x9000C01A: "IO_REPARSE_TAG_CLOUD_C", 

130 0x9000D01A: "IO_REPARSE_TAG_CLOUD_D", 

131 0x9000E01A: "IO_REPARSE_TAG_CLOUD_E", 

132 0x9000F01A: "IO_REPARSE_TAG_CLOUD_F", 

133 0x8000001B: "IO_REPARSE_TAG_APPEXECLINK", 

134 0x9000001C: "IO_REPARSE_TAG_PROJFS", 

135 0xA000001D: "IO_REPARSE_TAG_LX_SYMLINK", 

136 0x8000001E: "IO_REPARSE_TAG_STORAGE_SYNC", 

137 0xA000001F: "IO_REPARSE_TAG_WCI_TOMBSTONE", 

138 0x80000020: "IO_REPARSE_TAG_UNHANDLED", 

139 0x80000021: "IO_REPARSE_TAG_ONEDRIVE", 

140 0xA0000022: "IO_REPARSE_TAG_PROJFS_TOMBSTONE", 

141 0x80000023: "IO_REPARSE_TAG_AF_UNIX", 

142 0x80000024: "IO_REPARSE_TAG_LX_FIFO", 

143 0x80000025: "IO_REPARSE_TAG_LX_CHR", 

144 0x80000026: "IO_REPARSE_TAG_LX_BLK", 

145 0xA0000027: "IO_REPARSE_TAG_WCI_LINK", 

146 0xA0001027: "IO_REPARSE_TAG_WCI_LINK_1", 

147} 

148 

149# SMB2 sect 2.2.1.1 

150SMB2_COM = { 

151 0x0000: "SMB2_NEGOTIATE", 

152 0x0001: "SMB2_SESSION_SETUP", 

153 0x0002: "SMB2_LOGOFF", 

154 0x0003: "SMB2_TREE_CONNECT", 

155 0x0004: "SMB2_TREE_DISCONNECT", 

156 0x0005: "SMB2_CREATE", 

157 0x0006: "SMB2_CLOSE", 

158 0x0007: "SMB2_FLUSH", 

159 0x0008: "SMB2_READ", 

160 0x0009: "SMB2_WRITE", 

161 0x000A: "SMB2_LOCK", 

162 0x000B: "SMB2_IOCTL", 

163 0x000C: "SMB2_CANCEL", 

164 0x000D: "SMB2_ECHO", 

165 0x000E: "SMB2_QUERY_DIRECTORY", 

166 0x000F: "SMB2_CHANGE_NOTIFY", 

167 0x0010: "SMB2_QUERY_INFO", 

168 0x0011: "SMB2_SET_INFO", 

169 0x0012: "SMB2_OPLOCK_BREAK", 

170} 

171 

172# EnumField 

173SMB2_NEGOTIATE_CONTEXT_TYPES = { 

174 0x0001: "SMB2_PREAUTH_INTEGRITY_CAPABILITIES", 

175 0x0002: "SMB2_ENCRYPTION_CAPABILITIES", 

176 0x0003: "SMB2_COMPRESSION_CAPABILITIES", 

177 0x0005: "SMB2_NETNAME_NEGOTIATE_CONTEXT_ID", 

178 0x0006: "SMB2_TRANSPORT_CAPABILITIES", 

179 0x0007: "SMB2_RDMA_TRANSFORM_CAPABILITIES", 

180 0x0008: "SMB2_SIGNING_CAPABILITIES", 

181} 

182 

183# FlagField 

184SMB2_CAPABILITIES = { 

185 0x00000001: "DFS", 

186 0x00000002: "LEASING", 

187 0x00000004: "LARGE_MTU", 

188 0x00000008: "MULTI_CHANNEL", 

189 0x00000010: "PERSISTENT_HANDLES", 

190 0x00000020: "DIRECTORY_LEASING", 

191 0x00000040: "ENCRYPTION", 

192} 

193SMB2_SECURITY_MODE = { 

194 0x01: "SIGNING_ENABLED", 

195 0x02: "SIGNING_REQUIRED", 

196} 

197 

198# [MS-SMB2] 2.2.3.1.3 

199SMB2_COMPRESSION_ALGORITHMS = { 

200 0x0000: "None", 

201 0x0001: "LZNT1", 

202 0x0002: "LZ77", 

203 0x0003: "LZ77 + Huffman", 

204 0x0004: "Pattern_V1", 

205} 

206 

207# [MS-SMB2] sect 2.2.3.1.2 

208SMB2_ENCRYPTION_CIPHERS = { 

209 0x0001: "AES-128-CCM", 

210 0x0002: "AES-128-GCM", 

211 0x0003: "AES-256-CCM", 

212 0x0004: "AES-256-GCM", 

213} 

214 

215# [MS-SMB2] sect 2.2.3.1.7 

216SMB2_SIGNING_ALGORITHMS = { 

217 0x0000: "HMAC-SHA256", 

218 0x0001: "AES-CMAC", 

219 0x0002: "AES-GMAC", 

220} 

221 

222# [MS-SMB2] sect 2.2.3.1.1 

223SMB2_HASH_ALGORITHMS = { 

224 0x0001: "SHA-512", 

225} 

226 

227# sect [MS-SMB2] 2.2.13.1.1 

228SMB2_ACCESS_FLAGS_FILE = { 

229 0x00000001: "FILE_READ_DATA", 

230 0x00000002: "FILE_WRITE_DATA", 

231 0x00000004: "FILE_APPEND_DATA", 

232 0x00000008: "FILE_READ_EA", 

233 0x00000010: "FILE_WRITE_EA", 

234 0x00000040: "FILE_DELETE_CHILD", 

235 0x00000020: "FILE_EXECUTE", 

236 0x00000080: "FILE_READ_ATTRIBUTES", 

237 0x00000100: "FILE_WRITE_ATTRIBUTES", 

238 0x00010000: "DELETE", 

239 0x00020000: "READ_CONTROL", 

240 0x00040000: "WRITE_DAC", 

241 0x00080000: "WRITE_OWNER", 

242 0x00100000: "SYNCHRONIZE", 

243 0x01000000: "ACCESS_SYSTEM_SECURITY", 

244 0x02000000: "MAXIMUM_ALLOWED", 

245 0x10000000: "GENERIC_ALL", 

246 0x20000000: "GENERIC_EXECUTE", 

247 0x40000000: "GENERIC_WRITE", 

248 0x80000000: "GENERIC_READ", 

249} 

250 

251# sect [MS-SMB2] 2.2.13.1.2 

252SMB2_ACCESS_FLAGS_DIRECTORY = { 

253 0x00000001: "FILE_LIST_DIRECTORY", 

254 0x00000002: "FILE_ADD_FILE", 

255 0x00000004: "FILE_ADD_SUBDIRECTORY", 

256 0x00000008: "FILE_READ_EA", 

257 0x00000010: "FILE_WRITE_EA", 

258 0x00000020: "FILE_TRAVERSE", 

259 0x00000040: "FILE_DELETE_CHILD", 

260 0x00000080: "FILE_READ_ATTRIBUTES", 

261 0x00000100: "FILE_WRITE_ATTRIBUTES", 

262 0x00010000: "DELETE", 

263 0x00020000: "READ_CONTROL", 

264 0x00040000: "WRITE_DAC", 

265 0x00080000: "WRITE_OWNER", 

266 0x00100000: "SYNCHRONIZE", 

267 0x01000000: "ACCESS_SYSTEM_SECURITY", 

268 0x02000000: "MAXIMUM_ALLOWED", 

269 0x10000000: "GENERIC_ALL", 

270 0x20000000: "GENERIC_EXECUTE", 

271 0x40000000: "GENERIC_WRITE", 

272 0x80000000: "GENERIC_READ", 

273} 

274 

275# [MS-SRVS] sec 2.2.2.4 

276SRVSVC_SHARE_TYPES = { 

277 0x00000000: "DISKTREE", 

278 0x00000001: "PRINTQ", 

279 0x00000002: "DEVICE", 

280 0x00000003: "IPC", 

281 0x02000000: "CLUSTER_FS", 

282 0x04000000: "CLUSTER_SOFS", 

283 0x08000000: "CLUSTER_DFS", 

284} 

285 

286 

287# [MS-FSCC] sec 2.6 

288FileAttributes = { 

289 0x00000001: "FILE_ATTRIBUTE_READONLY", 

290 0x00000002: "FILE_ATTRIBUTE_HIDDEN", 

291 0x00000004: "FILE_ATTRIBUTE_SYSTEM", 

292 0x00000010: "FILE_ATTRIBUTE_DIRECTORY", 

293 0x00000020: "FILE_ATTRIBUTE_ARCHIVE", 

294 0x00000080: "FILE_ATTRIBUTE_NORMAL", 

295 0x00000100: "FILE_ATTRIBUTE_TEMPORARY", 

296 0x00000200: "FILE_ATTRIBUTE_SPARSE_FILE", 

297 0x00000400: "FILE_ATTRIBUTE_REPARSE_POINT", 

298 0x00000800: "FILE_ATTRIBUTE_COMPRESSED", 

299 0x00001000: "FILE_ATTRIBUTE_OFFLINE", 

300 0x00002000: "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED", 

301 0x00004000: "FILE_ATTRIBUTE_ENCRYPTED", 

302 0x00008000: "FILE_ATTRIBUTE_INTEGRITY_STREAM", 

303 0x00020000: "FILE_ATTRIBUTE_NO_SCRUB_DATA", 

304 0x00040000: "FILE_ATTRIBUTE_RECALL_ON_OPEN", 

305 0x00080000: "FILE_ATTRIBUTE_PINNED", 

306 0x00100000: "FILE_ATTRIBUTE_UNPINNED", 

307 0x00400000: "FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS", 

308} 

309 

310 

311# [MS-FSCC] sect 2.4 

312FileInformationClasses = { 

313 0x01: "FileDirectoryInformation", 

314 0x02: "FileFullDirectoryInformation", 

315 0x03: "FileBothDirectoryInformation", 

316 0x04: "FileBasicInformation", 

317 0x05: "FileStandardInformation", 

318 0x06: "FileInternalInformation", 

319 0x07: "FileEaInformation", 

320 0x08: "FileAccessInformation", 

321 0x0A: "FileRenameInformation", 

322 0x0E: "FilePositionInformation", 

323 0x10: "FileModeInformation", 

324 0x11: "FileAlignmentInformation", 

325 0x12: "FileAllInformation", 

326 0x22: "FileNetworkOpenInformation", 

327 0x25: "FileIdBothDirectoryInformation", 

328 0x26: "FileIdFullDirectoryInformation", 

329 0x0C: "FileNamesInformation", 

330 0x30: "FileNormalizedNameInformation", 

331 0x3C: "FileIdExtdDirectoryInformation", 

332} 

333_FileInformationClasses = {} 

334 

335 

336# [MS-FSCC] 2.1.7 FILE_NAME_INFORMATION 

337 

338 

339class FILE_NAME_INFORMATION(Packet): 

340 fields_desc = [ 

341 FieldLenField("FileNameLength", None, length_of="FileName", fmt="<I"), 

342 StrLenFieldUtf16("FileName", "", length_from=lambda pkt: pkt.FileNameLength), 

343 ] 

344 

345 def default_payload_class(self, s): 

346 return conf.padding_layer 

347 

348 

349# [MS-FSCC] 2.4.1 FileAccessInformation 

350 

351 

352class FileAccessInformation(Packet): 

353 fields_desc = [ 

354 FlagsField("AccessFlags", 0, -32, SMB2_ACCESS_FLAGS_FILE), 

355 ] 

356 

357 def default_payload_class(self, s): 

358 return conf.padding_layer 

359 

360 

361# [MS-FSCC] 2.4.3 FileAlignmentInformation 

362 

363 

364class FileAlignmentInformation(Packet): 

365 fields_desc = [ 

366 LEIntEnumField( 

367 "AccessFlags", 

368 0, 

369 { 

370 0x00000000: "FILE_BYTE_ALIGNMENT", 

371 0x00000001: "FILE_WORD_ALIGNMENT", 

372 0x00000003: "FILE_LONG_ALIGNMENT", 

373 0x00000007: "FILE_QUAD_ALIGNMENT", 

374 0x0000000F: "FILE_OCTA_ALIGNMENT", 

375 0x0000001F: "FILE_32_BYTE_ALIGNMENT", 

376 0x0000003F: "FILE_64_BYTE_ALIGNMENT", 

377 0x0000007F: "FILE_128_BYTE_ALIGNMENT", 

378 0x000000FF: "FILE_256_BYTE_ALIGNMENT", 

379 0x000001FF: "FILE_512_BYTE_ALIGNMENT", 

380 }, 

381 ), 

382 ] 

383 

384 def default_payload_class(self, s): 

385 return conf.padding_layer 

386 

387 

388# [MS-FSCC] 2.4.5 FileAlternateNameInformation 

389 

390 

391class FileAlternateNameInformation(Packet): 

392 fields_desc = [ 

393 FieldLenField("FileNameLength", None, length_of="FileName", fmt="<I"), 

394 StrLenFieldUtf16("FileName", b"", length_from=lambda pkt: pkt.FileNameLength), 

395 ] 

396 

397 

398# [MS-FSCC] 2.4.7 FileBasicInformation 

399 

400 

401class FileBasicInformation(Packet): 

402 fields_desc = [ 

403 UTCTimeField( 

404 "CreationTime", 

405 None, 

406 fmt="<Q", 

407 epoch=[1601, 1, 1, 0, 0, 0], 

408 custom_scaling=1e7, 

409 ), 

410 UTCTimeField( 

411 "LastAccessTime", 

412 None, 

413 fmt="<Q", 

414 epoch=[1601, 1, 1, 0, 0, 0], 

415 custom_scaling=1e7, 

416 ), 

417 UTCTimeField( 

418 "LastWriteTime", 

419 None, 

420 fmt="<Q", 

421 epoch=[1601, 1, 1, 0, 0, 0], 

422 custom_scaling=1e7, 

423 ), 

424 UTCTimeField( 

425 "ChangeTime", 

426 None, 

427 fmt="<Q", 

428 epoch=[1601, 1, 1, 0, 0, 0], 

429 custom_scaling=1e7, 

430 ), 

431 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes), 

432 IntField("Reserved", 0), 

433 ] 

434 

435 def default_payload_class(self, s): 

436 return conf.padding_layer 

437 

438 

439# [MS-FSCC] 2.4.12 FileEaInformation 

440 

441 

442class FileEaInformation(Packet): 

443 fields_desc = [ 

444 LEIntField("EaSize", 0), 

445 ] 

446 

447 def default_payload_class(self, s): 

448 return conf.padding_layer 

449 

450 

451# [MS-FSCC] 2.4.29 FileNetworkOpenInformation 

452 

453 

454class FileNetworkOpenInformation(Packet): 

455 fields_desc = [ 

456 UTCTimeField( 

457 "CreationTime", 

458 None, 

459 fmt="<Q", 

460 epoch=[1601, 1, 1, 0, 0, 0], 

461 custom_scaling=1e7, 

462 ), 

463 UTCTimeField( 

464 "LastAccessTime", 

465 None, 

466 fmt="<Q", 

467 epoch=[1601, 1, 1, 0, 0, 0], 

468 custom_scaling=1e7, 

469 ), 

470 UTCTimeField( 

471 "LastWriteTime", 

472 None, 

473 fmt="<Q", 

474 epoch=[1601, 1, 1, 0, 0, 0], 

475 custom_scaling=1e7, 

476 ), 

477 UTCTimeField( 

478 "ChangeTime", 

479 None, 

480 fmt="<Q", 

481 epoch=[1601, 1, 1, 0, 0, 0], 

482 custom_scaling=1e7, 

483 ), 

484 LELongField("AllocationSize", 4096), 

485 LELongField("EndOfFile", 0), 

486 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes), 

487 IntField("Reserved2", 0), 

488 ] 

489 

490 def default_payload_class(self, s): 

491 return conf.padding_layer 

492 

493 

494# [MS-FSCC] 2.4.8 FileBothDirectoryInformation 

495 

496 

497class FILE_BOTH_DIR_INFORMATION(Packet): 

498 fields_desc = ( 

499 [ 

500 LEIntField("Next", None), # 0 = no next entry 

501 LEIntField("FileIndex", 0), 

502 ] 

503 + ( 

504 FileNetworkOpenInformation.fields_desc[:4] 

505 + FileNetworkOpenInformation.fields_desc[4:6][::-1] 

506 + [FileNetworkOpenInformation.fields_desc[6]] 

507 ) 

508 + [ 

509 FieldLenField("FileNameLength", None, fmt="<I", length_of="FileName"), 

510 MultipleTypeField( 

511 # "If FILE_ATTRIBUTE_REPARSE_POINT is set in the FileAttributes field, 

512 # this field MUST contain a reparse tag as specified in section 

513 # 2.1.2.1." 

514 [ 

515 ( 

516 LEIntEnumField("EaSize", 0, REPARSE_TAGS), 

517 lambda pkt: pkt.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT, 

518 ) 

519 ], 

520 LEIntField("EaSize", 0), 

521 ), 

522 ByteField("ShortNameLength", 0), 

523 ByteField("Reserved1", 0), 

524 StrFixedLenField("ShortName", b"", length=24), 

525 PadField( 

526 StrLenFieldUtf16( 

527 "FileName", b".", length_from=lambda pkt: pkt.FileNameLength 

528 ), 

529 align=8, 

530 ), 

531 ] 

532 ) 

533 

534 def default_payload_class(self, s): 

535 return conf.padding_layer 

536 

537 

538class _NextPacketListField(PacketListField): 

539 def addfield(self, pkt, s, val): 

540 # we use this field to set NextEntryOffset 

541 res = b"" 

542 for i, v in enumerate(val): 

543 x = self.i2m(pkt, v) 

544 if v.Next is None and i != len(val) - 1: 

545 x = struct.pack("<I", len(x)) + x[4:] 

546 res += x 

547 return s + res 

548 

549 

550class FileBothDirectoryInformation(Packet): 

551 fields_desc = [ 

552 _NextPacketListField( 

553 "files", 

554 [], 

555 FILE_BOTH_DIR_INFORMATION, 

556 max_count=1000, 

557 ), 

558 ] 

559 

560 

561# [MS-FSCC] 2.4.14 FileFullDirectoryInformation 

562 

563 

564class FILE_FULL_DIR_INFORMATION(Packet): 

565 fields_desc = FILE_BOTH_DIR_INFORMATION.fields_desc[:11] + [ 

566 FILE_BOTH_DIR_INFORMATION.fields_desc[-1] 

567 ] 

568 

569 

570class FileFullDirectoryInformation(Packet): 

571 fields_desc = [ 

572 _NextPacketListField( 

573 "files", 

574 [], 

575 FILE_FULL_DIR_INFORMATION, 

576 max_count=1000, 

577 ), 

578 ] 

579 

580 

581# [MS-FSCC] 2.4.17 FileIdBothDirectoryInformation 

582 

583 

584class FILE_ID_BOTH_DIR_INFORMATION(Packet): 

585 fields_desc = FILE_BOTH_DIR_INFORMATION.fields_desc[:14] + [ 

586 LEShortField("Reserved2", 0), 

587 LELongField("FileId", 0), 

588 FILE_BOTH_DIR_INFORMATION.fields_desc[-1], 

589 ] 

590 

591 def default_payload_class(self, s): 

592 return conf.padding_layer 

593 

594 

595class FileIdBothDirectoryInformation(Packet): 

596 fields_desc = [ 

597 _NextPacketListField( 

598 "files", 

599 [], 

600 FILE_ID_BOTH_DIR_INFORMATION, 

601 max_count=1000, # > 65535 / len(FILE_ID_BOTH_DIR_INFORMATION()) 

602 ), 

603 ] 

604 

605 

606# [MS-FSCC] 2.4.22 FileInternalInformation 

607 

608 

609class FileInternalInformation(Packet): 

610 fields_desc = [ 

611 LELongField("IndexNumber", 0), 

612 ] 

613 

614 def default_payload_class(self, s): 

615 return conf.padding_layer 

616 

617 

618# [MS-FSCC] 2.4.26 FileModeInformation 

619 

620 

621class FileModeInformation(Packet): 

622 fields_desc = [ 

623 FlagsField( 

624 "Mode", 

625 0, 

626 -32, 

627 { 

628 0x00000002: "FILE_WRITE_TROUGH", 

629 0x00000004: "FILE_SEQUENTIAL_ONLY", 

630 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING", 

631 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT", 

632 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT", 

633 0x00001000: "FILE_DELETE_ON_CLOSE", 

634 }, 

635 ) 

636 ] 

637 

638 def default_payload_class(self, s): 

639 return conf.padding_layer 

640 

641 

642# [MS-FSCC] 2.4.35 FilePositionInformation 

643 

644 

645class FilePositionInformation(Packet): 

646 fields_desc = [ 

647 LELongField("CurrentByteOffset", 0), 

648 ] 

649 

650 def default_payload_class(self, s): 

651 return conf.padding_layer 

652 

653 

654# [MS-FSCC] 2.4.37 FileRenameInformation 

655 

656 

657class FileRenameInformation(Packet): 

658 fields_desc = [ 

659 YesNoByteField("ReplaceIfExists", False), 

660 XStrFixedLenField("Reserved", b"", length=7), 

661 LELongField("RootDirectory", 0), 

662 FieldLenField("FileNameLength", 0, length_of="FileName", fmt="<I"), 

663 StrLenFieldUtf16("FileName", b"", length_from=lambda pkt: pkt.FileNameLength), 

664 ] 

665 

666 def post_build(self, pkt, pay): 

667 # type: (bytes, bytes) -> bytes 

668 if len(pkt) < 24: 

669 # 'Length of this field MUST be the number of bytes required to make the 

670 # size of this structure at least 24.' 

671 pkt += (24 - len(pkt)) * b"\x00" 

672 return pkt + pay 

673 

674 def default_payload_class(self, s): 

675 return conf.padding_layer 

676 

677 

678_FileInformationClasses[0x0A] = FileRenameInformation 

679 

680 

681# [MS-FSCC] 2.4.41 FileStandardInformation 

682 

683 

684class FileStandardInformation(Packet): 

685 fields_desc = [ 

686 LELongField("AllocationSize", 4096), 

687 LELongField("EndOfFile", 0), 

688 LEIntField("NumberOfLinks", 1), 

689 ByteField("DeletePending", 0), 

690 ByteField("Directory", 0), 

691 ShortField("Reserved", 0), 

692 ] 

693 

694 def default_payload_class(self, s): 

695 return conf.padding_layer 

696 

697 

698# [MS-FSCC] 2.4.43 FileStreamInformation 

699 

700 

701class FileStreamInformation(Packet): 

702 fields_desc = [ 

703 LEIntField("Next", 0), 

704 FieldLenField("StreamNameLength", None, length_of="StreamName", fmt="<I"), 

705 LELongField("StreamSize", 0), 

706 LELongField("StreamAllocationSize", 4096), 

707 StrLenFieldUtf16( 

708 "StreamName", b"::$DATA", length_from=lambda pkt: pkt.StreamNameLength 

709 ), 

710 ] 

711 

712 

713# [MS-FSCC] 2.4.2 FileAllInformation 

714 

715 

716class FileAllInformation(Packet): 

717 fields_desc = [ 

718 PacketField("BasicInformation", FileBasicInformation(), FileBasicInformation), 

719 PacketField( 

720 "StandardInformation", FileStandardInformation(), FileStandardInformation 

721 ), 

722 PacketField( 

723 "InternalInformation", FileInternalInformation(), FileInternalInformation 

724 ), 

725 PacketField("EaInformation", FileEaInformation(), FileEaInformation), 

726 PacketField( 

727 "AccessInformation", FileAccessInformation(), FileAccessInformation 

728 ), 

729 PacketField( 

730 "PositionInformation", FilePositionInformation(), FilePositionInformation 

731 ), 

732 PacketField("ModeInformation", FileModeInformation(), FileModeInformation), 

733 PacketField( 

734 "AlignmentInformation", FileAlignmentInformation(), FileAlignmentInformation 

735 ), 

736 PacketField("NameInformation", FILE_NAME_INFORMATION(), FILE_NAME_INFORMATION), 

737 ] 

738 

739 

740# [MS-FSCC] 2.5.1 FileFsAttributeInformation 

741 

742 

743class FileFsAttributeInformation(Packet): 

744 fields_desc = [ 

745 FlagsField( 

746 "FileSystemAttributes", 

747 0x00C706FF, 

748 -32, 

749 { 

750 0x02000000: "FILE_SUPPORTS_USN_JOURNAL", 

751 0x01000000: "FILE_SUPPORTS_OPEN_BY_FILE_ID", 

752 0x00800000: "FILE_SUPPORTS_EXTENDED_ATTRIBUTES", 

753 0x00400000: "FILE_SUPPORTS_HARD_LINKS", 

754 0x00200000: "FILE_SUPPORTS_TRANSACTIONS", 

755 0x00100000: "FILE_SEQUENTIAL_WRITE_ONCE", 

756 0x00080000: "FILE_READ_ONLY_VOLUME", 

757 0x00040000: "FILE_NAMED_STREAMS", 

758 0x00020000: "FILE_SUPPORTS_ENCRYPTION", 

759 0x00010000: "FILE_SUPPORTS_OBJECT_IDS", 

760 0x00008000: "FILE_VOLUME_IS_COMPRESSED", 

761 0x00000100: "FILE_SUPPORTS_REMOTE_STORAGE", 

762 0x00000080: "FILE_SUPPORTS_REPARSE_POINTS", 

763 0x00000040: "FILE_SUPPORTS_SPARSE_FILES", 

764 0x00000020: "FILE_VOLUME_QUOTAS", 

765 0x00000010: "FILE_FILE_COMPRESSION", 

766 0x00000008: "FILE_PERSISTENT_ACLS", 

767 0x00000004: "FILE_UNICODE_ON_DISK", 

768 0x00000002: "FILE_CASE_PRESERVED_NAMES", 

769 0x00000001: "FILE_CASE_SENSITIVE_SEARCH", 

770 0x04000000: "FILE_SUPPORT_INTEGRITY_STREAMS", 

771 0x08000000: "FILE_SUPPORTS_BLOCK_REFCOUNTING", 

772 0x10000000: "FILE_SUPPORTS_SPARSE_VDL", 

773 }, 

774 ), 

775 LEIntField("MaximumComponentNameLength", 255), 

776 FieldLenField( 

777 "FileSystemNameLength", None, length_of="FileSystemName", fmt="<I" 

778 ), 

779 StrLenFieldUtf16( 

780 "FileSystemName", b"NTFS", length_from=lambda pkt: pkt.FileSystemNameLength 

781 ), 

782 ] 

783 

784 

785# [MS-FSCC] 2.5.8 FileFsSizeInformation 

786 

787 

788class FileFsSizeInformation(Packet): 

789 fields_desc = [ 

790 LELongField("TotalAllocationUnits", 10485760), 

791 LELongField("AvailableAllocationUnits", 1048576), 

792 LEIntField("SectorsPerAllocationUnit", 8), 

793 LEIntField("BytesPerSector", 512), 

794 ] 

795 

796 

797# [MS-FSCC] 2.5.9 FileFsVolumeInformation 

798 

799 

800class FileFsVolumeInformation(Packet): 

801 fields_desc = [ 

802 UTCTimeField( 

803 "VolumeCreationTime", 

804 None, 

805 fmt="<Q", 

806 epoch=[1601, 1, 1, 0, 0, 0], 

807 custom_scaling=1e7, 

808 ), 

809 LEIntField("VolumeSerialNumber", 0), 

810 LEIntField("VolumeLabelLength", 0), 

811 ByteField("SupportsObjects", 1), 

812 ByteField("Reserved", 0), 

813 StrNullFieldUtf16("VolumeLabel", b"C"), 

814 ] 

815 

816 

817# [MS-FSCC] 2.7.1 FILE_NOTIFY_INFORMATION 

818 

819 

820class FILE_NOTIFY_INFORMATION(Packet): 

821 fields_desc = [ 

822 IntField("NextEntryOffset", 0), 

823 LEIntEnumField( 

824 "Action", 

825 0, 

826 { 

827 0x00000001: "FILE_ACTION_ADDED", 

828 0x00000002: "FILE_ACTION_REMOVED", 

829 0x00000003: "FILE_ACTION_MODIFIED", 

830 0x00000004: "FILE_ACTION_RENAMED_OLD_NAME", 

831 0x00000005: "FILE_ACTION_RENAMED_NEW_NAME", 

832 0x00000006: "FILE_ACTION_ADDED_STREAM", 

833 0x00000007: "FILE_ACTION_REMOVED_STREAM", 

834 0x00000008: "FILE_ACTION_MODIFIED_STREAM", 

835 0x00000009: "FILE_ACTION_REMOVED_BY_DELETE", 

836 0x0000000A: "FILE_ACTION_ID_NOT_TUNNELLED", 

837 0x0000000B: "FILE_ACTION_TUNNELLED_ID_COLLISION", 

838 }, 

839 ), 

840 FieldLenField( 

841 "FileNameLength", 

842 None, 

843 length_of="FileName", 

844 fmt="<I", 

845 ), 

846 StrLenFieldUtf16("FileName", b"", length_from=lambda x: x.FileNameLength), 

847 StrLenField( 

848 "pad", 

849 b"", 

850 length_from=lambda x: ( 

851 (x.NextEntryOffset - x.FileNameLength) if x.NextEntryOffset else 0 

852 ), 

853 ), 

854 ] 

855 

856 def default_payload_class(self, s): 

857 return conf.padding_layer 

858 

859 

860_SMB2_CONFIG = [ 

861 ("BufferOffset", _NTLM_ENUM.OFFSET), 

862 ("Len", _NTLM_ENUM.LEN), 

863] 

864 

865 

866def _SMB2_post_build(self, p, pay_offset, fields): 

867 """Util function to build the offset and populate the lengths""" 

868 return _NTLM_post_build(self, p, pay_offset, fields, config=_SMB2_CONFIG) 

869 

870 

871# SMB2 sect 2.1 

872 

873 

874class DirectTCP(NBTSession): 

875 name = "Direct TCP" 

876 MAXLENGTH = 0xFFFFFF 

877 fields_desc = [ByteField("zero", 0), ThreeBytesField("LENGTH", None)] 

878 

879 

880# SMB2 sect 2.2.1.1 

881 

882 

883class SMB2_Header(Packet): 

884 __slots__ = ["_decrypted"] 

885 

886 name = "SMB2 Header" 

887 fields_desc = [ 

888 StrFixedLenField("Start", b"\xfeSMB", 4), 

889 LEShortField("StructureSize", 64), 

890 LEShortField("CreditCharge", 0), 

891 LEIntEnumField("Status", 0, STATUS_ERREF), 

892 LEShortEnumField("Command", 0, SMB2_COM), 

893 LEShortField("CreditRequest", 0), 

894 FlagsField( 

895 "Flags", 

896 0, 

897 -32, 

898 { 

899 0x00000001: "SMB2_FLAGS_SERVER_TO_REDIR", 

900 0x00000002: "SMB2_FLAGS_ASYNC_COMMAND", 

901 0x00000004: "SMB2_FLAGS_RELATED_OPERATIONS", 

902 0x00000008: "SMB2_FLAGS_SIGNED", 

903 0x10000000: "SMB2_FLAGS_DFS_OPERATIONS", 

904 0x20000000: "SMB2_FLAGS_REPLAY_OPERATION", 

905 }, 

906 ), 

907 XLEIntField("NextCommand", 0), 

908 LELongField("MID", 0), # MessageID 

909 # ASYNC 

910 ConditionalField( 

911 LELongField("AsyncId", 0), lambda pkt: pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND 

912 ), 

913 # SYNC 

914 ConditionalField( 

915 LEIntField("PID", 0), # Reserved, but PID per wireshark 

916 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND, 

917 ), 

918 ConditionalField( 

919 LEIntField("TID", 0), # TreeID 

920 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND, 

921 ), 

922 # COMMON 

923 LELongField("SessionId", 0), 

924 XStrFixedLenField("SecuritySignature", 0, length=16), 

925 ] 

926 

927 _SMB2_OK_RETURNCODES = ( 

928 # sect 3.3.4.4 

929 (0xC0000016, 0x0001), # STATUS_MORE_PROCESSING_REQUIRED 

930 (0x80000005, 0x0008), # STATUS_BUFFER_OVERFLOW (Read) 

931 (0x80000005, 0x0010), # STATUS_BUFFER_OVERFLOW (QueryInfo) 

932 (0x80000005, 0x000B), # STATUS_BUFFER_OVERFLOW (IOCTL) 

933 (0xC000000D, 0x000B), # STATUS_INVALID_PARAMETER 

934 (0x0000010C, 0x000F), # STATUS_NOTIFY_ENUM_DIR 

935 ) 

936 

937 def __init__(self, *args, **kwargs): 

938 # The parent passes whether this packet was decrypted or not. 

939 self._decrypted = kwargs.pop("_decrypted", False) 

940 super(SMB2_Header, self).__init__(*args, **kwargs) 

941 

942 def guess_payload_class(self, payload): 

943 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR and self.Status != 0x00000000: 

944 # Check status for responses 

945 if (self.Status, self.Command) not in SMB2_Header._SMB2_OK_RETURNCODES: 

946 return SMB2_Error_Response 

947 if self.Command == 0x0000: # Negotiate 

948 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

949 return SMB2_Negotiate_Protocol_Response 

950 return SMB2_Negotiate_Protocol_Request 

951 elif self.Command == 0x0001: # Setup 

952 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

953 return SMB2_Session_Setup_Response 

954 return SMB2_Session_Setup_Request 

955 elif self.Command == 0x0002: # Logoff 

956 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

957 return SMB2_Session_Logoff_Response 

958 return SMB2_Session_Logoff_Request 

959 elif self.Command == 0x0003: # TREE connect 

960 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

961 return SMB2_Tree_Connect_Response 

962 return SMB2_Tree_Connect_Request 

963 elif self.Command == 0x0004: # TREE disconnect 

964 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

965 return SMB2_Tree_Disconnect_Response 

966 return SMB2_Tree_Disconnect_Request 

967 elif self.Command == 0x0005: # Create 

968 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

969 return SMB2_Create_Response 

970 return SMB2_Create_Request 

971 elif self.Command == 0x0006: # Close 

972 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

973 return SMB2_Close_Response 

974 return SMB2_Close_Request 

975 elif self.Command == 0x0008: # Read 

976 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

977 return SMB2_Read_Response 

978 return SMB2_Read_Request 

979 elif self.Command == 0x0009: # Write 

980 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

981 return SMB2_Write_Response 

982 return SMB2_Write_Request 

983 elif self.Command == 0x000C: # Cancel 

984 return SMB2_Cancel_Request 

985 elif self.Command == 0x000D: # Echo 

986 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

987 return SMB2_Echo_Response 

988 return SMB2_Echo_Request 

989 elif self.Command == 0x000E: # Query directory 

990 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

991 return SMB2_Query_Directory_Response 

992 return SMB2_Query_Directory_Request 

993 elif self.Command == 0x000F: # Change Notify 

994 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

995 return SMB2_Change_Notify_Response 

996 return SMB2_Change_Notify_Request 

997 elif self.Command == 0x0010: # Query info 

998 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

999 return SMB2_Query_Info_Response 

1000 return SMB2_Query_Info_Request 

1001 elif self.Command == 0x0011: # Set info 

1002 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1003 return SMB2_Set_Info_Response 

1004 return SMB2_Set_Info_Request 

1005 elif self.Command == 0x000B: # IOCTL 

1006 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1007 return SMB2_IOCTL_Response 

1008 return SMB2_IOCTL_Request 

1009 return super(SMB2_Header, self).guess_payload_class(payload) 

1010 

1011 def _calc_signature( 

1012 self, s, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None 

1013 ): 

1014 """ 

1015 This function calculates the signature of a SMB2 packet. 

1016 Detail is from [MS-SMB2] 3.1.4.1 

1017 """ 

1018 if len(s) <= 64: 

1019 log_runtime.warning("Cannot sign invalid SMB packet !") 

1020 return s 

1021 if dialect in [0x0300, 0x0302, 0x0311]: # SMB 3 

1022 if dialect == 0x0311: # SMB 3.1.1 

1023 if IsClient is None: 

1024 raise Exception("SMB 3.1.1 needs a IsClient") 

1025 if SigningAlgorithmId is None: 

1026 SigningAlgorithmId = "AES-CMAC" # AES-128-CMAC 

1027 else: 

1028 SigningAlgorithmId = "AES-CMAC" # AES-128-CMAC 

1029 if "GMAC" in SigningAlgorithmId: 

1030 from cryptography.hazmat.primitives.ciphers.aead import AESGCM 

1031 

1032 aesgcm = AESGCM(SigningSessionKey) 

1033 nonce = struct.pack("<Q", self.MID) + struct.pack( 

1034 "<I", 

1035 (0 if IsClient else 1) | (0x8000000 if self.Command == 9 else 0), 

1036 ) 

1037 sig = aesgcm.encrypt(nonce, b"", s) 

1038 elif "CMAC" in SigningAlgorithmId: 

1039 from cryptography.hazmat.primitives import cmac 

1040 from cryptography.hazmat.primitives.ciphers import algorithms 

1041 

1042 c = cmac.CMAC(algorithms.AES(SigningSessionKey)) 

1043 c.update(s) 

1044 sig = c.finalize() 

1045 elif "HMAC" in SigningAlgorithmId: 

1046 from scapy.layers.tls.crypto.h_mac import Hmac_SHA256 

1047 

1048 sig = Hmac_SHA256(SigningSessionKey).digest(s) 

1049 sig = sig[:16] 

1050 else: 

1051 raise ValueError("Unknown SigningAlgorithmId") 

1052 elif dialect in [0x0210, 0x0202]: # SMB 2.1 or SMB 2.0.2 

1053 from scapy.layers.tls.crypto.h_mac import Hmac_SHA256 

1054 

1055 sig = Hmac_SHA256(SigningSessionKey).digest(s) 

1056 sig = sig[:16] 

1057 else: 

1058 log_runtime.warning("Unknown SMB Version %s ! Cannot sign." % dialect) 

1059 sig = b"\x00" * 16 

1060 return sig 

1061 

1062 def sign(self, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None): 

1063 """ 

1064 [MS-SMB2] 3.1.4.1 - Signing An Outgoing Message 

1065 """ 

1066 # Set the current signature to nul 

1067 self.SecuritySignature = b"\x00" * 16 

1068 # Calculate the signature 

1069 s = bytes(self) 

1070 self.SecuritySignature = self._calc_signature( 

1071 s, 

1072 dialect=dialect, 

1073 SigningSessionKey=SigningSessionKey, 

1074 SigningAlgorithmId=SigningAlgorithmId, 

1075 IsClient=IsClient, 

1076 ) 

1077 # we make sure the payload is static 

1078 self.payload = conf.raw_layer(load=s[64:]) 

1079 

1080 def verify( 

1081 self, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None 

1082 ): 

1083 """ 

1084 [MS-SMB2] sect 3.2.5.1.3 - Verifying the signature 

1085 """ 

1086 s = bytes(self) 

1087 # Set SecuritySignature to nul 

1088 s = s[:48] + b"\x00" * 16 + s[64:] 

1089 # Calculate the signature 

1090 sig = self._calc_signature( 

1091 s, 

1092 dialect=dialect, 

1093 SigningSessionKey=SigningSessionKey, 

1094 SigningAlgorithmId=SigningAlgorithmId, 

1095 IsClient=IsClient, 

1096 ) 

1097 if self.SecuritySignature != sig: 

1098 log_runtime.error("SMB signature is invalid !") 

1099 raise Exception("ERROR: SMB signature is invalid !") 

1100 

1101 def encrypt(self, dialect, EncryptionKey, CipherId): 

1102 """ 

1103 [MS-SMB2] sect 3.1.4.3 - Encrypting the Message 

1104 """ 

1105 if dialect < 0x0300: 

1106 raise Exception("Encryption is not supported on this SMB dialect !") 

1107 elif dialect < 0x0311 and CipherId != "AES-128-CCM": 

1108 raise Exception("CipherId is not supported on this SMB dialect !") 

1109 

1110 data = bytes(self) 

1111 smbt = SMB2_Transform_Header( 

1112 OriginalMessageSize=len(self), 

1113 SessionId=self.SessionId, 

1114 Flags=0x0001, 

1115 ) 

1116 if "GCM" in CipherId: 

1117 from cryptography.hazmat.primitives.ciphers.aead import AESGCM 

1118 

1119 nonce = os.urandom(12) 

1120 cipher = AESGCM(EncryptionKey) 

1121 elif "CCM" in CipherId: 

1122 from cryptography.hazmat.primitives.ciphers.aead import AESCCM 

1123 

1124 nonce = os.urandom(11) 

1125 cipher = AESCCM(EncryptionKey) 

1126 else: 

1127 raise Exception("Unknown CipherId !") 

1128 

1129 # Add nonce to header and build the auth data 

1130 smbt.Nonce = nonce 

1131 aad = bytes(smbt)[20:] 

1132 

1133 # Perform the actual encryption 

1134 data = cipher.encrypt(nonce, data, aad) 

1135 

1136 # Put the auth tag in the Signature field 

1137 smbt.Signature, data = data[-16:], data[:-16] 

1138 

1139 return smbt / data 

1140 

1141 

1142class _SMB2_Payload(Packet): 

1143 def do_dissect_payload(self, s): 

1144 # There can be padding between this layer and the next one 

1145 if self.underlayer and isinstance(self.underlayer, SMB2_Header): 

1146 if self.underlayer.NextCommand: 

1147 padlen = self.underlayer.NextCommand - (64 + len(self.raw_packet_cache)) 

1148 if padlen: 

1149 self.add_payload(s[:padlen]) 

1150 s = s[padlen:] 

1151 super(_SMB2_Payload, self).do_dissect_payload(s) 

1152 

1153 def answers(self, other): 

1154 return ( 

1155 isinstance(other, _SMB2_Payload) 

1156 and self.__class__ != other.__class__ 

1157 and (self.Command == other.Command or self.Command == -1) 

1158 ) 

1159 

1160 def guess_payload_class(self, s): 

1161 if self.underlayer and isinstance(self.underlayer, SMB2_Header): 

1162 if self.underlayer.NextCommand: 

1163 return SMB2_Header 

1164 return super(_SMB2_Payload, self).guess_payload_class(s) 

1165 

1166 

1167# sect 2.2.2 

1168 

1169 

1170class SMB2_Error_Response(_SMB2_Payload): 

1171 Command = -1 

1172 __slots__ = ["NTStatus"] # extra info 

1173 name = "SMB2 Error Response" 

1174 fields_desc = [ 

1175 XLEShortField("StructureSize", 0x09), 

1176 ByteField("ErrorContextCount", 0), 

1177 ByteField("Reserved", 0), 

1178 FieldLenField("ByteCount", None, fmt="<I", length_of="ErrorData"), 

1179 XStrLenField("ErrorData", b"", length_from=lambda pkt: pkt.ByteCount), 

1180 ] 

1181 

1182 

1183bind_top_down(SMB2_Header, SMB2_Error_Response, Flags=1) # SMB2_FLAGS_SERVER_TO_REDIR 

1184 

1185# sect 2.2.2.2.2 

1186 

1187 

1188class MOVE_DST_IPADDR(Packet): 

1189 fields_desc = [ 

1190 # Wireshark appears to get this wrong 

1191 LEIntEnumField("Type", 1, {1: "IPv4", 2: "IPv6"}), 

1192 IntField("Reserved", 0), 

1193 MultipleTypeField( 

1194 [(IP6Field("IPAddress", None), lambda pkt: pkt.Type == 2)], 

1195 IPField("IPAddress", None), 

1196 ), 

1197 ConditionalField( 

1198 # For IPv4 

1199 StrFixedLenField("Reserved2", b"", length=12), 

1200 lambda pkt: pkt.Type == 1, 

1201 ), 

1202 ] 

1203 

1204 def default_payload_class(self, payload): 

1205 return conf.padding_layer 

1206 

1207 

1208class SMB2_Error_Share_Redirect_Context_Response(_NTLMPayloadPacket): 

1209 name = "Share Redirect Error Context Response" 

1210 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

1211 fields_desc = [ 

1212 XLEIntField("StructureSize", 0x30), 

1213 LEIntEnumField("NotificationType", 3, {3: "SHARE_MOVE_NOTIFICATION"}), 

1214 XLEIntField("ResourceNameBufferOffset", None), 

1215 LEIntField("ResourceNameLen", None), 

1216 ShortField("Reserved", 0), 

1217 ShortEnumField("TargetType", 0, {0: "IP"}), 

1218 FieldLenField("IPAddrCount", None, fmt="<I", count_of="IPAddrMoveList"), 

1219 PacketListField( 

1220 "IPAddrMoveList", 

1221 [], 

1222 MOVE_DST_IPADDR, 

1223 count_from=lambda pkt: pkt.IPAddrCount, 

1224 ), 

1225 _NTLMPayloadField( 

1226 "Buffer", 

1227 lambda pkt: 24 + len(pkt.IPAddrMoveList) * 24, 

1228 [ 

1229 StrLenFieldUtf16( 

1230 "ResourceName", b"", length_from=lambda pkt: pkt.ResourceNameLen 

1231 ), 

1232 ], 

1233 ), 

1234 ] 

1235 

1236 def post_build(self, pkt, pay): 

1237 # type: (bytes, bytes) -> bytes 

1238 return ( 

1239 _SMB2_post_build( 

1240 self, 

1241 pkt, 

1242 24 + len(self.IPAddrMoveList) * 24, 

1243 { 

1244 "ResourceName": 8, 

1245 }, 

1246 ) 

1247 + pay 

1248 ) 

1249 

1250 

1251# sect 2.2.2.1 

1252 

1253 

1254class SMB2_Error_ContextResponse(Packet): 

1255 fields_desc = [ 

1256 FieldLenField("ErrorDatalength", None, fmt="<I", length_of="ErrorContextData"), 

1257 LEIntEnumField("ErrorId", 0, {0: "DEFAULT", 0x72645253: "SHARE_REDIRECT"}), 

1258 MultipleTypeField( 

1259 [ 

1260 ( 

1261 PacketField( 

1262 "ErrorContextData", 

1263 SMB2_Error_Share_Redirect_Context_Response(), 

1264 SMB2_Error_Share_Redirect_Context_Response, 

1265 ), 

1266 lambda pkt: pkt.ErrorId == 0x72645253, 

1267 ) 

1268 ], 

1269 XStrLenField( 

1270 "ErrorContextData", b"", length_from=lambda pkt: pkt.ErrorDatalength 

1271 ), 

1272 ), 

1273 ] 

1274 

1275 

1276# sect 2.2.3 

1277 

1278 

1279class SMB2_Negotiate_Context(Packet): 

1280 name = "SMB2 Negotiate Context" 

1281 fields_desc = [ 

1282 LEShortEnumField("ContextType", 0x0, SMB2_NEGOTIATE_CONTEXT_TYPES), 

1283 LenField("DataLength", None, fmt="<H"), 

1284 IntField("Reserved", 0), 

1285 ] 

1286 

1287 def default_payload_class(self, payload): 

1288 return conf.padding_layer 

1289 

1290 

1291class SMB2_Negotiate_Protocol_Request(_SMB2_Payload, _NTLMPayloadPacket): 

1292 name = "SMB2 Negotiate Protocol Request" 

1293 Command = 0x0000 

1294 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

1295 fields_desc = [ 

1296 XLEShortField("StructureSize", 0x24), 

1297 FieldLenField("DialectCount", None, fmt="<H", count_of="Dialects"), 

1298 # SecurityMode 

1299 FlagsField("SecurityMode", 0, -16, SMB2_SECURITY_MODE), 

1300 LEShortField("Reserved", 0), 

1301 # Capabilities 

1302 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES), 

1303 UUIDField("ClientGUID", 0x0, uuid_fmt=UUIDField.FORMAT_LE), 

1304 XLEIntField("NegotiateContextsBufferOffset", None), 

1305 LEShortField("NegotiateContextsCount", None), 

1306 ShortField("Reserved2", 0), 

1307 FieldListField( 

1308 "Dialects", 

1309 [0x0202], 

1310 LEShortEnumField("", 0x0, SMB_DIALECTS), 

1311 count_from=lambda pkt: pkt.DialectCount, 

1312 ), 

1313 _NTLMPayloadField( 

1314 "Buffer", 

1315 lambda pkt: 64 + 36 + len(pkt.Dialects) * 2, 

1316 [ 

1317 # Field only exists if Dialects contains 0x0311 

1318 FieldListField( 

1319 "NegotiateContexts", 

1320 [], 

1321 ReversePadField( 

1322 PacketField("Context", None, SMB2_Negotiate_Context), 

1323 8, 

1324 ), 

1325 count_from=lambda pkt: pkt.NegotiateContextsCount, 

1326 ), 

1327 ], 

1328 ), 

1329 ] 

1330 

1331 def post_build(self, pkt, pay): 

1332 # type: (bytes, bytes) -> bytes 

1333 return ( 

1334 _NTLM_post_build( 

1335 self, 

1336 pkt, 

1337 64 + 36 + len(self.Dialects) * 2, 

1338 { 

1339 "NegotiateContexts": 28, 

1340 }, 

1341 config=[ 

1342 ("BufferOffset", _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8), 

1343 ("Count", _NTLM_ENUM.COUNT), 

1344 ], 

1345 ) 

1346 + pay 

1347 ) 

1348 

1349 

1350bind_top_down( 

1351 SMB2_Header, 

1352 SMB2_Negotiate_Protocol_Request, 

1353 Command=0x0000, 

1354) 

1355 

1356# sect 2.2.3.1.1 

1357 

1358 

1359class SMB2_Preauth_Integrity_Capabilities(Packet): 

1360 name = "SMB2 Preauth Integrity Capabilities" 

1361 fields_desc = [ 

1362 # According to the spec, this field value must be greater than 0 

1363 # (cf Section 2.2.3.1.1 of MS-SMB2.pdf) 

1364 FieldLenField("HashAlgorithmCount", None, fmt="<H", count_of="HashAlgorithms"), 

1365 FieldLenField("SaltLength", None, fmt="<H", length_of="Salt"), 

1366 FieldListField( 

1367 "HashAlgorithms", 

1368 [0x0001], 

1369 LEShortEnumField( 

1370 "", 

1371 0x0, 

1372 SMB2_HASH_ALGORITHMS, 

1373 ), 

1374 count_from=lambda pkt: pkt.HashAlgorithmCount, 

1375 ), 

1376 XStrLenField("Salt", "", length_from=lambda pkt: pkt.SaltLength), 

1377 ] 

1378 

1379 def default_payload_class(self, payload): 

1380 return conf.padding_layer 

1381 

1382 

1383bind_layers( 

1384 SMB2_Negotiate_Context, SMB2_Preauth_Integrity_Capabilities, ContextType=0x0001 

1385) 

1386 

1387# sect 2.2.3.1.2 

1388 

1389 

1390class SMB2_Encryption_Capabilities(Packet): 

1391 name = "SMB2 Encryption Capabilities" 

1392 fields_desc = [ 

1393 # According to the spec, this field value must be greater than 0 

1394 # (cf Section 2.2.3.1.2 of MS-SMB2.pdf) 

1395 FieldLenField("CipherCount", None, fmt="<H", count_of="Ciphers"), 

1396 FieldListField( 

1397 "Ciphers", 

1398 [0x0001], 

1399 LEShortEnumField( 

1400 "", 

1401 0x0, 

1402 SMB2_ENCRYPTION_CIPHERS, 

1403 ), 

1404 count_from=lambda pkt: pkt.CipherCount, 

1405 ), 

1406 ] 

1407 

1408 def default_payload_class(self, payload): 

1409 return conf.padding_layer 

1410 

1411 

1412bind_layers(SMB2_Negotiate_Context, SMB2_Encryption_Capabilities, ContextType=0x0002) 

1413 

1414# sect 2.2.3.1.3 

1415 

1416 

1417class SMB2_Compression_Capabilities(Packet): 

1418 name = "SMB2 Compression Capabilities" 

1419 fields_desc = [ 

1420 FieldLenField( 

1421 "CompressionAlgorithmCount", 

1422 None, 

1423 fmt="<H", 

1424 count_of="CompressionAlgorithms", 

1425 ), 

1426 ShortField("Padding", 0x0), 

1427 LEIntEnumField( 

1428 "Flags", 

1429 0x0, 

1430 { 

1431 0x00000000: "SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE", 

1432 0x00000001: "SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED", 

1433 }, 

1434 ), 

1435 FieldListField( 

1436 "CompressionAlgorithms", 

1437 None, 

1438 LEShortEnumField("", 0x0, SMB2_COMPRESSION_ALGORITHMS), 

1439 count_from=lambda pkt: pkt.CompressionAlgorithmCount, 

1440 ), 

1441 ] 

1442 

1443 def default_payload_class(self, payload): 

1444 return conf.padding_layer 

1445 

1446 

1447bind_layers(SMB2_Negotiate_Context, SMB2_Compression_Capabilities, ContextType=0x0003) 

1448 

1449# sect 2.2.3.1.4 

1450 

1451 

1452class SMB2_Netname_Negotiate_Context_ID(Packet): 

1453 name = "SMB2 Netname Negotiate Context ID" 

1454 fields_desc = [ 

1455 StrLenFieldUtf16( 

1456 "NetName", "", length_from=lambda pkt: pkt.underlayer.DataLength 

1457 ) 

1458 ] 

1459 

1460 def default_payload_class(self, payload): 

1461 return conf.padding_layer 

1462 

1463 

1464bind_layers( 

1465 SMB2_Negotiate_Context, SMB2_Netname_Negotiate_Context_ID, ContextType=0x0005 

1466) 

1467 

1468# sect 2.2.3.1.5 

1469 

1470 

1471class SMB2_Transport_Capabilities(Packet): 

1472 name = "SMB2 Transport Capabilities" 

1473 fields_desc = [ 

1474 FlagsField( 

1475 "Flags", 

1476 0x0, 

1477 -32, 

1478 { 

1479 0x00000001: "SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY", 

1480 }, 

1481 ), 

1482 ] 

1483 

1484 def default_payload_class(self, payload): 

1485 return conf.padding_layer 

1486 

1487 

1488bind_layers(SMB2_Negotiate_Context, SMB2_Transport_Capabilities, ContextType=0x0006) 

1489 

1490# sect 2.2.3.1.6 

1491 

1492 

1493class SMB2_RDMA_Transform_Capabilities(Packet): 

1494 name = "SMB2 RDMA Transform Capabilities" 

1495 fields_desc = [ 

1496 FieldLenField("TransformCount", None, fmt="<H", count_of="RDMATransformIds"), 

1497 LEShortField("Reserved1", 0), 

1498 LEIntField("Reserved2", 0), 

1499 FieldListField( 

1500 "RDMATransformIds", 

1501 None, 

1502 LEShortEnumField( 

1503 "", 

1504 0x0, 

1505 { 

1506 0x0000: "SMB2_RDMA_TRANSFORM_NONE", 

1507 0x0001: "SMB2_RDMA_TRANSFORM_ENCRYPTION", 

1508 0x0002: "SMB2_RDMA_TRANSFORM_SIGNING", 

1509 }, 

1510 ), 

1511 count_from=lambda pkt: pkt.TransformCount, 

1512 ), 

1513 ] 

1514 

1515 def default_payload_class(self, payload): 

1516 return conf.padding_layer 

1517 

1518 

1519bind_layers( 

1520 SMB2_Negotiate_Context, SMB2_RDMA_Transform_Capabilities, ContextType=0x0007 

1521) 

1522 

1523# sect 2.2.3.1.7 

1524 

1525 

1526class SMB2_Signing_Capabilities(Packet): 

1527 name = "SMB2 Signing Capabilities" 

1528 fields_desc = [ 

1529 FieldLenField( 

1530 "SigningAlgorithmCount", None, fmt="<H", count_of="SigningAlgorithms" 

1531 ), 

1532 FieldListField( 

1533 "SigningAlgorithms", 

1534 None, 

1535 LEShortEnumField( 

1536 "", 

1537 0x0, 

1538 SMB2_SIGNING_ALGORITHMS, 

1539 ), 

1540 count_from=lambda pkt: pkt.SigningAlgorithmCount, 

1541 ), 

1542 ] 

1543 

1544 def default_payload_class(self, payload): 

1545 return conf.padding_layer 

1546 

1547 

1548bind_layers(SMB2_Negotiate_Context, SMB2_Signing_Capabilities, ContextType=0x0008) 

1549 

1550# sect 2.2.4 

1551 

1552 

1553class SMB2_Negotiate_Protocol_Response(_SMB2_Payload, _NTLMPayloadPacket): 

1554 name = "SMB2 Negotiate Protocol Response" 

1555 Command = 0x0000 

1556 OFFSET = 64 + 64 

1557 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

1558 fields_desc = [ 

1559 XLEShortField("StructureSize", 0x41), 

1560 FlagsField("SecurityMode", 0, -16, SMB2_SECURITY_MODE), 

1561 LEShortEnumField("DialectRevision", 0x0, SMB_DIALECTS), 

1562 LEShortField("NegotiateContextsCount", None), 

1563 UUIDField("GUID", 0x0, uuid_fmt=UUIDField.FORMAT_LE), 

1564 # Capabilities 

1565 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES), 

1566 LEIntField("MaxTransactionSize", 65536), 

1567 LEIntField("MaxReadSize", 65536), 

1568 LEIntField("MaxWriteSize", 65536), 

1569 UTCTimeField( 

1570 "ServerTime", 

1571 None, 

1572 fmt="<Q", 

1573 epoch=[1601, 1, 1, 0, 0, 0], 

1574 custom_scaling=1e7, 

1575 ), 

1576 UTCTimeField( 

1577 "ServerStartTime", 

1578 None, 

1579 fmt="<Q", 

1580 epoch=[1601, 1, 1, 0, 0, 0], 

1581 custom_scaling=1e7, 

1582 ), 

1583 XLEShortField("SecurityBlobBufferOffset", None), 

1584 LEShortField("SecurityBlobLen", None), 

1585 XLEIntField("NegotiateContextsBufferOffset", None), 

1586 _NTLMPayloadField( 

1587 "Buffer", 

1588 OFFSET, 

1589 [ 

1590 PacketLenField( 

1591 "SecurityBlob", 

1592 None, 

1593 GSSAPI_BLOB, 

1594 length_from=lambda x: x.SecurityBlobLen, 

1595 ), 

1596 # Field only exists if Dialect is 0x0311 

1597 FieldListField( 

1598 "NegotiateContexts", 

1599 [], 

1600 ReversePadField( 

1601 PacketField("Context", None, SMB2_Negotiate_Context), 

1602 8, 

1603 ), 

1604 count_from=lambda pkt: pkt.NegotiateContextsCount, 

1605 ), 

1606 ], 

1607 force_order=["SecurityBlob", "NegotiateContexts"], 

1608 ), 

1609 ] 

1610 

1611 def post_build(self, pkt, pay): 

1612 # type: (bytes, bytes) -> bytes 

1613 pkt = _NTLM_post_build( 

1614 self, 

1615 pkt, 

1616 self.OFFSET, 

1617 { 

1618 "SecurityBlob": 56, 

1619 "NegotiateContexts": 60, 

1620 }, 

1621 config=[ 

1622 ( 

1623 "BufferOffset", 

1624 { 

1625 "SecurityBlob": _NTLM_ENUM.OFFSET, 

1626 "NegotiateContexts": _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8, 

1627 }, 

1628 ), 

1629 ], 

1630 ) 

1631 if getattr(self, "SecurityBlob", None): 

1632 if self.SecurityBlobLen is None: 

1633 pkt = pkt[:58] + struct.pack("<H", len(self.SecurityBlob)) + pkt[60:] 

1634 if getattr(self, "NegotiateContexts", None): 

1635 if self.NegotiateContextsCount is None: 

1636 pkt = pkt[:6] + struct.pack("<H", len(self.NegotiateContexts)) + pkt[8:] 

1637 return pkt + pay 

1638 

1639 

1640bind_top_down( 

1641 SMB2_Header, 

1642 SMB2_Negotiate_Protocol_Response, 

1643 Command=0x0000, 

1644 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

1645) 

1646 

1647# sect 2.2.5 

1648 

1649 

1650class SMB2_Session_Setup_Request(_SMB2_Payload, _NTLMPayloadPacket): 

1651 name = "SMB2 Session Setup Request" 

1652 Command = 0x0001 

1653 OFFSET = 24 + 64 

1654 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

1655 fields_desc = [ 

1656 XLEShortField("StructureSize", 0x19), 

1657 FlagsField("Flags", 0, -8, ["SMB2_SESSION_FLAG_BINDING"]), 

1658 FlagsField("SecurityMode", 0, -8, SMB2_SECURITY_MODE), 

1659 FlagsField("Capabilities", 0, -32, SMB2_CAPABILITIES), 

1660 LEIntField("Channel", 0), 

1661 XLEShortField("SecurityBlobBufferOffset", None), 

1662 LEShortField("SecurityBlobLen", None), 

1663 XLELongField("PreviousSessionId", 0), 

1664 _NTLMPayloadField( 

1665 "Buffer", 

1666 OFFSET, 

1667 [ 

1668 PacketField("SecurityBlob", None, GSSAPI_BLOB), 

1669 ], 

1670 ), 

1671 ] 

1672 

1673 def post_build(self, pkt, pay): 

1674 # type: (bytes, bytes) -> bytes 

1675 return ( 

1676 _SMB2_post_build( 

1677 self, 

1678 pkt, 

1679 self.OFFSET, 

1680 { 

1681 "SecurityBlob": 12, 

1682 }, 

1683 ) 

1684 + pay 

1685 ) 

1686 

1687 

1688bind_top_down( 

1689 SMB2_Header, 

1690 SMB2_Session_Setup_Request, 

1691 Command=0x0001, 

1692) 

1693 

1694# sect 2.2.6 

1695 

1696 

1697class SMB2_Session_Setup_Response(_SMB2_Payload, _NTLMPayloadPacket): 

1698 name = "SMB2 Session Setup Response" 

1699 Command = 0x0001 

1700 OFFSET = 8 + 64 

1701 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

1702 fields_desc = [ 

1703 XLEShortField("StructureSize", 0x9), 

1704 FlagsField( 

1705 "SessionFlags", 

1706 0, 

1707 -16, 

1708 { 

1709 0x0001: "IS_GUEST", 

1710 0x0002: "IS_NULL", 

1711 0x0004: "ENCRYPT_DATA", 

1712 }, 

1713 ), 

1714 XLEShortField("SecurityBufferOffset", None), 

1715 LEShortField("SecurityLen", None), 

1716 _NTLMPayloadField( 

1717 "Buffer", 

1718 OFFSET, 

1719 [ 

1720 PacketField("Security", None, GSSAPI_BLOB), 

1721 ], 

1722 ), 

1723 ] 

1724 

1725 def __getattr__(self, attr): 

1726 # Ease SMB1 backward compatibility 

1727 if attr == "SecurityBlob": 

1728 return ( 

1729 super(SMB2_Session_Setup_Response, self).__getattr__("Buffer") 

1730 or [(None, None)] 

1731 )[0][1] 

1732 return super(SMB2_Session_Setup_Response, self).__getattr__(attr) 

1733 

1734 def setfieldval(self, attr, val): 

1735 if attr == "SecurityBlob": 

1736 return super(SMB2_Session_Setup_Response, self).setfieldval( 

1737 "Buffer", [("Security", val)] 

1738 ) 

1739 return super(SMB2_Session_Setup_Response, self).setfieldval(attr, val) 

1740 

1741 def post_build(self, pkt, pay): 

1742 # type: (bytes, bytes) -> bytes 

1743 return ( 

1744 _SMB2_post_build( 

1745 self, 

1746 pkt, 

1747 self.OFFSET, 

1748 { 

1749 "Security": 4, 

1750 }, 

1751 ) 

1752 + pay 

1753 ) 

1754 

1755 

1756bind_top_down( 

1757 SMB2_Header, 

1758 SMB2_Session_Setup_Response, 

1759 Command=0x0001, 

1760 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

1761) 

1762 

1763# sect 2.2.7 

1764 

1765 

1766class SMB2_Session_Logoff_Request(_SMB2_Payload): 

1767 name = "SMB2 LOGOFF Request" 

1768 Command = 0x0002 

1769 fields_desc = [ 

1770 XLEShortField("StructureSize", 0x4), 

1771 ShortField("reserved", 0), 

1772 ] 

1773 

1774 

1775bind_top_down( 

1776 SMB2_Header, 

1777 SMB2_Session_Logoff_Request, 

1778 Command=0x0002, 

1779) 

1780 

1781# sect 2.2.8 

1782 

1783 

1784class SMB2_Session_Logoff_Response(_SMB2_Payload): 

1785 name = "SMB2 LOGOFF Request" 

1786 Command = 0x0002 

1787 fields_desc = [ 

1788 XLEShortField("StructureSize", 0x4), 

1789 ShortField("reserved", 0), 

1790 ] 

1791 

1792 

1793bind_top_down( 

1794 SMB2_Header, 

1795 SMB2_Session_Logoff_Response, 

1796 Command=0x0002, 

1797 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

1798) 

1799 

1800# sect 2.2.9 

1801 

1802 

1803class SMB2_Tree_Connect_Request(_SMB2_Payload, _NTLMPayloadPacket): 

1804 name = "SMB2 TREE_CONNECT Request" 

1805 Command = 0x0003 

1806 OFFSET = 8 + 64 

1807 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

1808 fields_desc = [ 

1809 XLEShortField("StructureSize", 0x9), 

1810 FlagsField( 

1811 "Flags", 

1812 0, 

1813 -16, 

1814 ["CLUSTER_RECONNECT", "REDIRECT_TO_OWNER", "EXTENSION_PRESENT"], 

1815 ), 

1816 XLEShortField("PathBufferOffset", None), 

1817 LEShortField("PathLen", None), 

1818 _NTLMPayloadField( 

1819 "Buffer", 

1820 OFFSET, 

1821 [ 

1822 StrFieldUtf16("Path", b""), 

1823 ], 

1824 ), 

1825 ] 

1826 

1827 def post_build(self, pkt, pay): 

1828 # type: (bytes, bytes) -> bytes 

1829 return ( 

1830 _SMB2_post_build( 

1831 self, 

1832 pkt, 

1833 self.OFFSET, 

1834 { 

1835 "Path": 4, 

1836 }, 

1837 ) 

1838 + pay 

1839 ) 

1840 

1841 

1842bind_top_down( 

1843 SMB2_Header, 

1844 SMB2_Tree_Connect_Request, 

1845 Command=0x0003, 

1846) 

1847 

1848# sect 2.2.10 

1849 

1850 

1851class SMB2_Tree_Connect_Response(_SMB2_Payload): 

1852 name = "SMB2 TREE_CONNECT Response" 

1853 Command = 0x0003 

1854 fields_desc = [ 

1855 XLEShortField("StructureSize", 0x10), 

1856 ByteEnumField("ShareType", 0, {0x01: "DISK", 0x02: "PIPE", 0x03: "PRINT"}), 

1857 ByteField("Reserved", 0), 

1858 FlagsField( 

1859 "ShareFlags", 

1860 0x30, 

1861 -32, 

1862 { 

1863 0x00000010: "AUTO_CACHING", 

1864 0x00000020: "VDO_CACHING", 

1865 0x00000030: "NO_CACHING", 

1866 0x00000001: "DFS", 

1867 0x00000002: "DFS_ROOT", 

1868 0x00000100: "RESTRICT_EXCLUSIVE_OPENS", 

1869 0x00000200: "FORCE_SHARED_DELETE", 

1870 0x00000400: "ALLOW_NAMESPACE_CACHING", 

1871 0x00000800: "ACCESS_BASED_DIRECTORY_ENUM", 

1872 0x00001000: "FORCE_LEVELII_OPLOCK", 

1873 0x00002000: "ENABLE_HASH_V1", 

1874 0x00004000: "ENABLE_HASH_V2", 

1875 0x00008000: "ENCRYPT_DATA", 

1876 0x00040000: "IDENTITY_REMOTING", 

1877 0x00100000: "COMPRESS_DATA", 

1878 }, 

1879 ), 

1880 FlagsField( 

1881 "Capabilities", 

1882 0, 

1883 -32, 

1884 { 

1885 0x00000008: "DFS", 

1886 0x00000010: "CONTINUOUS_AVAILABILITY", 

1887 0x00000020: "SCALEOUT", 

1888 0x00000040: "CLUSTER", 

1889 0x00000080: "ASYMMETRIC", 

1890 0x00000100: "REDIRECT_TO_OWNER", 

1891 }, 

1892 ), 

1893 FlagsField("MaximalAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE), 

1894 ] 

1895 

1896 

1897bind_top_down(SMB2_Header, SMB2_Tree_Connect_Response, Command=0x0003, Flags=1) 

1898 

1899# sect 2.2.11 

1900 

1901 

1902class SMB2_Tree_Disconnect_Request(_SMB2_Payload): 

1903 name = "SMB2 TREE_DISCONNECT Request" 

1904 Command = 0x0004 

1905 fields_desc = [ 

1906 XLEShortField("StructureSize", 0x4), 

1907 XLEShortField("Reserved", 0), 

1908 ] 

1909 

1910 

1911bind_top_down(SMB2_Header, SMB2_Tree_Disconnect_Request, Command=0x0004) 

1912 

1913# sect 2.2.12 

1914 

1915 

1916class SMB2_Tree_Disconnect_Response(_SMB2_Payload): 

1917 name = "SMB2 TREE_DISCONNECT Response" 

1918 Command = 0x0004 

1919 fields_desc = [ 

1920 XLEShortField("StructureSize", 0x4), 

1921 XLEShortField("Reserved", 0), 

1922 ] 

1923 

1924 

1925bind_top_down(SMB2_Header, SMB2_Tree_Disconnect_Response, Command=0x0004, Flags=1) 

1926 

1927 

1928# sect 2.2.14.1 

1929 

1930 

1931class SMB2_FILEID(Packet): 

1932 fields_desc = [XLELongField("Persistent", 0), XLELongField("Volatile", 0)] 

1933 

1934 def __hash__(self): 

1935 return self.Persistent + self.Volatile << 64 

1936 

1937 def default_payload_class(self, payload): 

1938 return conf.padding_layer 

1939 

1940 

1941# sect 2.2.14.2 

1942 

1943 

1944class SMB2_CREATE_DURABLE_HANDLE_RESPONSE(Packet): 

1945 fields_desc = [ 

1946 XStrFixedLenField("Reserved", b"\x00" * 8, length=8), 

1947 ] 

1948 

1949 

1950class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE(Packet): 

1951 fields_desc = [ 

1952 LEIntEnumField("QueryStatus", 0, STATUS_ERREF), 

1953 FlagsField("MaximalAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE), 

1954 ] 

1955 

1956 

1957class SMB2_CREATE_QUERY_ON_DISK_ID(Packet): 

1958 fields_desc = [ 

1959 XLELongField("DiskFileId", 0), 

1960 XLELongField("VolumeId", 0), 

1961 XStrFixedLenField("Reserved", b"", length=16), 

1962 ] 

1963 

1964 

1965class SMB2_CREATE_RESPONSE_LEASE(Packet): 

1966 fields_desc = [ 

1967 UUIDField("LeaseKey", None), 

1968 FlagsField( 

1969 "LeaseState", 

1970 0x7, 

1971 -32, 

1972 { 

1973 0x01: "SMB2_LEASE_READ_CACHING", 

1974 0x02: "SMB2_LEASE_HANDLE_CACHING", 

1975 0x04: "SMB2_LEASE_WRITE_CACHING", 

1976 }, 

1977 ), 

1978 FlagsField( 

1979 "LeaseFlags", 

1980 0, 

1981 -32, 

1982 { 

1983 0x02: "SMB2_LEASE_FLAG_BREAK_IN_PROGRESS", 

1984 0x04: "SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET", 

1985 }, 

1986 ), 

1987 LELongField("LeaseDuration", 0), 

1988 ] 

1989 

1990 

1991class SMB2_CREATE_RESPONSE_LEASE_V2(Packet): 

1992 fields_desc = [ 

1993 SMB2_CREATE_RESPONSE_LEASE, 

1994 UUIDField("ParentLeaseKey", None), 

1995 LEShortField("Epoch", 0), 

1996 LEShortField("Reserved", 0), 

1997 ] 

1998 

1999 

2000class SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2(Packet): 

2001 fields_desc = [ 

2002 LEIntField("Timeout", 0), 

2003 FlagsField( 

2004 "Flags", 

2005 0, 

2006 -32, 

2007 { 

2008 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT", 

2009 }, 

2010 ), 

2011 ] 

2012 

2013 

2014# sect 2.2.13 

2015 

2016 

2017class SMB2_CREATE_DURABLE_HANDLE_REQUEST(Packet): 

2018 fields_desc = [ 

2019 XStrFixedLenField("DurableRequest", b"", length=16), 

2020 ] 

2021 

2022 

2023class SMB2_CREATE_DURABLE_HANDLE_RECONNECT(Packet): 

2024 fields_desc = [ 

2025 PacketField("Data", SMB2_FILEID(), SMB2_FILEID), 

2026 ] 

2027 

2028 

2029class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST(Packet): 

2030 fields_desc = [ 

2031 LELongField("Timestamp", 0), 

2032 ] 

2033 

2034 

2035class SMB2_CREATE_ALLOCATION_SIZE(Packet): 

2036 fields_desc = [ 

2037 LELongField("AllocationSize", 0), 

2038 ] 

2039 

2040 

2041class SMB2_CREATE_TIMEWARP_TOKEN(Packet): 

2042 fields_desc = [ 

2043 LELongField("Timestamp", 0), 

2044 ] 

2045 

2046 

2047class SMB2_CREATE_REQUEST_LEASE(Packet): 

2048 fields_desc = [ 

2049 SMB2_CREATE_RESPONSE_LEASE, 

2050 ] 

2051 

2052 

2053class SMB2_CREATE_REQUEST_LEASE_V2(Packet): 

2054 fields_desc = [ 

2055 SMB2_CREATE_RESPONSE_LEASE_V2, 

2056 ] 

2057 

2058 

2059class SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2(Packet): 

2060 fields_desc = [ 

2061 SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2, 

2062 XStrFixedLenField("Reserved", b"", length=8), 

2063 UUIDField("CreateGuid", 0x0, uuid_fmt=UUIDField.FORMAT_LE), 

2064 ] 

2065 

2066 

2067class SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2(Packet): 

2068 fields_desc = [ 

2069 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

2070 UUIDField("CreateGuid", 0x0, uuid_fmt=UUIDField.FORMAT_LE), 

2071 FlagsField( 

2072 "Flags", 

2073 0, 

2074 -32, 

2075 { 

2076 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT", 

2077 }, 

2078 ), 

2079 ] 

2080 

2081 

2082class SMB2_CREATE_APP_INSTANCE_ID(Packet): 

2083 fields_desc = [ 

2084 XLEShortField("StructureSize", 0x14), 

2085 LEShortField("Reserved", 0), 

2086 XStrFixedLenField("AppInstanceId", b"", length=16), 

2087 ] 

2088 

2089 

2090class SMB2_CREATE_APP_INSTANCE_VERSION(Packet): 

2091 fields_desc = [ 

2092 XLEShortField("StructureSize", 0x18), 

2093 LEShortField("Reserved", 0), 

2094 LEIntField("Padding", 0), 

2095 LELongField("AppInstanceVersionHigh", 0), 

2096 LELongField("AppInstanceVersionLow", 0), 

2097 ] 

2098 

2099 

2100class SMB2_Create_Context(_NTLMPayloadPacket): 

2101 name = "SMB2 CREATE CONTEXT" 

2102 OFFSET = 16 

2103 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2104 fields_desc = [ 

2105 LEIntField("Next", None), 

2106 XLEShortField("NameBufferOffset", None), 

2107 LEShortField("NameLen", None), 

2108 ShortField("Reserved", 0), 

2109 XLEShortField("DataBufferOffset", None), 

2110 LEIntField("DataLen", None), 

2111 _NTLMPayloadField( 

2112 "Buffer", 

2113 OFFSET, 

2114 [ 

2115 PadField( 

2116 StrLenField("Name", b"", length_from=lambda pkt: pkt.NameLen), 

2117 8, 

2118 ), 

2119 # Must be padded on 8-octet alignment 

2120 PacketLenField( 

2121 "Data", None, conf.raw_layer, length_from=lambda pkt: pkt.DataLen 

2122 ), 

2123 ], 

2124 force_order=["Name", "Data"], 

2125 ), 

2126 StrLenField( 

2127 "pad", 

2128 b"", 

2129 length_from=lambda x: ( 

2130 ( 

2131 x.Next 

2132 - max( 

2133 x.DataBufferOffset + x.DataLen, x.NameBufferOffset + x.NameLen 

2134 ) 

2135 ) 

2136 if x.Next 

2137 else 0 

2138 ), 

2139 ), 

2140 ] 

2141 

2142 def post_dissect(self, s): 

2143 if not self.DataLen: 

2144 return s 

2145 try: 

2146 if isinstance(self.parent, SMB2_Create_Request): 

2147 data_cls = { 

2148 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_REQUEST, 

2149 b"DHnC": SMB2_CREATE_DURABLE_HANDLE_RECONNECT, 

2150 b"AISi": SMB2_CREATE_ALLOCATION_SIZE, 

2151 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 

2152 b"TWrp": SMB2_CREATE_TIMEWARP_TOKEN, 

2153 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID, 

2154 b"RqLs": SMB2_CREATE_REQUEST_LEASE, 

2155 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, 

2156 b"DH2C": SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, 

2157 # 3.1.1 only 

2158 b"E\xbc\xa6j\xef\xa7\xf7J\x90\x08\xfaF.\x14Mt": SMB2_CREATE_APP_INSTANCE_ID, # noqa: E501 

2159 b"\xb9\x82\xd0\xb7;V\x07O\xa0{RJ\x81\x16\xa0\x10": SMB2_CREATE_APP_INSTANCE_VERSION, # noqa: E501 

2160 }[self.Name] 

2161 if self.Name == b"RqLs" and self.DataLen > 32: 

2162 data_cls = SMB2_CREATE_REQUEST_LEASE_V2 

2163 elif isinstance(self.parent, SMB2_Create_Response): 

2164 data_cls = { 

2165 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_RESPONSE, 

2166 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE, 

2167 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID, 

2168 b"RqLs": SMB2_CREATE_RESPONSE_LEASE, 

2169 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2, 

2170 }[self.Name] 

2171 if self.Name == b"RqLs" and self.DataLen > 32: 

2172 data_cls = SMB2_CREATE_RESPONSE_LEASE_V2 

2173 else: 

2174 return s 

2175 except KeyError: 

2176 return s 

2177 self.Data = data_cls(self.Data.load) 

2178 return s 

2179 

2180 def default_payload_class(self, _): 

2181 return conf.padding_layer 

2182 

2183 def post_build(self, pkt, pay): 

2184 # type: (bytes, bytes) -> bytes 

2185 return ( 

2186 _NTLM_post_build( 

2187 self, 

2188 pkt, 

2189 self.OFFSET, 

2190 { 

2191 "Name": 4, 

2192 "Data": 10, 

2193 }, 

2194 config=[ 

2195 ( 

2196 "BufferOffset", 

2197 { 

2198 "Name": _NTLM_ENUM.OFFSET, 

2199 "Data": _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8, 

2200 }, 

2201 ), 

2202 ("Len", _NTLM_ENUM.LEN), 

2203 ], 

2204 ) 

2205 + pay 

2206 ) 

2207 

2208 

2209# sect 2.2.13 

2210 

2211SMB2_OPLOCK_LEVELS = { 

2212 0x00: "SMB2_OPLOCK_LEVEL_NONE", 

2213 0x01: "SMB2_OPLOCK_LEVEL_II", 

2214 0x08: "SMB2_OPLOCK_LEVEL_EXCLUSIVE", 

2215 0x09: "SMB2_OPLOCK_LEVEL_BATCH", 

2216 0xFF: "SMB2_OPLOCK_LEVEL_LEASE", 

2217} 

2218 

2219 

2220class SMB2_Create_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2221 name = "SMB2 CREATE Request" 

2222 Command = 0x0005 

2223 OFFSET = 56 + 64 

2224 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2225 fields_desc = [ 

2226 XLEShortField("StructureSize", 0x39), 

2227 ByteField("ShareType", 0), 

2228 ByteEnumField("RequestedOplockLevel", 0, SMB2_OPLOCK_LEVELS), 

2229 LEIntEnumField( 

2230 "ImpersonationLevel", 

2231 0, 

2232 { 

2233 0x00000000: "Anonymous", 

2234 0x00000001: "Identification", 

2235 0x00000002: "Impersonation", 

2236 0x00000003: "Delegate", 

2237 }, 

2238 ), 

2239 LELongField("SmbCreateFlags", 0), 

2240 LELongField("Reserved", 0), 

2241 FlagsField("DesiredAccess", 0, -32, SMB2_ACCESS_FLAGS_FILE), 

2242 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes), 

2243 FlagsField( 

2244 "ShareAccess", 

2245 0, 

2246 -32, 

2247 { 

2248 0x00000001: "FILE_SHARE_READ", 

2249 0x00000002: "FILE_SHARE_WRITE", 

2250 0x00000004: "FILE_SHARE_DELETE", 

2251 }, 

2252 ), 

2253 LEIntEnumField( 

2254 "CreateDisposition", 

2255 1, 

2256 { 

2257 0x00000000: "FILE_SUPERSEDE", 

2258 0x00000001: "FILE_OPEN", 

2259 0x00000002: "FILE_CREATE", 

2260 0x00000003: "FILE_OPEN_IF", 

2261 0x00000004: "FILE_OVERWRITE", 

2262 0x00000005: "FILE_OVERWRITE_IF", 

2263 }, 

2264 ), 

2265 FlagsField( 

2266 "CreateOptions", 

2267 0, 

2268 -32, 

2269 { 

2270 0x00000001: "FILE_DIRECTORY_FILE", 

2271 0x00000002: "FILE_WRITE_THROUGH", 

2272 0x00000004: "FILE_SEQUENTIAL_ONLY", 

2273 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING", 

2274 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT", 

2275 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT", 

2276 0x00000040: "FILE_NON_DIRECTORY_FILE", 

2277 0x00000100: "FILE_COMPLETE_IF_OPLOCKED", 

2278 0x00000200: "FILE_RANDOM_ACCESS", 

2279 0x00001000: "FILE_DELETE_ON_CLOSE", 

2280 0x00002000: "FILE_OPEN_BY_FILE_ID", 

2281 0x00004000: "FILE_OPEN_FOR_BACKUP_INTENT", 

2282 0x00008000: "FILE_NO_COMPRESSION", 

2283 0x00000400: "FILE_OPEN_REMOTE_INSTANCE", 

2284 0x00010000: "FILE_OPEN_REQUIRING_OPLOCK", 

2285 0x00020000: "FILE_DISALLOW_EXCLUSIVE", 

2286 0x00100000: "FILE_RESERVE_OPFILTER", 

2287 0x00200000: "FILE_OPEN_REPARSE_POINT", 

2288 0x00400000: "FILE_OPEN_NO_RECALL", 

2289 0x00800000: "FILE_OPEN_FOR_FREE_SPACE_QUERY", 

2290 }, 

2291 ), 

2292 XLEShortField("NameBufferOffset", None), 

2293 LEShortField("NameLen", None), 

2294 XLEIntField("CreateContextsBufferOffset", None), 

2295 LEIntField("CreateContextsLen", None), 

2296 _NTLMPayloadField( 

2297 "Buffer", 

2298 OFFSET, 

2299 [ 

2300 StrFieldUtf16("Name", b""), 

2301 _NextPacketListField( 

2302 "CreateContexts", 

2303 [], 

2304 SMB2_Create_Context, 

2305 length_from=lambda pkt: pkt.CreateContextsLen, 

2306 ), 

2307 ], 

2308 ), 

2309 ] 

2310 

2311 def post_build(self, pkt, pay): 

2312 # type: (bytes, bytes) -> bytes 

2313 if len(pkt) == 0x38: 

2314 # 'In the request, the Buffer field MUST be at least one byte in length.' 

2315 pkt += b"\x00" 

2316 return ( 

2317 _SMB2_post_build( 

2318 self, 

2319 pkt, 

2320 self.OFFSET, 

2321 { 

2322 "Name": 44, 

2323 "CreateContexts": 48, 

2324 }, 

2325 ) 

2326 + pay 

2327 ) 

2328 

2329 

2330bind_top_down(SMB2_Header, SMB2_Create_Request, Command=0x0005) 

2331 

2332 

2333# sect 2.2.14 

2334 

2335 

2336class SMB2_Create_Response(_SMB2_Payload, _NTLMPayloadPacket): 

2337 name = "SMB2 CREATE Response" 

2338 Command = 0x0005 

2339 OFFSET = 88 + 64 

2340 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2341 fields_desc = [ 

2342 XLEShortField("StructureSize", 0x59), 

2343 ByteEnumField("OplockLevel", 0, SMB2_OPLOCK_LEVELS), 

2344 FlagsField("Flags", 0, -8, {0x01: "SMB2_CREATE_FLAG_REPARSEPOINT"}), 

2345 LEIntEnumField( 

2346 "CreateAction", 

2347 1, 

2348 { 

2349 0x00000000: "FILE_SUPERSEDED", 

2350 0x00000001: "FILE_OPENED", 

2351 0x00000002: "FILE_CREATED", 

2352 0x00000003: "FILE_OVERWRITEN", 

2353 }, 

2354 ), 

2355 FileNetworkOpenInformation, 

2356 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

2357 XLEIntField("CreateContextsBufferOffset", None), 

2358 LEIntField("CreateContextsLen", None), 

2359 _NTLMPayloadField( 

2360 "Buffer", 

2361 OFFSET, 

2362 [ 

2363 _NextPacketListField( 

2364 "CreateContexts", 

2365 [], 

2366 SMB2_Create_Context, 

2367 length_from=lambda pkt: pkt.CreateContextsLen, 

2368 ), 

2369 ], 

2370 ), 

2371 ] 

2372 

2373 def post_build(self, pkt, pay): 

2374 # type: (bytes, bytes) -> bytes 

2375 return ( 

2376 _SMB2_post_build( 

2377 self, 

2378 pkt, 

2379 self.OFFSET, 

2380 { 

2381 "CreateContexts": 80, 

2382 }, 

2383 ) 

2384 + pay 

2385 ) 

2386 

2387 

2388bind_top_down(SMB2_Header, SMB2_Create_Response, Command=0x0005, Flags=1) 

2389 

2390# sect 2.2.15 

2391 

2392 

2393class SMB2_Close_Request(_SMB2_Payload): 

2394 name = "SMB2 CLOSE Request" 

2395 Command = 0x0006 

2396 fields_desc = [ 

2397 XLEShortField("StructureSize", 0x18), 

2398 FlagsField("Flags", 0, -16, ["SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB"]), 

2399 LEIntField("Reserved", 0), 

2400 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

2401 ] 

2402 

2403 

2404bind_top_down( 

2405 SMB2_Header, 

2406 SMB2_Close_Request, 

2407 Command=0x0006, 

2408) 

2409 

2410# sect 2.2.16 

2411 

2412 

2413class SMB2_Close_Response(_SMB2_Payload): 

2414 name = "SMB2 CLOSE Response" 

2415 Command = 0x0006 

2416 FileAttributes = 0 

2417 CreationTime = 0 

2418 LastAccessTime = 0 

2419 LastWriteTime = 0 

2420 ChangeTime = 0 

2421 fields_desc = [ 

2422 XLEShortField("StructureSize", 0x3C), 

2423 FlagsField("Flags", 0, -16, ["SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB"]), 

2424 LEIntField("Reserved", 0), 

2425 ] + FileNetworkOpenInformation.fields_desc[:7] 

2426 

2427 

2428bind_top_down( 

2429 SMB2_Header, 

2430 SMB2_Close_Response, 

2431 Command=0x0006, 

2432 Flags=1, 

2433) 

2434 

2435# sect 2.2.19 

2436 

2437 

2438class SMB2_Read_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2439 name = "SMB2 READ Request" 

2440 Command = 0x0008 

2441 OFFSET = 48 + 64 

2442 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2443 fields_desc = [ 

2444 XLEShortField("StructureSize", 0x31), 

2445 ByteField("Padding", 0x00), 

2446 FlagsField( 

2447 "Flags", 

2448 0, 

2449 -8, 

2450 { 

2451 0x01: "SMB2_READFLAG_READ_UNBUFFERED", 

2452 0x02: "SMB2_READFLAG_REQUEST_COMPRESSED", 

2453 }, 

2454 ), 

2455 LEIntField("Length", 4280), 

2456 LELongField("Offset", 0), 

2457 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

2458 LEIntField("MinimumCount", 0), 

2459 LEIntEnumField( 

2460 "Channel", 

2461 0, 

2462 { 

2463 0x00000000: "SMB2_CHANNEL_NONE", 

2464 0x00000001: "SMB2_CHANNEL_RDMA_V1", 

2465 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE", 

2466 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM", 

2467 }, 

2468 ), 

2469 LEIntField("RemainingBytes", 0), 

2470 LEShortField("ReadChannelInfoBufferOffset", None), 

2471 LEShortField("ReadChannelInfoLen", None), 

2472 _NTLMPayloadField( 

2473 "Buffer", 

2474 OFFSET, 

2475 [ 

2476 StrLenField( 

2477 "ReadChannelInfo", 

2478 b"", 

2479 length_from=lambda pkt: pkt.ReadChannelInfoLen, 

2480 ) 

2481 ], 

2482 ), 

2483 ] 

2484 

2485 def post_build(self, pkt, pay): 

2486 # type: (bytes, bytes) -> bytes 

2487 if len(pkt) == 0x30: 

2488 # 'The first byte of the Buffer field MUST be set to 0.' 

2489 pkt += b"\x00" 

2490 return ( 

2491 _SMB2_post_build( 

2492 self, 

2493 pkt, 

2494 self.OFFSET, 

2495 { 

2496 "ReadChannelInfo": 44, 

2497 }, 

2498 ) 

2499 + pay 

2500 ) 

2501 

2502 

2503bind_top_down( 

2504 SMB2_Header, 

2505 SMB2_Read_Request, 

2506 Command=0x0008, 

2507) 

2508 

2509# sect 2.2.20 

2510 

2511 

2512class SMB2_Read_Response(_SMB2_Payload, _NTLMPayloadPacket): 

2513 name = "SMB2 READ Response" 

2514 Command = 0x0008 

2515 OFFSET = 16 + 64 

2516 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2517 fields_desc = [ 

2518 XLEShortField("StructureSize", 0x11), 

2519 LEShortField("DataBufferOffset", None), 

2520 LEIntField("DataLen", None), 

2521 LEIntField("DataRemaining", 0), 

2522 FlagsField( 

2523 "Flags", 

2524 0, 

2525 -32, 

2526 { 

2527 0x01: "SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM", 

2528 }, 

2529 ), 

2530 _NTLMPayloadField( 

2531 "Buffer", 

2532 OFFSET, 

2533 [StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen)], 

2534 ), 

2535 ] 

2536 

2537 def post_build(self, pkt, pay): 

2538 # type: (bytes, bytes) -> bytes 

2539 return ( 

2540 _SMB2_post_build( 

2541 self, 

2542 pkt, 

2543 self.OFFSET, 

2544 { 

2545 "Data": 2, 

2546 }, 

2547 ) 

2548 + pay 

2549 ) 

2550 

2551 

2552bind_top_down( 

2553 SMB2_Header, 

2554 SMB2_Read_Response, 

2555 Command=0x0008, 

2556 Flags=1, 

2557) 

2558 

2559 

2560# sect 2.2.21 

2561 

2562 

2563class SMB2_Write_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2564 name = "SMB2 WRITE Request" 

2565 Command = 0x0009 

2566 OFFSET = 48 + 64 

2567 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2568 fields_desc = [ 

2569 XLEShortField("StructureSize", 0x31), 

2570 LEShortField("DataBufferOffset", None), 

2571 LEIntField("DataLen", None), 

2572 LELongField("Offset", 0), 

2573 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

2574 LEIntEnumField( 

2575 "Channel", 

2576 0, 

2577 { 

2578 0x00000000: "SMB2_CHANNEL_NONE", 

2579 0x00000001: "SMB2_CHANNEL_RDMA_V1", 

2580 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE", 

2581 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM", 

2582 }, 

2583 ), 

2584 LEIntField("RemainingBytes", 0), 

2585 LEShortField("WriteChannelInfoBufferOffset", None), 

2586 LEShortField("WriteChannelInfoLen", None), 

2587 FlagsField( 

2588 "Flags", 

2589 0, 

2590 -32, 

2591 { 

2592 0x00000001: "SMB2_WRITEFLAG_WRITE_THROUGH", 

2593 0x00000002: "SMB2_WRITEFLAG_WRITE_UNBUFFERED", 

2594 }, 

2595 ), 

2596 _NTLMPayloadField( 

2597 "Buffer", 

2598 OFFSET, 

2599 [ 

2600 StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen), 

2601 StrLenField( 

2602 "WriteChannelInfo", 

2603 b"", 

2604 length_from=lambda pkt: pkt.WriteChannelInfoLen, 

2605 ), 

2606 ], 

2607 ), 

2608 ] 

2609 

2610 def post_build(self, pkt, pay): 

2611 # type: (bytes, bytes) -> bytes 

2612 return ( 

2613 _SMB2_post_build( 

2614 self, 

2615 pkt, 

2616 self.OFFSET, 

2617 { 

2618 "Data": 2, 

2619 "WriteChannelInfo": 40, 

2620 }, 

2621 ) 

2622 + pay 

2623 ) 

2624 

2625 

2626bind_top_down( 

2627 SMB2_Header, 

2628 SMB2_Write_Request, 

2629 Command=0x0009, 

2630) 

2631 

2632# sect 2.2.22 

2633 

2634 

2635class SMB2_Write_Response(_SMB2_Payload): 

2636 name = "SMB2 WRITE Response" 

2637 Command = 0x0009 

2638 fields_desc = [ 

2639 XLEShortField("StructureSize", 0x11), 

2640 LEShortField("Reserved", 0), 

2641 LEIntField("Count", 0), 

2642 LEIntField("Remaining", 0), 

2643 LEShortField("WriteChannelInfoBufferOffset", 0), 

2644 LEShortField("WriteChannelInfoLen", 0), 

2645 ] 

2646 

2647 

2648bind_top_down(SMB2_Header, SMB2_Write_Response, Command=0x0009, Flags=1) 

2649 

2650# sect 2.2.28 

2651 

2652 

2653class SMB2_Echo_Request(_SMB2_Payload): 

2654 name = "SMB2 ECHO Request" 

2655 Command = 0x000D 

2656 fields_desc = [ 

2657 XLEShortField("StructureSize", 0x4), 

2658 LEShortField("Reserved", 0), 

2659 ] 

2660 

2661 

2662bind_top_down( 

2663 SMB2_Header, 

2664 SMB2_Echo_Request, 

2665 Command=0x000D, 

2666) 

2667 

2668# sect 2.2.29 

2669 

2670 

2671class SMB2_Echo_Response(_SMB2_Payload): 

2672 name = "SMB2 ECHO Response" 

2673 Command = 0x000D 

2674 fields_desc = [ 

2675 XLEShortField("StructureSize", 0x4), 

2676 LEShortField("Reserved", 0), 

2677 ] 

2678 

2679 

2680bind_top_down( 

2681 SMB2_Header, 

2682 SMB2_Echo_Response, 

2683 Command=0x000D, 

2684 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

2685) 

2686 

2687# sect 2.2.30 

2688 

2689 

2690class SMB2_Cancel_Request(_SMB2_Payload): 

2691 name = "SMB2 CANCEL Request" 

2692 fields_desc = [ 

2693 XLEShortField("StructureSize", 0x4), 

2694 LEShortField("Reserved", 0), 

2695 ] 

2696 

2697 

2698bind_top_down( 

2699 SMB2_Header, 

2700 SMB2_Cancel_Request, 

2701 Command=0x0009, 

2702) 

2703 

2704# sect 2.2.31.4 

2705 

2706 

2707class SMB2_IOCTL_Validate_Negotiate_Info_Request(Packet): 

2708 name = "SMB2 IOCTL Validate Negotiate Info" 

2709 fields_desc = ( 

2710 SMB2_Negotiate_Protocol_Request.fields_desc[4:6] 

2711 + SMB2_Negotiate_Protocol_Request.fields_desc[1:3][::-1] # Cap/GUID 

2712 + [SMB2_Negotiate_Protocol_Request.fields_desc[9]] # SecMod/DC # Dialects 

2713 ) 

2714 

2715 

2716# sect 2.2.31 

2717 

2718 

2719class _SMB2_IOCTL_Request_PacketLenField(PacketLenField): 

2720 def m2i(self, pkt, m): 

2721 if pkt.CtlCode == 0x00140204: # FSCTL_VALIDATE_NEGOTIATE_INFO 

2722 return SMB2_IOCTL_Validate_Negotiate_Info_Request(m) 

2723 elif pkt.CtlCode == 0x00060194: # FSCTL_DFS_GET_REFERRALS 

2724 return SMB2_IOCTL_REQ_GET_DFS_Referral(m) 

2725 elif pkt.CtlCode == 0x00094264: # FSCTL_OFFLOAD_READ 

2726 return SMB2_IOCTL_OFFLOAD_READ_Request(m) 

2727 return conf.raw_layer(m) 

2728 

2729 

2730class SMB2_IOCTL_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2731 name = "SMB2 IOCTL Request" 

2732 Command = 0x000B 

2733 OFFSET = 56 + 64 

2734 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2735 deprecated_fields = { 

2736 "IntputCount": ("InputLen", "alias"), 

2737 "OutputCount": ("OutputLen", "alias"), 

2738 } 

2739 fields_desc = [ 

2740 XLEShortField("StructureSize", 0x39), 

2741 LEShortField("Reserved", 0), 

2742 LEIntEnumField( 

2743 "CtlCode", 

2744 0, 

2745 { 

2746 0x00060194: "FSCTL_DFS_GET_REFERRALS", 

2747 0x0011400C: "FSCTL_PIPE_PEEK", 

2748 0x00110018: "FSCTL_PIPE_WAIT", 

2749 0x0011C017: "FSCTL_PIPE_TRANSCEIVE", 

2750 0x001440F2: "FSCTL_SRV_COPYCHUNK", 

2751 0x00144064: "FSCTL_SRV_ENUMERATE_SNAPSHOTS", 

2752 0x00140078: "FSCTL_SRV_REQUEST_RESUME_KEY", 

2753 0x001441BB: "FSCTL_SRV_READ_HASH", 

2754 0x001480F2: "FSCTL_SRV_COPYCHUNK_WRITE", 

2755 0x001401D4: "FSCTL_LMR_REQUEST_RESILIENCY", 

2756 0x001401FC: "FSCTL_QUERY_NETWORK_INTERFACE_INFO", 

2757 0x000900A4: "FSCTL_SET_REPARSE_POINT", 

2758 0x000601B0: "FSCTL_DFS_GET_REFERRALS_EX", 

2759 0x00098208: "FSCTL_FILE_LEVEL_TRIM", 

2760 0x00140204: "FSCTL_VALIDATE_NEGOTIATE_INFO", 

2761 0x00094264: "FSCTL_OFFLOAD_READ", 

2762 }, 

2763 ), 

2764 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

2765 LEIntField("InputBufferOffset", None), 

2766 LEIntField("InputLen", None), # Called InputCount but it's a length 

2767 LEIntField("MaxInputResponse", 0), 

2768 LEIntField("OutputBufferOffset", None), 

2769 LEIntField("OutputLen", None), # Called OutputCount. 

2770 LEIntField("MaxOutputResponse", 65535), 

2771 FlagsField("Flags", 0, -32, {0x00000001: "SMB2_0_IOCTL_IS_FSCTL"}), 

2772 LEIntField("Reserved2", 0), 

2773 _NTLMPayloadField( 

2774 "Buffer", 

2775 OFFSET, 

2776 [ 

2777 _SMB2_IOCTL_Request_PacketLenField( 

2778 "Input", None, conf.raw_layer, length_from=lambda pkt: pkt.InputLen 

2779 ), 

2780 _SMB2_IOCTL_Request_PacketLenField( 

2781 "Output", 

2782 None, 

2783 conf.raw_layer, 

2784 length_from=lambda pkt: pkt.OutputLen, 

2785 ), 

2786 ], 

2787 ), 

2788 ] 

2789 

2790 def post_build(self, pkt, pay): 

2791 # type: (bytes, bytes) -> bytes 

2792 return ( 

2793 _SMB2_post_build( 

2794 self, 

2795 pkt, 

2796 self.OFFSET, 

2797 { 

2798 "Input": 24, 

2799 "Output": 36, 

2800 }, 

2801 ) 

2802 + pay 

2803 ) 

2804 

2805 

2806bind_top_down( 

2807 SMB2_Header, 

2808 SMB2_IOCTL_Request, 

2809 Command=0x000B, 

2810) 

2811 

2812# sect 2.2.32.5 

2813 

2814 

2815class SOCKADDR_STORAGE(Packet): 

2816 fields_desc = [ 

2817 LEShortEnumField("Family", 0x0002, {0x0002: "IPv4", 0x0017: "IPv6"}), 

2818 ShortField("Port", 0), 

2819 # IPv4 

2820 ConditionalField( 

2821 IPField("IPv4Adddress", None), 

2822 lambda pkt: pkt.Family == 0x0002, 

2823 ), 

2824 ConditionalField( 

2825 StrFixedLenField("Reserved", b"", length=8), 

2826 lambda pkt: pkt.Family == 0x0002, 

2827 ), 

2828 # IPv6 

2829 ConditionalField( 

2830 LEIntField("FlowInfo", 0), 

2831 lambda pkt: pkt.Family == 0x00017, 

2832 ), 

2833 ConditionalField( 

2834 IP6Field("IPv6Address", None), 

2835 lambda pkt: pkt.Family == 0x00017, 

2836 ), 

2837 ConditionalField( 

2838 LEIntField("ScopeId", 0), 

2839 lambda pkt: pkt.Family == 0x00017, 

2840 ), 

2841 ] 

2842 

2843 def default_payload_class(self, _): 

2844 return conf.padding_layer 

2845 

2846 

2847class NETWORK_INTERFACE_INFO(Packet): 

2848 fields_desc = [ 

2849 LEIntField("Next", None), # 0 = no next entry 

2850 LEIntField("IfIndex", 1), 

2851 FlagsField( 

2852 "Capability", 

2853 1, 

2854 -32, 

2855 { 

2856 0x00000001: "RSS_CAPABLE", 

2857 0x00000002: "RDMA_CAPABLE", 

2858 }, 

2859 ), 

2860 LEIntField("Reserved", 0), 

2861 ScalingField("LinkSpeed", 10000000000, fmt="<Q", unit="bit/s"), 

2862 PacketField("SockAddr_Storage", SOCKADDR_STORAGE(), SOCKADDR_STORAGE), 

2863 ] 

2864 

2865 def default_payload_class(self, _): 

2866 return conf.padding_layer 

2867 

2868 

2869class SMB2_IOCTL_Network_Interface_Info(Packet): 

2870 name = "SMB2 IOCTL Network Interface Info response" 

2871 fields_desc = [ 

2872 _NextPacketListField("interfaces", [], NETWORK_INTERFACE_INFO), 

2873 ] 

2874 

2875 

2876# sect 2.2.32.6 

2877 

2878 

2879class SMB2_IOCTL_Validate_Negotiate_Info_Response(Packet): 

2880 name = "SMB2 IOCTL Validate Negotiate Info" 

2881 fields_desc = ( 

2882 SMB2_Negotiate_Protocol_Response.fields_desc[4:6][::-1] 

2883 + SMB2_Negotiate_Protocol_Response.fields_desc[ # Cap/GUID 

2884 1:3 

2885 ] # SecMod/DialectRevision 

2886 ) 

2887 

2888 

2889# [MS-FSCC] sect 2.3.42 

2890 

2891 

2892class SMB2_IOCTL_OFFLOAD_READ_Request(Packet): 

2893 name = "SMB2 IOCTL OFFLOAD_READ Request" 

2894 fields_desc = [ 

2895 LEIntField("StructureSize", 0x20), 

2896 LEIntField("Flags", 0), 

2897 LEIntField("TokenTimeToLive", 0), 

2898 LEIntField("Reserved", 0), 

2899 LELongField("FileOffset", 0), 

2900 LELongField("CopyLength", 0), 

2901 ] 

2902 

2903 

2904# [MS-FSCC] sect 2.1.11 

2905 

2906 

2907class STORAGE_OFFLOAD_TOKEN(Packet): 

2908 fields_desc = [ 

2909 LEIntEnumField( 

2910 "TokenType", 

2911 0xFFFF0001, 

2912 { 

2913 0xFFFF0001: "STORAGE_OFFLOAD_TOKEN_TYPE_ZERO_DATA", 

2914 }, 

2915 ), 

2916 LEShortField("Reserved", 0), 

2917 FieldLenField("TokenIdLength", None, fmt="<H", length_of="TokenId"), 

2918 StrFixedLenField("TokenId", b"", length=504), 

2919 ] 

2920 

2921 

2922# [MS-FSCC] sect 2.3.42 

2923 

2924 

2925class SMB2_IOCTL_OFFLOAD_READ_Response(Packet): 

2926 name = "SMB2 IOCTL OFFLOAD_READ Response" 

2927 fields_desc = [ 

2928 LEIntField("StructureSize", 0x210), 

2929 FlagsField( 

2930 "Flags", 

2931 0, 

2932 -32, 

2933 { 

2934 0x00000001: "OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE", 

2935 }, 

2936 ), 

2937 LELongField("TransferLength", 0), 

2938 PacketField("Token", STORAGE_OFFLOAD_TOKEN(), STORAGE_OFFLOAD_TOKEN), 

2939 ] 

2940 

2941 

2942# sect 2.2.32 

2943 

2944 

2945class _SMB2_IOCTL_Response_PacketLenField(PacketLenField): 

2946 def m2i(self, pkt, m): 

2947 if pkt.CtlCode == 0x00140204: # FSCTL_VALIDATE_NEGOTIATE_INFO 

2948 return SMB2_IOCTL_Validate_Negotiate_Info_Response(m) 

2949 elif pkt.CtlCode == 0x001401FC: # FSCTL_QUERY_NETWORK_INTERFACE_INFO 

2950 return SMB2_IOCTL_Network_Interface_Info(m) 

2951 elif pkt.CtlCode == 0x00060194: # FSCTL_DFS_GET_REFERRALS 

2952 return SMB2_IOCTL_RESP_GET_DFS_Referral(m) 

2953 return conf.raw_layer(m) 

2954 

2955 

2956class SMB2_IOCTL_Response(_SMB2_Payload, _NTLMPayloadPacket): 

2957 name = "SMB2 IOCTL Response" 

2958 Command = 0x000B 

2959 OFFSET = 48 + 64 

2960 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2961 StructureSize = 0x31 

2962 MaxOutputResponse = 0 

2963 fields_desc = ( 

2964 SMB2_IOCTL_Request.fields_desc[:6] 

2965 + SMB2_IOCTL_Request.fields_desc[7:9] 

2966 + SMB2_IOCTL_Request.fields_desc[10:12] 

2967 + [ 

2968 _NTLMPayloadField( 

2969 "Buffer", 

2970 OFFSET, 

2971 [ 

2972 _SMB2_IOCTL_Response_PacketLenField( 

2973 "Input", 

2974 None, 

2975 conf.raw_layer, 

2976 length_from=lambda pkt: pkt.InputLen, 

2977 ), 

2978 _SMB2_IOCTL_Response_PacketLenField( 

2979 "Output", 

2980 None, 

2981 conf.raw_layer, 

2982 length_from=lambda pkt: pkt.OutputLen, 

2983 ), 

2984 ], 

2985 ), 

2986 ] 

2987 ) 

2988 

2989 def post_build(self, pkt, pay): 

2990 # type: (bytes, bytes) -> bytes 

2991 return ( 

2992 _SMB2_post_build( 

2993 self, 

2994 pkt, 

2995 self.OFFSET, 

2996 { 

2997 "Input": 24, 

2998 "Output": 32, 

2999 }, 

3000 ) 

3001 + pay 

3002 ) 

3003 

3004 

3005bind_top_down( 

3006 SMB2_Header, 

3007 SMB2_IOCTL_Response, 

3008 Command=0x000B, 

3009 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

3010) 

3011 

3012# sect 2.2.33 

3013 

3014 

3015class SMB2_Query_Directory_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3016 name = "SMB2 QUERY DIRECTORY Request" 

3017 Command = 0x000E 

3018 OFFSET = 32 + 64 

3019 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3020 fields_desc = [ 

3021 XLEShortField("StructureSize", 0x21), 

3022 ByteEnumField("FileInformationClass", 0x1, FileInformationClasses), 

3023 FlagsField( 

3024 "Flags", 

3025 0, 

3026 -8, 

3027 { 

3028 0x01: "SMB2_RESTART_SCANS", 

3029 0x02: "SMB2_RETURN_SINGLE_ENTRY", 

3030 0x04: "SMB2_INDEX_SPECIFIED", 

3031 0x10: "SMB2_REOPEN", 

3032 }, 

3033 ), 

3034 LEIntField("FileIndex", 0), 

3035 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3036 LEShortField("FileNameBufferOffset", None), 

3037 LEShortField("FileNameLen", None), 

3038 LEIntField("OutputBufferLength", 65535), 

3039 _NTLMPayloadField("Buffer", OFFSET, [StrFieldUtf16("FileName", b"")]), 

3040 ] 

3041 

3042 def post_build(self, pkt, pay): 

3043 # type: (bytes, bytes) -> bytes 

3044 return ( 

3045 _SMB2_post_build( 

3046 self, 

3047 pkt, 

3048 self.OFFSET, 

3049 { 

3050 "FileName": 24, 

3051 }, 

3052 ) 

3053 + pay 

3054 ) 

3055 

3056 

3057bind_top_down( 

3058 SMB2_Header, 

3059 SMB2_Query_Directory_Request, 

3060 Command=0x000E, 

3061) 

3062 

3063# sect 2.2.34 

3064 

3065 

3066class SMB2_Query_Directory_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3067 name = "SMB2 QUERY DIRECTORY Response" 

3068 Command = 0x000E 

3069 OFFSET = 8 + 64 

3070 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3071 fields_desc = [ 

3072 XLEShortField("StructureSize", 0x9), 

3073 LEShortField("OutputBufferOffset", None), 

3074 LEIntField("OutputLen", None), 

3075 _NTLMPayloadField( 

3076 "Buffer", 

3077 OFFSET, 

3078 [ 

3079 # TODO 

3080 StrFixedLenField("Output", b"", length_from=lambda pkt: pkt.OutputLen) 

3081 ], 

3082 ), 

3083 ] 

3084 

3085 def post_build(self, pkt, pay): 

3086 # type: (bytes, bytes) -> bytes 

3087 return ( 

3088 _SMB2_post_build( 

3089 self, 

3090 pkt, 

3091 self.OFFSET, 

3092 { 

3093 "Output": 2, 

3094 }, 

3095 ) 

3096 + pay 

3097 ) 

3098 

3099 

3100bind_top_down( 

3101 SMB2_Header, 

3102 SMB2_Query_Directory_Response, 

3103 Command=0x000E, 

3104 Flags=1, 

3105) 

3106 

3107# sect 2.2.35 

3108 

3109 

3110class SMB2_Change_Notify_Request(_SMB2_Payload): 

3111 name = "SMB2 CHANGE NOTIFY Request" 

3112 Command = 0x000F 

3113 fields_desc = [ 

3114 XLEShortField("StructureSize", 0x20), 

3115 FlagsField( 

3116 "Flags", 

3117 0, 

3118 -16, 

3119 { 

3120 0x0001: "SMB2_WATCH_TREE", 

3121 }, 

3122 ), 

3123 LEIntField("OutputBufferLength", 2048), 

3124 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3125 FlagsField( 

3126 "CompletionFilter", 

3127 0, 

3128 -32, 

3129 { 

3130 0x00000001: "FILE_NOTIFY_CHANGE_FILE_NAME", 

3131 0x00000002: "FILE_NOTIFY_CHANGE_DIR_NAME", 

3132 0x00000004: "FILE_NOTIFY_CHANGE_ATTRIBUTES", 

3133 0x00000008: "FILE_NOTIFY_CHANGE_SIZE", 

3134 0x00000010: "FILE_NOTIFY_CHANGE_LAST_WRITE", 

3135 0x00000020: "FILE_NOTIFY_CHANGE_LAST_ACCESS", 

3136 0x00000040: "FILE_NOTIFY_CHANGE_CREATION", 

3137 0x00000080: "FILE_NOTIFY_CHANGE_EA", 

3138 0x00000100: "FILE_NOTIFY_CHANGE_SECURITY", 

3139 0x00000200: "FILE_NOTIFY_CHANGE_STREAM_NAME", 

3140 0x00000400: "FILE_NOTIFY_CHANGE_STREAM_SIZE", 

3141 0x00000800: "FILE_NOTIFY_CHANGE_STREAM_WRITE", 

3142 }, 

3143 ), 

3144 LEIntField("Reserved", 0), 

3145 ] 

3146 

3147 

3148bind_top_down( 

3149 SMB2_Header, 

3150 SMB2_Change_Notify_Request, 

3151 Command=0x000F, 

3152) 

3153 

3154# sect 2.2.36 

3155 

3156 

3157class SMB2_Change_Notify_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3158 name = "SMB2 CHANGE NOTIFY Response" 

3159 Command = 0x000F 

3160 OFFSET = 8 + 64 

3161 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3162 fields_desc = [ 

3163 XLEShortField("StructureSize", 0x9), 

3164 LEShortField("OutputBufferOffset", None), 

3165 LEIntField("OutputLen", None), 

3166 _NTLMPayloadField( 

3167 "Buffer", 

3168 OFFSET, 

3169 [ 

3170 _NextPacketListField( 

3171 "Output", 

3172 [], 

3173 FILE_NOTIFY_INFORMATION, 

3174 length_from=lambda pkt: pkt.OutputLen, 

3175 max_count=1000, 

3176 ) 

3177 ], 

3178 ), 

3179 ] 

3180 

3181 def post_build(self, pkt, pay): 

3182 # type: (bytes, bytes) -> bytes 

3183 return ( 

3184 _SMB2_post_build( 

3185 self, 

3186 pkt, 

3187 self.OFFSET, 

3188 { 

3189 "Output": 2, 

3190 }, 

3191 ) 

3192 + pay 

3193 ) 

3194 

3195 

3196bind_top_down( 

3197 SMB2_Header, 

3198 SMB2_Change_Notify_Response, 

3199 Command=0x000F, 

3200 Flags=1, 

3201) 

3202 

3203# sect 2.2.37 

3204 

3205 

3206class FILE_GET_QUOTA_INFORMATION(Packet): 

3207 fields_desc = [ 

3208 IntField("NextEntryOffset", 0), 

3209 FieldLenField("SidLength", None, length_of="Sid"), 

3210 StrLenField("Sid", b"", length_from=lambda x: x.SidLength), 

3211 StrLenField( 

3212 "pad", 

3213 b"", 

3214 length_from=lambda x: ( 

3215 (x.NextEntryOffset - x.SidLength) if x.NextEntryOffset else 0 

3216 ), 

3217 ), 

3218 ] 

3219 

3220 

3221class SMB2_Query_Quota_Info(Packet): 

3222 fields_desc = [ 

3223 ByteField("ReturnSingle", 0), 

3224 ByteField("ReturnBoolean", 0), 

3225 ShortField("Reserved", 0), 

3226 LEIntField("SidListLength", 0), 

3227 LEIntField("StartSidLength", 0), 

3228 LEIntField("StartSidOffset", 0), 

3229 StrLenField("pad", b"", length_from=lambda x: x.StartSidOffset), 

3230 MultipleTypeField( 

3231 [ 

3232 ( 

3233 PacketListField( 

3234 "SidBuffer", 

3235 [], 

3236 FILE_GET_QUOTA_INFORMATION, 

3237 length_from=lambda x: x.SidListLength, 

3238 ), 

3239 lambda x: x.SidListLength, 

3240 ), 

3241 ( 

3242 StrLenField( 

3243 "SidBuffer", b"", length_from=lambda x: x.StartSidLength 

3244 ), 

3245 lambda x: x.StartSidLength, 

3246 ), 

3247 ], 

3248 StrFixedLenField("SidBuffer", b"", length=0), 

3249 ), 

3250 ] 

3251 

3252 

3253SMB2_INFO_TYPE = { 

3254 0x01: "SMB2_0_INFO_FILE", 

3255 0x02: "SMB2_0_INFO_FILESYSTEM", 

3256 0x03: "SMB2_0_INFO_SECURITY", 

3257 0x04: "SMB2_0_INFO_QUOTA", 

3258} 

3259 

3260SMB2_ADDITIONAL_INFORMATION = { 

3261 0x00000001: "OWNER_SECURITY_INFORMATION", 

3262 0x00000002: "GROUP_SECURITY_INFORMATION", 

3263 0x00000004: "DACL_SECURITY_INFORMATION", 

3264 0x00000008: "SACL_SECURITY_INFORMATION", 

3265 0x00000010: "LABEL_SECURITY_INFORMATION", 

3266 0x00000020: "ATTRIBUTE_SECURITY_INFORMATION", 

3267 0x00000040: "SCOPE_SECURITY_INFORMATION", 

3268 0x00010000: "BACKUP_SECURITY_INFORMATION", 

3269} 

3270 

3271 

3272class SMB2_Query_Info_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3273 name = "SMB2 QUERY INFO Request" 

3274 Command = 0x0010 

3275 OFFSET = 40 + 64 

3276 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3277 fields_desc = [ 

3278 XLEShortField("StructureSize", 0x29), 

3279 ByteEnumField( 

3280 "InfoType", 

3281 0, 

3282 SMB2_INFO_TYPE, 

3283 ), 

3284 ByteEnumField("FileInfoClass", 0, FileInformationClasses), 

3285 LEIntField("OutputBufferLength", 0), 

3286 XLEIntField("InputBufferOffset", None), # Short + Reserved = Int 

3287 LEIntField("InputLen", None), 

3288 FlagsField( 

3289 "AdditionalInformation", 

3290 0, 

3291 -32, 

3292 SMB2_ADDITIONAL_INFORMATION, 

3293 ), 

3294 FlagsField( 

3295 "Flags", 

3296 0, 

3297 -32, 

3298 { 

3299 0x00000001: "SL_RESTART_SCAN", 

3300 0x00000002: "SL_RETURN_SINGLE_ENTRY", 

3301 0x00000004: "SL_INDEX_SPECIFIED", 

3302 }, 

3303 ), 

3304 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3305 _NTLMPayloadField( 

3306 "Buffer", 

3307 OFFSET, 

3308 [ 

3309 MultipleTypeField( 

3310 [ 

3311 ( 

3312 # QUOTA 

3313 PacketListField( 

3314 "Input", 

3315 None, 

3316 SMB2_Query_Quota_Info, 

3317 length_from=lambda pkt: pkt.InputLen, 

3318 ), 

3319 lambda pkt: pkt.InfoType == 0x04, 

3320 ), 

3321 ], 

3322 StrLenField("Input", b"", length_from=lambda pkt: pkt.InputLen), 

3323 ), 

3324 ], 

3325 ), 

3326 ] 

3327 

3328 def post_build(self, pkt, pay): 

3329 # type: (bytes, bytes) -> bytes 

3330 return ( 

3331 _SMB2_post_build( 

3332 self, 

3333 pkt, 

3334 self.OFFSET, 

3335 { 

3336 "Input": 4, 

3337 }, 

3338 ) 

3339 + pay 

3340 ) 

3341 

3342 

3343bind_top_down( 

3344 SMB2_Header, 

3345 SMB2_Query_Info_Request, 

3346 Command=0x00010, 

3347) 

3348 

3349 

3350class SMB2_Query_Info_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3351 name = "SMB2 QUERY INFO Response" 

3352 Command = 0x0010 

3353 OFFSET = 8 + 64 

3354 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3355 fields_desc = [ 

3356 XLEShortField("StructureSize", 0x9), 

3357 LEShortField("OutputBufferOffset", None), 

3358 LEIntField("OutputLen", None), 

3359 _NTLMPayloadField( 

3360 "Buffer", 

3361 OFFSET, 

3362 [ 

3363 # TODO 

3364 StrFixedLenField("Output", b"", length_from=lambda pkt: pkt.OutputLen) 

3365 ], 

3366 ), 

3367 ] 

3368 

3369 def post_build(self, pkt, pay): 

3370 # type: (bytes, bytes) -> bytes 

3371 return ( 

3372 _SMB2_post_build( 

3373 self, 

3374 pkt, 

3375 self.OFFSET, 

3376 { 

3377 "Output": 2, 

3378 }, 

3379 ) 

3380 + pay 

3381 ) 

3382 

3383 

3384bind_top_down( 

3385 SMB2_Header, 

3386 SMB2_Query_Info_Response, 

3387 Command=0x00010, 

3388 Flags=1, 

3389) 

3390 

3391 

3392# sect 2.2.39 

3393 

3394 

3395class SMB2_Set_Info_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3396 name = "SMB2 SET INFO Request" 

3397 Command = 0x0011 

3398 OFFSET = 32 + 64 

3399 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3400 fields_desc = [ 

3401 XLEShortField("StructureSize", 0x21), 

3402 ByteEnumField( 

3403 "InfoType", 

3404 0, 

3405 SMB2_INFO_TYPE, 

3406 ), 

3407 ByteEnumField("FileInfoClass", 0, FileInformationClasses), 

3408 LEIntField("DataLen", None), 

3409 XLEIntField("DataBufferOffset", None), # Short + Reserved = Int 

3410 FlagsField( 

3411 "AdditionalInformation", 

3412 0, 

3413 -32, 

3414 SMB2_ADDITIONAL_INFORMATION, 

3415 ), 

3416 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3417 _NTLMPayloadField( 

3418 "Buffer", 

3419 OFFSET, 

3420 [ 

3421 MultipleTypeField( 

3422 [ 

3423 ( 

3424 # FILE 

3425 PacketLenField( 

3426 "Data", 

3427 None, 

3428 lambda x, _parent: _FileInformationClasses.get( 

3429 _parent.FileInfoClass, conf.raw_layer 

3430 )(x), 

3431 length_from=lambda pkt: pkt.DataLen, 

3432 ), 

3433 lambda pkt: pkt.InfoType == 0x01, 

3434 ), 

3435 ( 

3436 # QUOTA 

3437 PacketListField( 

3438 "Data", 

3439 None, 

3440 SMB2_Query_Quota_Info, 

3441 length_from=lambda pkt: pkt.DataLen, 

3442 ), 

3443 lambda pkt: pkt.InfoType == 0x04, 

3444 ), 

3445 ], 

3446 StrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen), 

3447 ), 

3448 ], 

3449 ), 

3450 ] 

3451 

3452 def post_build(self, pkt, pay): 

3453 # type: (bytes, bytes) -> bytes 

3454 return ( 

3455 _SMB2_post_build( 

3456 self, 

3457 pkt, 

3458 self.OFFSET, 

3459 { 

3460 "Data": 4, 

3461 }, 

3462 ) 

3463 + pay 

3464 ) 

3465 

3466 

3467bind_top_down( 

3468 SMB2_Header, 

3469 SMB2_Set_Info_Request, 

3470 Command=0x00011, 

3471) 

3472 

3473 

3474class SMB2_Set_Info_Response(_SMB2_Payload): 

3475 name = "SMB2 SET INFO Request" 

3476 Command = 0x0011 

3477 fields_desc = [ 

3478 XLEShortField("StructureSize", 0x02), 

3479 ] 

3480 

3481 

3482bind_top_down( 

3483 SMB2_Header, 

3484 SMB2_Set_Info_Response, 

3485 Command=0x00011, 

3486 Flags=1, 

3487) 

3488 

3489 

3490# sect 2.2.41 

3491 

3492 

3493class SMB2_Transform_Header(Packet): 

3494 name = "SMB2 Transform Header" 

3495 fields_desc = [ 

3496 StrFixedLenField("Start", b"\xfdSMB", 4), 

3497 XStrFixedLenField("Signature", 0, length=16), 

3498 XStrFixedLenField("Nonce", b"", length=16), 

3499 LEIntField("OriginalMessageSize", 0x0), 

3500 LEShortField("Reserved", 0), 

3501 LEShortEnumField( 

3502 "Flags", 

3503 0x1, 

3504 { 

3505 0x0001: "ENCRYPTED", 

3506 }, 

3507 ), 

3508 LELongField("SessionId", 0), 

3509 ] 

3510 

3511 def decrypt(self, dialect, DecryptionKey, CipherId): 

3512 """ 

3513 [MS-SMB2] sect 3.2.5.1.1.1 - Decrypting the Message 

3514 """ 

3515 if not isinstance(self.payload, conf.raw_layer): 

3516 raise Exception("No payload to decrypt !") 

3517 

3518 if "GCM" in CipherId: 

3519 from cryptography.hazmat.primitives.ciphers.aead import AESGCM 

3520 

3521 nonce = self.Nonce[:12] 

3522 cipher = AESGCM(DecryptionKey) 

3523 elif "CCM" in CipherId: 

3524 from cryptography.hazmat.primitives.ciphers.aead import AESCCM 

3525 

3526 nonce = self.Nonce[:11] 

3527 cipher = AESCCM(DecryptionKey) 

3528 else: 

3529 raise Exception("Unknown CipherId !") 

3530 

3531 # Decrypt the data 

3532 aad = self.self_build()[20:] 

3533 data = cipher.decrypt( 

3534 nonce, 

3535 self.payload.load + self.Signature, 

3536 aad, 

3537 ) 

3538 return SMB2_Header(data, _decrypted=True) 

3539 

3540 

3541bind_layers(SMB2_Transform_Header, conf.raw_layer) 

3542 

3543 

3544# sect 2.2.42.1 

3545 

3546 

3547class SMB2_Compression_Transform_Header(Packet): 

3548 name = "SMB2 Compression Transform Header" 

3549 fields_desc = [ 

3550 StrFixedLenField("Start", b"\xfcSMB", 4), 

3551 LEIntField("OriginalCompressedSegmentSize", 0x0), 

3552 LEShortEnumField("CompressionAlgorithm", 0, SMB2_COMPRESSION_ALGORITHMS), 

3553 LEShortEnumField( 

3554 "Flags", 

3555 0x0, 

3556 { 

3557 0x0000: "SMB2_COMPRESSION_FLAG_NONE", 

3558 0x0001: "SMB2_COMPRESSION_FLAG_CHAINED", 

3559 }, 

3560 ), 

3561 XLEIntField("Offset_or_Length", 0), 

3562 ] 

3563 

3564 

3565# [MS-DFSC] sect 2.2 

3566 

3567 

3568class SMB2_IOCTL_REQ_GET_DFS_Referral(Packet): 

3569 fields_desc = [ 

3570 LEShortField("MaxReferralLevel", 0), 

3571 StrNullFieldUtf16("RequestFileName", ""), 

3572 ] 

3573 

3574 

3575class DFS_REFERRAL(Packet): 

3576 fields_desc = [ 

3577 LEShortField("Version", 1), 

3578 FieldLenField( 

3579 "Size", None, fmt="<H", length_of="ShareName", adjust=lambda pkt, x: x + 9 

3580 ), 

3581 LEShortEnumField("ServerType", 0, {0: "non-root", 1: "root"}), 

3582 LEShortField("ReferralEntryFlags", 0), 

3583 StrNullFieldUtf16("ShareName", ""), 

3584 ] 

3585 

3586 @classmethod 

3587 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

3588 if _pkt and len(_pkt) >= 2: 

3589 version = struct.unpack("<H", _pkt[:2])[0] 

3590 if version == 1: 

3591 return DFS_REFERRAL 

3592 elif version == 3: 

3593 return DFS_REFERRAL_V3 

3594 elif version == 4: 

3595 return DFS_REFERRAL_V4 

3596 return cls 

3597 

3598 def default_payload_class(self, s): 

3599 return conf.padding_layer 

3600 

3601 

3602class DFS_REFERRAL_V3(DFS_REFERRAL): 

3603 fields_desc = [ 

3604 LEShortField("Version", 3), 

3605 LEShortField("Size", None), 

3606 LEShortEnumField("ServerType", 0, {0: "non-root", 1: "root"}), 

3607 FlagsField( 

3608 "ReferralEntryFlags", 

3609 0, 

3610 -16, 

3611 { 

3612 0x0002: "NameListReferral", 

3613 0x0004: "TargetSetBoundary", 

3614 }, 

3615 ), 

3616 LEIntField("TimeToLive", 300), 

3617 # NameListReferral is 0 

3618 ConditionalField( 

3619 LEShortField("DFSPathOffset", None), 

3620 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

3621 ), 

3622 ConditionalField( 

3623 LEShortField("DFSAlternatePathOffset", None), 

3624 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

3625 ), 

3626 ConditionalField( 

3627 LEShortField("NetworkAddressOffset", None), 

3628 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

3629 ), 

3630 ConditionalField( 

3631 StrFixedLenField("ServiceSiteGuid", 0, length=16), 

3632 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

3633 ), 

3634 # NameListReferral is 1 

3635 ConditionalField( 

3636 LEShortField("SpecialNameOffset", None), 

3637 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

3638 ), 

3639 ConditionalField( 

3640 LEShortField("NumberOfExpandedNames", None), 

3641 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

3642 ), 

3643 ConditionalField( 

3644 LEShortField("ExpandedNameOffset", None), 

3645 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

3646 ), 

3647 ConditionalField( 

3648 StrLenField("Padding", None, length_from=lambda pkt: pkt.Size - 18), 

3649 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

3650 ), 

3651 ] 

3652 

3653 def post_build(self, pkt, pay): 

3654 # type: (bytes, bytes) -> bytes 

3655 if self.Size is None: 

3656 pkt = pkt[:2] + struct.pack("<H", len(pkt)) + pkt[4:] 

3657 return pkt + pay 

3658 

3659 

3660class DFS_REFERRAL_V4(DFS_REFERRAL_V3): 

3661 Version = 4 

3662 

3663 

3664class DFS_REFERRAL_ENTRY0(Packet): 

3665 fields_desc = [ 

3666 StrNullFieldUtf16("DFSPath", ""), 

3667 StrNullFieldUtf16("DFSAlternatePath", ""), 

3668 StrNullFieldUtf16("NetworkAddress", ""), 

3669 ] 

3670 

3671 

3672class DFS_REFERRAL_ENTRY1(Packet): 

3673 fields_desc = [ 

3674 StrNullFieldUtf16("SpecialName", ""), 

3675 FieldListField( 

3676 "ExpandedName", 

3677 [], 

3678 StrNullFieldUtf16("", ""), 

3679 ), 

3680 ] 

3681 

3682 

3683class _DFS_Referrals_BufferField(PacketListField): 

3684 def getfield(self, pkt, s): 

3685 results = [] 

3686 offset = sum(x.Size for x in pkt.ReferralEntries) 

3687 for ref in pkt.ReferralEntries: 

3688 # For every ref 

3689 if not ref.ReferralEntryFlags.NameListReferral: 

3690 cls = DFS_REFERRAL_ENTRY0 

3691 else: 

3692 cls = DFS_REFERRAL_ENTRY1 

3693 # Build the fields manually 

3694 fld = _NTLMPayloadField( 

3695 "", 

3696 offset, 

3697 cls.fields_desc, 

3698 force_order=[x.name for x in cls.fields_desc], 

3699 offset_name="Offset", 

3700 ) 

3701 remain, vals = fld.getfield(ref, s) 

3702 vals = fld.i2h(ref, vals) 

3703 # Append the entry class 

3704 results.append(cls(**{x[0]: x[1] for x in vals})) 

3705 offset -= ref.Size 

3706 return b"", results 

3707 

3708 def addfield(self, pkt, s, vals): 

3709 offset = sum(len(x) for x in pkt.ReferralEntries) 

3710 for i, val in enumerate(vals): 

3711 try: 

3712 ref = pkt.ReferralEntries[i] 

3713 except KeyError: 

3714 ref = None 

3715 fld = _NTLMPayloadField( 

3716 "", 

3717 offset, 

3718 val.fields_desc, 

3719 force_order=[x.name for x in val.fields_desc], 

3720 offset_name="Offset", 

3721 ) 

3722 # Append the bytes manually 

3723 values = [(fld.name, getattr(val, fld.name)) for fld in val.fields_desc] 

3724 values = fld.h2i(ref, values) 

3725 s += fld.addfield(ref, b"", values) 

3726 offset -= len(ref) 

3727 return s 

3728 

3729 

3730class SMB2_IOCTL_RESP_GET_DFS_Referral(Packet): 

3731 fields_desc = [ 

3732 LEShortField("PathConsumed", 0), 

3733 FieldLenField("NumberOfReferrals", None, fmt="<H", count_of="ReferralEntries"), 

3734 FlagsField( 

3735 "ReferralHeaderFlags", 

3736 0, 

3737 -32, 

3738 { 

3739 0x00000001: "ReferralServers", 

3740 0x00000002: "StorageServers", 

3741 0x00000004: "TargetFailback", 

3742 }, 

3743 ), 

3744 PacketListField( 

3745 "ReferralEntries", 

3746 [], 

3747 DFS_REFERRAL, 

3748 count_from=lambda pkt: pkt.NumberOfReferrals, 

3749 ), 

3750 _DFS_Referrals_BufferField("ReferralBuffer", []), 

3751 ] 

3752 

3753 def post_build(self, pkt, pay): 

3754 # type: (bytes, bytes) -> bytes 

3755 # Note: Windows is smart and uses some sort of compression in the sense 

3756 # that it reuses fields that are used several times across ReferralBuffer. 

3757 # But we just do the dumb thing because it's 'easier', and do no compression. 

3758 offsets = { 

3759 # DFS_REFERRAL_ENTRY0 

3760 "DFSPath": 12, 

3761 "DFSAlternatePath": 14, 

3762 "NetworkAddress": 16, 

3763 # DFS_REFERRAL_ENTRY1 

3764 "SpecialName": 12, 

3765 "ExpandedName": 16, 

3766 } 

3767 # dataoffset = pointer in the ReferralBuffer 

3768 # entryoffset = pointer in the ReferralEntries 

3769 dataoffset = sum(len(x) for x in self.ReferralEntries) 

3770 entryoffset = 8 

3771 for ref, buf in zip(self.ReferralEntries, self.ReferralBuffer): 

3772 for fld in buf.fields_desc: 

3773 off = entryoffset + offsets[fld.name] 

3774 if ref.getfieldval(fld.name + "Offset") is None and buf.getfieldval( 

3775 fld.name 

3776 ): 

3777 pkt = pkt[:off] + struct.pack("<H", dataoffset) + pkt[off + 2 :] 

3778 dataoffset += len(fld.addfield(self, b"", buf.getfieldval(fld.name))) 

3779 dataoffset -= len(ref) 

3780 entryoffset += len(ref) 

3781 return pkt + pay 

3782 

3783 

3784# [MS-SMB2] various usages 

3785 

3786 

3787def SMB2computePreauthIntegrityHashValue( 

3788 PreauthIntegrityHashValue, s, HashId="SHA-512" 

3789): 

3790 """ 

3791 Update the PreauthIntegrityHashValue 

3792 """ 

3793 # get hasher 

3794 hasher = {"SHA-512": hashlib.sha512}[HashId] 

3795 # compute the hash of concatenation of previous and bytes 

3796 return hasher(PreauthIntegrityHashValue + s).digest() 

3797 

3798 

3799# SMB2 socket and session 

3800 

3801 

3802class SMBStreamSocket(StreamSocket): 

3803 """ 

3804 A modified StreamSocket to dissect SMB compounded requests 

3805 [MS-SMB2] 3.3.5.2.7 

3806 """ 

3807 

3808 def __init__(self, *args, **kwargs): 

3809 self.queue = collections.deque() 

3810 self.session = SMBSession() 

3811 super(SMBStreamSocket, self).__init__(*args, **kwargs) 

3812 

3813 def recv(self, x=None): 

3814 # note: normal StreamSocket takes care of NBTSession / DirectTCP fragments. 

3815 # this takes care of splitting compounded requests 

3816 if self.queue: 

3817 pkt = self.queue.popleft() 

3818 else: 

3819 pkt = super(SMBStreamSocket, self).recv(x) 

3820 

3821 # If there are multiple SMB2_Header requests (aka. compounded), 

3822 # take the first and store the rest in a queue. 

3823 if pkt is not None and ( 

3824 SMB2_Header in pkt 

3825 or SMB2_Transform_Header in pkt 

3826 or SMB2_Compression_Transform_Header in pkt 

3827 ): 

3828 pkt = self.session.in_pkt(pkt) 

3829 smbh = pkt[SMB2_Header] 

3830 pay = smbh.payload 

3831 while SMB2_Header in pay: 

3832 pay = pay[SMB2_Header] 

3833 pay._decrypted = smbh._decrypted # Keep the _decrypted flag 

3834 pay.underlayer.remove_payload() 

3835 self.queue.append(pay) 

3836 if not pay.NextCommand: 

3837 break 

3838 pay = pay.payload 

3839 

3840 # Verify the signature if required. 

3841 # This happens here because we must have split compounded requests first. 

3842 smbh = pkt.getlayer(SMB2_Header) 

3843 if ( 

3844 smbh 

3845 and self.session.Dialect 

3846 and self.session.SigningKey 

3847 and self.session.SigningRequired 

3848 # [MS-SMB2] sect 3.2.5.1.3 Verifying the Signature 

3849 # "The client MUST skip the processing in this section if any of:" 

3850 # - [...] decryption in section 3.2.5.1.1.1 succeeds 

3851 and not smbh._decrypted 

3852 # - MessageId is 0xFFFFFFFFFFFFFFFF 

3853 and smbh.MID != 0xFFFFFFFFFFFFFFFF 

3854 # - Message is not ECHO request 

3855 and smbh.Command != 0x000D 

3856 # - Status in the SMB2 header is STATUS_PENDING 

3857 and smbh.Status != 0x00000103 

3858 ): 

3859 smbh.verify( 

3860 self.session.Dialect, 

3861 self.session.SigningKey, 

3862 # SMB 3.1.1 parameters: 

3863 SigningAlgorithmId=self.session.SigningAlgorithmId, 

3864 IsClient=False, 

3865 ) 

3866 return pkt 

3867 

3868 def send(self, x, Compounded=False, ForceSign=False, ForceEncrypt=False, **kwargs): 

3869 for pkt in self.session.out_pkt( 

3870 x, Compounded=Compounded, ForceSign=ForceSign, ForceEncrypt=ForceEncrypt 

3871 ): 

3872 return super(SMBStreamSocket, self).send(pkt, **kwargs) 

3873 

3874 @staticmethod 

3875 def select(sockets, remain=conf.recv_poll_rate): 

3876 if any(getattr(x, "queue", None) for x in sockets): 

3877 return [x for x in sockets if isinstance(x, SMBStreamSocket) and x.queue] 

3878 return select_objects(sockets, remain=remain) 

3879 

3880 

3881class SMBSession(DefaultSession): 

3882 """ 

3883 A SMB session within a TCP socket. 

3884 """ 

3885 

3886 def __init__(self, *args, **kwargs): 

3887 self.smb_header = None 

3888 self.ssp = kwargs.pop("ssp", None) 

3889 self.sspcontext = kwargs.pop("sspcontext", None) 

3890 self.sniffsspcontexts = {} # Unfinished contexts for passive 

3891 # SMB session parameters 

3892 self.CompoundQueue = [] 

3893 self.Dialect = 0x0202 # Updated by parent 

3894 self.Credits = 0 

3895 self.IsGuest = False 

3896 self.MaxTransactionSize = 0 

3897 self.MaxReadSize = 0 

3898 self.MaxWriteSize = 0 

3899 # Crypto parameters. Go read [MS-SMB2] to understand the names. 

3900 self.SigningRequired = True 

3901 self.SupportsEncryption = False 

3902 self.EncryptData = False 

3903 self.TreeEncryptData = False 

3904 self.SigningKey = None 

3905 self.EncryptionKey = None 

3906 self.DecryptionKey = None 

3907 self.PreauthIntegrityHashId = "SHA-512" 

3908 self.SupportedCipherIds = [ 

3909 "AES-128-CCM", 

3910 "AES-128-GCM", 

3911 "AES-256-CCM", 

3912 "AES-256-GCM", 

3913 ] 

3914 self.CipherId = "AES-128-CCM" 

3915 self.SupportedSigningAlgorithmIds = [ 

3916 "AES-CMAC", 

3917 "HMAC-SHA256", 

3918 ] 

3919 self.SigningAlgorithmId = None 

3920 self.Salt = os.urandom(32) 

3921 self.ConnectionPreauthIntegrityHashValue = None 

3922 self.SessionPreauthIntegrityHashValue = None 

3923 # SMB 3.1.1 

3924 self.SessionPreauthIntegrityHashValue = None 

3925 if conf.winssps_passive: 

3926 for ssp in conf.winssps_passive: 

3927 self.sniffsspcontexts[ssp] = None 

3928 super(SMBSession, self).__init__(*args, **kwargs) 

3929 

3930 # SMB crypto functions 

3931 

3932 @crypto_validator 

3933 def computeSMBSessionKeys(self, IsClient=None): 

3934 """ 

3935 Compute the SigningKey and EncryptionKey (for SMB 3+) 

3936 """ 

3937 if not getattr(self.sspcontext, "SessionKey", None): 

3938 # no signing key, no session key 

3939 return 

3940 # [MS-SMB2] sect 3.3.5.5.3 

3941 # SigningKey 

3942 if self.Dialect >= 0x0300: 

3943 if self.Dialect == 0x0311: 

3944 label = b"SMBSigningKey\x00" 

3945 context = self.SessionPreauthIntegrityHashValue 

3946 else: 

3947 label = b"SMB2AESCMAC\x00" 

3948 context = b"SmbSign\x00" 

3949 # [MS-SMB2] sect 3.1.4.2 

3950 if "256" in self.CipherId: 

3951 L = 256 

3952 elif "128" in self.CipherId: 

3953 L = 128 

3954 else: 

3955 raise ValueError 

3956 self.SigningKey = SP800108_KDFCTR( 

3957 self.sspcontext.SessionKey[:16], 

3958 label, 

3959 context, 

3960 L, 

3961 ) 

3962 # EncryptionKey / DecryptionKey 

3963 if self.Dialect == 0x0311: 

3964 if IsClient: 

3965 label_out = b"SMBC2SCipherKey\x00" 

3966 label_in = b"SMBS2CCipherKey\x00" 

3967 else: 

3968 label_out = b"SMBS2CCipherKey\x00" 

3969 label_in = b"SMBC2SCipherKey\x00" 

3970 context_out = context_in = self.SessionPreauthIntegrityHashValue 

3971 else: 

3972 label_out = label_in = b"SMB2AESCCM\x00" 

3973 if IsClient: 

3974 context_out = b"ServerIn \x00" # extra space per spec 

3975 context_in = b"ServerOut\x00" 

3976 else: 

3977 context_out = b"ServerOut\x00" 

3978 context_in = b"ServerIn \x00" 

3979 self.EncryptionKey = SP800108_KDFCTR( 

3980 self.sspcontext.SessionKey[: L // 8], 

3981 label_out, 

3982 context_out, 

3983 L, 

3984 ) 

3985 self.DecryptionKey = SP800108_KDFCTR( 

3986 self.sspcontext.SessionKey[: L // 8], 

3987 label_in, 

3988 context_in, 

3989 L, 

3990 ) 

3991 elif self.Dialect <= 0x0210: 

3992 self.SigningKey = self.sspcontext.SessionKey[:16] 

3993 else: 

3994 raise ValueError("Hmmm ? >:(") 

3995 

3996 def computeSMBConnectionPreauth(self, *negopkts): 

3997 if self.Dialect and self.Dialect >= 0x0311: # SMB 3.1.1 only 

3998 # [MS-SMB2] 3.3.5.4 

3999 # TODO: handle SMB2_SESSION_FLAG_BINDING 

4000 if self.ConnectionPreauthIntegrityHashValue is None: 

4001 # New auth or failure 

4002 self.ConnectionPreauthIntegrityHashValue = b"\x00" * 64 

4003 # Calculate the *Connection* PreauthIntegrityHashValue 

4004 for negopkt in negopkts: 

4005 self.ConnectionPreauthIntegrityHashValue = ( 

4006 SMB2computePreauthIntegrityHashValue( 

4007 self.ConnectionPreauthIntegrityHashValue, 

4008 negopkt, 

4009 HashId=self.PreauthIntegrityHashId, 

4010 ) 

4011 ) 

4012 

4013 def computeSMBSessionPreauth(self, *sesspkts): 

4014 if self.Dialect and self.Dialect >= 0x0311: # SMB 3.1.1 only 

4015 # [MS-SMB2] 3.3.5.5.3 

4016 if self.SessionPreauthIntegrityHashValue is None: 

4017 # New auth or failure 

4018 self.SessionPreauthIntegrityHashValue = ( 

4019 self.ConnectionPreauthIntegrityHashValue 

4020 ) 

4021 # Calculate the *Session* PreauthIntegrityHashValue 

4022 for sesspkt in sesspkts: 

4023 self.SessionPreauthIntegrityHashValue = ( 

4024 SMB2computePreauthIntegrityHashValue( 

4025 self.SessionPreauthIntegrityHashValue, 

4026 sesspkt, 

4027 HashId=self.PreauthIntegrityHashId, 

4028 ) 

4029 ) 

4030 

4031 # I/O 

4032 

4033 def in_pkt(self, pkt): 

4034 """ 

4035 Incoming SMB packet 

4036 """ 

4037 if SMB2_Transform_Header in pkt: 

4038 # Packet is encrypted 

4039 pkt = pkt[SMB2_Transform_Header].decrypt( 

4040 self.Dialect, 

4041 self.DecryptionKey, 

4042 CipherId=self.CipherId, 

4043 ) 

4044 # Signature is verified in SMBStreamSocket 

4045 return pkt 

4046 

4047 def out_pkt(self, pkt, Compounded=False, ForceSign=False, ForceEncrypt=False): 

4048 """ 

4049 Outgoing SMB packet 

4050 

4051 :param pkt: the packet to send 

4052 :param Compound: if True, will be stack to be send with the next 

4053 un-compounded packet 

4054 :param ForceSign: if True, force to sign the packet. 

4055 :param ForceEncrypt: if True, force to encrypt the packet. 

4056 

4057 Handles: 

4058 - handle compounded requests (if any): [MS-SMB2] 3.3.5.2.7 

4059 - handles signing and encryption (if required) 

4060 """ 

4061 # Note: impacket and wireshark get crazy on compounded+signature, but 

4062 # windows+samba tells we're right :D 

4063 if SMB2_Header in pkt: 

4064 if self.CompoundQueue: 

4065 # this is a subsequent compound: only keep the SMB2 

4066 pkt = pkt[SMB2_Header] 

4067 if Compounded: 

4068 # [MS-SMB2] 3.2.4.1.4 

4069 # "Compounded requests MUST be aligned on 8-byte boundaries; the 

4070 # last request of the compounded requests does not need to be padded to 

4071 # an 8-byte boundary." 

4072 # [MS-SMB2] 3.1.4.1 

4073 # "If the message is part of a compounded chain, any 

4074 # padding at the end of the message MUST be used in the hash 

4075 # computation." 

4076 length = len(pkt[SMB2_Header]) 

4077 padlen = (-length) % 8 

4078 if padlen: 

4079 pkt.add_payload(b"\x00" * padlen) 

4080 pkt[SMB2_Header].NextCommand = length + padlen 

4081 if ( 

4082 self.Dialect 

4083 and self.SigningKey 

4084 and (ForceSign or self.SigningRequired and not ForceEncrypt) 

4085 ): 

4086 # [MS-SMB2] sect 3.2.4.1.1 - Signing 

4087 smb = pkt[SMB2_Header] 

4088 smb.Flags += "SMB2_FLAGS_SIGNED" 

4089 smb.sign( 

4090 self.Dialect, 

4091 self.SigningKey, 

4092 # SMB 3.1.1 parameters: 

4093 SigningAlgorithmId=self.SigningAlgorithmId, 

4094 IsClient=False, 

4095 ) 

4096 if Compounded: 

4097 # There IS a next compound. Store in queue 

4098 self.CompoundQueue.append(pkt) 

4099 return [] 

4100 else: 

4101 # If there are any compounded responses in store, sum them 

4102 if self.CompoundQueue: 

4103 pkt = functools.reduce(lambda x, y: x / y, self.CompoundQueue) / pkt 

4104 self.CompoundQueue.clear() 

4105 if self.EncryptionKey and ( 

4106 ForceEncrypt or self.EncryptData or self.TreeEncryptData 

4107 ): 

4108 # [MS-SMB2] sect 3.1.4.3 - Encrypting the message 

4109 smb = pkt[SMB2_Header] 

4110 assert not smb.Flags.SMB2_FLAGS_SIGNED 

4111 smbt = smb.encrypt( 

4112 self.Dialect, 

4113 self.EncryptionKey, 

4114 CipherId=self.CipherId, 

4115 ) 

4116 if smb.underlayer: 

4117 # If there's an underlayer, replace current SMB header 

4118 smb.underlayer.payload = smbt 

4119 else: 

4120 smb = smbt 

4121 return [pkt] 

4122 

4123 def process(self, pkt: Packet): 

4124 # Called when passively sniffing 

4125 pkt = super(SMBSession, self).process(pkt) 

4126 if pkt is not None and SMB2_Header in pkt: 

4127 return self.in_pkt(pkt) 

4128 return pkt