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

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

1103 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 re 

19import struct 

20 

21from scapy.automaton import select_objects 

22from scapy.config import conf, crypto_validator 

23from scapy.error import log_runtime 

24from scapy.packet import Packet, bind_layers, bind_top_down 

25from scapy.fields import ( 

26 ByteEnumField, 

27 ByteField, 

28 ConditionalField, 

29 FieldLenField, 

30 FieldListField, 

31 FlagValue, 

32 FlagsField, 

33 IP6Field, 

34 IPField, 

35 IntField, 

36 LEIntField, 

37 LEIntEnumField, 

38 LELongField, 

39 LenField, 

40 LEShortEnumField, 

41 LEShortField, 

42 MultipleTypeField, 

43 PadField, 

44 PacketField, 

45 PacketLenField, 

46 PacketListField, 

47 ReversePadField, 

48 ScalingField, 

49 ShortEnumField, 

50 ShortField, 

51 StrFieldUtf16, 

52 StrFixedLenField, 

53 StrLenField, 

54 StrLenFieldUtf16, 

55 StrNullFieldUtf16, 

56 ThreeBytesField, 

57 UTCTimeField, 

58 UUIDField, 

59 XLEIntField, 

60 XLELongField, 

61 XLEShortField, 

62 XStrLenField, 

63 XStrFixedLenField, 

64 YesNoByteField, 

65) 

66from scapy.sessions import DefaultSession 

67from scapy.supersocket import StreamSocket 

68 

69if conf.crypto_valid: 

70 from scapy.libs.rfc3961 import SP800108_KDFCTR 

71 

72from scapy.layers.gssapi import GSSAPI_BLOB 

73from scapy.layers.netbios import NBTSession 

74from scapy.layers.ntlm import ( 

75 _NTLMPayloadField, 

76 _NTLMPayloadPacket, 

77 _NTLM_ENUM, 

78 _NTLM_post_build, 

79) 

80 

81 

82# EnumField 

83SMB_DIALECTS = { 

84 0x0202: "SMB 2.002", 

85 0x0210: "SMB 2.1", 

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

87 0x0300: "SMB 3.0", 

88 0x0302: "SMB 3.0.2", 

89 0x0311: "SMB 3.1.1", 

90} 

91 

92# SMB2 sect 3.3.5.15 + [MS-ERREF] 

93STATUS_ERREF = { 

94 0x00000000: "STATUS_SUCCESS", 

95 0x00000103: "STATUS_PENDING", 

96 0x0000010B: "STATUS_NOTIFY_CLEANUP", 

97 0x0000010C: "STATUS_NOTIFY_ENUM_DIR", 

98 0x00000532: "ERROR_PASSWORD_EXPIRED", 

99 0x00000533: "ERROR_ACCOUNT_DISABLED", 

100 0x000006FE: "ERROR_TRUST_FAILURE", 

101 0x80000005: "STATUS_BUFFER_OVERFLOW", 

102 0x80000006: "STATUS_NO_MORE_FILES", 

103 0x8000002D: "STATUS_STOPPED_ON_SYMLINK", 

104 0x80090308: "SEC_E_INVALID_TOKEN", 

105 0x8009030C: "SEC_E_LOGON_DENIED", 

106 0x8009030F: "SEC_E_MESSAGE_ALTERED", 

107 0x80090310: "SEC_E_OUT_OF_SEQUENCE", 

108 0x80090346: "SEC_E_BAD_BINDINGS", 

109 0x80090351: "SEC_E_SMARTCARD_CERT_REVOKED", 

110 0xC0000003: "STATUS_INVALID_INFO_CLASS", 

111 0xC0000004: "STATUS_INFO_LENGTH_MISMATCH", 

112 0xC000000D: "STATUS_INVALID_PARAMETER", 

113 0xC000000F: "STATUS_NO_SUCH_FILE", 

114 0xC0000016: "STATUS_MORE_PROCESSING_REQUIRED", 

115 0xC0000022: "STATUS_ACCESS_DENIED", 

116 0xC0000033: "STATUS_OBJECT_NAME_INVALID", 

117 0xC0000034: "STATUS_OBJECT_NAME_NOT_FOUND", 

118 0xC0000043: "STATUS_SHARING_VIOLATION", 

119 0xC0000061: "STATUS_PRIVILEGE_NOT_HELD", 

120 0xC0000064: "STATUS_NO_SUCH_USER", 

121 0xC000006D: "STATUS_LOGON_FAILURE", 

122 0xC000006E: "STATUS_ACCOUNT_RESTRICTION", 

123 0xC0000070: "STATUS_INVALID_WORKSTATION", 

124 0xC0000071: "STATUS_PASSWORD_EXPIRED", 

125 0xC0000072: "STATUS_ACCOUNT_DISABLED", 

126 0xC000009A: "STATUS_INSUFFICIENT_RESOURCES", 

127 0xC00000BA: "STATUS_FILE_IS_A_DIRECTORY", 

128 0xC00000BB: "STATUS_NOT_SUPPORTED", 

129 0xC00000C9: "STATUS_NETWORK_NAME_DELETED", 

130 0xC00000CC: "STATUS_BAD_NETWORK_NAME", 

131 0xC0000120: "STATUS_CANCELLED", 

132 0xC0000122: "STATUS_INVALID_COMPUTER_NAME", 

133 0xC0000128: "STATUS_FILE_CLOSED", # backup error for older Win versions 

134 0xC000015B: "STATUS_LOGON_TYPE_NOT_GRANTED", 

135 0xC000018B: "STATUS_NO_TRUST_SAM_ACCOUNT", 

136 0xC000019C: "STATUS_FS_DRIVER_REQUIRED", 

137 0xC0000203: "STATUS_USER_SESSION_DELETED", 

138 0xC000020C: "STATUS_CONNECTION_DISCONNECTED", 

139 0xC0000225: "STATUS_NOT_FOUND", 

140 0xC0000257: "STATUS_PATH_NOT_COVERED", 

141 0xC000035C: "STATUS_NETWORK_SESSION_EXPIRED", 

142} 

143 

144# SMB2 sect 2.1.2.1 

145REPARSE_TAGS = { 

146 0x00000000: "IO_REPARSE_TAG_RESERVED_ZERO", 

147 0x00000001: "IO_REPARSE_TAG_RESERVED_ONE", 

148 0x00000002: "IO_REPARSE_TAG_RESERVED_TWO", 

149 0xA0000003: "IO_REPARSE_TAG_MOUNT_POINT", 

150 0xC0000004: "IO_REPARSE_TAG_HSM", 

151 0x80000005: "IO_REPARSE_TAG_DRIVE_EXTENDER", 

152 0x80000006: "IO_REPARSE_TAG_HSM2", 

153 0x80000007: "IO_REPARSE_TAG_SIS", 

154 0x80000008: "IO_REPARSE_TAG_WIM", 

155 0x80000009: "IO_REPARSE_TAG_CSV", 

156 0x8000000A: "IO_REPARSE_TAG_DFS", 

157 0x8000000B: "IO_REPARSE_TAG_FILTER_MANAGER", 

158 0xA000000C: "IO_REPARSE_TAG_SYMLINK", 

159 0xA0000010: "IO_REPARSE_TAG_IIS_CACHE", 

160 0x80000012: "IO_REPARSE_TAG_DFSR", 

161 0x80000013: "IO_REPARSE_TAG_DEDUP", 

162 0xC0000014: "IO_REPARSE_TAG_APPXSTRM", 

163 0x80000014: "IO_REPARSE_TAG_NFS", 

164 0x80000015: "IO_REPARSE_TAG_FILE_PLACEHOLDER", 

165 0x80000016: "IO_REPARSE_TAG_DFM", 

166 0x80000017: "IO_REPARSE_TAG_WOF", 

167 0x80000018: "IO_REPARSE_TAG_WCI", 

168 0x90001018: "IO_REPARSE_TAG_WCI_1", 

169 0xA0000019: "IO_REPARSE_TAG_GLOBAL_REPARSE", 

170 0x9000001A: "IO_REPARSE_TAG_CLOUD", 

171 0x9000101A: "IO_REPARSE_TAG_CLOUD_1", 

172 0x9000201A: "IO_REPARSE_TAG_CLOUD_2", 

173 0x9000301A: "IO_REPARSE_TAG_CLOUD_3", 

174 0x9000401A: "IO_REPARSE_TAG_CLOUD_4", 

175 0x9000501A: "IO_REPARSE_TAG_CLOUD_5", 

176 0x9000601A: "IO_REPARSE_TAG_CLOUD_6", 

177 0x9000701A: "IO_REPARSE_TAG_CLOUD_7", 

178 0x9000801A: "IO_REPARSE_TAG_CLOUD_8", 

179 0x9000901A: "IO_REPARSE_TAG_CLOUD_9", 

180 0x9000A01A: "IO_REPARSE_TAG_CLOUD_A", 

181 0x9000B01A: "IO_REPARSE_TAG_CLOUD_B", 

182 0x9000C01A: "IO_REPARSE_TAG_CLOUD_C", 

183 0x9000D01A: "IO_REPARSE_TAG_CLOUD_D", 

184 0x9000E01A: "IO_REPARSE_TAG_CLOUD_E", 

185 0x9000F01A: "IO_REPARSE_TAG_CLOUD_F", 

186 0x8000001B: "IO_REPARSE_TAG_APPEXECLINK", 

187 0x9000001C: "IO_REPARSE_TAG_PROJFS", 

188 0xA000001D: "IO_REPARSE_TAG_LX_SYMLINK", 

189 0x8000001E: "IO_REPARSE_TAG_STORAGE_SYNC", 

190 0xA000001F: "IO_REPARSE_TAG_WCI_TOMBSTONE", 

191 0x80000020: "IO_REPARSE_TAG_UNHANDLED", 

192 0x80000021: "IO_REPARSE_TAG_ONEDRIVE", 

193 0xA0000022: "IO_REPARSE_TAG_PROJFS_TOMBSTONE", 

194 0x80000023: "IO_REPARSE_TAG_AF_UNIX", 

195 0x80000024: "IO_REPARSE_TAG_LX_FIFO", 

196 0x80000025: "IO_REPARSE_TAG_LX_CHR", 

197 0x80000026: "IO_REPARSE_TAG_LX_BLK", 

198 0xA0000027: "IO_REPARSE_TAG_WCI_LINK", 

199 0xA0001027: "IO_REPARSE_TAG_WCI_LINK_1", 

200} 

201 

202# SMB2 sect 2.2.1.1 

203SMB2_COM = { 

204 0x0000: "SMB2_NEGOTIATE", 

205 0x0001: "SMB2_SESSION_SETUP", 

206 0x0002: "SMB2_LOGOFF", 

207 0x0003: "SMB2_TREE_CONNECT", 

208 0x0004: "SMB2_TREE_DISCONNECT", 

209 0x0005: "SMB2_CREATE", 

210 0x0006: "SMB2_CLOSE", 

211 0x0007: "SMB2_FLUSH", 

212 0x0008: "SMB2_READ", 

213 0x0009: "SMB2_WRITE", 

214 0x000A: "SMB2_LOCK", 

215 0x000B: "SMB2_IOCTL", 

216 0x000C: "SMB2_CANCEL", 

217 0x000D: "SMB2_ECHO", 

218 0x000E: "SMB2_QUERY_DIRECTORY", 

219 0x000F: "SMB2_CHANGE_NOTIFY", 

220 0x0010: "SMB2_QUERY_INFO", 

221 0x0011: "SMB2_SET_INFO", 

222 0x0012: "SMB2_OPLOCK_BREAK", 

223} 

224 

225# EnumField 

226SMB2_NEGOTIATE_CONTEXT_TYPES = { 

227 0x0001: "SMB2_PREAUTH_INTEGRITY_CAPABILITIES", 

228 0x0002: "SMB2_ENCRYPTION_CAPABILITIES", 

229 0x0003: "SMB2_COMPRESSION_CAPABILITIES", 

230 0x0005: "SMB2_NETNAME_NEGOTIATE_CONTEXT_ID", 

231 0x0006: "SMB2_TRANSPORT_CAPABILITIES", 

232 0x0007: "SMB2_RDMA_TRANSFORM_CAPABILITIES", 

233 0x0008: "SMB2_SIGNING_CAPABILITIES", 

234} 

235 

236# FlagField 

237SMB2_CAPABILITIES = { 

238 0x00000001: "DFS", 

239 0x00000002: "LEASING", 

240 0x00000004: "LARGE_MTU", 

241 0x00000008: "MULTI_CHANNEL", 

242 0x00000010: "PERSISTENT_HANDLES", 

243 0x00000020: "DIRECTORY_LEASING", 

244 0x00000040: "ENCRYPTION", 

245} 

246SMB2_SECURITY_MODE = { 

247 0x01: "SIGNING_ENABLED", 

248 0x02: "SIGNING_REQUIRED", 

249} 

250 

251# [MS-SMB2] 2.2.3.1.3 

252SMB2_COMPRESSION_ALGORITHMS = { 

253 0x0000: "None", 

254 0x0001: "LZNT1", 

255 0x0002: "LZ77", 

256 0x0003: "LZ77 + Huffman", 

257 0x0004: "Pattern_V1", 

258} 

259 

260# [MS-SMB2] sect 2.2.3.1.2 

261SMB2_ENCRYPTION_CIPHERS = { 

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

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

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

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

266} 

267 

268# [MS-SMB2] sect 2.2.3.1.7 

269SMB2_SIGNING_ALGORITHMS = { 

270 0x0000: "HMAC-SHA256", 

271 0x0001: "AES-CMAC", 

272 0x0002: "AES-GMAC", 

273} 

274 

275# [MS-SMB2] sect 2.2.3.1.1 

276SMB2_HASH_ALGORITHMS = { 

277 0x0001: "SHA-512", 

278} 

279 

280# sect [MS-SMB2] 2.2.13.1.1 

281SMB2_ACCESS_FLAGS_FILE = { 

282 0x00000001: "FILE_READ_DATA", 

283 0x00000002: "FILE_WRITE_DATA", 

284 0x00000004: "FILE_APPEND_DATA", 

285 0x00000008: "FILE_READ_EA", 

286 0x00000010: "FILE_WRITE_EA", 

287 0x00000040: "FILE_DELETE_CHILD", 

288 0x00000020: "FILE_EXECUTE", 

289 0x00000080: "FILE_READ_ATTRIBUTES", 

290 0x00000100: "FILE_WRITE_ATTRIBUTES", 

291 0x00010000: "DELETE", 

292 0x00020000: "READ_CONTROL", 

293 0x00040000: "WRITE_DAC", 

294 0x00080000: "WRITE_OWNER", 

295 0x00100000: "SYNCHRONIZE", 

296 0x01000000: "ACCESS_SYSTEM_SECURITY", 

297 0x02000000: "MAXIMUM_ALLOWED", 

298 0x10000000: "GENERIC_ALL", 

299 0x20000000: "GENERIC_EXECUTE", 

300 0x40000000: "GENERIC_WRITE", 

301 0x80000000: "GENERIC_READ", 

302} 

303 

304# sect [MS-SMB2] 2.2.13.1.2 

305SMB2_ACCESS_FLAGS_DIRECTORY = { 

306 0x00000001: "FILE_LIST_DIRECTORY", 

307 0x00000002: "FILE_ADD_FILE", 

308 0x00000004: "FILE_ADD_SUBDIRECTORY", 

309 0x00000008: "FILE_READ_EA", 

310 0x00000010: "FILE_WRITE_EA", 

311 0x00000020: "FILE_TRAVERSE", 

312 0x00000040: "FILE_DELETE_CHILD", 

313 0x00000080: "FILE_READ_ATTRIBUTES", 

314 0x00000100: "FILE_WRITE_ATTRIBUTES", 

315 0x00010000: "DELETE", 

316 0x00020000: "READ_CONTROL", 

317 0x00040000: "WRITE_DAC", 

318 0x00080000: "WRITE_OWNER", 

319 0x00100000: "SYNCHRONIZE", 

320 0x01000000: "ACCESS_SYSTEM_SECURITY", 

321 0x02000000: "MAXIMUM_ALLOWED", 

322 0x10000000: "GENERIC_ALL", 

323 0x20000000: "GENERIC_EXECUTE", 

324 0x40000000: "GENERIC_WRITE", 

325 0x80000000: "GENERIC_READ", 

326} 

327 

328# [MS-SRVS] sec 2.2.2.4 

329SRVSVC_SHARE_TYPES = { 

330 0x00000000: "DISKTREE", 

331 0x00000001: "PRINTQ", 

332 0x00000002: "DEVICE", 

333 0x00000003: "IPC", 

334 0x02000000: "CLUSTER_FS", 

335 0x04000000: "CLUSTER_SOFS", 

336 0x08000000: "CLUSTER_DFS", 

337} 

338 

339 

340# [MS-FSCC] sec 2.6 

341FileAttributes = { 

342 0x00000001: "FILE_ATTRIBUTE_READONLY", 

343 0x00000002: "FILE_ATTRIBUTE_HIDDEN", 

344 0x00000004: "FILE_ATTRIBUTE_SYSTEM", 

345 0x00000010: "FILE_ATTRIBUTE_DIRECTORY", 

346 0x00000020: "FILE_ATTRIBUTE_ARCHIVE", 

347 0x00000080: "FILE_ATTRIBUTE_NORMAL", 

348 0x00000100: "FILE_ATTRIBUTE_TEMPORARY", 

349 0x00000200: "FILE_ATTRIBUTE_SPARSE_FILE", 

350 0x00000400: "FILE_ATTRIBUTE_REPARSE_POINT", 

351 0x00000800: "FILE_ATTRIBUTE_COMPRESSED", 

352 0x00001000: "FILE_ATTRIBUTE_OFFLINE", 

353 0x00002000: "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED", 

354 0x00004000: "FILE_ATTRIBUTE_ENCRYPTED", 

355 0x00008000: "FILE_ATTRIBUTE_INTEGRITY_STREAM", 

356 0x00020000: "FILE_ATTRIBUTE_NO_SCRUB_DATA", 

357 0x00040000: "FILE_ATTRIBUTE_RECALL_ON_OPEN", 

358 0x00080000: "FILE_ATTRIBUTE_PINNED", 

359 0x00100000: "FILE_ATTRIBUTE_UNPINNED", 

360 0x00400000: "FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS", 

361} 

362 

363 

364# [MS-FSCC] sect 2.4 

365FileInformationClasses = { 

366 0x01: "FileDirectoryInformation", 

367 0x02: "FileFullDirectoryInformation", 

368 0x03: "FileBothDirectoryInformation", 

369 0x04: "FileBasicInformation", 

370 0x05: "FileStandardInformation", 

371 0x06: "FileInternalInformation", 

372 0x07: "FileEaInformation", 

373 0x08: "FileAccessInformation", 

374 0x0A: "FileRenameInformation", 

375 0x0E: "FilePositionInformation", 

376 0x10: "FileModeInformation", 

377 0x11: "FileAlignmentInformation", 

378 0x12: "FileAllInformation", 

379 0x22: "FileNetworkOpenInformation", 

380 0x25: "FileIdBothDirectoryInformation", 

381 0x26: "FileIdFullDirectoryInformation", 

382 0x0C: "FileNamesInformation", 

383 0x30: "FileNormalizedNameInformation", 

384 0x3C: "FileIdExtdDirectoryInformation", 

385} 

386_FileInformationClasses = {} 

387 

388 

389# [MS-FSCC] 2.1.7 FILE_NAME_INFORMATION 

390 

391 

392class FILE_NAME_INFORMATION(Packet): 

393 fields_desc = [ 

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

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

396 ] 

397 

398 def default_payload_class(self, s): 

399 return conf.padding_layer 

400 

401 

402# [MS-FSCC] 2.4.1 FileAccessInformation 

403 

404 

405class FileAccessInformation(Packet): 

406 fields_desc = [ 

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

408 ] 

409 

410 def default_payload_class(self, s): 

411 return conf.padding_layer 

412 

413 

414# [MS-FSCC] 2.4.3 FileAlignmentInformation 

415 

416 

417class FileAlignmentInformation(Packet): 

418 fields_desc = [ 

419 LEIntEnumField( 

420 "AccessFlags", 

421 0, 

422 { 

423 0x00000000: "FILE_BYTE_ALIGNMENT", 

424 0x00000001: "FILE_WORD_ALIGNMENT", 

425 0x00000003: "FILE_LONG_ALIGNMENT", 

426 0x00000007: "FILE_QUAD_ALIGNMENT", 

427 0x0000000F: "FILE_OCTA_ALIGNMENT", 

428 0x0000001F: "FILE_32_BYTE_ALIGNMENT", 

429 0x0000003F: "FILE_64_BYTE_ALIGNMENT", 

430 0x0000007F: "FILE_128_BYTE_ALIGNMENT", 

431 0x000000FF: "FILE_256_BYTE_ALIGNMENT", 

432 0x000001FF: "FILE_512_BYTE_ALIGNMENT", 

433 }, 

434 ), 

435 ] 

436 

437 def default_payload_class(self, s): 

438 return conf.padding_layer 

439 

440 

441# [MS-FSCC] 2.4.5 FileAlternateNameInformation 

442 

443 

444class FileAlternateNameInformation(Packet): 

445 fields_desc = [ 

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

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

448 ] 

449 

450 

451# [MS-FSCC] 2.4.7 FileBasicInformation 

452 

453 

454class FileBasicInformation(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 FlagsField("FileAttributes", 0x00000080, -32, FileAttributes), 

485 IntField("Reserved", 0), 

486 ] 

487 

488 def default_payload_class(self, s): 

489 return conf.padding_layer 

490 

491 

492# [MS-FSCC] 2.4.12 FileEaInformation 

493 

494 

495class FileEaInformation(Packet): 

496 fields_desc = [ 

497 LEIntField("EaSize", 0), 

498 ] 

499 

500 def default_payload_class(self, s): 

501 return conf.padding_layer 

502 

503 

504# [MS-FSCC] 2.4.29 FileNetworkOpenInformation 

505 

506 

507class FileNetworkOpenInformation(Packet): 

508 fields_desc = [ 

509 UTCTimeField( 

510 "CreationTime", 

511 None, 

512 fmt="<Q", 

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

514 custom_scaling=1e7, 

515 ), 

516 UTCTimeField( 

517 "LastAccessTime", 

518 None, 

519 fmt="<Q", 

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

521 custom_scaling=1e7, 

522 ), 

523 UTCTimeField( 

524 "LastWriteTime", 

525 None, 

526 fmt="<Q", 

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

528 custom_scaling=1e7, 

529 ), 

530 UTCTimeField( 

531 "ChangeTime", 

532 None, 

533 fmt="<Q", 

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

535 custom_scaling=1e7, 

536 ), 

537 LELongField("AllocationSize", 4096), 

538 LELongField("EndOfFile", 0), 

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

540 IntField("Reserved2", 0), 

541 ] 

542 

543 def default_payload_class(self, s): 

544 return conf.padding_layer 

545 

546 

547# [MS-FSCC] 2.4.8 FileBothDirectoryInformation 

548 

549 

550class FILE_BOTH_DIR_INFORMATION(Packet): 

551 fields_desc = ( 

552 [ 

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

554 LEIntField("FileIndex", 0), 

555 ] 

556 + ( 

557 FileNetworkOpenInformation.fields_desc[:4] 

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

559 + [FileNetworkOpenInformation.fields_desc[6]] 

560 ) 

561 + [ 

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

563 MultipleTypeField( 

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

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

566 # 2.1.2.1." 

567 [ 

568 ( 

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

570 lambda pkt: pkt.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT, 

571 ) 

572 ], 

573 LEIntField("EaSize", 0), 

574 ), 

575 ByteField("ShortNameLength", 0), 

576 ByteField("Reserved1", 0), 

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

578 PadField( 

579 StrLenFieldUtf16( 

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

581 ), 

582 align=8, 

583 ), 

584 ] 

585 ) 

586 

587 def default_payload_class(self, s): 

588 return conf.padding_layer 

589 

590 

591class _NextPacketListField(PacketListField): 

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

593 # we use this field to set NextEntryOffset 

594 res = b"" 

595 for i, v in enumerate(val): 

596 x = self.i2m(pkt, v) 

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

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

599 res += x 

600 return s + res 

601 

602 

603class FileBothDirectoryInformation(Packet): 

604 fields_desc = [ 

605 _NextPacketListField( 

606 "files", 

607 [], 

608 FILE_BOTH_DIR_INFORMATION, 

609 max_count=1000, 

610 ), 

611 ] 

612 

613 

614# [MS-FSCC] 2.4.14 FileFullDirectoryInformation 

615 

616 

617class FILE_FULL_DIR_INFORMATION(Packet): 

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

619 FILE_BOTH_DIR_INFORMATION.fields_desc[-1] 

620 ] 

621 

622 

623class FileFullDirectoryInformation(Packet): 

624 fields_desc = [ 

625 _NextPacketListField( 

626 "files", 

627 [], 

628 FILE_FULL_DIR_INFORMATION, 

629 max_count=1000, 

630 ), 

631 ] 

632 

633 

634# [MS-FSCC] 2.4.17 FileIdBothDirectoryInformation 

635 

636 

637class FILE_ID_BOTH_DIR_INFORMATION(Packet): 

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

639 LEShortField("Reserved2", 0), 

640 LELongField("FileId", 0), 

641 FILE_BOTH_DIR_INFORMATION.fields_desc[-1], 

642 ] 

643 

644 def default_payload_class(self, s): 

645 return conf.padding_layer 

646 

647 

648class FileIdBothDirectoryInformation(Packet): 

649 fields_desc = [ 

650 _NextPacketListField( 

651 "files", 

652 [], 

653 FILE_ID_BOTH_DIR_INFORMATION, 

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

655 ), 

656 ] 

657 

658 

659# [MS-FSCC] 2.4.22 FileInternalInformation 

660 

661 

662class FileInternalInformation(Packet): 

663 fields_desc = [ 

664 LELongField("IndexNumber", 0), 

665 ] 

666 

667 def default_payload_class(self, s): 

668 return conf.padding_layer 

669 

670 

671# [MS-FSCC] 2.4.26 FileModeInformation 

672 

673 

674class FileModeInformation(Packet): 

675 fields_desc = [ 

676 FlagsField( 

677 "Mode", 

678 0, 

679 -32, 

680 { 

681 0x00000002: "FILE_WRITE_TROUGH", 

682 0x00000004: "FILE_SEQUENTIAL_ONLY", 

683 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING", 

684 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT", 

685 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT", 

686 0x00001000: "FILE_DELETE_ON_CLOSE", 

687 }, 

688 ) 

689 ] 

690 

691 def default_payload_class(self, s): 

692 return conf.padding_layer 

693 

694 

695# [MS-FSCC] 2.4.35 FilePositionInformation 

696 

697 

698class FilePositionInformation(Packet): 

699 fields_desc = [ 

700 LELongField("CurrentByteOffset", 0), 

701 ] 

702 

703 def default_payload_class(self, s): 

704 return conf.padding_layer 

705 

706 

707# [MS-FSCC] 2.4.37 FileRenameInformation 

708 

709 

710class FileRenameInformation(Packet): 

711 fields_desc = [ 

712 YesNoByteField("ReplaceIfExists", False), 

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

714 LELongField("RootDirectory", 0), 

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

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

717 ] 

718 

719 def post_build(self, pkt, pay): 

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

721 if len(pkt) < 24: 

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

723 # size of this structure at least 24.' 

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

725 return pkt + pay 

726 

727 def default_payload_class(self, s): 

728 return conf.padding_layer 

729 

730 

731_FileInformationClasses[0x0A] = FileRenameInformation 

732 

733 

734# [MS-FSCC] 2.4.41 FileStandardInformation 

735 

736 

737class FileStandardInformation(Packet): 

738 fields_desc = [ 

739 LELongField("AllocationSize", 4096), 

740 LELongField("EndOfFile", 0), 

741 LEIntField("NumberOfLinks", 1), 

742 ByteField("DeletePending", 0), 

743 ByteField("Directory", 0), 

744 ShortField("Reserved", 0), 

745 ] 

746 

747 def default_payload_class(self, s): 

748 return conf.padding_layer 

749 

750 

751# [MS-FSCC] 2.4.43 FileStreamInformation 

752 

753 

754class FileStreamInformation(Packet): 

755 fields_desc = [ 

756 LEIntField("Next", 0), 

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

758 LELongField("StreamSize", 0), 

759 LELongField("StreamAllocationSize", 4096), 

760 StrLenFieldUtf16( 

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

762 ), 

763 ] 

764 

765 

766# [MS-DTYP] sect 2.4.1 

767 

768 

769class WINNT_SID_IDENTIFIER_AUTHORITY(Packet): 

770 fields_desc = [ 

771 StrFixedLenField("Value", b"\x00\x00\x00\x00\x00\x01", length=6), 

772 ] 

773 

774 def default_payload_class(self, payload): 

775 return conf.padding_layer 

776 

777 

778# [MS-DTYP] sect 2.4.2 

779 

780 

781class WINNT_SID(Packet): 

782 fields_desc = [ 

783 ByteField("Revision", 1), 

784 FieldLenField("SubAuthorityCount", None, count_of="SubAuthority", fmt="B"), 

785 PacketField( 

786 "IdentifierAuthority", 

787 WINNT_SID_IDENTIFIER_AUTHORITY(), 

788 WINNT_SID_IDENTIFIER_AUTHORITY, 

789 ), 

790 FieldListField( 

791 "SubAuthority", 

792 [0], 

793 LEIntField("", 0), 

794 count_from=lambda pkt: pkt.SubAuthorityCount, 

795 ), 

796 ] 

797 

798 def default_payload_class(self, payload): 

799 return conf.padding_layer 

800 

801 _SID_REG = re.compile(r"^S-(\d)-(\d+)((?:-\d+)*)$") 

802 

803 @staticmethod 

804 def fromstr(x): 

805 m = WINNT_SID._SID_REG.match(x) 

806 if not m: 

807 raise ValueError("Invalid SID format !") 

808 rev, authority, subauthority = m.groups() 

809 return WINNT_SID( 

810 Revision=int(rev), 

811 IdentifierAuthority=WINNT_SID_IDENTIFIER_AUTHORITY( 

812 Value=struct.pack(">Q", int(authority))[2:] 

813 ), 

814 SubAuthority=[int(x) for x in subauthority[1:].split("-")], 

815 ) 

816 

817 def summary(self): 

818 return "S-%s-%s%s" % ( 

819 self.Revision, 

820 struct.unpack(">Q", b"\x00\x00" + self.IdentifierAuthority.Value)[0], 

821 ( 

822 ("-%s" % "-".join(str(x) for x in self.SubAuthority)) 

823 if self.SubAuthority 

824 else "" 

825 ), 

826 ) 

827 

828 

829# https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers 

830 

831WELL_KNOWN_SIDS = { 

832 # Universal well-known SID 

833 "S-1-0-0": "Null SID", 

834 "S-1-1-0": "Everyone", 

835 "S-1-2-0": "Local", 

836 "S-1-2-1": "Console Logon", 

837 "S-1-3-0": "Creator Owner ID", 

838 "S-1-3-1": "Creator Group ID", 

839 "S-1-3-2": "Owner Server", 

840 "S-1-3-3": "Group Server", 

841 "S-1-3-4": "Owner Rights", 

842 "S-1-4": "Non-unique Authority", 

843 "S-1-5": "NT Authority", 

844 "S-1-5-80-0": "All Services", 

845 # NT well-known SIDs 

846 "S-1-5-1": "Dialup", 

847 "S-1-5-113": "Local account", 

848 "S-1-5-114": "Local account and member of Administrators group", 

849 "S-1-5-2": "Network", 

850 "S-1-5-3": "Batch", 

851 "S-1-5-4": "Interactive", 

852 "S-1-5-6": "Service", 

853 "S-1-5-7": "Anonymous Logon", 

854 "S-1-5-8": "Proxy", 

855 "S-1-5-9": "Enterprise Domain Controllers", 

856 "S-1-5-10": "Self", 

857 "S-1-5-11": "Authenticated Users", 

858 "S-1-5-12": "Restricted Code", 

859 "S-1-5-13": "Terminal Server User", 

860 "S-1-5-14": "Remote Interactive Logon", 

861 "S-1-5-15": "This Organization", 

862 "S-1-5-17": "IUSR", 

863 "S-1-5-18": "System (or LocalSystem)", 

864 "S-1-5-19": "NT Authority (LocalService)", 

865 "S-1-5-20": "Network Service", 

866 "S-1-5-32-544": "Administrators", 

867 "S-1-5-32-545": "Users", 

868 "S-1-5-32-546": "Guests", 

869 "S-1-5-32-547": "Power Users", 

870 "S-1-5-32-548": "Account Operators", 

871 "S-1-5-32-549": "Server Operators", 

872 "S-1-5-32-550": "Print Operators", 

873 "S-1-5-32-551": "Backup Operators", 

874 "S-1-5-32-552": "Replicators", 

875 "S-1-5-32-554": r"Builtin\Pre-Windows 2000 Compatible Access", 

876 "S-1-5-32-555": r"Builtin\Remote Desktop Users", 

877 "S-1-5-32-556": r"Builtin\Network Configuration Operators", 

878 "S-1-5-32-557": r"Builtin\Incoming Forest Trust Builders", 

879 "S-1-5-32-558": r"Builtin\Performance Monitor Users", 

880 "S-1-5-32-559": r"Builtin\Performance Log Users", 

881 "S-1-5-32-560": r"Builtin\Windows Authorization Access Group", 

882 "S-1-5-32-561": r"Builtin\Terminal Server License Servers", 

883 "S-1-5-32-562": r"Builtin\Distributed COM Users", 

884 "S-1-5-32-568": r"Builtin\IIS_IUSRS", 

885 "S-1-5-32-569": r"Builtin\Cryptographic Operators", 

886 "S-1-5-32-573": r"Builtin\Event Log Readers", 

887 "S-1-5-32-574": r"Builtin\Certificate Service DCOM Access", 

888 "S-1-5-32-575": r"Builtin\RDS Remote Access Servers", 

889 "S-1-5-32-576": r"Builtin\RDS Endpoint Servers", 

890 "S-1-5-32-577": r"Builtin\RDS Management Servers", 

891 "S-1-5-32-578": r"Builtin\Hyper-V Administrators", 

892 "S-1-5-32-579": r"Builtin\Access Control Assistance Operators", 

893 "S-1-5-32-580": r"Builtin\Remote Management Users", 

894 "S-1-5-32-581": r"Builtin\Default Account", 

895 "S-1-5-32-582": r"Builtin\Storage Replica Admins", 

896 "S-1-5-32-583": r"Builtin\Device Owners", 

897 "S-1-5-64-10": "NTLM Authentication", 

898 "S-1-5-64-14": "SChannel Authentication", 

899 "S-1-5-64-21": "Digest Authentication", 

900 "S-1-5-80": "NT Service", 

901 "S-1-5-80-0": "All Services", 

902 "S-1-5-83-0": r"NT VIRTUAL MACHINE\Virtual Machines", 

903} 

904 

905 

906# [MS-DTYP] sect 2.4.3 

907 

908_WINNT_ACCESS_MASK = { 

909 0x80000000: "GENERIC_READ", 

910 0x40000000: "GENERIC_WRITE", 

911 0x20000000: "GENERIC_EXECUTE", 

912 0x10000000: "GENERIC_ALL", 

913 0x02000000: "MAXIMUM_ALLOWED", 

914 0x01000000: "ACCESS_SYSTEM_SECURITY", 

915 0x00100000: "SYNCHRONIZE", 

916 0x00080000: "WRITE_OWNER", 

917 0x00040000: "WRITE_DACL", 

918 0x00020000: "READ_CONTROL", 

919 0x00010000: "DELETE", 

920} 

921 

922 

923# [MS-DTYP] sect 2.4.4.1 

924 

925 

926WINNT_ACE_FLAGS = { 

927 0x01: "OBJECT_INHERIT", 

928 0x02: "CONTAINER_INHERIT", 

929 0x04: "NO_PROPAGATE_INHERIT", 

930 0x08: "INHERIT_ONLY", 

931 0x10: "INHERITED_ACE", 

932 0x40: "SUCCESSFUL_ACCESS", 

933 0x80: "FAILED_ACCESS", 

934} 

935 

936 

937class WINNT_ACE_HEADER(Packet): 

938 fields_desc = [ 

939 ByteEnumField( 

940 "AceType", 

941 0, 

942 { 

943 0x00: "ACCESS_ALLOWED", 

944 0x01: "ACCESS_DENIED", 

945 0x02: "SYSTEM_AUDIT", 

946 0x03: "SYSTEM_ALARM", 

947 0x04: "ACCESS_ALLOWED_COMPOUND", 

948 0x05: "ACCESS_ALLOWED_OBJECT", 

949 0x06: "ACCESS_DENIED_OBJECT", 

950 0x07: "SYSTEM_AUDIT_OBJECT", 

951 0x08: "SYSTEM_ALARM_OBJECT", 

952 0x09: "ACCESS_ALLOWED_CALLBACK", 

953 0x0A: "ACCESS_DENIED_CALLBACK", 

954 0x0B: "ACCESS_ALLOWED_CALLBACK_OBJECT", 

955 0x0C: "ACCESS_DENIED_CALLBACK_OBJECT", 

956 0x0D: "SYSTEM_AUDIT_CALLBACK", 

957 0x0E: "SYSTEM_ALARM_CALLBACK", 

958 0x0F: "SYSTEM_AUDIT_CALLBACK_OBJECT", 

959 0x10: "SYSTEM_ALARM_CALLBACK_OBJECT", 

960 0x11: "SYSTEM_MANDATORY_LABEL", 

961 0x12: "SYSTEM_RESOURCE_ATTRIBUTE", 

962 0x13: "SYSTEM_SCOPED_POLICY_ID", 

963 }, 

964 ), 

965 FlagsField( 

966 "AceFlags", 

967 0, 

968 8, 

969 WINNT_ACE_FLAGS, 

970 ), 

971 LenField("AceSize", None, fmt="<H", adjust=lambda x: x + 4), 

972 ] 

973 

974 def extract_padding(self, p): 

975 return p[: self.AceSize - 4], p[self.AceSize - 4 :] 

976 

977 # fmt: off 

978 def extractData(self, accessMask=None): 

979 """ 

980 Return the ACE data as usable data. 

981 

982 :param accessMask: context-specific flags for the ACE Mask. 

983 """ 

984 sid_string = self.payload.Sid.summary() 

985 mask = self.payload.Mask 

986 if accessMask is not None: 

987 mask = FlagValue(mask, FlagsField("", 0, 32, accessMask).names) 

988 ace_flag_string = str( 

989 FlagValue(self.AceFlags, ["OI", "CI", "NP", "IO", "ID", "SA", "FA"]) 

990 ) 

991 object_guid = getattr(self.payload, "ObjectType", "") 

992 inherit_object_guid = getattr(self.payload, "InheritedObjectType", "") 

993 # ApplicationData -> conditional expression 

994 cond_expr = None 

995 if hasattr(self.payload, "ApplicationData"): 

996 # Parse tokens 

997 res = [] 

998 for ct in self.payload.ApplicationData.Tokens: 

999 if ct.TokenType in [ 

1000 # binary operators 

1001 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x88, 0x8e, 0x8f, 

1002 0xa0, 0xa1 

1003 ]: 

1004 t1 = res.pop(-1) 

1005 t0 = res.pop(-1) 

1006 tt = ct.sprintf("%TokenType%") 

1007 if ct.TokenType in [0xa0, 0xa1]: # && and || 

1008 res.append(f"({t0}) {tt} ({t1})") 

1009 else: 

1010 res.append(f"{t0} {tt} {t1}") 

1011 elif ct.TokenType in [ 

1012 # unary operators 

1013 0x87, 0x8d, 0xa2, 0x89, 0x8a, 0x8b, 0x8c, 0x91, 0x92, 0x93 

1014 ]: 

1015 t0 = res.pop(-1) 

1016 tt = ct.sprintf("%TokenType%") 

1017 res.append(f"{tt}{t0}") 

1018 elif ct.TokenType in [ 

1019 # values 

1020 0x01, 0x02, 0x03, 0x04, 0x10, 0x18, 0x50, 0x51, 0xf8, 0xf9, 

1021 0xfa, 0xfb 

1022 ]: 

1023 def lit(ct): 

1024 if ct.TokenType in [0x10, 0x18]: # literal strings 

1025 return '"%s"' % ct.value 

1026 elif ct.TokenType == 0x50: # composite 

1027 return "({%s})" % ",".join(lit(x) for x in ct.value) 

1028 else: 

1029 return str(ct.value) 

1030 res.append(lit(ct)) 

1031 elif ct.TokenType == 0x00: # padding 

1032 pass 

1033 else: 

1034 raise ValueError("Unhandled token type %s" % ct.TokenType) 

1035 if len(res) != 1: 

1036 raise ValueError("Incomplete SDDL !") 

1037 cond_expr = "(%s)" % res[0] 

1038 return { 

1039 "ace-flags-string": ace_flag_string, 

1040 "sid-string": sid_string, 

1041 "mask": mask, 

1042 "object-guid": object_guid, 

1043 "inherited-object-guid": inherit_object_guid, 

1044 "cond-expr": cond_expr, 

1045 } 

1046 # fmt: on 

1047 

1048 def toSDDL(self, accessMask=None): 

1049 """ 

1050 Return SDDL 

1051 """ 

1052 data = self.extractData(accessMask=accessMask) 

1053 ace_rights = "" # TODO 

1054 if self.AceType in [0x9, 0xA, 0xB, 0xD]: # Conditional ACE 

1055 conditional_ace_type = { 

1056 0x09: "XA", 

1057 0x0A: "XD", 

1058 0x0B: "XU", 

1059 0x0D: "ZA", 

1060 }[self.AceType] 

1061 return "D:(%s)" % ( 

1062 ";".join( 

1063 x 

1064 for x in [ 

1065 conditional_ace_type, 

1066 data["ace-flags-string"], 

1067 ace_rights, 

1068 str(data["object-guid"]), 

1069 str(data["inherited-object-guid"]), 

1070 data["sid-string"], 

1071 data["cond-expr"], 

1072 ] 

1073 if x is not None 

1074 ) 

1075 ) 

1076 else: 

1077 ace_type = { 

1078 0x00: "A", 

1079 0x01: "D", 

1080 0x02: "AU", 

1081 0x05: "OA", 

1082 0x06: "OD", 

1083 0x07: "OU", 

1084 0x11: "ML", 

1085 0x13: "SP", 

1086 }[self.AceType] 

1087 return "(%s)" % ( 

1088 ";".join( 

1089 x 

1090 for x in [ 

1091 ace_type, 

1092 data["ace-flags-string"], 

1093 ace_rights, 

1094 str(data["object-guid"]), 

1095 str(data["inherited-object-guid"]), 

1096 data["sid-string"], 

1097 data["cond-expr"], 

1098 ] 

1099 if x is not None 

1100 ) 

1101 ) 

1102 

1103 

1104# [MS-DTYP] sect 2.4.4.2 

1105 

1106 

1107class WINNT_ACCESS_ALLOWED_ACE(Packet): 

1108 fields_desc = [ 

1109 FlagsField("Mask", 0, -32, _WINNT_ACCESS_MASK), 

1110 PacketField("Sid", WINNT_SID(), WINNT_SID), 

1111 ] 

1112 

1113 

1114bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_ACE, AceType=0x00) 

1115 

1116 

1117# [MS-DTYP] sect 2.4.4.3 

1118 

1119 

1120class WINNT_ACCESS_ALLOWED_OBJECT_ACE(Packet): 

1121 fields_desc = [ 

1122 FlagsField("Mask", 0, -32, _WINNT_ACCESS_MASK), 

1123 FlagsField( 

1124 "Flags", 

1125 0, 

1126 -32, 

1127 { 

1128 0x00000001: "OBJECT_TYPE_PRESENT", 

1129 0x00000002: "INHERITED_OBJECT_TYPE_PRESENT", 

1130 }, 

1131 ), 

1132 ConditionalField( 

1133 UUIDField("ObjectType", None, uuid_fmt=UUIDField.FORMAT_LE), 

1134 lambda pkt: pkt.Flags.OBJECT_TYPE_PRESENT, 

1135 ), 

1136 ConditionalField( 

1137 UUIDField("InheritedObjectType", None, uuid_fmt=UUIDField.FORMAT_LE), 

1138 lambda pkt: pkt.Flags.INHERITED_OBJECT_TYPE_PRESENT, 

1139 ), 

1140 PacketField("Sid", WINNT_SID(), WINNT_SID), 

1141 ] 

1142 

1143 

1144bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_OBJECT_ACE, AceType=0x05) 

1145 

1146 

1147# [MS-DTYP] sect 2.4.4.4 

1148 

1149 

1150class WINNT_ACCESS_DENIED_ACE(Packet): 

1151 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

1152 

1153 

1154bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_ACE, AceType=0x01) 

1155 

1156 

1157# [MS-DTYP] sect 2.4.4.5 

1158 

1159 

1160class WINNT_ACCESS_DENIED_OBJECT_ACE(Packet): 

1161 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc 

1162 

1163 

1164bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_OBJECT_ACE, AceType=0x06) 

1165 

1166 

1167# [MS-DTYP] sect 2.4.4.17.4+ 

1168 

1169 

1170class WINNT_APPLICATION_DATA_LITERAL_TOKEN(Packet): 

1171 def default_payload_class(self, payload): 

1172 return conf.padding_layer 

1173 

1174 

1175# fmt: off 

1176WINNT_APPLICATION_DATA_LITERAL_TOKEN.fields_desc = [ 

1177 ByteEnumField( 

1178 "TokenType", 

1179 0, 

1180 { 

1181 # [MS-DTYP] sect 2.4.4.17.5 

1182 0x00: "Padding token", 

1183 0x01: "Signed int8", 

1184 0x02: "Signed int16", 

1185 0x03: "Signed int32", 

1186 0x04: "Signed int64", 

1187 0x10: "Unicode", 

1188 0x18: "Octet String", 

1189 0x50: "Composite", 

1190 0x51: "SID", 

1191 # [MS-DTYP] sect 2.4.4.17.6 

1192 0x80: "==", 

1193 0x81: "!=", 

1194 0x82: "<", 

1195 0x83: "<=", 

1196 0x84: ">", 

1197 0x85: ">=", 

1198 0x86: "Contains", 

1199 0x88: "Any_of", 

1200 0x8e: "Not_Contains", 

1201 0x8f: "Not_Any_of", 

1202 0x89: "Member_of", 

1203 0x8a: "Device_Member_of", 

1204 0x8b: "Member_of_Any", 

1205 0x8c: "Device_Member_of_Any", 

1206 0x90: "Not_Member_of", 

1207 0x91: "Not_Device_Member_of", 

1208 0x92: "Not_Member_of_Any", 

1209 0x93: "Not_Device_Member_of_Any", 

1210 # [MS-DTYP] sect 2.4.4.17.7 

1211 0x87: "Exists", 

1212 0x8d: "Not_Exists", 

1213 0xa0: "&&", 

1214 0xa1: "||", 

1215 0xa2: "!", 

1216 # [MS-DTYP] sect 2.4.4.17.8 

1217 0xf8: "Local attribute", 

1218 0xf9: "User Attribute", 

1219 0xfa: "Resource Attribute", 

1220 0xfb: "Device Attribute", 

1221 } 

1222 ), 

1223 ConditionalField( 

1224 # Strings 

1225 LEIntField("length", 0), 

1226 lambda pkt: pkt.TokenType in [ 

1227 0x10, # Unicode string 

1228 0x18, # Octet string 

1229 0xf8, 0xf9, 0xfa, 0xfb, # Attribute tokens 

1230 0x50, # Composite 

1231 ] 

1232 ), 

1233 ConditionalField( 

1234 MultipleTypeField( 

1235 [ 

1236 ( 

1237 LELongField("value", 0), 

1238 lambda pkt: pkt.TokenType in [ 

1239 0x01, # signed int8 

1240 0x02, # signed int16 

1241 0x03, # signed int32 

1242 0x04, # signed int64 

1243 ] 

1244 ), 

1245 ( 

1246 StrLenFieldUtf16("value", b"", length_from=lambda pkt: pkt.length), 

1247 lambda pkt: pkt.TokenType in [ 

1248 0x10, # Unicode string 

1249 0xf8, 0xf9, 0xfa, 0xfb, # Attribute tokens 

1250 ] 

1251 ), 

1252 ( 

1253 StrLenField("value", b"", length_from=lambda pkt: pkt.length), 

1254 lambda pkt: pkt.TokenType == 0x18, # Octet string 

1255 ), 

1256 ( 

1257 PacketListField("value", [], WINNT_APPLICATION_DATA_LITERAL_TOKEN, 

1258 length_from=lambda pkt: pkt.length), 

1259 lambda pkt: pkt.TokenType == 0x50, # Composite 

1260 ), 

1261 

1262 ], 

1263 StrFixedLenField("value", b"", length=0), 

1264 ), 

1265 lambda pkt: pkt.TokenType in [ 

1266 0x01, 0x02, 0x03, 0x04, 0x10, 0x18, 0xf8, 0xf9, 0xfa, 0xfb, 0x50 

1267 ] 

1268 ), 

1269 ConditionalField( 

1270 # Literal 

1271 ByteEnumField("sign", 0, { 

1272 0x01: "+", 

1273 0x02: "-", 

1274 0x03: "None", 

1275 }), 

1276 lambda pkt: pkt.TokenType in [ 

1277 0x01, # signed int8 

1278 0x02, # signed int16 

1279 0x03, # signed int32 

1280 0x04, # signed int64 

1281 ] 

1282 ), 

1283 ConditionalField( 

1284 # Literal 

1285 ByteEnumField("base", 0, { 

1286 0x01: "Octal", 

1287 0x02: "Decimal", 

1288 0x03: "Hexadecimal", 

1289 }), 

1290 lambda pkt: pkt.TokenType in [ 

1291 0x01, # signed int8 

1292 0x02, # signed int16 

1293 0x03, # signed int32 

1294 0x04, # signed int64 

1295 ] 

1296 ), 

1297] 

1298# fmt: on 

1299 

1300 

1301class WINNT_APPLICATION_DATA(Packet): 

1302 fields_desc = [ 

1303 StrFixedLenField("Magic", b"\x61\x72\x74\x78", length=4), 

1304 PacketListField( 

1305 "Tokens", 

1306 [], 

1307 WINNT_APPLICATION_DATA_LITERAL_TOKEN, 

1308 ), 

1309 ] 

1310 

1311 def default_payload_class(self, payload): 

1312 return conf.padding_layer 

1313 

1314 

1315# [MS-DTYP] sect 2.4.4.6 

1316 

1317 

1318class WINNT_ACCESS_ALLOWED_CALLBACK_ACE(Packet): 

1319 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [ 

1320 PacketField( 

1321 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

1322 ), 

1323 ] 

1324 

1325 

1326bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_CALLBACK_ACE, AceType=0x09) 

1327 

1328 

1329# [MS-DTYP] sect 2.4.4.7 

1330 

1331 

1332class WINNT_ACCESS_DENIED_CALLBACK_ACE(Packet): 

1333 fields_desc = WINNT_ACCESS_ALLOWED_CALLBACK_ACE.fields_desc 

1334 

1335 

1336bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_CALLBACK_ACE, AceType=0x0A) 

1337 

1338 

1339# [MS-DTYP] sect 2.4.4.8 

1340 

1341 

1342class WINNT_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE(Packet): 

1343 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc + [ 

1344 PacketField( 

1345 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

1346 ), 

1347 ] 

1348 

1349 

1350bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE, AceType=0x0B) 

1351 

1352 

1353# [MS-DTYP] sect 2.4.4.9 

1354 

1355 

1356class WINNT_ACCESS_DENIED_CALLBACK_OBJECT_ACE(Packet): 

1357 fields_desc = WINNT_ACCESS_DENIED_OBJECT_ACE.fields_desc + [ 

1358 PacketField( 

1359 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

1360 ), 

1361 ] 

1362 

1363 

1364bind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_CALLBACK_OBJECT_ACE, AceType=0x0C) 

1365 

1366 

1367# [MS-DTYP] sect 2.4.4.10 

1368 

1369 

1370class WINNT_SYSTEM_AUDIT_ACE(Packet): 

1371 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

1372 

1373 

1374bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_ACE, AceType=0x02) 

1375 

1376 

1377# [MS-DTYP] sect 2.4.4.11 

1378 

1379 

1380class WINNT_SYSTEM_AUDIT_OBJECT_ACE(Packet): 

1381 # doc is wrong. 

1382 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc 

1383 

1384 

1385bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_OBJECT_ACE, AceType=0x07) 

1386 

1387 

1388# [MS-DTYP] sect 2.4.4.12 

1389 

1390 

1391class WINNT_SYSTEM_AUDIT_CALLBACK_ACE(Packet): 

1392 fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc + [ 

1393 PacketField( 

1394 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

1395 ), 

1396 ] 

1397 

1398 

1399bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_CALLBACK_ACE, AceType=0x0D) 

1400 

1401 

1402# [MS-DTYP] sect 2.4.4.13 

1403 

1404 

1405class WINNT_SYSTEM_MANDATORY_LABEL_ACE(Packet): 

1406 fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc 

1407 

1408 

1409bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_MANDATORY_LABEL_ACE, AceType=0x11) 

1410 

1411 

1412# [MS-DTYP] sect 2.4.4.14 

1413 

1414 

1415class WINNT_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE(Packet): 

1416 fields_desc = WINNT_SYSTEM_AUDIT_OBJECT_ACE.fields_desc 

1417 

1418 

1419bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE, AceType=0x0F) 

1420 

1421# [MS-DTYP] sect 2.4.10.1 

1422 

1423 

1424class CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(_NTLMPayloadPacket): 

1425 _NTLM_PAYLOAD_FIELD_NAME = "Data" 

1426 fields_desc = [ 

1427 LEIntField("NameOffset", 0), 

1428 LEShortEnumField( 

1429 "ValueType", 

1430 0, 

1431 { 

1432 0x0001: "CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64", 

1433 0x0002: "CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64", 

1434 0x0003: "CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING", 

1435 0x0005: "CLAIM_SECURITY_ATTRIBUTE_TYPE_SID", 

1436 0x0006: "CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN", 

1437 0x0010: "CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING", 

1438 }, 

1439 ), 

1440 LEShortField("Reserved", 0), 

1441 FlagsField( 

1442 "Flags", 

1443 0, 

1444 -32, 

1445 { 

1446 0x0001: "CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE", 

1447 0x0002: "CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE", 

1448 0x0004: "CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY", 

1449 0x0008: "CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT", 

1450 0x0010: "CLAIM_SECURITY_ATTRIBUTE_DISABLED", 

1451 0x0020: "CLAIM_SECURITY_ATTRIBUTE_MANDATORY", 

1452 }, 

1453 ), 

1454 LEIntField("ValueCount", 0), 

1455 FieldListField( 

1456 "ValueOffsets", [], LEIntField("", 0), count_from=lambda pkt: pkt.ValueCount 

1457 ), 

1458 _NTLMPayloadField( 

1459 "Data", 

1460 lambda pkt: 16 + pkt.ValueCount * 4, 

1461 [ 

1462 ConditionalField( 

1463 StrFieldUtf16("Name", b""), 

1464 lambda pkt: pkt.NameOffset, 

1465 ), 

1466 # TODO: Values 

1467 ], 

1468 offset_name="Offset", 

1469 ), 

1470 ] 

1471 

1472 

1473# [MS-DTYP] sect 2.4.4.15 

1474 

1475 

1476class WINNT_SYSTEM_RESOURCE_ATTRIBUTE_ACE(Packet): 

1477 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [ 

1478 PacketField( 

1479 "AttributeData", 

1480 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(), 

1481 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1, 

1482 ) 

1483 ] 

1484 

1485 

1486bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_RESOURCE_ATTRIBUTE_ACE, AceType=0x12) 

1487 

1488# [MS-DTYP] sect 2.4.4.16 

1489 

1490 

1491class WINNT_SYSTEM_SCOPED_POLICY_ID_ACE(Packet): 

1492 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

1493 

1494 

1495bind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_SCOPED_POLICY_ID_ACE, AceType=0x13) 

1496 

1497# [MS-DTYP] sect 2.4.5 

1498 

1499 

1500class WINNT_ACL(Packet): 

1501 fields_desc = [ 

1502 ByteField("AclRevision", 2), 

1503 ByteField("Sbz1", 0x00), 

1504 FieldLenField( 

1505 "AclSize", None, length_of="Aces", adjust=lambda _, x: x + 14, fmt="<H" 

1506 ), 

1507 FieldLenField("AceCount", None, count_of="Aces", fmt="<H"), 

1508 ShortField("Sbz2", 0), 

1509 PacketListField( 

1510 "Aces", 

1511 [], 

1512 WINNT_ACE_HEADER, 

1513 count_from=lambda pkt: pkt.AceCount, 

1514 ), 

1515 ] 

1516 

1517 def toSDDL(self): 

1518 return [x.toSDDL() for x in self.Aces] 

1519 

1520 

1521# [MS-DTYP] 2.4.6 SECURITY_DESCRIPTOR 

1522 

1523 

1524class SECURITY_DESCRIPTOR(_NTLMPayloadPacket): 

1525 OFFSET = 20 

1526 _NTLM_PAYLOAD_FIELD_NAME = "Data" 

1527 fields_desc = [ 

1528 ByteField("Revision", 0x01), 

1529 ByteField("Sbz1", 0x00), 

1530 FlagsField( 

1531 "Control", 

1532 0x00, 

1533 -16, 

1534 [ 

1535 "OWNER_DEFAULTED", 

1536 "GROUP_DEFAULTED", 

1537 "DACL_PRESENT", 

1538 "DACL_DEFAULTED", 

1539 "SACL_PRESENT", 

1540 "SACL_DEFAULTED", 

1541 "DACL_TRUSTED", 

1542 "SERVER_SECURITY", 

1543 "DACL_COMPUTED", 

1544 "SACL_COMPUTED", 

1545 "DACL_AUTO_INHERITED", 

1546 "SACL_AUTO_INHERITED", 

1547 "DACL_PROTECTED", 

1548 "SACL_PROTECTED", 

1549 "RM_CONTROL_VALID", 

1550 "SELF_RELATIVE", 

1551 ], 

1552 ), 

1553 LEIntField("OwnerSidOffset", 0), 

1554 LEIntField("GroupSidOffset", 0), 

1555 LEIntField("SACLOffset", 0), 

1556 LEIntField("DACLOffset", 0), 

1557 _NTLMPayloadField( 

1558 "Data", 

1559 OFFSET, 

1560 [ 

1561 ConditionalField( 

1562 PacketField("OwnerSid", WINNT_SID(), WINNT_SID), 

1563 lambda pkt: pkt.OwnerSidOffset, 

1564 ), 

1565 ConditionalField( 

1566 PacketField("GroupSid", WINNT_SID(), WINNT_SID), 

1567 lambda pkt: pkt.GroupSidOffset, 

1568 ), 

1569 ConditionalField( 

1570 PacketField("SACL", WINNT_ACL(), WINNT_ACL), 

1571 lambda pkt: pkt.Control.SACL_PRESENT, 

1572 ), 

1573 ConditionalField( 

1574 PacketField("DACL", WINNT_ACL(), WINNT_ACL), 

1575 lambda pkt: pkt.Control.DACL_PRESENT, 

1576 ), 

1577 ], 

1578 offset_name="Offset", 

1579 ), 

1580 ] 

1581 

1582 

1583# [MS-FSCC] 2.4.2 FileAllInformation 

1584 

1585 

1586class FileAllInformation(Packet): 

1587 fields_desc = [ 

1588 PacketField("BasicInformation", FileBasicInformation(), FileBasicInformation), 

1589 PacketField( 

1590 "StandardInformation", FileStandardInformation(), FileStandardInformation 

1591 ), 

1592 PacketField( 

1593 "InternalInformation", FileInternalInformation(), FileInternalInformation 

1594 ), 

1595 PacketField("EaInformation", FileEaInformation(), FileEaInformation), 

1596 PacketField( 

1597 "AccessInformation", FileAccessInformation(), FileAccessInformation 

1598 ), 

1599 PacketField( 

1600 "PositionInformation", FilePositionInformation(), FilePositionInformation 

1601 ), 

1602 PacketField("ModeInformation", FileModeInformation(), FileModeInformation), 

1603 PacketField( 

1604 "AlignmentInformation", FileAlignmentInformation(), FileAlignmentInformation 

1605 ), 

1606 PacketField("NameInformation", FILE_NAME_INFORMATION(), FILE_NAME_INFORMATION), 

1607 ] 

1608 

1609 

1610# [MS-FSCC] 2.5.1 FileFsAttributeInformation 

1611 

1612 

1613class FileFsAttributeInformation(Packet): 

1614 fields_desc = [ 

1615 FlagsField( 

1616 "FileSystemAttributes", 

1617 0x00C706FF, 

1618 -32, 

1619 { 

1620 0x02000000: "FILE_SUPPORTS_USN_JOURNAL", 

1621 0x01000000: "FILE_SUPPORTS_OPEN_BY_FILE_ID", 

1622 0x00800000: "FILE_SUPPORTS_EXTENDED_ATTRIBUTES", 

1623 0x00400000: "FILE_SUPPORTS_HARD_LINKS", 

1624 0x00200000: "FILE_SUPPORTS_TRANSACTIONS", 

1625 0x00100000: "FILE_SEQUENTIAL_WRITE_ONCE", 

1626 0x00080000: "FILE_READ_ONLY_VOLUME", 

1627 0x00040000: "FILE_NAMED_STREAMS", 

1628 0x00020000: "FILE_SUPPORTS_ENCRYPTION", 

1629 0x00010000: "FILE_SUPPORTS_OBJECT_IDS", 

1630 0x00008000: "FILE_VOLUME_IS_COMPRESSED", 

1631 0x00000100: "FILE_SUPPORTS_REMOTE_STORAGE", 

1632 0x00000080: "FILE_SUPPORTS_REPARSE_POINTS", 

1633 0x00000040: "FILE_SUPPORTS_SPARSE_FILES", 

1634 0x00000020: "FILE_VOLUME_QUOTAS", 

1635 0x00000010: "FILE_FILE_COMPRESSION", 

1636 0x00000008: "FILE_PERSISTENT_ACLS", 

1637 0x00000004: "FILE_UNICODE_ON_DISK", 

1638 0x00000002: "FILE_CASE_PRESERVED_NAMES", 

1639 0x00000001: "FILE_CASE_SENSITIVE_SEARCH", 

1640 0x04000000: "FILE_SUPPORT_INTEGRITY_STREAMS", 

1641 0x08000000: "FILE_SUPPORTS_BLOCK_REFCOUNTING", 

1642 0x10000000: "FILE_SUPPORTS_SPARSE_VDL", 

1643 }, 

1644 ), 

1645 LEIntField("MaximumComponentNameLength", 255), 

1646 FieldLenField( 

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

1648 ), 

1649 StrLenFieldUtf16( 

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

1651 ), 

1652 ] 

1653 

1654 

1655# [MS-FSCC] 2.5.8 FileFsSizeInformation 

1656 

1657 

1658class FileFsSizeInformation(Packet): 

1659 fields_desc = [ 

1660 LELongField("TotalAllocationUnits", 10485760), 

1661 LELongField("AvailableAllocationUnits", 1048576), 

1662 LEIntField("SectorsPerAllocationUnit", 8), 

1663 LEIntField("BytesPerSector", 512), 

1664 ] 

1665 

1666 

1667# [MS-FSCC] 2.5.9 FileFsVolumeInformation 

1668 

1669 

1670class FileFsVolumeInformation(Packet): 

1671 fields_desc = [ 

1672 UTCTimeField( 

1673 "VolumeCreationTime", 

1674 None, 

1675 fmt="<Q", 

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

1677 custom_scaling=1e7, 

1678 ), 

1679 LEIntField("VolumeSerialNumber", 0), 

1680 LEIntField("VolumeLabelLength", 0), 

1681 ByteField("SupportsObjects", 1), 

1682 ByteField("Reserved", 0), 

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

1684 ] 

1685 

1686 

1687# [MS-FSCC] 2.7.1 FILE_NOTIFY_INFORMATION 

1688 

1689 

1690class FILE_NOTIFY_INFORMATION(Packet): 

1691 fields_desc = [ 

1692 IntField("NextEntryOffset", 0), 

1693 LEIntEnumField( 

1694 "Action", 

1695 0, 

1696 { 

1697 0x00000001: "FILE_ACTION_ADDED", 

1698 0x00000002: "FILE_ACTION_REMOVED", 

1699 0x00000003: "FILE_ACTION_MODIFIED", 

1700 0x00000004: "FILE_ACTION_RENAMED_OLD_NAME", 

1701 0x00000005: "FILE_ACTION_RENAMED_NEW_NAME", 

1702 0x00000006: "FILE_ACTION_ADDED_STREAM", 

1703 0x00000007: "FILE_ACTION_REMOVED_STREAM", 

1704 0x00000008: "FILE_ACTION_MODIFIED_STREAM", 

1705 0x00000009: "FILE_ACTION_REMOVED_BY_DELETE", 

1706 0x0000000A: "FILE_ACTION_ID_NOT_TUNNELLED", 

1707 0x0000000B: "FILE_ACTION_TUNNELLED_ID_COLLISION", 

1708 }, 

1709 ), 

1710 FieldLenField( 

1711 "FileNameLength", 

1712 None, 

1713 length_of="FileName", 

1714 fmt="<I", 

1715 ), 

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

1717 StrLenField( 

1718 "pad", 

1719 b"", 

1720 length_from=lambda x: ( 

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

1722 ), 

1723 ), 

1724 ] 

1725 

1726 def default_payload_class(self, s): 

1727 return conf.padding_layer 

1728 

1729 

1730_SMB2_CONFIG = [ 

1731 ("BufferOffset", _NTLM_ENUM.OFFSET), 

1732 ("Len", _NTLM_ENUM.LEN), 

1733] 

1734 

1735 

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

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

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

1739 

1740 

1741# SMB2 sect 2.1 

1742 

1743 

1744class DirectTCP(NBTSession): 

1745 name = "Direct TCP" 

1746 MAXLENGTH = 0xFFFFFF 

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

1748 

1749 

1750# SMB2 sect 2.2.1.1 

1751 

1752 

1753class SMB2_Header(Packet): 

1754 __slots__ = ["_decrypted"] 

1755 

1756 name = "SMB2 Header" 

1757 fields_desc = [ 

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

1759 LEShortField("StructureSize", 64), 

1760 LEShortField("CreditCharge", 0), 

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

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

1763 LEShortField("CreditRequest", 0), 

1764 FlagsField( 

1765 "Flags", 

1766 0, 

1767 -32, 

1768 { 

1769 0x00000001: "SMB2_FLAGS_SERVER_TO_REDIR", 

1770 0x00000002: "SMB2_FLAGS_ASYNC_COMMAND", 

1771 0x00000004: "SMB2_FLAGS_RELATED_OPERATIONS", 

1772 0x00000008: "SMB2_FLAGS_SIGNED", 

1773 0x10000000: "SMB2_FLAGS_DFS_OPERATIONS", 

1774 0x20000000: "SMB2_FLAGS_REPLAY_OPERATION", 

1775 }, 

1776 ), 

1777 XLEIntField("NextCommand", 0), 

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

1779 # ASYNC 

1780 ConditionalField( 

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

1782 ), 

1783 # SYNC 

1784 ConditionalField( 

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

1786 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND, 

1787 ), 

1788 ConditionalField( 

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

1790 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND, 

1791 ), 

1792 # COMMON 

1793 LELongField("SessionId", 0), 

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

1795 ] 

1796 

1797 _SMB2_OK_RETURNCODES = ( 

1798 # sect 3.3.4.4 

1799 (0xC0000016, 0x0001), # STATUS_MORE_PROCESSING_REQUIRED 

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

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

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

1803 (0xC000000D, 0x000B), # STATUS_INVALID_PARAMETER 

1804 (0x0000010C, 0x000F), # STATUS_NOTIFY_ENUM_DIR 

1805 ) 

1806 

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

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

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

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

1811 

1812 def guess_payload_class(self, payload): 

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

1814 # Check status for responses 

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

1816 return SMB2_Error_Response 

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

1818 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1819 return SMB2_Negotiate_Protocol_Response 

1820 return SMB2_Negotiate_Protocol_Request 

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

1822 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1823 return SMB2_Session_Setup_Response 

1824 return SMB2_Session_Setup_Request 

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

1826 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1827 return SMB2_Session_Logoff_Response 

1828 return SMB2_Session_Logoff_Request 

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

1830 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1831 return SMB2_Tree_Connect_Response 

1832 return SMB2_Tree_Connect_Request 

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

1834 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1835 return SMB2_Tree_Disconnect_Response 

1836 return SMB2_Tree_Disconnect_Request 

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

1838 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1839 return SMB2_Create_Response 

1840 return SMB2_Create_Request 

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

1842 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1843 return SMB2_Close_Response 

1844 return SMB2_Close_Request 

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

1846 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1847 return SMB2_Read_Response 

1848 return SMB2_Read_Request 

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

1850 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1851 return SMB2_Write_Response 

1852 return SMB2_Write_Request 

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

1854 return SMB2_Cancel_Request 

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

1856 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1857 return SMB2_Echo_Response 

1858 return SMB2_Echo_Request 

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

1860 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1861 return SMB2_Query_Directory_Response 

1862 return SMB2_Query_Directory_Request 

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

1864 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1865 return SMB2_Change_Notify_Response 

1866 return SMB2_Change_Notify_Request 

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

1868 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1869 return SMB2_Query_Info_Response 

1870 return SMB2_Query_Info_Request 

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

1872 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1873 return SMB2_Set_Info_Response 

1874 return SMB2_Set_Info_Request 

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

1876 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1877 return SMB2_IOCTL_Response 

1878 return SMB2_IOCTL_Request 

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

1880 

1881 def _calc_signature( 

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

1883 ): 

1884 """ 

1885 This function calculates the signature of a SMB2 packet. 

1886 Detail is from [MS-SMB2] 3.1.4.1 

1887 """ 

1888 if len(s) <= 64: 

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

1890 return s 

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

1892 if dialect == 0x0311: # SMB 3.1.1 

1893 if IsClient is None: 

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

1895 if SigningAlgorithmId is None: 

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

1897 else: 

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

1899 if "GMAC" in SigningAlgorithmId: 

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

1901 

1902 aesgcm = AESGCM(SigningSessionKey) 

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

1904 "<I", 

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

1906 ) 

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

1908 elif "CMAC" in SigningAlgorithmId: 

1909 from cryptography.hazmat.primitives import cmac 

1910 from cryptography.hazmat.primitives.ciphers import algorithms 

1911 

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

1913 c.update(s) 

1914 sig = c.finalize() 

1915 elif "HMAC" in SigningAlgorithmId: 

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

1917 

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

1919 sig = sig[:16] 

1920 else: 

1921 raise ValueError("Unknown SigningAlgorithmId") 

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

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

1924 

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

1926 sig = sig[:16] 

1927 else: 

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

1929 sig = b"\x00" * 16 

1930 return sig 

1931 

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

1933 """ 

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

1935 """ 

1936 # Set the current signature to nul 

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

1938 # Calculate the signature 

1939 s = bytes(self) 

1940 self.SecuritySignature = self._calc_signature( 

1941 s, 

1942 dialect=dialect, 

1943 SigningSessionKey=SigningSessionKey, 

1944 SigningAlgorithmId=SigningAlgorithmId, 

1945 IsClient=IsClient, 

1946 ) 

1947 # we make sure the payload is static 

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

1949 

1950 def verify( 

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

1952 ): 

1953 """ 

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

1955 """ 

1956 s = bytes(self) 

1957 # Set SecuritySignature to nul 

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

1959 # Calculate the signature 

1960 sig = self._calc_signature( 

1961 s, 

1962 dialect=dialect, 

1963 SigningSessionKey=SigningSessionKey, 

1964 SigningAlgorithmId=SigningAlgorithmId, 

1965 IsClient=IsClient, 

1966 ) 

1967 if self.SecuritySignature != sig: 

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

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

1970 

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

1972 """ 

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

1974 """ 

1975 if dialect < 0x0300: 

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

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

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

1979 

1980 data = bytes(self) 

1981 smbt = SMB2_Transform_Header( 

1982 OriginalMessageSize=len(self), 

1983 SessionId=self.SessionId, 

1984 Flags=0x0001, 

1985 ) 

1986 if "GCM" in CipherId: 

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

1988 

1989 nonce = os.urandom(12) 

1990 cipher = AESGCM(EncryptionKey) 

1991 elif "CCM" in CipherId: 

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

1993 

1994 nonce = os.urandom(11) 

1995 cipher = AESCCM(EncryptionKey) 

1996 else: 

1997 raise Exception("Unknown CipherId !") 

1998 

1999 # Add nonce to header and build the auth data 

2000 smbt.Nonce = nonce 

2001 aad = bytes(smbt)[20:] 

2002 

2003 # Perform the actual encryption 

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

2005 

2006 # Put the auth tag in the Signature field 

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

2008 

2009 return smbt / data 

2010 

2011 

2012class _SMB2_Payload(Packet): 

2013 def do_dissect_payload(self, s): 

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

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

2016 if self.underlayer.NextCommand: 

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

2018 if padlen: 

2019 self.add_payload(s[:padlen]) 

2020 s = s[padlen:] 

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

2022 

2023 def answers(self, other): 

2024 return ( 

2025 isinstance(other, _SMB2_Payload) 

2026 and self.__class__ != other.__class__ 

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

2028 ) 

2029 

2030 def guess_payload_class(self, s): 

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

2032 if self.underlayer.NextCommand: 

2033 return SMB2_Header 

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

2035 

2036 

2037# sect 2.2.2 

2038 

2039 

2040class SMB2_Error_Response(_SMB2_Payload): 

2041 Command = -1 

2042 __slots__ = ["NTStatus"] # extra info 

2043 name = "SMB2 Error Response" 

2044 fields_desc = [ 

2045 XLEShortField("StructureSize", 0x09), 

2046 ByteField("ErrorContextCount", 0), 

2047 ByteField("Reserved", 0), 

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

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

2050 ] 

2051 

2052 

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

2054 

2055# sect 2.2.2.2.2 

2056 

2057 

2058class MOVE_DST_IPADDR(Packet): 

2059 fields_desc = [ 

2060 # Wireshark appears to get this wrong 

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

2062 IntField("Reserved", 0), 

2063 MultipleTypeField( 

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

2065 IPField("IPAddress", None), 

2066 ), 

2067 ConditionalField( 

2068 # For IPv4 

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

2070 lambda pkt: pkt.Type == 1, 

2071 ), 

2072 ] 

2073 

2074 def default_payload_class(self, payload): 

2075 return conf.padding_layer 

2076 

2077 

2078class SMB2_Error_Share_Redirect_Context_Response(_NTLMPayloadPacket): 

2079 name = "Share Redirect Error Context Response" 

2080 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2081 fields_desc = [ 

2082 XLEIntField("StructureSize", 0x30), 

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

2084 XLEIntField("ResourceNameBufferOffset", None), 

2085 LEIntField("ResourceNameLen", None), 

2086 ShortField("Reserved", 0), 

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

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

2089 PacketListField( 

2090 "IPAddrMoveList", 

2091 [], 

2092 MOVE_DST_IPADDR, 

2093 count_from=lambda pkt: pkt.IPAddrCount, 

2094 ), 

2095 _NTLMPayloadField( 

2096 "Buffer", 

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

2098 [ 

2099 StrLenFieldUtf16( 

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

2101 ), 

2102 ], 

2103 ), 

2104 ] 

2105 

2106 def post_build(self, pkt, pay): 

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

2108 return ( 

2109 _SMB2_post_build( 

2110 self, 

2111 pkt, 

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

2113 { 

2114 "ResourceName": 8, 

2115 }, 

2116 ) 

2117 + pay 

2118 ) 

2119 

2120 

2121# sect 2.2.2.1 

2122 

2123 

2124class SMB2_Error_ContextResponse(Packet): 

2125 fields_desc = [ 

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

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

2128 MultipleTypeField( 

2129 [ 

2130 ( 

2131 PacketField( 

2132 "ErrorContextData", 

2133 SMB2_Error_Share_Redirect_Context_Response(), 

2134 SMB2_Error_Share_Redirect_Context_Response, 

2135 ), 

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

2137 ) 

2138 ], 

2139 XStrLenField( 

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

2141 ), 

2142 ), 

2143 ] 

2144 

2145 

2146# sect 2.2.3 

2147 

2148 

2149class SMB2_Negotiate_Context(Packet): 

2150 name = "SMB2 Negotiate Context" 

2151 fields_desc = [ 

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

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

2154 IntField("Reserved", 0), 

2155 ] 

2156 

2157 def default_payload_class(self, payload): 

2158 return conf.padding_layer 

2159 

2160 

2161class SMB2_Negotiate_Protocol_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2162 name = "SMB2 Negotiate Protocol Request" 

2163 Command = 0x0000 

2164 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2165 fields_desc = [ 

2166 XLEShortField("StructureSize", 0x24), 

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

2168 # SecurityMode 

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

2170 LEShortField("Reserved", 0), 

2171 # Capabilities 

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

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

2174 XLEIntField("NegotiateContextsBufferOffset", None), 

2175 LEShortField("NegotiateContextsCount", None), 

2176 ShortField("Reserved2", 0), 

2177 FieldListField( 

2178 "Dialects", 

2179 [0x0202], 

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

2181 count_from=lambda pkt: pkt.DialectCount, 

2182 ), 

2183 _NTLMPayloadField( 

2184 "Buffer", 

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

2186 [ 

2187 # Field only exists if Dialects contains 0x0311 

2188 FieldListField( 

2189 "NegotiateContexts", 

2190 [], 

2191 ReversePadField( 

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

2193 8, 

2194 ), 

2195 count_from=lambda pkt: pkt.NegotiateContextsCount, 

2196 ), 

2197 ], 

2198 ), 

2199 ] 

2200 

2201 def post_build(self, pkt, pay): 

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

2203 return ( 

2204 _NTLM_post_build( 

2205 self, 

2206 pkt, 

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

2208 { 

2209 "NegotiateContexts": 28, 

2210 }, 

2211 config=[ 

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

2213 ("Count", _NTLM_ENUM.COUNT), 

2214 ], 

2215 ) 

2216 + pay 

2217 ) 

2218 

2219 

2220bind_top_down( 

2221 SMB2_Header, 

2222 SMB2_Negotiate_Protocol_Request, 

2223 Command=0x0000, 

2224) 

2225 

2226# sect 2.2.3.1.1 

2227 

2228 

2229class SMB2_Preauth_Integrity_Capabilities(Packet): 

2230 name = "SMB2 Preauth Integrity Capabilities" 

2231 fields_desc = [ 

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

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

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

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

2236 FieldListField( 

2237 "HashAlgorithms", 

2238 [0x0001], 

2239 LEShortEnumField( 

2240 "", 

2241 0x0, 

2242 SMB2_HASH_ALGORITHMS, 

2243 ), 

2244 count_from=lambda pkt: pkt.HashAlgorithmCount, 

2245 ), 

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

2247 ] 

2248 

2249 def default_payload_class(self, payload): 

2250 return conf.padding_layer 

2251 

2252 

2253bind_layers( 

2254 SMB2_Negotiate_Context, SMB2_Preauth_Integrity_Capabilities, ContextType=0x0001 

2255) 

2256 

2257# sect 2.2.3.1.2 

2258 

2259 

2260class SMB2_Encryption_Capabilities(Packet): 

2261 name = "SMB2 Encryption Capabilities" 

2262 fields_desc = [ 

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

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

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

2266 FieldListField( 

2267 "Ciphers", 

2268 [0x0001], 

2269 LEShortEnumField( 

2270 "", 

2271 0x0, 

2272 SMB2_ENCRYPTION_CIPHERS, 

2273 ), 

2274 count_from=lambda pkt: pkt.CipherCount, 

2275 ), 

2276 ] 

2277 

2278 def default_payload_class(self, payload): 

2279 return conf.padding_layer 

2280 

2281 

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

2283 

2284# sect 2.2.3.1.3 

2285 

2286 

2287class SMB2_Compression_Capabilities(Packet): 

2288 name = "SMB2 Compression Capabilities" 

2289 fields_desc = [ 

2290 FieldLenField( 

2291 "CompressionAlgorithmCount", 

2292 None, 

2293 fmt="<H", 

2294 count_of="CompressionAlgorithms", 

2295 ), 

2296 ShortField("Padding", 0x0), 

2297 LEIntEnumField( 

2298 "Flags", 

2299 0x0, 

2300 { 

2301 0x00000000: "SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE", 

2302 0x00000001: "SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED", 

2303 }, 

2304 ), 

2305 FieldListField( 

2306 "CompressionAlgorithms", 

2307 None, 

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

2309 count_from=lambda pkt: pkt.CompressionAlgorithmCount, 

2310 ), 

2311 ] 

2312 

2313 def default_payload_class(self, payload): 

2314 return conf.padding_layer 

2315 

2316 

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

2318 

2319# sect 2.2.3.1.4 

2320 

2321 

2322class SMB2_Netname_Negotiate_Context_ID(Packet): 

2323 name = "SMB2 Netname Negotiate Context ID" 

2324 fields_desc = [ 

2325 StrLenFieldUtf16( 

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

2327 ) 

2328 ] 

2329 

2330 def default_payload_class(self, payload): 

2331 return conf.padding_layer 

2332 

2333 

2334bind_layers( 

2335 SMB2_Negotiate_Context, SMB2_Netname_Negotiate_Context_ID, ContextType=0x0005 

2336) 

2337 

2338# sect 2.2.3.1.5 

2339 

2340 

2341class SMB2_Transport_Capabilities(Packet): 

2342 name = "SMB2 Transport Capabilities" 

2343 fields_desc = [ 

2344 FlagsField( 

2345 "Flags", 

2346 0x0, 

2347 -32, 

2348 { 

2349 0x00000001: "SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY", 

2350 }, 

2351 ), 

2352 ] 

2353 

2354 def default_payload_class(self, payload): 

2355 return conf.padding_layer 

2356 

2357 

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

2359 

2360# sect 2.2.3.1.6 

2361 

2362 

2363class SMB2_RDMA_Transform_Capabilities(Packet): 

2364 name = "SMB2 RDMA Transform Capabilities" 

2365 fields_desc = [ 

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

2367 LEShortField("Reserved1", 0), 

2368 LEIntField("Reserved2", 0), 

2369 FieldListField( 

2370 "RDMATransformIds", 

2371 None, 

2372 LEShortEnumField( 

2373 "", 

2374 0x0, 

2375 { 

2376 0x0000: "SMB2_RDMA_TRANSFORM_NONE", 

2377 0x0001: "SMB2_RDMA_TRANSFORM_ENCRYPTION", 

2378 0x0002: "SMB2_RDMA_TRANSFORM_SIGNING", 

2379 }, 

2380 ), 

2381 count_from=lambda pkt: pkt.TransformCount, 

2382 ), 

2383 ] 

2384 

2385 def default_payload_class(self, payload): 

2386 return conf.padding_layer 

2387 

2388 

2389bind_layers( 

2390 SMB2_Negotiate_Context, SMB2_RDMA_Transform_Capabilities, ContextType=0x0007 

2391) 

2392 

2393# sect 2.2.3.1.7 

2394 

2395 

2396class SMB2_Signing_Capabilities(Packet): 

2397 name = "SMB2 Signing Capabilities" 

2398 fields_desc = [ 

2399 FieldLenField( 

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

2401 ), 

2402 FieldListField( 

2403 "SigningAlgorithms", 

2404 None, 

2405 LEShortEnumField( 

2406 "", 

2407 0x0, 

2408 SMB2_SIGNING_ALGORITHMS, 

2409 ), 

2410 count_from=lambda pkt: pkt.SigningAlgorithmCount, 

2411 ), 

2412 ] 

2413 

2414 def default_payload_class(self, payload): 

2415 return conf.padding_layer 

2416 

2417 

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

2419 

2420# sect 2.2.4 

2421 

2422 

2423class SMB2_Negotiate_Protocol_Response(_SMB2_Payload, _NTLMPayloadPacket): 

2424 name = "SMB2 Negotiate Protocol Response" 

2425 Command = 0x0000 

2426 OFFSET = 64 + 64 

2427 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2428 fields_desc = [ 

2429 XLEShortField("StructureSize", 0x41), 

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

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

2432 LEShortField("NegotiateContextsCount", None), 

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

2434 # Capabilities 

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

2436 LEIntField("MaxTransactionSize", 65536), 

2437 LEIntField("MaxReadSize", 65536), 

2438 LEIntField("MaxWriteSize", 65536), 

2439 UTCTimeField( 

2440 "ServerTime", 

2441 None, 

2442 fmt="<Q", 

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

2444 custom_scaling=1e7, 

2445 ), 

2446 UTCTimeField( 

2447 "ServerStartTime", 

2448 None, 

2449 fmt="<Q", 

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

2451 custom_scaling=1e7, 

2452 ), 

2453 XLEShortField("SecurityBlobBufferOffset", None), 

2454 LEShortField("SecurityBlobLen", None), 

2455 XLEIntField("NegotiateContextsBufferOffset", None), 

2456 _NTLMPayloadField( 

2457 "Buffer", 

2458 OFFSET, 

2459 [ 

2460 PacketLenField( 

2461 "SecurityBlob", 

2462 None, 

2463 GSSAPI_BLOB, 

2464 length_from=lambda x: x.SecurityBlobLen, 

2465 ), 

2466 # Field only exists if Dialect is 0x0311 

2467 FieldListField( 

2468 "NegotiateContexts", 

2469 [], 

2470 ReversePadField( 

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

2472 8, 

2473 ), 

2474 count_from=lambda pkt: pkt.NegotiateContextsCount, 

2475 ), 

2476 ], 

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

2478 ), 

2479 ] 

2480 

2481 def post_build(self, pkt, pay): 

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

2483 pkt = _NTLM_post_build( 

2484 self, 

2485 pkt, 

2486 self.OFFSET, 

2487 { 

2488 "SecurityBlob": 56, 

2489 "NegotiateContexts": 60, 

2490 }, 

2491 config=[ 

2492 ( 

2493 "BufferOffset", 

2494 { 

2495 "SecurityBlob": _NTLM_ENUM.OFFSET, 

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

2497 }, 

2498 ), 

2499 ], 

2500 ) 

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

2502 if self.SecurityBlobLen is None: 

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

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

2505 if self.NegotiateContextsCount is None: 

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

2507 return pkt + pay 

2508 

2509 

2510bind_top_down( 

2511 SMB2_Header, 

2512 SMB2_Negotiate_Protocol_Response, 

2513 Command=0x0000, 

2514 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

2515) 

2516 

2517# sect 2.2.5 

2518 

2519 

2520class SMB2_Session_Setup_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2521 name = "SMB2 Session Setup Request" 

2522 Command = 0x0001 

2523 OFFSET = 24 + 64 

2524 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2525 fields_desc = [ 

2526 XLEShortField("StructureSize", 0x19), 

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

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

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

2530 LEIntField("Channel", 0), 

2531 XLEShortField("SecurityBlobBufferOffset", None), 

2532 LEShortField("SecurityBlobLen", None), 

2533 XLELongField("PreviousSessionId", 0), 

2534 _NTLMPayloadField( 

2535 "Buffer", 

2536 OFFSET, 

2537 [ 

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

2539 ], 

2540 ), 

2541 ] 

2542 

2543 def post_build(self, pkt, pay): 

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

2545 return ( 

2546 _SMB2_post_build( 

2547 self, 

2548 pkt, 

2549 self.OFFSET, 

2550 { 

2551 "SecurityBlob": 12, 

2552 }, 

2553 ) 

2554 + pay 

2555 ) 

2556 

2557 

2558bind_top_down( 

2559 SMB2_Header, 

2560 SMB2_Session_Setup_Request, 

2561 Command=0x0001, 

2562) 

2563 

2564# sect 2.2.6 

2565 

2566 

2567class SMB2_Session_Setup_Response(_SMB2_Payload, _NTLMPayloadPacket): 

2568 name = "SMB2 Session Setup Response" 

2569 Command = 0x0001 

2570 OFFSET = 8 + 64 

2571 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2572 fields_desc = [ 

2573 XLEShortField("StructureSize", 0x9), 

2574 FlagsField( 

2575 "SessionFlags", 

2576 0, 

2577 -16, 

2578 { 

2579 0x0001: "IS_GUEST", 

2580 0x0002: "IS_NULL", 

2581 0x0004: "ENCRYPT_DATA", 

2582 }, 

2583 ), 

2584 XLEShortField("SecurityBufferOffset", None), 

2585 LEShortField("SecurityLen", None), 

2586 _NTLMPayloadField( 

2587 "Buffer", 

2588 OFFSET, 

2589 [ 

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

2591 ], 

2592 ), 

2593 ] 

2594 

2595 def __getattr__(self, attr): 

2596 # Ease SMB1 backward compatibility 

2597 if attr == "SecurityBlob": 

2598 return ( 

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

2600 or [(None, None)] 

2601 )[0][1] 

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

2603 

2604 def setfieldval(self, attr, val): 

2605 if attr == "SecurityBlob": 

2606 return super(SMB2_Session_Setup_Response, self).setfieldval( 

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

2608 ) 

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

2610 

2611 def post_build(self, pkt, pay): 

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

2613 return ( 

2614 _SMB2_post_build( 

2615 self, 

2616 pkt, 

2617 self.OFFSET, 

2618 { 

2619 "Security": 4, 

2620 }, 

2621 ) 

2622 + pay 

2623 ) 

2624 

2625 

2626bind_top_down( 

2627 SMB2_Header, 

2628 SMB2_Session_Setup_Response, 

2629 Command=0x0001, 

2630 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

2631) 

2632 

2633# sect 2.2.7 

2634 

2635 

2636class SMB2_Session_Logoff_Request(_SMB2_Payload): 

2637 name = "SMB2 LOGOFF Request" 

2638 Command = 0x0002 

2639 fields_desc = [ 

2640 XLEShortField("StructureSize", 0x4), 

2641 ShortField("reserved", 0), 

2642 ] 

2643 

2644 

2645bind_top_down( 

2646 SMB2_Header, 

2647 SMB2_Session_Logoff_Request, 

2648 Command=0x0002, 

2649) 

2650 

2651# sect 2.2.8 

2652 

2653 

2654class SMB2_Session_Logoff_Response(_SMB2_Payload): 

2655 name = "SMB2 LOGOFF Request" 

2656 Command = 0x0002 

2657 fields_desc = [ 

2658 XLEShortField("StructureSize", 0x4), 

2659 ShortField("reserved", 0), 

2660 ] 

2661 

2662 

2663bind_top_down( 

2664 SMB2_Header, 

2665 SMB2_Session_Logoff_Response, 

2666 Command=0x0002, 

2667 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

2668) 

2669 

2670# sect 2.2.9 

2671 

2672 

2673class SMB2_Tree_Connect_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2674 name = "SMB2 TREE_CONNECT Request" 

2675 Command = 0x0003 

2676 OFFSET = 8 + 64 

2677 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2678 fields_desc = [ 

2679 XLEShortField("StructureSize", 0x9), 

2680 FlagsField( 

2681 "Flags", 

2682 0, 

2683 -16, 

2684 ["CLUSTER_RECONNECT", "REDIRECT_TO_OWNER", "EXTENSION_PRESENT"], 

2685 ), 

2686 XLEShortField("PathBufferOffset", None), 

2687 LEShortField("PathLen", None), 

2688 _NTLMPayloadField( 

2689 "Buffer", 

2690 OFFSET, 

2691 [ 

2692 StrFieldUtf16("Path", b""), 

2693 ], 

2694 ), 

2695 ] 

2696 

2697 def post_build(self, pkt, pay): 

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

2699 return ( 

2700 _SMB2_post_build( 

2701 self, 

2702 pkt, 

2703 self.OFFSET, 

2704 { 

2705 "Path": 4, 

2706 }, 

2707 ) 

2708 + pay 

2709 ) 

2710 

2711 

2712bind_top_down( 

2713 SMB2_Header, 

2714 SMB2_Tree_Connect_Request, 

2715 Command=0x0003, 

2716) 

2717 

2718# sect 2.2.10 

2719 

2720 

2721class SMB2_Tree_Connect_Response(_SMB2_Payload): 

2722 name = "SMB2 TREE_CONNECT Response" 

2723 Command = 0x0003 

2724 fields_desc = [ 

2725 XLEShortField("StructureSize", 0x10), 

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

2727 ByteField("Reserved", 0), 

2728 FlagsField( 

2729 "ShareFlags", 

2730 0x30, 

2731 -32, 

2732 { 

2733 0x00000010: "AUTO_CACHING", 

2734 0x00000020: "VDO_CACHING", 

2735 0x00000030: "NO_CACHING", 

2736 0x00000001: "DFS", 

2737 0x00000002: "DFS_ROOT", 

2738 0x00000100: "RESTRICT_EXCLUSIVE_OPENS", 

2739 0x00000200: "FORCE_SHARED_DELETE", 

2740 0x00000400: "ALLOW_NAMESPACE_CACHING", 

2741 0x00000800: "ACCESS_BASED_DIRECTORY_ENUM", 

2742 0x00001000: "FORCE_LEVELII_OPLOCK", 

2743 0x00002000: "ENABLE_HASH_V1", 

2744 0x00004000: "ENABLE_HASH_V2", 

2745 0x00008000: "ENCRYPT_DATA", 

2746 0x00040000: "IDENTITY_REMOTING", 

2747 0x00100000: "COMPRESS_DATA", 

2748 }, 

2749 ), 

2750 FlagsField( 

2751 "Capabilities", 

2752 0, 

2753 -32, 

2754 { 

2755 0x00000008: "DFS", 

2756 0x00000010: "CONTINUOUS_AVAILABILITY", 

2757 0x00000020: "SCALEOUT", 

2758 0x00000040: "CLUSTER", 

2759 0x00000080: "ASYMMETRIC", 

2760 0x00000100: "REDIRECT_TO_OWNER", 

2761 }, 

2762 ), 

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

2764 ] 

2765 

2766 

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

2768 

2769# sect 2.2.11 

2770 

2771 

2772class SMB2_Tree_Disconnect_Request(_SMB2_Payload): 

2773 name = "SMB2 TREE_DISCONNECT Request" 

2774 Command = 0x0004 

2775 fields_desc = [ 

2776 XLEShortField("StructureSize", 0x4), 

2777 XLEShortField("Reserved", 0), 

2778 ] 

2779 

2780 

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

2782 

2783# sect 2.2.12 

2784 

2785 

2786class SMB2_Tree_Disconnect_Response(_SMB2_Payload): 

2787 name = "SMB2 TREE_DISCONNECT Response" 

2788 Command = 0x0004 

2789 fields_desc = [ 

2790 XLEShortField("StructureSize", 0x4), 

2791 XLEShortField("Reserved", 0), 

2792 ] 

2793 

2794 

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

2796 

2797 

2798# sect 2.2.14.1 

2799 

2800 

2801class SMB2_FILEID(Packet): 

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

2803 

2804 def __hash__(self): 

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

2806 

2807 def default_payload_class(self, payload): 

2808 return conf.padding_layer 

2809 

2810 

2811# sect 2.2.14.2 

2812 

2813 

2814class SMB2_CREATE_DURABLE_HANDLE_RESPONSE(Packet): 

2815 fields_desc = [ 

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

2817 ] 

2818 

2819 

2820class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE(Packet): 

2821 fields_desc = [ 

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

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

2824 ] 

2825 

2826 

2827class SMB2_CREATE_QUERY_ON_DISK_ID(Packet): 

2828 fields_desc = [ 

2829 XLELongField("DiskFileId", 0), 

2830 XLELongField("VolumeId", 0), 

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

2832 ] 

2833 

2834 

2835class SMB2_CREATE_RESPONSE_LEASE(Packet): 

2836 fields_desc = [ 

2837 UUIDField("LeaseKey", None), 

2838 FlagsField( 

2839 "LeaseState", 

2840 0x7, 

2841 -32, 

2842 { 

2843 0x01: "SMB2_LEASE_READ_CACHING", 

2844 0x02: "SMB2_LEASE_HANDLE_CACHING", 

2845 0x04: "SMB2_LEASE_WRITE_CACHING", 

2846 }, 

2847 ), 

2848 FlagsField( 

2849 "LeaseFlags", 

2850 0, 

2851 -32, 

2852 { 

2853 0x02: "SMB2_LEASE_FLAG_BREAK_IN_PROGRESS", 

2854 0x04: "SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET", 

2855 }, 

2856 ), 

2857 LELongField("LeaseDuration", 0), 

2858 ] 

2859 

2860 

2861class SMB2_CREATE_RESPONSE_LEASE_V2(Packet): 

2862 fields_desc = [ 

2863 SMB2_CREATE_RESPONSE_LEASE, 

2864 UUIDField("ParentLeaseKey", None), 

2865 LEShortField("Epoch", 0), 

2866 LEShortField("Reserved", 0), 

2867 ] 

2868 

2869 

2870class SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2(Packet): 

2871 fields_desc = [ 

2872 LEIntField("Timeout", 0), 

2873 FlagsField( 

2874 "Flags", 

2875 0, 

2876 -32, 

2877 { 

2878 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT", 

2879 }, 

2880 ), 

2881 ] 

2882 

2883 

2884# sect 2.2.13 

2885 

2886 

2887class SMB2_CREATE_DURABLE_HANDLE_REQUEST(Packet): 

2888 fields_desc = [ 

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

2890 ] 

2891 

2892 

2893class SMB2_CREATE_DURABLE_HANDLE_RECONNECT(Packet): 

2894 fields_desc = [ 

2895 PacketField("Data", SMB2_FILEID(), SMB2_FILEID), 

2896 ] 

2897 

2898 

2899class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST(Packet): 

2900 fields_desc = [ 

2901 LELongField("Timestamp", 0), 

2902 ] 

2903 

2904 

2905class SMB2_CREATE_ALLOCATION_SIZE(Packet): 

2906 fields_desc = [ 

2907 LELongField("AllocationSize", 0), 

2908 ] 

2909 

2910 

2911class SMB2_CREATE_TIMEWARP_TOKEN(Packet): 

2912 fields_desc = [ 

2913 LELongField("Timestamp", 0), 

2914 ] 

2915 

2916 

2917class SMB2_CREATE_REQUEST_LEASE(Packet): 

2918 fields_desc = [ 

2919 SMB2_CREATE_RESPONSE_LEASE, 

2920 ] 

2921 

2922 

2923class SMB2_CREATE_REQUEST_LEASE_V2(Packet): 

2924 fields_desc = [ 

2925 SMB2_CREATE_RESPONSE_LEASE_V2, 

2926 ] 

2927 

2928 

2929class SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2(Packet): 

2930 fields_desc = [ 

2931 SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2, 

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

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

2934 ] 

2935 

2936 

2937class SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2(Packet): 

2938 fields_desc = [ 

2939 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

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

2941 FlagsField( 

2942 "Flags", 

2943 0, 

2944 -32, 

2945 { 

2946 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT", 

2947 }, 

2948 ), 

2949 ] 

2950 

2951 

2952class SMB2_CREATE_APP_INSTANCE_ID(Packet): 

2953 fields_desc = [ 

2954 XLEShortField("StructureSize", 0x14), 

2955 LEShortField("Reserved", 0), 

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

2957 ] 

2958 

2959 

2960class SMB2_CREATE_APP_INSTANCE_VERSION(Packet): 

2961 fields_desc = [ 

2962 XLEShortField("StructureSize", 0x18), 

2963 LEShortField("Reserved", 0), 

2964 LEIntField("Padding", 0), 

2965 LELongField("AppInstanceVersionHigh", 0), 

2966 LELongField("AppInstanceVersionLow", 0), 

2967 ] 

2968 

2969 

2970class SMB2_Create_Context(_NTLMPayloadPacket): 

2971 name = "SMB2 CREATE CONTEXT" 

2972 OFFSET = 16 

2973 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2974 fields_desc = [ 

2975 LEIntField("Next", None), 

2976 XLEShortField("NameBufferOffset", None), 

2977 LEShortField("NameLen", None), 

2978 ShortField("Reserved", 0), 

2979 XLEShortField("DataBufferOffset", None), 

2980 LEIntField("DataLen", None), 

2981 _NTLMPayloadField( 

2982 "Buffer", 

2983 OFFSET, 

2984 [ 

2985 PadField( 

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

2987 8, 

2988 ), 

2989 # Must be padded on 8-octet alignment 

2990 PacketLenField( 

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

2992 ), 

2993 ], 

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

2995 ), 

2996 StrLenField( 

2997 "pad", 

2998 b"", 

2999 length_from=lambda x: ( 

3000 ( 

3001 x.Next 

3002 - max( 

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

3004 ) 

3005 ) 

3006 if x.Next 

3007 else 0 

3008 ), 

3009 ), 

3010 ] 

3011 

3012 def post_dissect(self, s): 

3013 if not self.DataLen: 

3014 return s 

3015 try: 

3016 if isinstance(self.parent, SMB2_Create_Request): 

3017 data_cls = { 

3018 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_REQUEST, 

3019 b"DHnC": SMB2_CREATE_DURABLE_HANDLE_RECONNECT, 

3020 b"AISi": SMB2_CREATE_ALLOCATION_SIZE, 

3021 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 

3022 b"TWrp": SMB2_CREATE_TIMEWARP_TOKEN, 

3023 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID, 

3024 b"RqLs": SMB2_CREATE_REQUEST_LEASE, 

3025 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, 

3026 b"DH2C": SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, 

3027 # 3.1.1 only 

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

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

3030 }[self.Name] 

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

3032 data_cls = SMB2_CREATE_REQUEST_LEASE_V2 

3033 elif isinstance(self.parent, SMB2_Create_Response): 

3034 data_cls = { 

3035 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_RESPONSE, 

3036 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE, 

3037 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID, 

3038 b"RqLs": SMB2_CREATE_RESPONSE_LEASE, 

3039 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2, 

3040 }[self.Name] 

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

3042 data_cls = SMB2_CREATE_RESPONSE_LEASE_V2 

3043 else: 

3044 return s 

3045 except KeyError: 

3046 return s 

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

3048 return s 

3049 

3050 def default_payload_class(self, _): 

3051 return conf.padding_layer 

3052 

3053 def post_build(self, pkt, pay): 

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

3055 return ( 

3056 _NTLM_post_build( 

3057 self, 

3058 pkt, 

3059 self.OFFSET, 

3060 { 

3061 "Name": 4, 

3062 "Data": 10, 

3063 }, 

3064 config=[ 

3065 ( 

3066 "BufferOffset", 

3067 { 

3068 "Name": _NTLM_ENUM.OFFSET, 

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

3070 }, 

3071 ), 

3072 ("Len", _NTLM_ENUM.LEN), 

3073 ], 

3074 ) 

3075 + pay 

3076 ) 

3077 

3078 

3079# sect 2.2.13 

3080 

3081SMB2_OPLOCK_LEVELS = { 

3082 0x00: "SMB2_OPLOCK_LEVEL_NONE", 

3083 0x01: "SMB2_OPLOCK_LEVEL_II", 

3084 0x08: "SMB2_OPLOCK_LEVEL_EXCLUSIVE", 

3085 0x09: "SMB2_OPLOCK_LEVEL_BATCH", 

3086 0xFF: "SMB2_OPLOCK_LEVEL_LEASE", 

3087} 

3088 

3089 

3090class SMB2_Create_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3091 name = "SMB2 CREATE Request" 

3092 Command = 0x0005 

3093 OFFSET = 56 + 64 

3094 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3095 fields_desc = [ 

3096 XLEShortField("StructureSize", 0x39), 

3097 ByteField("ShareType", 0), 

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

3099 LEIntEnumField( 

3100 "ImpersonationLevel", 

3101 0, 

3102 { 

3103 0x00000000: "Anonymous", 

3104 0x00000001: "Identification", 

3105 0x00000002: "Impersonation", 

3106 0x00000003: "Delegate", 

3107 }, 

3108 ), 

3109 LELongField("SmbCreateFlags", 0), 

3110 LELongField("Reserved", 0), 

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

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

3113 FlagsField( 

3114 "ShareAccess", 

3115 0, 

3116 -32, 

3117 { 

3118 0x00000001: "FILE_SHARE_READ", 

3119 0x00000002: "FILE_SHARE_WRITE", 

3120 0x00000004: "FILE_SHARE_DELETE", 

3121 }, 

3122 ), 

3123 LEIntEnumField( 

3124 "CreateDisposition", 

3125 1, 

3126 { 

3127 0x00000000: "FILE_SUPERSEDE", 

3128 0x00000001: "FILE_OPEN", 

3129 0x00000002: "FILE_CREATE", 

3130 0x00000003: "FILE_OPEN_IF", 

3131 0x00000004: "FILE_OVERWRITE", 

3132 0x00000005: "FILE_OVERWRITE_IF", 

3133 }, 

3134 ), 

3135 FlagsField( 

3136 "CreateOptions", 

3137 0, 

3138 -32, 

3139 { 

3140 0x00000001: "FILE_DIRECTORY_FILE", 

3141 0x00000002: "FILE_WRITE_THROUGH", 

3142 0x00000004: "FILE_SEQUENTIAL_ONLY", 

3143 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING", 

3144 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT", 

3145 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT", 

3146 0x00000040: "FILE_NON_DIRECTORY_FILE", 

3147 0x00000100: "FILE_COMPLETE_IF_OPLOCKED", 

3148 0x00000200: "FILE_RANDOM_ACCESS", 

3149 0x00001000: "FILE_DELETE_ON_CLOSE", 

3150 0x00002000: "FILE_OPEN_BY_FILE_ID", 

3151 0x00004000: "FILE_OPEN_FOR_BACKUP_INTENT", 

3152 0x00008000: "FILE_NO_COMPRESSION", 

3153 0x00000400: "FILE_OPEN_REMOTE_INSTANCE", 

3154 0x00010000: "FILE_OPEN_REQUIRING_OPLOCK", 

3155 0x00020000: "FILE_DISALLOW_EXCLUSIVE", 

3156 0x00100000: "FILE_RESERVE_OPFILTER", 

3157 0x00200000: "FILE_OPEN_REPARSE_POINT", 

3158 0x00400000: "FILE_OPEN_NO_RECALL", 

3159 0x00800000: "FILE_OPEN_FOR_FREE_SPACE_QUERY", 

3160 }, 

3161 ), 

3162 XLEShortField("NameBufferOffset", None), 

3163 LEShortField("NameLen", None), 

3164 XLEIntField("CreateContextsBufferOffset", None), 

3165 LEIntField("CreateContextsLen", None), 

3166 _NTLMPayloadField( 

3167 "Buffer", 

3168 OFFSET, 

3169 [ 

3170 StrFieldUtf16("Name", b""), 

3171 _NextPacketListField( 

3172 "CreateContexts", 

3173 [], 

3174 SMB2_Create_Context, 

3175 length_from=lambda pkt: pkt.CreateContextsLen, 

3176 ), 

3177 ], 

3178 ), 

3179 ] 

3180 

3181 def post_build(self, pkt, pay): 

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

3183 if len(pkt) == 0x38: 

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

3185 pkt += b"\x00" 

3186 return ( 

3187 _SMB2_post_build( 

3188 self, 

3189 pkt, 

3190 self.OFFSET, 

3191 { 

3192 "Name": 44, 

3193 "CreateContexts": 48, 

3194 }, 

3195 ) 

3196 + pay 

3197 ) 

3198 

3199 

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

3201 

3202 

3203# sect 2.2.14 

3204 

3205 

3206class SMB2_Create_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3207 name = "SMB2 CREATE Response" 

3208 Command = 0x0005 

3209 OFFSET = 88 + 64 

3210 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3211 fields_desc = [ 

3212 XLEShortField("StructureSize", 0x59), 

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

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

3215 LEIntEnumField( 

3216 "CreateAction", 

3217 1, 

3218 { 

3219 0x00000000: "FILE_SUPERSEDED", 

3220 0x00000001: "FILE_OPENED", 

3221 0x00000002: "FILE_CREATED", 

3222 0x00000003: "FILE_OVERWRITEN", 

3223 }, 

3224 ), 

3225 FileNetworkOpenInformation, 

3226 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3227 XLEIntField("CreateContextsBufferOffset", None), 

3228 LEIntField("CreateContextsLen", None), 

3229 _NTLMPayloadField( 

3230 "Buffer", 

3231 OFFSET, 

3232 [ 

3233 _NextPacketListField( 

3234 "CreateContexts", 

3235 [], 

3236 SMB2_Create_Context, 

3237 length_from=lambda pkt: pkt.CreateContextsLen, 

3238 ), 

3239 ], 

3240 ), 

3241 ] 

3242 

3243 def post_build(self, pkt, pay): 

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

3245 return ( 

3246 _SMB2_post_build( 

3247 self, 

3248 pkt, 

3249 self.OFFSET, 

3250 { 

3251 "CreateContexts": 80, 

3252 }, 

3253 ) 

3254 + pay 

3255 ) 

3256 

3257 

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

3259 

3260# sect 2.2.15 

3261 

3262 

3263class SMB2_Close_Request(_SMB2_Payload): 

3264 name = "SMB2 CLOSE Request" 

3265 Command = 0x0006 

3266 fields_desc = [ 

3267 XLEShortField("StructureSize", 0x18), 

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

3269 LEIntField("Reserved", 0), 

3270 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3271 ] 

3272 

3273 

3274bind_top_down( 

3275 SMB2_Header, 

3276 SMB2_Close_Request, 

3277 Command=0x0006, 

3278) 

3279 

3280# sect 2.2.16 

3281 

3282 

3283class SMB2_Close_Response(_SMB2_Payload): 

3284 name = "SMB2 CLOSE Response" 

3285 Command = 0x0006 

3286 FileAttributes = 0 

3287 CreationTime = 0 

3288 LastAccessTime = 0 

3289 LastWriteTime = 0 

3290 ChangeTime = 0 

3291 fields_desc = [ 

3292 XLEShortField("StructureSize", 0x3C), 

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

3294 LEIntField("Reserved", 0), 

3295 ] + FileNetworkOpenInformation.fields_desc[:7] 

3296 

3297 

3298bind_top_down( 

3299 SMB2_Header, 

3300 SMB2_Close_Response, 

3301 Command=0x0006, 

3302 Flags=1, 

3303) 

3304 

3305# sect 2.2.19 

3306 

3307 

3308class SMB2_Read_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3309 name = "SMB2 READ Request" 

3310 Command = 0x0008 

3311 OFFSET = 48 + 64 

3312 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3313 fields_desc = [ 

3314 XLEShortField("StructureSize", 0x31), 

3315 ByteField("Padding", 0x00), 

3316 FlagsField( 

3317 "Flags", 

3318 0, 

3319 -8, 

3320 { 

3321 0x01: "SMB2_READFLAG_READ_UNBUFFERED", 

3322 0x02: "SMB2_READFLAG_REQUEST_COMPRESSED", 

3323 }, 

3324 ), 

3325 LEIntField("Length", 4280), 

3326 LELongField("Offset", 0), 

3327 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3328 LEIntField("MinimumCount", 0), 

3329 LEIntEnumField( 

3330 "Channel", 

3331 0, 

3332 { 

3333 0x00000000: "SMB2_CHANNEL_NONE", 

3334 0x00000001: "SMB2_CHANNEL_RDMA_V1", 

3335 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE", 

3336 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM", 

3337 }, 

3338 ), 

3339 LEIntField("RemainingBytes", 0), 

3340 LEShortField("ReadChannelInfoBufferOffset", None), 

3341 LEShortField("ReadChannelInfoLen", None), 

3342 _NTLMPayloadField( 

3343 "Buffer", 

3344 OFFSET, 

3345 [ 

3346 StrLenField( 

3347 "ReadChannelInfo", 

3348 b"", 

3349 length_from=lambda pkt: pkt.ReadChannelInfoLen, 

3350 ) 

3351 ], 

3352 ), 

3353 ] 

3354 

3355 def post_build(self, pkt, pay): 

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

3357 if len(pkt) == 0x30: 

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

3359 pkt += b"\x00" 

3360 return ( 

3361 _SMB2_post_build( 

3362 self, 

3363 pkt, 

3364 self.OFFSET, 

3365 { 

3366 "ReadChannelInfo": 44, 

3367 }, 

3368 ) 

3369 + pay 

3370 ) 

3371 

3372 

3373bind_top_down( 

3374 SMB2_Header, 

3375 SMB2_Read_Request, 

3376 Command=0x0008, 

3377) 

3378 

3379# sect 2.2.20 

3380 

3381 

3382class SMB2_Read_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3383 name = "SMB2 READ Response" 

3384 Command = 0x0008 

3385 OFFSET = 16 + 64 

3386 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3387 fields_desc = [ 

3388 XLEShortField("StructureSize", 0x11), 

3389 LEShortField("DataBufferOffset", None), 

3390 LEIntField("DataLen", None), 

3391 LEIntField("DataRemaining", 0), 

3392 FlagsField( 

3393 "Flags", 

3394 0, 

3395 -32, 

3396 { 

3397 0x01: "SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM", 

3398 }, 

3399 ), 

3400 _NTLMPayloadField( 

3401 "Buffer", 

3402 OFFSET, 

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

3404 ), 

3405 ] 

3406 

3407 def post_build(self, pkt, pay): 

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

3409 return ( 

3410 _SMB2_post_build( 

3411 self, 

3412 pkt, 

3413 self.OFFSET, 

3414 { 

3415 "Data": 2, 

3416 }, 

3417 ) 

3418 + pay 

3419 ) 

3420 

3421 

3422bind_top_down( 

3423 SMB2_Header, 

3424 SMB2_Read_Response, 

3425 Command=0x0008, 

3426 Flags=1, 

3427) 

3428 

3429 

3430# sect 2.2.21 

3431 

3432 

3433class SMB2_Write_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3434 name = "SMB2 WRITE Request" 

3435 Command = 0x0009 

3436 OFFSET = 48 + 64 

3437 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3438 fields_desc = [ 

3439 XLEShortField("StructureSize", 0x31), 

3440 LEShortField("DataBufferOffset", None), 

3441 LEIntField("DataLen", None), 

3442 LELongField("Offset", 0), 

3443 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3444 LEIntEnumField( 

3445 "Channel", 

3446 0, 

3447 { 

3448 0x00000000: "SMB2_CHANNEL_NONE", 

3449 0x00000001: "SMB2_CHANNEL_RDMA_V1", 

3450 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE", 

3451 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM", 

3452 }, 

3453 ), 

3454 LEIntField("RemainingBytes", 0), 

3455 LEShortField("WriteChannelInfoBufferOffset", None), 

3456 LEShortField("WriteChannelInfoLen", None), 

3457 FlagsField( 

3458 "Flags", 

3459 0, 

3460 -32, 

3461 { 

3462 0x00000001: "SMB2_WRITEFLAG_WRITE_THROUGH", 

3463 0x00000002: "SMB2_WRITEFLAG_WRITE_UNBUFFERED", 

3464 }, 

3465 ), 

3466 _NTLMPayloadField( 

3467 "Buffer", 

3468 OFFSET, 

3469 [ 

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

3471 StrLenField( 

3472 "WriteChannelInfo", 

3473 b"", 

3474 length_from=lambda pkt: pkt.WriteChannelInfoLen, 

3475 ), 

3476 ], 

3477 ), 

3478 ] 

3479 

3480 def post_build(self, pkt, pay): 

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

3482 return ( 

3483 _SMB2_post_build( 

3484 self, 

3485 pkt, 

3486 self.OFFSET, 

3487 { 

3488 "Data": 2, 

3489 "WriteChannelInfo": 40, 

3490 }, 

3491 ) 

3492 + pay 

3493 ) 

3494 

3495 

3496bind_top_down( 

3497 SMB2_Header, 

3498 SMB2_Write_Request, 

3499 Command=0x0009, 

3500) 

3501 

3502# sect 2.2.22 

3503 

3504 

3505class SMB2_Write_Response(_SMB2_Payload): 

3506 name = "SMB2 WRITE Response" 

3507 Command = 0x0009 

3508 fields_desc = [ 

3509 XLEShortField("StructureSize", 0x11), 

3510 LEShortField("Reserved", 0), 

3511 LEIntField("Count", 0), 

3512 LEIntField("Remaining", 0), 

3513 LEShortField("WriteChannelInfoBufferOffset", 0), 

3514 LEShortField("WriteChannelInfoLen", 0), 

3515 ] 

3516 

3517 

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

3519 

3520# sect 2.2.28 

3521 

3522 

3523class SMB2_Echo_Request(_SMB2_Payload): 

3524 name = "SMB2 ECHO Request" 

3525 Command = 0x000D 

3526 fields_desc = [ 

3527 XLEShortField("StructureSize", 0x4), 

3528 LEShortField("Reserved", 0), 

3529 ] 

3530 

3531 

3532bind_top_down( 

3533 SMB2_Header, 

3534 SMB2_Echo_Request, 

3535 Command=0x000D, 

3536) 

3537 

3538# sect 2.2.29 

3539 

3540 

3541class SMB2_Echo_Response(_SMB2_Payload): 

3542 name = "SMB2 ECHO Response" 

3543 Command = 0x000D 

3544 fields_desc = [ 

3545 XLEShortField("StructureSize", 0x4), 

3546 LEShortField("Reserved", 0), 

3547 ] 

3548 

3549 

3550bind_top_down( 

3551 SMB2_Header, 

3552 SMB2_Echo_Response, 

3553 Command=0x000D, 

3554 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

3555) 

3556 

3557# sect 2.2.30 

3558 

3559 

3560class SMB2_Cancel_Request(_SMB2_Payload): 

3561 name = "SMB2 CANCEL Request" 

3562 fields_desc = [ 

3563 XLEShortField("StructureSize", 0x4), 

3564 LEShortField("Reserved", 0), 

3565 ] 

3566 

3567 

3568bind_top_down( 

3569 SMB2_Header, 

3570 SMB2_Cancel_Request, 

3571 Command=0x0009, 

3572) 

3573 

3574# sect 2.2.31.4 

3575 

3576 

3577class SMB2_IOCTL_Validate_Negotiate_Info_Request(Packet): 

3578 name = "SMB2 IOCTL Validate Negotiate Info" 

3579 fields_desc = ( 

3580 SMB2_Negotiate_Protocol_Request.fields_desc[4:6] 

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

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

3583 ) 

3584 

3585 

3586# sect 2.2.31 

3587 

3588 

3589class _SMB2_IOCTL_Request_PacketLenField(PacketLenField): 

3590 def m2i(self, pkt, m): 

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

3592 return SMB2_IOCTL_Validate_Negotiate_Info_Request(m) 

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

3594 return SMB2_IOCTL_REQ_GET_DFS_Referral(m) 

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

3596 return SMB2_IOCTL_OFFLOAD_READ_Request(m) 

3597 return conf.raw_layer(m) 

3598 

3599 

3600class SMB2_IOCTL_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3601 name = "SMB2 IOCTL Request" 

3602 Command = 0x000B 

3603 OFFSET = 56 + 64 

3604 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3605 deprecated_fields = { 

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

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

3608 } 

3609 fields_desc = [ 

3610 XLEShortField("StructureSize", 0x39), 

3611 LEShortField("Reserved", 0), 

3612 LEIntEnumField( 

3613 "CtlCode", 

3614 0, 

3615 { 

3616 0x00060194: "FSCTL_DFS_GET_REFERRALS", 

3617 0x0011400C: "FSCTL_PIPE_PEEK", 

3618 0x00110018: "FSCTL_PIPE_WAIT", 

3619 0x0011C017: "FSCTL_PIPE_TRANSCEIVE", 

3620 0x001440F2: "FSCTL_SRV_COPYCHUNK", 

3621 0x00144064: "FSCTL_SRV_ENUMERATE_SNAPSHOTS", 

3622 0x00140078: "FSCTL_SRV_REQUEST_RESUME_KEY", 

3623 0x001441BB: "FSCTL_SRV_READ_HASH", 

3624 0x001480F2: "FSCTL_SRV_COPYCHUNK_WRITE", 

3625 0x001401D4: "FSCTL_LMR_REQUEST_RESILIENCY", 

3626 0x001401FC: "FSCTL_QUERY_NETWORK_INTERFACE_INFO", 

3627 0x000900A4: "FSCTL_SET_REPARSE_POINT", 

3628 0x000601B0: "FSCTL_DFS_GET_REFERRALS_EX", 

3629 0x00098208: "FSCTL_FILE_LEVEL_TRIM", 

3630 0x00140204: "FSCTL_VALIDATE_NEGOTIATE_INFO", 

3631 0x00094264: "FSCTL_OFFLOAD_READ", 

3632 }, 

3633 ), 

3634 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3635 LEIntField("InputBufferOffset", None), 

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

3637 LEIntField("MaxInputResponse", 0), 

3638 LEIntField("OutputBufferOffset", None), 

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

3640 LEIntField("MaxOutputResponse", 65535), 

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

3642 LEIntField("Reserved2", 0), 

3643 _NTLMPayloadField( 

3644 "Buffer", 

3645 OFFSET, 

3646 [ 

3647 _SMB2_IOCTL_Request_PacketLenField( 

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

3649 ), 

3650 _SMB2_IOCTL_Request_PacketLenField( 

3651 "Output", 

3652 None, 

3653 conf.raw_layer, 

3654 length_from=lambda pkt: pkt.OutputLen, 

3655 ), 

3656 ], 

3657 ), 

3658 ] 

3659 

3660 def post_build(self, pkt, pay): 

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

3662 return ( 

3663 _SMB2_post_build( 

3664 self, 

3665 pkt, 

3666 self.OFFSET, 

3667 { 

3668 "Input": 24, 

3669 "Output": 36, 

3670 }, 

3671 ) 

3672 + pay 

3673 ) 

3674 

3675 

3676bind_top_down( 

3677 SMB2_Header, 

3678 SMB2_IOCTL_Request, 

3679 Command=0x000B, 

3680) 

3681 

3682# sect 2.2.32.5 

3683 

3684 

3685class SOCKADDR_STORAGE(Packet): 

3686 fields_desc = [ 

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

3688 ShortField("Port", 0), 

3689 # IPv4 

3690 ConditionalField( 

3691 IPField("IPv4Adddress", None), 

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

3693 ), 

3694 ConditionalField( 

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

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

3697 ), 

3698 # IPv6 

3699 ConditionalField( 

3700 LEIntField("FlowInfo", 0), 

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

3702 ), 

3703 ConditionalField( 

3704 IP6Field("IPv6Address", None), 

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

3706 ), 

3707 ConditionalField( 

3708 LEIntField("ScopeId", 0), 

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

3710 ), 

3711 ] 

3712 

3713 def default_payload_class(self, _): 

3714 return conf.padding_layer 

3715 

3716 

3717class NETWORK_INTERFACE_INFO(Packet): 

3718 fields_desc = [ 

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

3720 LEIntField("IfIndex", 1), 

3721 FlagsField( 

3722 "Capability", 

3723 1, 

3724 -32, 

3725 { 

3726 0x00000001: "RSS_CAPABLE", 

3727 0x00000002: "RDMA_CAPABLE", 

3728 }, 

3729 ), 

3730 LEIntField("Reserved", 0), 

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

3732 PacketField("SockAddr_Storage", SOCKADDR_STORAGE(), SOCKADDR_STORAGE), 

3733 ] 

3734 

3735 def default_payload_class(self, _): 

3736 return conf.padding_layer 

3737 

3738 

3739class SMB2_IOCTL_Network_Interface_Info(Packet): 

3740 name = "SMB2 IOCTL Network Interface Info response" 

3741 fields_desc = [ 

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

3743 ] 

3744 

3745 

3746# sect 2.2.32.6 

3747 

3748 

3749class SMB2_IOCTL_Validate_Negotiate_Info_Response(Packet): 

3750 name = "SMB2 IOCTL Validate Negotiate Info" 

3751 fields_desc = ( 

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

3753 + SMB2_Negotiate_Protocol_Response.fields_desc[ # Cap/GUID 

3754 1:3 

3755 ] # SecMod/DialectRevision 

3756 ) 

3757 

3758 

3759# [MS-FSCC] sect 2.3.42 

3760 

3761 

3762class SMB2_IOCTL_OFFLOAD_READ_Request(Packet): 

3763 name = "SMB2 IOCTL OFFLOAD_READ Request" 

3764 fields_desc = [ 

3765 LEIntField("StructureSize", 0x20), 

3766 LEIntField("Flags", 0), 

3767 LEIntField("TokenTimeToLive", 0), 

3768 LEIntField("Reserved", 0), 

3769 LELongField("FileOffset", 0), 

3770 LELongField("CopyLength", 0), 

3771 ] 

3772 

3773 

3774# [MS-FSCC] sect 2.1.11 

3775 

3776 

3777class STORAGE_OFFLOAD_TOKEN(Packet): 

3778 fields_desc = [ 

3779 LEIntEnumField( 

3780 "TokenType", 

3781 0xFFFF0001, 

3782 { 

3783 0xFFFF0001: "STORAGE_OFFLOAD_TOKEN_TYPE_ZERO_DATA", 

3784 }, 

3785 ), 

3786 LEShortField("Reserved", 0), 

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

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

3789 ] 

3790 

3791 

3792# [MS-FSCC] sect 2.3.42 

3793 

3794 

3795class SMB2_IOCTL_OFFLOAD_READ_Response(Packet): 

3796 name = "SMB2 IOCTL OFFLOAD_READ Response" 

3797 fields_desc = [ 

3798 LEIntField("StructureSize", 0x210), 

3799 FlagsField( 

3800 "Flags", 

3801 0, 

3802 -32, 

3803 { 

3804 0x00000001: "OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE", 

3805 }, 

3806 ), 

3807 LELongField("TransferLength", 0), 

3808 PacketField("Token", STORAGE_OFFLOAD_TOKEN(), STORAGE_OFFLOAD_TOKEN), 

3809 ] 

3810 

3811 

3812# sect 2.2.32 

3813 

3814 

3815class _SMB2_IOCTL_Response_PacketLenField(PacketLenField): 

3816 def m2i(self, pkt, m): 

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

3818 return SMB2_IOCTL_Validate_Negotiate_Info_Response(m) 

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

3820 return SMB2_IOCTL_Network_Interface_Info(m) 

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

3822 return SMB2_IOCTL_RESP_GET_DFS_Referral(m) 

3823 return conf.raw_layer(m) 

3824 

3825 

3826class SMB2_IOCTL_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3827 name = "SMB2 IOCTL Response" 

3828 Command = 0x000B 

3829 OFFSET = 48 + 64 

3830 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3831 StructureSize = 0x31 

3832 MaxOutputResponse = 0 

3833 fields_desc = ( 

3834 SMB2_IOCTL_Request.fields_desc[:6] 

3835 + SMB2_IOCTL_Request.fields_desc[7:9] 

3836 + SMB2_IOCTL_Request.fields_desc[10:12] 

3837 + [ 

3838 _NTLMPayloadField( 

3839 "Buffer", 

3840 OFFSET, 

3841 [ 

3842 _SMB2_IOCTL_Response_PacketLenField( 

3843 "Input", 

3844 None, 

3845 conf.raw_layer, 

3846 length_from=lambda pkt: pkt.InputLen, 

3847 ), 

3848 _SMB2_IOCTL_Response_PacketLenField( 

3849 "Output", 

3850 None, 

3851 conf.raw_layer, 

3852 length_from=lambda pkt: pkt.OutputLen, 

3853 ), 

3854 ], 

3855 ), 

3856 ] 

3857 ) 

3858 

3859 def post_build(self, pkt, pay): 

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

3861 return ( 

3862 _SMB2_post_build( 

3863 self, 

3864 pkt, 

3865 self.OFFSET, 

3866 { 

3867 "Input": 24, 

3868 "Output": 32, 

3869 }, 

3870 ) 

3871 + pay 

3872 ) 

3873 

3874 

3875bind_top_down( 

3876 SMB2_Header, 

3877 SMB2_IOCTL_Response, 

3878 Command=0x000B, 

3879 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

3880) 

3881 

3882# sect 2.2.33 

3883 

3884 

3885class SMB2_Query_Directory_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3886 name = "SMB2 QUERY DIRECTORY Request" 

3887 Command = 0x000E 

3888 OFFSET = 32 + 64 

3889 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3890 fields_desc = [ 

3891 XLEShortField("StructureSize", 0x21), 

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

3893 FlagsField( 

3894 "Flags", 

3895 0, 

3896 -8, 

3897 { 

3898 0x01: "SMB2_RESTART_SCANS", 

3899 0x02: "SMB2_RETURN_SINGLE_ENTRY", 

3900 0x04: "SMB2_INDEX_SPECIFIED", 

3901 0x10: "SMB2_REOPEN", 

3902 }, 

3903 ), 

3904 LEIntField("FileIndex", 0), 

3905 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3906 LEShortField("FileNameBufferOffset", None), 

3907 LEShortField("FileNameLen", None), 

3908 LEIntField("OutputBufferLength", 65535), 

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

3910 ] 

3911 

3912 def post_build(self, pkt, pay): 

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

3914 return ( 

3915 _SMB2_post_build( 

3916 self, 

3917 pkt, 

3918 self.OFFSET, 

3919 { 

3920 "FileName": 24, 

3921 }, 

3922 ) 

3923 + pay 

3924 ) 

3925 

3926 

3927bind_top_down( 

3928 SMB2_Header, 

3929 SMB2_Query_Directory_Request, 

3930 Command=0x000E, 

3931) 

3932 

3933# sect 2.2.34 

3934 

3935 

3936class SMB2_Query_Directory_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3937 name = "SMB2 QUERY DIRECTORY Response" 

3938 Command = 0x000E 

3939 OFFSET = 8 + 64 

3940 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3941 fields_desc = [ 

3942 XLEShortField("StructureSize", 0x9), 

3943 LEShortField("OutputBufferOffset", None), 

3944 LEIntField("OutputLen", None), 

3945 _NTLMPayloadField( 

3946 "Buffer", 

3947 OFFSET, 

3948 [ 

3949 # TODO 

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

3951 ], 

3952 ), 

3953 ] 

3954 

3955 def post_build(self, pkt, pay): 

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

3957 return ( 

3958 _SMB2_post_build( 

3959 self, 

3960 pkt, 

3961 self.OFFSET, 

3962 { 

3963 "Output": 2, 

3964 }, 

3965 ) 

3966 + pay 

3967 ) 

3968 

3969 

3970bind_top_down( 

3971 SMB2_Header, 

3972 SMB2_Query_Directory_Response, 

3973 Command=0x000E, 

3974 Flags=1, 

3975) 

3976 

3977# sect 2.2.35 

3978 

3979 

3980class SMB2_Change_Notify_Request(_SMB2_Payload): 

3981 name = "SMB2 CHANGE NOTIFY Request" 

3982 Command = 0x000F 

3983 fields_desc = [ 

3984 XLEShortField("StructureSize", 0x20), 

3985 FlagsField( 

3986 "Flags", 

3987 0, 

3988 -16, 

3989 { 

3990 0x0001: "SMB2_WATCH_TREE", 

3991 }, 

3992 ), 

3993 LEIntField("OutputBufferLength", 2048), 

3994 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3995 FlagsField( 

3996 "CompletionFilter", 

3997 0, 

3998 -32, 

3999 { 

4000 0x00000001: "FILE_NOTIFY_CHANGE_FILE_NAME", 

4001 0x00000002: "FILE_NOTIFY_CHANGE_DIR_NAME", 

4002 0x00000004: "FILE_NOTIFY_CHANGE_ATTRIBUTES", 

4003 0x00000008: "FILE_NOTIFY_CHANGE_SIZE", 

4004 0x00000010: "FILE_NOTIFY_CHANGE_LAST_WRITE", 

4005 0x00000020: "FILE_NOTIFY_CHANGE_LAST_ACCESS", 

4006 0x00000040: "FILE_NOTIFY_CHANGE_CREATION", 

4007 0x00000080: "FILE_NOTIFY_CHANGE_EA", 

4008 0x00000100: "FILE_NOTIFY_CHANGE_SECURITY", 

4009 0x00000200: "FILE_NOTIFY_CHANGE_STREAM_NAME", 

4010 0x00000400: "FILE_NOTIFY_CHANGE_STREAM_SIZE", 

4011 0x00000800: "FILE_NOTIFY_CHANGE_STREAM_WRITE", 

4012 }, 

4013 ), 

4014 LEIntField("Reserved", 0), 

4015 ] 

4016 

4017 

4018bind_top_down( 

4019 SMB2_Header, 

4020 SMB2_Change_Notify_Request, 

4021 Command=0x000F, 

4022) 

4023 

4024# sect 2.2.36 

4025 

4026 

4027class SMB2_Change_Notify_Response(_SMB2_Payload, _NTLMPayloadPacket): 

4028 name = "SMB2 CHANGE NOTIFY Response" 

4029 Command = 0x000F 

4030 OFFSET = 8 + 64 

4031 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

4032 fields_desc = [ 

4033 XLEShortField("StructureSize", 0x9), 

4034 LEShortField("OutputBufferOffset", None), 

4035 LEIntField("OutputLen", None), 

4036 _NTLMPayloadField( 

4037 "Buffer", 

4038 OFFSET, 

4039 [ 

4040 _NextPacketListField( 

4041 "Output", 

4042 [], 

4043 FILE_NOTIFY_INFORMATION, 

4044 length_from=lambda pkt: pkt.OutputLen, 

4045 max_count=1000, 

4046 ) 

4047 ], 

4048 ), 

4049 ] 

4050 

4051 def post_build(self, pkt, pay): 

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

4053 return ( 

4054 _SMB2_post_build( 

4055 self, 

4056 pkt, 

4057 self.OFFSET, 

4058 { 

4059 "Output": 2, 

4060 }, 

4061 ) 

4062 + pay 

4063 ) 

4064 

4065 

4066bind_top_down( 

4067 SMB2_Header, 

4068 SMB2_Change_Notify_Response, 

4069 Command=0x000F, 

4070 Flags=1, 

4071) 

4072 

4073# sect 2.2.37 

4074 

4075 

4076class FILE_GET_QUOTA_INFORMATION(Packet): 

4077 fields_desc = [ 

4078 IntField("NextEntryOffset", 0), 

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

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

4081 StrLenField( 

4082 "pad", 

4083 b"", 

4084 length_from=lambda x: ( 

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

4086 ), 

4087 ), 

4088 ] 

4089 

4090 

4091class SMB2_Query_Quota_Info(Packet): 

4092 fields_desc = [ 

4093 ByteField("ReturnSingle", 0), 

4094 ByteField("ReturnBoolean", 0), 

4095 ShortField("Reserved", 0), 

4096 LEIntField("SidListLength", 0), 

4097 LEIntField("StartSidLength", 0), 

4098 LEIntField("StartSidOffset", 0), 

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

4100 MultipleTypeField( 

4101 [ 

4102 ( 

4103 PacketListField( 

4104 "SidBuffer", 

4105 [], 

4106 FILE_GET_QUOTA_INFORMATION, 

4107 length_from=lambda x: x.SidListLength, 

4108 ), 

4109 lambda x: x.SidListLength, 

4110 ), 

4111 ( 

4112 StrLenField( 

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

4114 ), 

4115 lambda x: x.StartSidLength, 

4116 ), 

4117 ], 

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

4119 ), 

4120 ] 

4121 

4122 

4123SMB2_INFO_TYPE = { 

4124 0x01: "SMB2_0_INFO_FILE", 

4125 0x02: "SMB2_0_INFO_FILESYSTEM", 

4126 0x03: "SMB2_0_INFO_SECURITY", 

4127 0x04: "SMB2_0_INFO_QUOTA", 

4128} 

4129 

4130SMB2_ADDITIONAL_INFORMATION = { 

4131 0x00000001: "OWNER_SECURITY_INFORMATION", 

4132 0x00000002: "GROUP_SECURITY_INFORMATION", 

4133 0x00000004: "DACL_SECURITY_INFORMATION", 

4134 0x00000008: "SACL_SECURITY_INFORMATION", 

4135 0x00000010: "LABEL_SECURITY_INFORMATION", 

4136 0x00000020: "ATTRIBUTE_SECURITY_INFORMATION", 

4137 0x00000040: "SCOPE_SECURITY_INFORMATION", 

4138 0x00010000: "BACKUP_SECURITY_INFORMATION", 

4139} 

4140 

4141 

4142class SMB2_Query_Info_Request(_SMB2_Payload, _NTLMPayloadPacket): 

4143 name = "SMB2 QUERY INFO Request" 

4144 Command = 0x0010 

4145 OFFSET = 40 + 64 

4146 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

4147 fields_desc = [ 

4148 XLEShortField("StructureSize", 0x29), 

4149 ByteEnumField( 

4150 "InfoType", 

4151 0, 

4152 SMB2_INFO_TYPE, 

4153 ), 

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

4155 LEIntField("OutputBufferLength", 0), 

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

4157 LEIntField("InputLen", None), 

4158 FlagsField( 

4159 "AdditionalInformation", 

4160 0, 

4161 -32, 

4162 SMB2_ADDITIONAL_INFORMATION, 

4163 ), 

4164 FlagsField( 

4165 "Flags", 

4166 0, 

4167 -32, 

4168 { 

4169 0x00000001: "SL_RESTART_SCAN", 

4170 0x00000002: "SL_RETURN_SINGLE_ENTRY", 

4171 0x00000004: "SL_INDEX_SPECIFIED", 

4172 }, 

4173 ), 

4174 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

4175 _NTLMPayloadField( 

4176 "Buffer", 

4177 OFFSET, 

4178 [ 

4179 MultipleTypeField( 

4180 [ 

4181 ( 

4182 # QUOTA 

4183 PacketListField( 

4184 "Input", 

4185 None, 

4186 SMB2_Query_Quota_Info, 

4187 length_from=lambda pkt: pkt.InputLen, 

4188 ), 

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

4190 ), 

4191 ], 

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

4193 ), 

4194 ], 

4195 ), 

4196 ] 

4197 

4198 def post_build(self, pkt, pay): 

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

4200 return ( 

4201 _SMB2_post_build( 

4202 self, 

4203 pkt, 

4204 self.OFFSET, 

4205 { 

4206 "Input": 4, 

4207 }, 

4208 ) 

4209 + pay 

4210 ) 

4211 

4212 

4213bind_top_down( 

4214 SMB2_Header, 

4215 SMB2_Query_Info_Request, 

4216 Command=0x00010, 

4217) 

4218 

4219 

4220class SMB2_Query_Info_Response(_SMB2_Payload, _NTLMPayloadPacket): 

4221 name = "SMB2 QUERY INFO Response" 

4222 Command = 0x0010 

4223 OFFSET = 8 + 64 

4224 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

4225 fields_desc = [ 

4226 XLEShortField("StructureSize", 0x9), 

4227 LEShortField("OutputBufferOffset", None), 

4228 LEIntField("OutputLen", None), 

4229 _NTLMPayloadField( 

4230 "Buffer", 

4231 OFFSET, 

4232 [ 

4233 # TODO 

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

4235 ], 

4236 ), 

4237 ] 

4238 

4239 def post_build(self, pkt, pay): 

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

4241 return ( 

4242 _SMB2_post_build( 

4243 self, 

4244 pkt, 

4245 self.OFFSET, 

4246 { 

4247 "Output": 2, 

4248 }, 

4249 ) 

4250 + pay 

4251 ) 

4252 

4253 

4254bind_top_down( 

4255 SMB2_Header, 

4256 SMB2_Query_Info_Response, 

4257 Command=0x00010, 

4258 Flags=1, 

4259) 

4260 

4261 

4262# sect 2.2.39 

4263 

4264 

4265class SMB2_Set_Info_Request(_SMB2_Payload, _NTLMPayloadPacket): 

4266 name = "SMB2 SET INFO Request" 

4267 Command = 0x0011 

4268 OFFSET = 32 + 64 

4269 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

4270 fields_desc = [ 

4271 XLEShortField("StructureSize", 0x21), 

4272 ByteEnumField( 

4273 "InfoType", 

4274 0, 

4275 SMB2_INFO_TYPE, 

4276 ), 

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

4278 LEIntField("DataLen", None), 

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

4280 FlagsField( 

4281 "AdditionalInformation", 

4282 0, 

4283 -32, 

4284 SMB2_ADDITIONAL_INFORMATION, 

4285 ), 

4286 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

4287 _NTLMPayloadField( 

4288 "Buffer", 

4289 OFFSET, 

4290 [ 

4291 MultipleTypeField( 

4292 [ 

4293 ( 

4294 # FILE 

4295 PacketLenField( 

4296 "Data", 

4297 None, 

4298 lambda x, _parent: _FileInformationClasses.get( 

4299 _parent.FileInfoClass, conf.raw_layer 

4300 )(x), 

4301 length_from=lambda pkt: pkt.DataLen, 

4302 ), 

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

4304 ), 

4305 ( 

4306 # QUOTA 

4307 PacketListField( 

4308 "Data", 

4309 None, 

4310 SMB2_Query_Quota_Info, 

4311 length_from=lambda pkt: pkt.DataLen, 

4312 ), 

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

4314 ), 

4315 ], 

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

4317 ), 

4318 ], 

4319 ), 

4320 ] 

4321 

4322 def post_build(self, pkt, pay): 

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

4324 return ( 

4325 _SMB2_post_build( 

4326 self, 

4327 pkt, 

4328 self.OFFSET, 

4329 { 

4330 "Data": 4, 

4331 }, 

4332 ) 

4333 + pay 

4334 ) 

4335 

4336 

4337bind_top_down( 

4338 SMB2_Header, 

4339 SMB2_Set_Info_Request, 

4340 Command=0x00011, 

4341) 

4342 

4343 

4344class SMB2_Set_Info_Response(_SMB2_Payload): 

4345 name = "SMB2 SET INFO Request" 

4346 Command = 0x0011 

4347 fields_desc = [ 

4348 XLEShortField("StructureSize", 0x02), 

4349 ] 

4350 

4351 

4352bind_top_down( 

4353 SMB2_Header, 

4354 SMB2_Set_Info_Response, 

4355 Command=0x00011, 

4356 Flags=1, 

4357) 

4358 

4359 

4360# sect 2.2.41 

4361 

4362 

4363class SMB2_Transform_Header(Packet): 

4364 name = "SMB2 Transform Header" 

4365 fields_desc = [ 

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

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

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

4369 LEIntField("OriginalMessageSize", 0x0), 

4370 LEShortField("Reserved", 0), 

4371 LEShortEnumField( 

4372 "Flags", 

4373 0x1, 

4374 { 

4375 0x0001: "ENCRYPTED", 

4376 }, 

4377 ), 

4378 LELongField("SessionId", 0), 

4379 ] 

4380 

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

4382 """ 

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

4384 """ 

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

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

4387 

4388 if "GCM" in CipherId: 

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

4390 

4391 nonce = self.Nonce[:12] 

4392 cipher = AESGCM(DecryptionKey) 

4393 elif "CCM" in CipherId: 

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

4395 

4396 nonce = self.Nonce[:11] 

4397 cipher = AESCCM(DecryptionKey) 

4398 else: 

4399 raise Exception("Unknown CipherId !") 

4400 

4401 # Decrypt the data 

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

4403 data = cipher.decrypt( 

4404 nonce, 

4405 self.payload.load + self.Signature, 

4406 aad, 

4407 ) 

4408 return SMB2_Header(data, _decrypted=True) 

4409 

4410 

4411bind_layers(SMB2_Transform_Header, conf.raw_layer) 

4412 

4413 

4414# sect 2.2.42.1 

4415 

4416 

4417class SMB2_Compression_Transform_Header(Packet): 

4418 name = "SMB2 Compression Transform Header" 

4419 fields_desc = [ 

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

4421 LEIntField("OriginalCompressedSegmentSize", 0x0), 

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

4423 LEShortEnumField( 

4424 "Flags", 

4425 0x0, 

4426 { 

4427 0x0000: "SMB2_COMPRESSION_FLAG_NONE", 

4428 0x0001: "SMB2_COMPRESSION_FLAG_CHAINED", 

4429 }, 

4430 ), 

4431 XLEIntField("Offset_or_Length", 0), 

4432 ] 

4433 

4434 

4435# [MS-DFSC] sect 2.2 

4436 

4437 

4438class SMB2_IOCTL_REQ_GET_DFS_Referral(Packet): 

4439 fields_desc = [ 

4440 LEShortField("MaxReferralLevel", 0), 

4441 StrNullFieldUtf16("RequestFileName", ""), 

4442 ] 

4443 

4444 

4445class DFS_REFERRAL(Packet): 

4446 fields_desc = [ 

4447 LEShortField("Version", 1), 

4448 FieldLenField( 

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

4450 ), 

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

4452 LEShortField("ReferralEntryFlags", 0), 

4453 StrNullFieldUtf16("ShareName", ""), 

4454 ] 

4455 

4456 @classmethod 

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

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

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

4460 if version == 1: 

4461 return DFS_REFERRAL 

4462 elif version == 3: 

4463 return DFS_REFERRAL_V3 

4464 elif version == 4: 

4465 return DFS_REFERRAL_V4 

4466 return cls 

4467 

4468 def default_payload_class(self, s): 

4469 return conf.padding_layer 

4470 

4471 

4472class DFS_REFERRAL_V3(DFS_REFERRAL): 

4473 fields_desc = [ 

4474 LEShortField("Version", 3), 

4475 LEShortField("Size", None), 

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

4477 FlagsField( 

4478 "ReferralEntryFlags", 

4479 0, 

4480 -16, 

4481 { 

4482 0x0002: "NameListReferral", 

4483 0x0004: "TargetSetBoundary", 

4484 }, 

4485 ), 

4486 LEIntField("TimeToLive", 300), 

4487 # NameListReferral is 0 

4488 ConditionalField( 

4489 LEShortField("DFSPathOffset", None), 

4490 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

4491 ), 

4492 ConditionalField( 

4493 LEShortField("DFSAlternatePathOffset", None), 

4494 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

4495 ), 

4496 ConditionalField( 

4497 LEShortField("NetworkAddressOffset", None), 

4498 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

4499 ), 

4500 ConditionalField( 

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

4502 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

4503 ), 

4504 # NameListReferral is 1 

4505 ConditionalField( 

4506 LEShortField("SpecialNameOffset", None), 

4507 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

4508 ), 

4509 ConditionalField( 

4510 LEShortField("NumberOfExpandedNames", None), 

4511 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

4512 ), 

4513 ConditionalField( 

4514 LEShortField("ExpandedNameOffset", None), 

4515 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

4516 ), 

4517 ConditionalField( 

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

4519 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

4520 ), 

4521 ] 

4522 

4523 def post_build(self, pkt, pay): 

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

4525 if self.Size is None: 

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

4527 return pkt + pay 

4528 

4529 

4530class DFS_REFERRAL_V4(DFS_REFERRAL_V3): 

4531 Version = 4 

4532 

4533 

4534class DFS_REFERRAL_ENTRY0(Packet): 

4535 fields_desc = [ 

4536 StrNullFieldUtf16("DFSPath", ""), 

4537 StrNullFieldUtf16("DFSAlternatePath", ""), 

4538 StrNullFieldUtf16("NetworkAddress", ""), 

4539 ] 

4540 

4541 

4542class DFS_REFERRAL_ENTRY1(Packet): 

4543 fields_desc = [ 

4544 StrNullFieldUtf16("SpecialName", ""), 

4545 FieldListField( 

4546 "ExpandedName", 

4547 [], 

4548 StrNullFieldUtf16("", ""), 

4549 ), 

4550 ] 

4551 

4552 

4553class _DFS_Referrals_BufferField(PacketListField): 

4554 def getfield(self, pkt, s): 

4555 results = [] 

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

4557 for ref in pkt.ReferralEntries: 

4558 # For every ref 

4559 if not ref.ReferralEntryFlags.NameListReferral: 

4560 cls = DFS_REFERRAL_ENTRY0 

4561 else: 

4562 cls = DFS_REFERRAL_ENTRY1 

4563 # Build the fields manually 

4564 fld = _NTLMPayloadField( 

4565 "", 

4566 offset, 

4567 cls.fields_desc, 

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

4569 offset_name="Offset", 

4570 ) 

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

4572 vals = fld.i2h(ref, vals) 

4573 # Append the entry class 

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

4575 offset -= ref.Size 

4576 return b"", results 

4577 

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

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

4580 for i, val in enumerate(vals): 

4581 try: 

4582 ref = pkt.ReferralEntries[i] 

4583 except KeyError: 

4584 ref = None 

4585 fld = _NTLMPayloadField( 

4586 "", 

4587 offset, 

4588 val.fields_desc, 

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

4590 offset_name="Offset", 

4591 ) 

4592 # Append the bytes manually 

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

4594 values = fld.h2i(ref, values) 

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

4596 offset -= len(ref) 

4597 return s 

4598 

4599 

4600class SMB2_IOCTL_RESP_GET_DFS_Referral(Packet): 

4601 fields_desc = [ 

4602 LEShortField("PathConsumed", 0), 

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

4604 FlagsField( 

4605 "ReferralHeaderFlags", 

4606 0, 

4607 -32, 

4608 { 

4609 0x00000001: "ReferralServers", 

4610 0x00000002: "StorageServers", 

4611 0x00000004: "TargetFailback", 

4612 }, 

4613 ), 

4614 PacketListField( 

4615 "ReferralEntries", 

4616 [], 

4617 DFS_REFERRAL, 

4618 count_from=lambda pkt: pkt.NumberOfReferrals, 

4619 ), 

4620 _DFS_Referrals_BufferField("ReferralBuffer", []), 

4621 ] 

4622 

4623 def post_build(self, pkt, pay): 

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

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

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

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

4628 offsets = { 

4629 # DFS_REFERRAL_ENTRY0 

4630 "DFSPath": 12, 

4631 "DFSAlternatePath": 14, 

4632 "NetworkAddress": 16, 

4633 # DFS_REFERRAL_ENTRY1 

4634 "SpecialName": 12, 

4635 "ExpandedName": 16, 

4636 } 

4637 # dataoffset = pointer in the ReferralBuffer 

4638 # entryoffset = pointer in the ReferralEntries 

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

4640 entryoffset = 8 

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

4642 for fld in buf.fields_desc: 

4643 off = entryoffset + offsets[fld.name] 

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

4645 fld.name 

4646 ): 

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

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

4649 dataoffset -= len(ref) 

4650 entryoffset += len(ref) 

4651 return pkt + pay 

4652 

4653 

4654# [MS-SMB2] various usages 

4655 

4656 

4657def SMB2computePreauthIntegrityHashValue( 

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

4659): 

4660 """ 

4661 Update the PreauthIntegrityHashValue 

4662 """ 

4663 # get hasher 

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

4665 # compute the hash of concatenation of previous and bytes 

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

4667 

4668 

4669# SMB2 socket and session 

4670 

4671 

4672class SMBStreamSocket(StreamSocket): 

4673 """ 

4674 A modified StreamSocket to dissect SMB compounded requests 

4675 [MS-SMB2] 3.3.5.2.7 

4676 """ 

4677 

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

4679 self.queue = collections.deque() 

4680 self.session = SMBSession() 

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

4682 

4683 def recv(self, x=None): 

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

4685 # this takes care of splitting compounded requests 

4686 if self.queue: 

4687 pkt = self.queue.popleft() 

4688 else: 

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

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

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

4692 if pkt is not None and ( 

4693 SMB2_Header in pkt 

4694 or SMB2_Transform_Header in pkt 

4695 or SMB2_Compression_Transform_Header in pkt 

4696 ): 

4697 pkt = self.session.in_pkt(pkt) 

4698 pay = pkt[SMB2_Header].payload 

4699 while SMB2_Header in pay: 

4700 pay = pay[SMB2_Header] 

4701 pay.underlayer.remove_payload() 

4702 self.queue.append(pay) 

4703 if not pay.NextCommand: 

4704 break 

4705 pay = pay.payload 

4706 # Verify the signature if required. 

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

4708 smbh = pkt.getlayer(SMB2_Header) 

4709 if ( 

4710 smbh 

4711 and self.session.Dialect 

4712 and self.session.SigningKey 

4713 and self.session.SigningRequired 

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

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

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

4717 and not smbh._decrypted 

4718 # - MessageId is 0xFFFFFFFFFFFFFFFF 

4719 and smbh.MID != 0xFFFFFFFFFFFFFFFF 

4720 # - Status in the SMB2 header is STATUS_PENDING 

4721 and smbh.Status != 0x00000103 

4722 ): 

4723 smbh.verify( 

4724 self.session.Dialect, 

4725 self.session.SigningKey, 

4726 # SMB 3.1.1 parameters: 

4727 SigningAlgorithmId=self.session.SigningAlgorithmId, 

4728 IsClient=False, 

4729 ) 

4730 return pkt 

4731 

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

4733 for pkt in self.session.out_pkt( 

4734 x, Compounded=Compounded, ForceSign=ForceSign, ForceEncrypt=ForceEncrypt 

4735 ): 

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

4737 

4738 @staticmethod 

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

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

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

4742 return select_objects(sockets, remain=remain) 

4743 

4744 

4745class SMBSession(DefaultSession): 

4746 """ 

4747 A SMB session within a TCP socket. 

4748 """ 

4749 

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

4751 self.smb_header = None 

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

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

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

4755 # SMB session parameters 

4756 self.CompoundQueue = [] 

4757 self.Dialect = 0x0202 # Updated by parent 

4758 self.Credits = 0 

4759 self.IsGuest = False 

4760 self.MaxTransactionSize = 0 

4761 self.MaxReadSize = 0 

4762 self.MaxWriteSize = 0 

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

4764 self.SigningRequired = True 

4765 self.SupportsEncryption = False 

4766 self.EncryptData = False 

4767 self.TreeEncryptData = False 

4768 self.SigningKey = None 

4769 self.EncryptionKey = None 

4770 self.DecryptionKey = None 

4771 self.PreauthIntegrityHashId = "SHA-512" 

4772 self.SupportedCipherIds = [ 

4773 "AES-128-CCM", 

4774 "AES-128-GCM", 

4775 "AES-256-CCM", 

4776 "AES-256-GCM", 

4777 ] 

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

4779 self.SupportedSigningAlgorithmIds = [ 

4780 "AES-CMAC", 

4781 "HMAC-SHA256", 

4782 ] 

4783 self.SigningAlgorithmId = None 

4784 self.Salt = os.urandom(32) 

4785 self.ConnectionPreauthIntegrityHashValue = None 

4786 self.SessionPreauthIntegrityHashValue = None 

4787 # SMB 3.1.1 

4788 self.SessionPreauthIntegrityHashValue = None 

4789 if conf.winssps_passive: 

4790 for ssp in conf.winssps_passive: 

4791 self.sniffsspcontexts[ssp] = None 

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

4793 

4794 # SMB crypto functions 

4795 

4796 @crypto_validator 

4797 def computeSMBSessionKeys(self, IsClient=None): 

4798 """ 

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

4800 """ 

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

4802 # no signing key, no session key 

4803 return 

4804 # [MS-SMB2] sect 3.3.5.5.3 

4805 # SigningKey 

4806 if self.Dialect >= 0x0300: 

4807 if self.Dialect == 0x0311: 

4808 label = b"SMBSigningKey\x00" 

4809 context = self.SessionPreauthIntegrityHashValue 

4810 else: 

4811 label = b"SMB2AESCMAC\x00" 

4812 context = b"SmbSign\x00" 

4813 # [MS-SMB2] sect 3.1.4.2 

4814 if "256" in self.CipherId: 

4815 L = 256 

4816 elif "128" in self.CipherId: 

4817 L = 128 

4818 else: 

4819 raise ValueError 

4820 self.SigningKey = SP800108_KDFCTR( 

4821 self.sspcontext.SessionKey[:16], 

4822 label, 

4823 context, 

4824 L, 

4825 ) 

4826 # EncryptionKey / DecryptionKey 

4827 if self.Dialect == 0x0311: 

4828 if IsClient: 

4829 label_out = b"SMBC2SCipherKey\x00" 

4830 label_in = b"SMBS2CCipherKey\x00" 

4831 else: 

4832 label_out = b"SMBS2CCipherKey\x00" 

4833 label_in = b"SMBC2SCipherKey\x00" 

4834 context_out = context_in = self.SessionPreauthIntegrityHashValue 

4835 else: 

4836 label_out = label_in = b"SMB2AESCCM\x00" 

4837 if IsClient: 

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

4839 context_in = b"ServerOut\x00" 

4840 else: 

4841 context_out = b"ServerOut\x00" 

4842 context_in = b"ServerIn \x00" 

4843 self.EncryptionKey = SP800108_KDFCTR( 

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

4845 label_out, 

4846 context_out, 

4847 L, 

4848 ) 

4849 self.DecryptionKey = SP800108_KDFCTR( 

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

4851 label_in, 

4852 context_in, 

4853 L, 

4854 ) 

4855 elif self.Dialect <= 0x0210: 

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

4857 else: 

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

4859 

4860 def computeSMBConnectionPreauth(self, *negopkts): 

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

4862 # [MS-SMB2] 3.3.5.4 

4863 # TODO: handle SMB2_SESSION_FLAG_BINDING 

4864 if self.ConnectionPreauthIntegrityHashValue is None: 

4865 # New auth or failure 

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

4867 # Calculate the *Connection* PreauthIntegrityHashValue 

4868 for negopkt in negopkts: 

4869 self.ConnectionPreauthIntegrityHashValue = ( 

4870 SMB2computePreauthIntegrityHashValue( 

4871 self.ConnectionPreauthIntegrityHashValue, 

4872 negopkt, 

4873 HashId=self.PreauthIntegrityHashId, 

4874 ) 

4875 ) 

4876 

4877 def computeSMBSessionPreauth(self, *sesspkts): 

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

4879 # [MS-SMB2] 3.3.5.5.3 

4880 if self.SessionPreauthIntegrityHashValue is None: 

4881 # New auth or failure 

4882 self.SessionPreauthIntegrityHashValue = ( 

4883 self.ConnectionPreauthIntegrityHashValue 

4884 ) 

4885 # Calculate the *Session* PreauthIntegrityHashValue 

4886 for sesspkt in sesspkts: 

4887 self.SessionPreauthIntegrityHashValue = ( 

4888 SMB2computePreauthIntegrityHashValue( 

4889 self.SessionPreauthIntegrityHashValue, 

4890 sesspkt, 

4891 HashId=self.PreauthIntegrityHashId, 

4892 ) 

4893 ) 

4894 

4895 # I/O 

4896 

4897 def in_pkt(self, pkt): 

4898 """ 

4899 Incoming SMB packet 

4900 """ 

4901 if SMB2_Transform_Header in pkt: 

4902 # Packet is encrypted 

4903 pkt = pkt[SMB2_Transform_Header].decrypt( 

4904 self.Dialect, 

4905 self.DecryptionKey, 

4906 CipherId=self.CipherId, 

4907 ) 

4908 # Signature is verified in SMBStreamSocket 

4909 return pkt 

4910 

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

4912 """ 

4913 Outgoing SMB packet 

4914 

4915 :param pkt: the packet to send 

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

4917 un-compounded packet 

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

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

4920 

4921 Handles: 

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

4923 - handles signing and encryption (if required) 

4924 """ 

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

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

4927 if SMB2_Header in pkt: 

4928 if self.CompoundQueue: 

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

4930 pkt = pkt[SMB2_Header] 

4931 if Compounded: 

4932 # [MS-SMB2] 3.2.4.1.4 

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

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

4935 # an 8-byte boundary." 

4936 # [MS-SMB2] 3.1.4.1 

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

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

4939 # computation." 

4940 length = len(pkt[SMB2_Header]) 

4941 padlen = (-length) % 8 

4942 if padlen: 

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

4944 pkt[SMB2_Header].NextCommand = length + padlen 

4945 if ( 

4946 self.Dialect 

4947 and self.SigningKey 

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

4949 ): 

4950 # [MS-SMB2] sect 3.2.4.1.1 - Signing 

4951 smb = pkt[SMB2_Header] 

4952 smb.Flags += "SMB2_FLAGS_SIGNED" 

4953 smb.sign( 

4954 self.Dialect, 

4955 self.SigningKey, 

4956 # SMB 3.1.1 parameters: 

4957 SigningAlgorithmId=self.SigningAlgorithmId, 

4958 IsClient=False, 

4959 ) 

4960 if Compounded: 

4961 # There IS a next compound. Store in queue 

4962 self.CompoundQueue.append(pkt) 

4963 return [] 

4964 else: 

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

4966 if self.CompoundQueue: 

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

4968 self.CompoundQueue.clear() 

4969 if self.EncryptionKey and ( 

4970 ForceEncrypt or self.EncryptData or self.TreeEncryptData 

4971 ): 

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

4973 smb = pkt[SMB2_Header] 

4974 assert not smb.Flags.SMB2_FLAGS_SIGNED 

4975 smbt = smb.encrypt( 

4976 self.Dialect, 

4977 self.EncryptionKey, 

4978 CipherId=self.CipherId, 

4979 ) 

4980 if smb.underlayer: 

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

4982 smb.underlayer.payload = smbt 

4983 else: 

4984 smb = smbt 

4985 return [pkt] 

4986 

4987 def process(self, pkt: Packet): 

4988 # Called when passively sniffing 

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

4990 if pkt is not None and SMB2_Header in pkt: 

4991 return self.in_pkt(pkt) 

4992 return pkt