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

1105 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 0x00000002: "ERROR_FILE_NOT_FOUND", 

96 0x00000005: "ERROR_ACCESS_DENIED", 

97 0x00000103: "STATUS_PENDING", 

98 0x0000010B: "STATUS_NOTIFY_CLEANUP", 

99 0x0000010C: "STATUS_NOTIFY_ENUM_DIR", 

100 0x00000532: "ERROR_PASSWORD_EXPIRED", 

101 0x00000533: "ERROR_ACCOUNT_DISABLED", 

102 0x000006FE: "ERROR_TRUST_FAILURE", 

103 0x80000005: "STATUS_BUFFER_OVERFLOW", 

104 0x80000006: "STATUS_NO_MORE_FILES", 

105 0x8000002D: "STATUS_STOPPED_ON_SYMLINK", 

106 0x80070005: "E_ACCESSDENIED", 

107 0x8007000E: "E_OUTOFMEMORY", 

108 0x80090308: "SEC_E_INVALID_TOKEN", 

109 0x8009030C: "SEC_E_LOGON_DENIED", 

110 0x8009030F: "SEC_E_MESSAGE_ALTERED", 

111 0x80090310: "SEC_E_OUT_OF_SEQUENCE", 

112 0x80090346: "SEC_E_BAD_BINDINGS", 

113 0x80090351: "SEC_E_SMARTCARD_CERT_REVOKED", 

114 0xC0000003: "STATUS_INVALID_INFO_CLASS", 

115 0xC0000004: "STATUS_INFO_LENGTH_MISMATCH", 

116 0xC000000D: "STATUS_INVALID_PARAMETER", 

117 0xC000000F: "STATUS_NO_SUCH_FILE", 

118 0xC0000016: "STATUS_MORE_PROCESSING_REQUIRED", 

119 0xC0000022: "STATUS_ACCESS_DENIED", 

120 0xC0000033: "STATUS_OBJECT_NAME_INVALID", 

121 0xC0000034: "STATUS_OBJECT_NAME_NOT_FOUND", 

122 0xC0000043: "STATUS_SHARING_VIOLATION", 

123 0xC0000061: "STATUS_PRIVILEGE_NOT_HELD", 

124 0xC0000064: "STATUS_NO_SUCH_USER", 

125 0xC000006D: "STATUS_LOGON_FAILURE", 

126 0xC000006E: "STATUS_ACCOUNT_RESTRICTION", 

127 0xC0000070: "STATUS_INVALID_WORKSTATION", 

128 0xC0000071: "STATUS_PASSWORD_EXPIRED", 

129 0xC0000072: "STATUS_ACCOUNT_DISABLED", 

130 0xC000009A: "STATUS_INSUFFICIENT_RESOURCES", 

131 0xC00000BA: "STATUS_FILE_IS_A_DIRECTORY", 

132 0xC00000BB: "STATUS_NOT_SUPPORTED", 

133 0xC00000C9: "STATUS_NETWORK_NAME_DELETED", 

134 0xC00000CC: "STATUS_BAD_NETWORK_NAME", 

135 0xC0000120: "STATUS_CANCELLED", 

136 0xC0000122: "STATUS_INVALID_COMPUTER_NAME", 

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

138 0xC000015B: "STATUS_LOGON_TYPE_NOT_GRANTED", 

139 0xC000018B: "STATUS_NO_TRUST_SAM_ACCOUNT", 

140 0xC000019C: "STATUS_FS_DRIVER_REQUIRED", 

141 0xC0000203: "STATUS_USER_SESSION_DELETED", 

142 0xC000020C: "STATUS_CONNECTION_DISCONNECTED", 

143 0xC0000225: "STATUS_NOT_FOUND", 

144 0xC0000257: "STATUS_PATH_NOT_COVERED", 

145 0xC000035C: "STATUS_NETWORK_SESSION_EXPIRED", 

146} 

147 

148# SMB2 sect 2.1.2.1 

149REPARSE_TAGS = { 

150 0x00000000: "IO_REPARSE_TAG_RESERVED_ZERO", 

151 0x00000001: "IO_REPARSE_TAG_RESERVED_ONE", 

152 0x00000002: "IO_REPARSE_TAG_RESERVED_TWO", 

153 0xA0000003: "IO_REPARSE_TAG_MOUNT_POINT", 

154 0xC0000004: "IO_REPARSE_TAG_HSM", 

155 0x80000005: "IO_REPARSE_TAG_DRIVE_EXTENDER", 

156 0x80000006: "IO_REPARSE_TAG_HSM2", 

157 0x80000007: "IO_REPARSE_TAG_SIS", 

158 0x80000008: "IO_REPARSE_TAG_WIM", 

159 0x80000009: "IO_REPARSE_TAG_CSV", 

160 0x8000000A: "IO_REPARSE_TAG_DFS", 

161 0x8000000B: "IO_REPARSE_TAG_FILTER_MANAGER", 

162 0xA000000C: "IO_REPARSE_TAG_SYMLINK", 

163 0xA0000010: "IO_REPARSE_TAG_IIS_CACHE", 

164 0x80000012: "IO_REPARSE_TAG_DFSR", 

165 0x80000013: "IO_REPARSE_TAG_DEDUP", 

166 0xC0000014: "IO_REPARSE_TAG_APPXSTRM", 

167 0x80000014: "IO_REPARSE_TAG_NFS", 

168 0x80000015: "IO_REPARSE_TAG_FILE_PLACEHOLDER", 

169 0x80000016: "IO_REPARSE_TAG_DFM", 

170 0x80000017: "IO_REPARSE_TAG_WOF", 

171 0x80000018: "IO_REPARSE_TAG_WCI", 

172 0x90001018: "IO_REPARSE_TAG_WCI_1", 

173 0xA0000019: "IO_REPARSE_TAG_GLOBAL_REPARSE", 

174 0x9000001A: "IO_REPARSE_TAG_CLOUD", 

175 0x9000101A: "IO_REPARSE_TAG_CLOUD_1", 

176 0x9000201A: "IO_REPARSE_TAG_CLOUD_2", 

177 0x9000301A: "IO_REPARSE_TAG_CLOUD_3", 

178 0x9000401A: "IO_REPARSE_TAG_CLOUD_4", 

179 0x9000501A: "IO_REPARSE_TAG_CLOUD_5", 

180 0x9000601A: "IO_REPARSE_TAG_CLOUD_6", 

181 0x9000701A: "IO_REPARSE_TAG_CLOUD_7", 

182 0x9000801A: "IO_REPARSE_TAG_CLOUD_8", 

183 0x9000901A: "IO_REPARSE_TAG_CLOUD_9", 

184 0x9000A01A: "IO_REPARSE_TAG_CLOUD_A", 

185 0x9000B01A: "IO_REPARSE_TAG_CLOUD_B", 

186 0x9000C01A: "IO_REPARSE_TAG_CLOUD_C", 

187 0x9000D01A: "IO_REPARSE_TAG_CLOUD_D", 

188 0x9000E01A: "IO_REPARSE_TAG_CLOUD_E", 

189 0x9000F01A: "IO_REPARSE_TAG_CLOUD_F", 

190 0x8000001B: "IO_REPARSE_TAG_APPEXECLINK", 

191 0x9000001C: "IO_REPARSE_TAG_PROJFS", 

192 0xA000001D: "IO_REPARSE_TAG_LX_SYMLINK", 

193 0x8000001E: "IO_REPARSE_TAG_STORAGE_SYNC", 

194 0xA000001F: "IO_REPARSE_TAG_WCI_TOMBSTONE", 

195 0x80000020: "IO_REPARSE_TAG_UNHANDLED", 

196 0x80000021: "IO_REPARSE_TAG_ONEDRIVE", 

197 0xA0000022: "IO_REPARSE_TAG_PROJFS_TOMBSTONE", 

198 0x80000023: "IO_REPARSE_TAG_AF_UNIX", 

199 0x80000024: "IO_REPARSE_TAG_LX_FIFO", 

200 0x80000025: "IO_REPARSE_TAG_LX_CHR", 

201 0x80000026: "IO_REPARSE_TAG_LX_BLK", 

202 0xA0000027: "IO_REPARSE_TAG_WCI_LINK", 

203 0xA0001027: "IO_REPARSE_TAG_WCI_LINK_1", 

204} 

205 

206# SMB2 sect 2.2.1.1 

207SMB2_COM = { 

208 0x0000: "SMB2_NEGOTIATE", 

209 0x0001: "SMB2_SESSION_SETUP", 

210 0x0002: "SMB2_LOGOFF", 

211 0x0003: "SMB2_TREE_CONNECT", 

212 0x0004: "SMB2_TREE_DISCONNECT", 

213 0x0005: "SMB2_CREATE", 

214 0x0006: "SMB2_CLOSE", 

215 0x0007: "SMB2_FLUSH", 

216 0x0008: "SMB2_READ", 

217 0x0009: "SMB2_WRITE", 

218 0x000A: "SMB2_LOCK", 

219 0x000B: "SMB2_IOCTL", 

220 0x000C: "SMB2_CANCEL", 

221 0x000D: "SMB2_ECHO", 

222 0x000E: "SMB2_QUERY_DIRECTORY", 

223 0x000F: "SMB2_CHANGE_NOTIFY", 

224 0x0010: "SMB2_QUERY_INFO", 

225 0x0011: "SMB2_SET_INFO", 

226 0x0012: "SMB2_OPLOCK_BREAK", 

227} 

228 

229# EnumField 

230SMB2_NEGOTIATE_CONTEXT_TYPES = { 

231 0x0001: "SMB2_PREAUTH_INTEGRITY_CAPABILITIES", 

232 0x0002: "SMB2_ENCRYPTION_CAPABILITIES", 

233 0x0003: "SMB2_COMPRESSION_CAPABILITIES", 

234 0x0005: "SMB2_NETNAME_NEGOTIATE_CONTEXT_ID", 

235 0x0006: "SMB2_TRANSPORT_CAPABILITIES", 

236 0x0007: "SMB2_RDMA_TRANSFORM_CAPABILITIES", 

237 0x0008: "SMB2_SIGNING_CAPABILITIES", 

238} 

239 

240# FlagField 

241SMB2_CAPABILITIES = { 

242 0x00000001: "DFS", 

243 0x00000002: "LEASING", 

244 0x00000004: "LARGE_MTU", 

245 0x00000008: "MULTI_CHANNEL", 

246 0x00000010: "PERSISTENT_HANDLES", 

247 0x00000020: "DIRECTORY_LEASING", 

248 0x00000040: "ENCRYPTION", 

249} 

250SMB2_SECURITY_MODE = { 

251 0x01: "SIGNING_ENABLED", 

252 0x02: "SIGNING_REQUIRED", 

253} 

254 

255# [MS-SMB2] 2.2.3.1.3 

256SMB2_COMPRESSION_ALGORITHMS = { 

257 0x0000: "None", 

258 0x0001: "LZNT1", 

259 0x0002: "LZ77", 

260 0x0003: "LZ77 + Huffman", 

261 0x0004: "Pattern_V1", 

262} 

263 

264# [MS-SMB2] sect 2.2.3.1.2 

265SMB2_ENCRYPTION_CIPHERS = { 

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

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

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

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

270} 

271 

272# [MS-SMB2] sect 2.2.3.1.7 

273SMB2_SIGNING_ALGORITHMS = { 

274 0x0000: "HMAC-SHA256", 

275 0x0001: "AES-CMAC", 

276 0x0002: "AES-GMAC", 

277} 

278 

279# [MS-SMB2] sect 2.2.3.1.1 

280SMB2_HASH_ALGORITHMS = { 

281 0x0001: "SHA-512", 

282} 

283 

284# sect [MS-SMB2] 2.2.13.1.1 

285SMB2_ACCESS_FLAGS_FILE = { 

286 0x00000001: "FILE_READ_DATA", 

287 0x00000002: "FILE_WRITE_DATA", 

288 0x00000004: "FILE_APPEND_DATA", 

289 0x00000008: "FILE_READ_EA", 

290 0x00000010: "FILE_WRITE_EA", 

291 0x00000040: "FILE_DELETE_CHILD", 

292 0x00000020: "FILE_EXECUTE", 

293 0x00000080: "FILE_READ_ATTRIBUTES", 

294 0x00000100: "FILE_WRITE_ATTRIBUTES", 

295 0x00010000: "DELETE", 

296 0x00020000: "READ_CONTROL", 

297 0x00040000: "WRITE_DAC", 

298 0x00080000: "WRITE_OWNER", 

299 0x00100000: "SYNCHRONIZE", 

300 0x01000000: "ACCESS_SYSTEM_SECURITY", 

301 0x02000000: "MAXIMUM_ALLOWED", 

302 0x10000000: "GENERIC_ALL", 

303 0x20000000: "GENERIC_EXECUTE", 

304 0x40000000: "GENERIC_WRITE", 

305 0x80000000: "GENERIC_READ", 

306} 

307 

308# sect [MS-SMB2] 2.2.13.1.2 

309SMB2_ACCESS_FLAGS_DIRECTORY = { 

310 0x00000001: "FILE_LIST_DIRECTORY", 

311 0x00000002: "FILE_ADD_FILE", 

312 0x00000004: "FILE_ADD_SUBDIRECTORY", 

313 0x00000008: "FILE_READ_EA", 

314 0x00000010: "FILE_WRITE_EA", 

315 0x00000020: "FILE_TRAVERSE", 

316 0x00000040: "FILE_DELETE_CHILD", 

317 0x00000080: "FILE_READ_ATTRIBUTES", 

318 0x00000100: "FILE_WRITE_ATTRIBUTES", 

319 0x00010000: "DELETE", 

320 0x00020000: "READ_CONTROL", 

321 0x00040000: "WRITE_DAC", 

322 0x00080000: "WRITE_OWNER", 

323 0x00100000: "SYNCHRONIZE", 

324 0x01000000: "ACCESS_SYSTEM_SECURITY", 

325 0x02000000: "MAXIMUM_ALLOWED", 

326 0x10000000: "GENERIC_ALL", 

327 0x20000000: "GENERIC_EXECUTE", 

328 0x40000000: "GENERIC_WRITE", 

329 0x80000000: "GENERIC_READ", 

330} 

331 

332# [MS-SRVS] sec 2.2.2.4 

333SRVSVC_SHARE_TYPES = { 

334 0x00000000: "DISKTREE", 

335 0x00000001: "PRINTQ", 

336 0x00000002: "DEVICE", 

337 0x00000003: "IPC", 

338 0x02000000: "CLUSTER_FS", 

339 0x04000000: "CLUSTER_SOFS", 

340 0x08000000: "CLUSTER_DFS", 

341} 

342 

343 

344# [MS-FSCC] sec 2.6 

345FileAttributes = { 

346 0x00000001: "FILE_ATTRIBUTE_READONLY", 

347 0x00000002: "FILE_ATTRIBUTE_HIDDEN", 

348 0x00000004: "FILE_ATTRIBUTE_SYSTEM", 

349 0x00000010: "FILE_ATTRIBUTE_DIRECTORY", 

350 0x00000020: "FILE_ATTRIBUTE_ARCHIVE", 

351 0x00000080: "FILE_ATTRIBUTE_NORMAL", 

352 0x00000100: "FILE_ATTRIBUTE_TEMPORARY", 

353 0x00000200: "FILE_ATTRIBUTE_SPARSE_FILE", 

354 0x00000400: "FILE_ATTRIBUTE_REPARSE_POINT", 

355 0x00000800: "FILE_ATTRIBUTE_COMPRESSED", 

356 0x00001000: "FILE_ATTRIBUTE_OFFLINE", 

357 0x00002000: "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED", 

358 0x00004000: "FILE_ATTRIBUTE_ENCRYPTED", 

359 0x00008000: "FILE_ATTRIBUTE_INTEGRITY_STREAM", 

360 0x00020000: "FILE_ATTRIBUTE_NO_SCRUB_DATA", 

361 0x00040000: "FILE_ATTRIBUTE_RECALL_ON_OPEN", 

362 0x00080000: "FILE_ATTRIBUTE_PINNED", 

363 0x00100000: "FILE_ATTRIBUTE_UNPINNED", 

364 0x00400000: "FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS", 

365} 

366 

367 

368# [MS-FSCC] sect 2.4 

369FileInformationClasses = { 

370 0x01: "FileDirectoryInformation", 

371 0x02: "FileFullDirectoryInformation", 

372 0x03: "FileBothDirectoryInformation", 

373 0x04: "FileBasicInformation", 

374 0x05: "FileStandardInformation", 

375 0x06: "FileInternalInformation", 

376 0x07: "FileEaInformation", 

377 0x08: "FileAccessInformation", 

378 0x0A: "FileRenameInformation", 

379 0x0E: "FilePositionInformation", 

380 0x10: "FileModeInformation", 

381 0x11: "FileAlignmentInformation", 

382 0x12: "FileAllInformation", 

383 0x22: "FileNetworkOpenInformation", 

384 0x25: "FileIdBothDirectoryInformation", 

385 0x26: "FileIdFullDirectoryInformation", 

386 0x0C: "FileNamesInformation", 

387 0x30: "FileNormalizedNameInformation", 

388 0x3C: "FileIdExtdDirectoryInformation", 

389} 

390_FileInformationClasses = {} 

391 

392 

393# [MS-FSCC] 2.1.7 FILE_NAME_INFORMATION 

394 

395 

396class FILE_NAME_INFORMATION(Packet): 

397 fields_desc = [ 

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

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

400 ] 

401 

402 def default_payload_class(self, s): 

403 return conf.padding_layer 

404 

405 

406# [MS-FSCC] 2.4.1 FileAccessInformation 

407 

408 

409class FileAccessInformation(Packet): 

410 fields_desc = [ 

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

412 ] 

413 

414 def default_payload_class(self, s): 

415 return conf.padding_layer 

416 

417 

418# [MS-FSCC] 2.4.3 FileAlignmentInformation 

419 

420 

421class FileAlignmentInformation(Packet): 

422 fields_desc = [ 

423 LEIntEnumField( 

424 "AccessFlags", 

425 0, 

426 { 

427 0x00000000: "FILE_BYTE_ALIGNMENT", 

428 0x00000001: "FILE_WORD_ALIGNMENT", 

429 0x00000003: "FILE_LONG_ALIGNMENT", 

430 0x00000007: "FILE_QUAD_ALIGNMENT", 

431 0x0000000F: "FILE_OCTA_ALIGNMENT", 

432 0x0000001F: "FILE_32_BYTE_ALIGNMENT", 

433 0x0000003F: "FILE_64_BYTE_ALIGNMENT", 

434 0x0000007F: "FILE_128_BYTE_ALIGNMENT", 

435 0x000000FF: "FILE_256_BYTE_ALIGNMENT", 

436 0x000001FF: "FILE_512_BYTE_ALIGNMENT", 

437 }, 

438 ), 

439 ] 

440 

441 def default_payload_class(self, s): 

442 return conf.padding_layer 

443 

444 

445# [MS-FSCC] 2.4.5 FileAlternateNameInformation 

446 

447 

448class FileAlternateNameInformation(Packet): 

449 fields_desc = [ 

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

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

452 ] 

453 

454 

455# [MS-FSCC] 2.4.7 FileBasicInformation 

456 

457 

458class FileBasicInformation(Packet): 

459 fields_desc = [ 

460 UTCTimeField( 

461 "CreationTime", 

462 None, 

463 fmt="<Q", 

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

465 custom_scaling=1e7, 

466 ), 

467 UTCTimeField( 

468 "LastAccessTime", 

469 None, 

470 fmt="<Q", 

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

472 custom_scaling=1e7, 

473 ), 

474 UTCTimeField( 

475 "LastWriteTime", 

476 None, 

477 fmt="<Q", 

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

479 custom_scaling=1e7, 

480 ), 

481 UTCTimeField( 

482 "ChangeTime", 

483 None, 

484 fmt="<Q", 

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

486 custom_scaling=1e7, 

487 ), 

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

489 IntField("Reserved", 0), 

490 ] 

491 

492 def default_payload_class(self, s): 

493 return conf.padding_layer 

494 

495 

496# [MS-FSCC] 2.4.12 FileEaInformation 

497 

498 

499class FileEaInformation(Packet): 

500 fields_desc = [ 

501 LEIntField("EaSize", 0), 

502 ] 

503 

504 def default_payload_class(self, s): 

505 return conf.padding_layer 

506 

507 

508# [MS-FSCC] 2.4.29 FileNetworkOpenInformation 

509 

510 

511class FileNetworkOpenInformation(Packet): 

512 fields_desc = [ 

513 UTCTimeField( 

514 "CreationTime", 

515 None, 

516 fmt="<Q", 

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

518 custom_scaling=1e7, 

519 ), 

520 UTCTimeField( 

521 "LastAccessTime", 

522 None, 

523 fmt="<Q", 

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

525 custom_scaling=1e7, 

526 ), 

527 UTCTimeField( 

528 "LastWriteTime", 

529 None, 

530 fmt="<Q", 

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

532 custom_scaling=1e7, 

533 ), 

534 UTCTimeField( 

535 "ChangeTime", 

536 None, 

537 fmt="<Q", 

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

539 custom_scaling=1e7, 

540 ), 

541 LELongField("AllocationSize", 4096), 

542 LELongField("EndOfFile", 0), 

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

544 IntField("Reserved2", 0), 

545 ] 

546 

547 def default_payload_class(self, s): 

548 return conf.padding_layer 

549 

550 

551# [MS-FSCC] 2.4.8 FileBothDirectoryInformation 

552 

553 

554class FILE_BOTH_DIR_INFORMATION(Packet): 

555 fields_desc = ( 

556 [ 

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

558 LEIntField("FileIndex", 0), 

559 ] 

560 + ( 

561 FileNetworkOpenInformation.fields_desc[:4] 

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

563 + [FileNetworkOpenInformation.fields_desc[6]] 

564 ) 

565 + [ 

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

567 MultipleTypeField( 

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

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

570 # 2.1.2.1." 

571 [ 

572 ( 

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

574 lambda pkt: pkt.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT, 

575 ) 

576 ], 

577 LEIntField("EaSize", 0), 

578 ), 

579 ByteField("ShortNameLength", 0), 

580 ByteField("Reserved1", 0), 

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

582 PadField( 

583 StrLenFieldUtf16( 

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

585 ), 

586 align=8, 

587 ), 

588 ] 

589 ) 

590 

591 def default_payload_class(self, s): 

592 return conf.padding_layer 

593 

594 

595class _NextPacketListField(PacketListField): 

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

597 # we use this field to set NextEntryOffset 

598 res = b"" 

599 for i, v in enumerate(val): 

600 x = self.i2m(pkt, v) 

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

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

603 res += x 

604 return s + res 

605 

606 

607class FileBothDirectoryInformation(Packet): 

608 fields_desc = [ 

609 _NextPacketListField( 

610 "files", 

611 [], 

612 FILE_BOTH_DIR_INFORMATION, 

613 max_count=1000, 

614 ), 

615 ] 

616 

617 

618# [MS-FSCC] 2.4.14 FileFullDirectoryInformation 

619 

620 

621class FILE_FULL_DIR_INFORMATION(Packet): 

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

623 FILE_BOTH_DIR_INFORMATION.fields_desc[-1] 

624 ] 

625 

626 

627class FileFullDirectoryInformation(Packet): 

628 fields_desc = [ 

629 _NextPacketListField( 

630 "files", 

631 [], 

632 FILE_FULL_DIR_INFORMATION, 

633 max_count=1000, 

634 ), 

635 ] 

636 

637 

638# [MS-FSCC] 2.4.17 FileIdBothDirectoryInformation 

639 

640 

641class FILE_ID_BOTH_DIR_INFORMATION(Packet): 

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

643 LEShortField("Reserved2", 0), 

644 LELongField("FileId", 0), 

645 FILE_BOTH_DIR_INFORMATION.fields_desc[-1], 

646 ] 

647 

648 def default_payload_class(self, s): 

649 return conf.padding_layer 

650 

651 

652class FileIdBothDirectoryInformation(Packet): 

653 fields_desc = [ 

654 _NextPacketListField( 

655 "files", 

656 [], 

657 FILE_ID_BOTH_DIR_INFORMATION, 

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

659 ), 

660 ] 

661 

662 

663# [MS-FSCC] 2.4.22 FileInternalInformation 

664 

665 

666class FileInternalInformation(Packet): 

667 fields_desc = [ 

668 LELongField("IndexNumber", 0), 

669 ] 

670 

671 def default_payload_class(self, s): 

672 return conf.padding_layer 

673 

674 

675# [MS-FSCC] 2.4.26 FileModeInformation 

676 

677 

678class FileModeInformation(Packet): 

679 fields_desc = [ 

680 FlagsField( 

681 "Mode", 

682 0, 

683 -32, 

684 { 

685 0x00000002: "FILE_WRITE_TROUGH", 

686 0x00000004: "FILE_SEQUENTIAL_ONLY", 

687 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING", 

688 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT", 

689 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT", 

690 0x00001000: "FILE_DELETE_ON_CLOSE", 

691 }, 

692 ) 

693 ] 

694 

695 def default_payload_class(self, s): 

696 return conf.padding_layer 

697 

698 

699# [MS-FSCC] 2.4.35 FilePositionInformation 

700 

701 

702class FilePositionInformation(Packet): 

703 fields_desc = [ 

704 LELongField("CurrentByteOffset", 0), 

705 ] 

706 

707 def default_payload_class(self, s): 

708 return conf.padding_layer 

709 

710 

711# [MS-FSCC] 2.4.37 FileRenameInformation 

712 

713 

714class FileRenameInformation(Packet): 

715 fields_desc = [ 

716 YesNoByteField("ReplaceIfExists", False), 

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

718 LELongField("RootDirectory", 0), 

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

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

721 ] 

722 

723 def post_build(self, pkt, pay): 

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

725 if len(pkt) < 24: 

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

727 # size of this structure at least 24.' 

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

729 return pkt + pay 

730 

731 def default_payload_class(self, s): 

732 return conf.padding_layer 

733 

734 

735_FileInformationClasses[0x0A] = FileRenameInformation 

736 

737 

738# [MS-FSCC] 2.4.41 FileStandardInformation 

739 

740 

741class FileStandardInformation(Packet): 

742 fields_desc = [ 

743 LELongField("AllocationSize", 4096), 

744 LELongField("EndOfFile", 0), 

745 LEIntField("NumberOfLinks", 1), 

746 ByteField("DeletePending", 0), 

747 ByteField("Directory", 0), 

748 ShortField("Reserved", 0), 

749 ] 

750 

751 def default_payload_class(self, s): 

752 return conf.padding_layer 

753 

754 

755# [MS-FSCC] 2.4.43 FileStreamInformation 

756 

757 

758class FileStreamInformation(Packet): 

759 fields_desc = [ 

760 LEIntField("Next", 0), 

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

762 LELongField("StreamSize", 0), 

763 LELongField("StreamAllocationSize", 4096), 

764 StrLenFieldUtf16( 

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

766 ), 

767 ] 

768 

769 

770# [MS-DTYP] sect 2.4.1 

771 

772 

773class WINNT_SID_IDENTIFIER_AUTHORITY(Packet): 

774 fields_desc = [ 

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

776 ] 

777 

778 def default_payload_class(self, payload): 

779 return conf.padding_layer 

780 

781 

782# [MS-DTYP] sect 2.4.2 

783 

784 

785class WINNT_SID(Packet): 

786 fields_desc = [ 

787 ByteField("Revision", 1), 

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

789 PacketField( 

790 "IdentifierAuthority", 

791 WINNT_SID_IDENTIFIER_AUTHORITY(), 

792 WINNT_SID_IDENTIFIER_AUTHORITY, 

793 ), 

794 FieldListField( 

795 "SubAuthority", 

796 [0], 

797 LEIntField("", 0), 

798 count_from=lambda pkt: pkt.SubAuthorityCount, 

799 ), 

800 ] 

801 

802 def default_payload_class(self, payload): 

803 return conf.padding_layer 

804 

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

806 

807 @staticmethod 

808 def fromstr(x): 

809 m = WINNT_SID._SID_REG.match(x) 

810 if not m: 

811 raise ValueError("Invalid SID format !") 

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

813 return WINNT_SID( 

814 Revision=int(rev), 

815 IdentifierAuthority=WINNT_SID_IDENTIFIER_AUTHORITY( 

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

817 ), 

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

819 ) 

820 

821 def summary(self): 

822 return "S-%s-%s%s" % ( 

823 self.Revision, 

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

825 ( 

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

827 if self.SubAuthority 

828 else "" 

829 ), 

830 ) 

831 

832 

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

834 

835WELL_KNOWN_SIDS = { 

836 # Universal well-known SID 

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

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

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

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

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

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

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

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

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

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

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

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

849 # NT well-known SIDs 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

907} 

908 

909 

910# [MS-DTYP] sect 2.4.3 

911 

912_WINNT_ACCESS_MASK = { 

913 0x80000000: "GENERIC_READ", 

914 0x40000000: "GENERIC_WRITE", 

915 0x20000000: "GENERIC_EXECUTE", 

916 0x10000000: "GENERIC_ALL", 

917 0x02000000: "MAXIMUM_ALLOWED", 

918 0x01000000: "ACCESS_SYSTEM_SECURITY", 

919 0x00100000: "SYNCHRONIZE", 

920 0x00080000: "WRITE_OWNER", 

921 0x00040000: "WRITE_DACL", 

922 0x00020000: "READ_CONTROL", 

923 0x00010000: "DELETE", 

924} 

925 

926 

927# [MS-DTYP] sect 2.4.4.1 

928 

929 

930WINNT_ACE_FLAGS = { 

931 0x01: "OBJECT_INHERIT", 

932 0x02: "CONTAINER_INHERIT", 

933 0x04: "NO_PROPAGATE_INHERIT", 

934 0x08: "INHERIT_ONLY", 

935 0x10: "INHERITED_ACE", 

936 0x40: "SUCCESSFUL_ACCESS", 

937 0x80: "FAILED_ACCESS", 

938} 

939 

940 

941class WINNT_ACE_HEADER(Packet): 

942 fields_desc = [ 

943 ByteEnumField( 

944 "AceType", 

945 0, 

946 { 

947 0x00: "ACCESS_ALLOWED", 

948 0x01: "ACCESS_DENIED", 

949 0x02: "SYSTEM_AUDIT", 

950 0x03: "SYSTEM_ALARM", 

951 0x04: "ACCESS_ALLOWED_COMPOUND", 

952 0x05: "ACCESS_ALLOWED_OBJECT", 

953 0x06: "ACCESS_DENIED_OBJECT", 

954 0x07: "SYSTEM_AUDIT_OBJECT", 

955 0x08: "SYSTEM_ALARM_OBJECT", 

956 0x09: "ACCESS_ALLOWED_CALLBACK", 

957 0x0A: "ACCESS_DENIED_CALLBACK", 

958 0x0B: "ACCESS_ALLOWED_CALLBACK_OBJECT", 

959 0x0C: "ACCESS_DENIED_CALLBACK_OBJECT", 

960 0x0D: "SYSTEM_AUDIT_CALLBACK", 

961 0x0E: "SYSTEM_ALARM_CALLBACK", 

962 0x0F: "SYSTEM_AUDIT_CALLBACK_OBJECT", 

963 0x10: "SYSTEM_ALARM_CALLBACK_OBJECT", 

964 0x11: "SYSTEM_MANDATORY_LABEL", 

965 0x12: "SYSTEM_RESOURCE_ATTRIBUTE", 

966 0x13: "SYSTEM_SCOPED_POLICY_ID", 

967 }, 

968 ), 

969 FlagsField( 

970 "AceFlags", 

971 0, 

972 8, 

973 WINNT_ACE_FLAGS, 

974 ), 

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

976 ] 

977 

978 def extract_padding(self, p): 

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

980 

981 # fmt: off 

982 def extractData(self, accessMask=None): 

983 """ 

984 Return the ACE data as usable data. 

985 

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

987 """ 

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

989 mask = self.payload.Mask 

990 if accessMask is not None: 

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

992 ace_flag_string = str( 

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

994 ) 

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

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

997 # ApplicationData -> conditional expression 

998 cond_expr = None 

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

1000 # Parse tokens 

1001 res = [] 

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

1003 if ct.TokenType in [ 

1004 # binary operators 

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

1006 0xa0, 0xa1 

1007 ]: 

1008 t1 = res.pop(-1) 

1009 t0 = res.pop(-1) 

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

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

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

1013 else: 

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

1015 elif ct.TokenType in [ 

1016 # unary operators 

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

1018 ]: 

1019 t0 = res.pop(-1) 

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

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

1022 elif ct.TokenType in [ 

1023 # values 

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

1025 0xfa, 0xfb 

1026 ]: 

1027 def lit(ct): 

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

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

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

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

1032 else: 

1033 return str(ct.value) 

1034 res.append(lit(ct)) 

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

1036 pass 

1037 else: 

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

1039 if len(res) != 1: 

1040 raise ValueError("Incomplete SDDL !") 

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

1042 return { 

1043 "ace-flags-string": ace_flag_string, 

1044 "sid-string": sid_string, 

1045 "mask": mask, 

1046 "object-guid": object_guid, 

1047 "inherited-object-guid": inherit_object_guid, 

1048 "cond-expr": cond_expr, 

1049 } 

1050 # fmt: on 

1051 

1052 def toSDDL(self, accessMask=None): 

1053 """ 

1054 Return SDDL 

1055 """ 

1056 data = self.extractData(accessMask=accessMask) 

1057 ace_rights = "" # TODO 

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

1059 conditional_ace_type = { 

1060 0x09: "XA", 

1061 0x0A: "XD", 

1062 0x0B: "XU", 

1063 0x0D: "ZA", 

1064 }[self.AceType] 

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

1066 ";".join( 

1067 x 

1068 for x in [ 

1069 conditional_ace_type, 

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

1071 ace_rights, 

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

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

1074 data["sid-string"], 

1075 data["cond-expr"], 

1076 ] 

1077 if x is not None 

1078 ) 

1079 ) 

1080 else: 

1081 ace_type = { 

1082 0x00: "A", 

1083 0x01: "D", 

1084 0x02: "AU", 

1085 0x05: "OA", 

1086 0x06: "OD", 

1087 0x07: "OU", 

1088 0x11: "ML", 

1089 0x13: "SP", 

1090 }[self.AceType] 

1091 return "(%s)" % ( 

1092 ";".join( 

1093 x 

1094 for x in [ 

1095 ace_type, 

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

1097 ace_rights, 

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

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

1100 data["sid-string"], 

1101 data["cond-expr"], 

1102 ] 

1103 if x is not None 

1104 ) 

1105 ) 

1106 

1107 

1108# [MS-DTYP] sect 2.4.4.2 

1109 

1110 

1111class WINNT_ACCESS_ALLOWED_ACE(Packet): 

1112 fields_desc = [ 

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

1114 PacketField("Sid", WINNT_SID(), WINNT_SID), 

1115 ] 

1116 

1117 

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

1119 

1120 

1121# [MS-DTYP] sect 2.4.4.3 

1122 

1123 

1124class WINNT_ACCESS_ALLOWED_OBJECT_ACE(Packet): 

1125 fields_desc = [ 

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

1127 FlagsField( 

1128 "Flags", 

1129 0, 

1130 -32, 

1131 { 

1132 0x00000001: "OBJECT_TYPE_PRESENT", 

1133 0x00000002: "INHERITED_OBJECT_TYPE_PRESENT", 

1134 }, 

1135 ), 

1136 ConditionalField( 

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

1138 lambda pkt: pkt.Flags.OBJECT_TYPE_PRESENT, 

1139 ), 

1140 ConditionalField( 

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

1142 lambda pkt: pkt.Flags.INHERITED_OBJECT_TYPE_PRESENT, 

1143 ), 

1144 PacketField("Sid", WINNT_SID(), WINNT_SID), 

1145 ] 

1146 

1147 

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

1149 

1150 

1151# [MS-DTYP] sect 2.4.4.4 

1152 

1153 

1154class WINNT_ACCESS_DENIED_ACE(Packet): 

1155 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

1156 

1157 

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

1159 

1160 

1161# [MS-DTYP] sect 2.4.4.5 

1162 

1163 

1164class WINNT_ACCESS_DENIED_OBJECT_ACE(Packet): 

1165 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc 

1166 

1167 

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

1169 

1170 

1171# [MS-DTYP] sect 2.4.4.17.4+ 

1172 

1173 

1174class WINNT_APPLICATION_DATA_LITERAL_TOKEN(Packet): 

1175 def default_payload_class(self, payload): 

1176 return conf.padding_layer 

1177 

1178 

1179# fmt: off 

1180WINNT_APPLICATION_DATA_LITERAL_TOKEN.fields_desc = [ 

1181 ByteEnumField( 

1182 "TokenType", 

1183 0, 

1184 { 

1185 # [MS-DTYP] sect 2.4.4.17.5 

1186 0x00: "Padding token", 

1187 0x01: "Signed int8", 

1188 0x02: "Signed int16", 

1189 0x03: "Signed int32", 

1190 0x04: "Signed int64", 

1191 0x10: "Unicode", 

1192 0x18: "Octet String", 

1193 0x50: "Composite", 

1194 0x51: "SID", 

1195 # [MS-DTYP] sect 2.4.4.17.6 

1196 0x80: "==", 

1197 0x81: "!=", 

1198 0x82: "<", 

1199 0x83: "<=", 

1200 0x84: ">", 

1201 0x85: ">=", 

1202 0x86: "Contains", 

1203 0x88: "Any_of", 

1204 0x8e: "Not_Contains", 

1205 0x8f: "Not_Any_of", 

1206 0x89: "Member_of", 

1207 0x8a: "Device_Member_of", 

1208 0x8b: "Member_of_Any", 

1209 0x8c: "Device_Member_of_Any", 

1210 0x90: "Not_Member_of", 

1211 0x91: "Not_Device_Member_of", 

1212 0x92: "Not_Member_of_Any", 

1213 0x93: "Not_Device_Member_of_Any", 

1214 # [MS-DTYP] sect 2.4.4.17.7 

1215 0x87: "Exists", 

1216 0x8d: "Not_Exists", 

1217 0xa0: "&&", 

1218 0xa1: "||", 

1219 0xa2: "!", 

1220 # [MS-DTYP] sect 2.4.4.17.8 

1221 0xf8: "Local attribute", 

1222 0xf9: "User Attribute", 

1223 0xfa: "Resource Attribute", 

1224 0xfb: "Device Attribute", 

1225 } 

1226 ), 

1227 ConditionalField( 

1228 # Strings 

1229 LEIntField("length", 0), 

1230 lambda pkt: pkt.TokenType in [ 

1231 0x10, # Unicode string 

1232 0x18, # Octet string 

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

1234 0x50, # Composite 

1235 ] 

1236 ), 

1237 ConditionalField( 

1238 MultipleTypeField( 

1239 [ 

1240 ( 

1241 LELongField("value", 0), 

1242 lambda pkt: pkt.TokenType in [ 

1243 0x01, # signed int8 

1244 0x02, # signed int16 

1245 0x03, # signed int32 

1246 0x04, # signed int64 

1247 ] 

1248 ), 

1249 ( 

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

1251 lambda pkt: pkt.TokenType in [ 

1252 0x10, # Unicode string 

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

1254 ] 

1255 ), 

1256 ( 

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

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

1259 ), 

1260 ( 

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

1262 length_from=lambda pkt: pkt.length), 

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

1264 ), 

1265 

1266 ], 

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

1268 ), 

1269 lambda pkt: pkt.TokenType in [ 

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

1271 ] 

1272 ), 

1273 ConditionalField( 

1274 # Literal 

1275 ByteEnumField("sign", 0, { 

1276 0x01: "+", 

1277 0x02: "-", 

1278 0x03: "None", 

1279 }), 

1280 lambda pkt: pkt.TokenType in [ 

1281 0x01, # signed int8 

1282 0x02, # signed int16 

1283 0x03, # signed int32 

1284 0x04, # signed int64 

1285 ] 

1286 ), 

1287 ConditionalField( 

1288 # Literal 

1289 ByteEnumField("base", 0, { 

1290 0x01: "Octal", 

1291 0x02: "Decimal", 

1292 0x03: "Hexadecimal", 

1293 }), 

1294 lambda pkt: pkt.TokenType in [ 

1295 0x01, # signed int8 

1296 0x02, # signed int16 

1297 0x03, # signed int32 

1298 0x04, # signed int64 

1299 ] 

1300 ), 

1301] 

1302# fmt: on 

1303 

1304 

1305class WINNT_APPLICATION_DATA(Packet): 

1306 fields_desc = [ 

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

1308 PacketListField( 

1309 "Tokens", 

1310 [], 

1311 WINNT_APPLICATION_DATA_LITERAL_TOKEN, 

1312 ), 

1313 ] 

1314 

1315 def default_payload_class(self, payload): 

1316 return conf.padding_layer 

1317 

1318 

1319# [MS-DTYP] sect 2.4.4.6 

1320 

1321 

1322class WINNT_ACCESS_ALLOWED_CALLBACK_ACE(Packet): 

1323 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [ 

1324 PacketField( 

1325 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

1326 ), 

1327 ] 

1328 

1329 

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

1331 

1332 

1333# [MS-DTYP] sect 2.4.4.7 

1334 

1335 

1336class WINNT_ACCESS_DENIED_CALLBACK_ACE(Packet): 

1337 fields_desc = WINNT_ACCESS_ALLOWED_CALLBACK_ACE.fields_desc 

1338 

1339 

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

1341 

1342 

1343# [MS-DTYP] sect 2.4.4.8 

1344 

1345 

1346class WINNT_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE(Packet): 

1347 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc + [ 

1348 PacketField( 

1349 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

1350 ), 

1351 ] 

1352 

1353 

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

1355 

1356 

1357# [MS-DTYP] sect 2.4.4.9 

1358 

1359 

1360class WINNT_ACCESS_DENIED_CALLBACK_OBJECT_ACE(Packet): 

1361 fields_desc = WINNT_ACCESS_DENIED_OBJECT_ACE.fields_desc + [ 

1362 PacketField( 

1363 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

1364 ), 

1365 ] 

1366 

1367 

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

1369 

1370 

1371# [MS-DTYP] sect 2.4.4.10 

1372 

1373 

1374class WINNT_SYSTEM_AUDIT_ACE(Packet): 

1375 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

1376 

1377 

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

1379 

1380 

1381# [MS-DTYP] sect 2.4.4.11 

1382 

1383 

1384class WINNT_SYSTEM_AUDIT_OBJECT_ACE(Packet): 

1385 # doc is wrong. 

1386 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc 

1387 

1388 

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

1390 

1391 

1392# [MS-DTYP] sect 2.4.4.12 

1393 

1394 

1395class WINNT_SYSTEM_AUDIT_CALLBACK_ACE(Packet): 

1396 fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc + [ 

1397 PacketField( 

1398 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

1399 ), 

1400 ] 

1401 

1402 

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

1404 

1405 

1406# [MS-DTYP] sect 2.4.4.13 

1407 

1408 

1409class WINNT_SYSTEM_MANDATORY_LABEL_ACE(Packet): 

1410 fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc 

1411 

1412 

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

1414 

1415 

1416# [MS-DTYP] sect 2.4.4.14 

1417 

1418 

1419class WINNT_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE(Packet): 

1420 fields_desc = WINNT_SYSTEM_AUDIT_OBJECT_ACE.fields_desc 

1421 

1422 

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

1424 

1425# [MS-DTYP] sect 2.4.10.1 

1426 

1427 

1428class CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(_NTLMPayloadPacket): 

1429 _NTLM_PAYLOAD_FIELD_NAME = "Data" 

1430 fields_desc = [ 

1431 LEIntField("NameOffset", 0), 

1432 LEShortEnumField( 

1433 "ValueType", 

1434 0, 

1435 { 

1436 0x0001: "CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64", 

1437 0x0002: "CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64", 

1438 0x0003: "CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING", 

1439 0x0005: "CLAIM_SECURITY_ATTRIBUTE_TYPE_SID", 

1440 0x0006: "CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN", 

1441 0x0010: "CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING", 

1442 }, 

1443 ), 

1444 LEShortField("Reserved", 0), 

1445 FlagsField( 

1446 "Flags", 

1447 0, 

1448 -32, 

1449 { 

1450 0x0001: "CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE", 

1451 0x0002: "CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE", 

1452 0x0004: "CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY", 

1453 0x0008: "CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT", 

1454 0x0010: "CLAIM_SECURITY_ATTRIBUTE_DISABLED", 

1455 0x0020: "CLAIM_SECURITY_ATTRIBUTE_MANDATORY", 

1456 }, 

1457 ), 

1458 LEIntField("ValueCount", 0), 

1459 FieldListField( 

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

1461 ), 

1462 _NTLMPayloadField( 

1463 "Data", 

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

1465 [ 

1466 ConditionalField( 

1467 StrFieldUtf16("Name", b""), 

1468 lambda pkt: pkt.NameOffset, 

1469 ), 

1470 # TODO: Values 

1471 ], 

1472 offset_name="Offset", 

1473 ), 

1474 ] 

1475 

1476 

1477# [MS-DTYP] sect 2.4.4.15 

1478 

1479 

1480class WINNT_SYSTEM_RESOURCE_ATTRIBUTE_ACE(Packet): 

1481 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [ 

1482 PacketField( 

1483 "AttributeData", 

1484 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(), 

1485 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1, 

1486 ) 

1487 ] 

1488 

1489 

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

1491 

1492# [MS-DTYP] sect 2.4.4.16 

1493 

1494 

1495class WINNT_SYSTEM_SCOPED_POLICY_ID_ACE(Packet): 

1496 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

1497 

1498 

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

1500 

1501# [MS-DTYP] sect 2.4.5 

1502 

1503 

1504class WINNT_ACL(Packet): 

1505 fields_desc = [ 

1506 ByteField("AclRevision", 2), 

1507 ByteField("Sbz1", 0x00), 

1508 FieldLenField( 

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

1510 ), 

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

1512 ShortField("Sbz2", 0), 

1513 PacketListField( 

1514 "Aces", 

1515 [], 

1516 WINNT_ACE_HEADER, 

1517 count_from=lambda pkt: pkt.AceCount, 

1518 ), 

1519 ] 

1520 

1521 def toSDDL(self): 

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

1523 

1524 

1525# [MS-DTYP] 2.4.6 SECURITY_DESCRIPTOR 

1526 

1527 

1528class SECURITY_DESCRIPTOR(_NTLMPayloadPacket): 

1529 OFFSET = 20 

1530 _NTLM_PAYLOAD_FIELD_NAME = "Data" 

1531 fields_desc = [ 

1532 ByteField("Revision", 0x01), 

1533 ByteField("Sbz1", 0x00), 

1534 FlagsField( 

1535 "Control", 

1536 0x00, 

1537 -16, 

1538 [ 

1539 "OWNER_DEFAULTED", 

1540 "GROUP_DEFAULTED", 

1541 "DACL_PRESENT", 

1542 "DACL_DEFAULTED", 

1543 "SACL_PRESENT", 

1544 "SACL_DEFAULTED", 

1545 "DACL_TRUSTED", 

1546 "SERVER_SECURITY", 

1547 "DACL_COMPUTED", 

1548 "SACL_COMPUTED", 

1549 "DACL_AUTO_INHERITED", 

1550 "SACL_AUTO_INHERITED", 

1551 "DACL_PROTECTED", 

1552 "SACL_PROTECTED", 

1553 "RM_CONTROL_VALID", 

1554 "SELF_RELATIVE", 

1555 ], 

1556 ), 

1557 LEIntField("OwnerSidOffset", None), 

1558 LEIntField("GroupSidOffset", None), 

1559 LEIntField("SACLOffset", None), 

1560 LEIntField("DACLOffset", None), 

1561 _NTLMPayloadField( 

1562 "Data", 

1563 OFFSET, 

1564 [ 

1565 ConditionalField( 

1566 PacketField("OwnerSid", WINNT_SID(), WINNT_SID), 

1567 lambda pkt: pkt.OwnerSidOffset != 0, 

1568 ), 

1569 ConditionalField( 

1570 PacketField("GroupSid", WINNT_SID(), WINNT_SID), 

1571 lambda pkt: pkt.GroupSidOffset != 0, 

1572 ), 

1573 ConditionalField( 

1574 PacketField("SACL", WINNT_ACL(), WINNT_ACL), 

1575 lambda pkt: pkt.Control.SACL_PRESENT, 

1576 ), 

1577 ConditionalField( 

1578 PacketField("DACL", WINNT_ACL(), WINNT_ACL), 

1579 lambda pkt: pkt.Control.DACL_PRESENT, 

1580 ), 

1581 ], 

1582 offset_name="Offset", 

1583 ), 

1584 ] 

1585 

1586 def post_build(self, pkt, pay): 

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

1588 return ( 

1589 _NTLM_post_build( 

1590 self, 

1591 pkt, 

1592 self.OFFSET, 

1593 { 

1594 "OwnerSid": 4, 

1595 "GroupSid": 8, 

1596 "SACL": 12, 

1597 "DACL": 16, 

1598 }, 

1599 config=[ 

1600 ("Offset", _NTLM_ENUM.OFFSET), 

1601 ], 

1602 ) 

1603 + pay 

1604 ) 

1605 

1606 

1607# [MS-FSCC] 2.4.2 FileAllInformation 

1608 

1609 

1610class FileAllInformation(Packet): 

1611 fields_desc = [ 

1612 PacketField("BasicInformation", FileBasicInformation(), FileBasicInformation), 

1613 PacketField( 

1614 "StandardInformation", FileStandardInformation(), FileStandardInformation 

1615 ), 

1616 PacketField( 

1617 "InternalInformation", FileInternalInformation(), FileInternalInformation 

1618 ), 

1619 PacketField("EaInformation", FileEaInformation(), FileEaInformation), 

1620 PacketField( 

1621 "AccessInformation", FileAccessInformation(), FileAccessInformation 

1622 ), 

1623 PacketField( 

1624 "PositionInformation", FilePositionInformation(), FilePositionInformation 

1625 ), 

1626 PacketField("ModeInformation", FileModeInformation(), FileModeInformation), 

1627 PacketField( 

1628 "AlignmentInformation", FileAlignmentInformation(), FileAlignmentInformation 

1629 ), 

1630 PacketField("NameInformation", FILE_NAME_INFORMATION(), FILE_NAME_INFORMATION), 

1631 ] 

1632 

1633 

1634# [MS-FSCC] 2.5.1 FileFsAttributeInformation 

1635 

1636 

1637class FileFsAttributeInformation(Packet): 

1638 fields_desc = [ 

1639 FlagsField( 

1640 "FileSystemAttributes", 

1641 0x00C706FF, 

1642 -32, 

1643 { 

1644 0x02000000: "FILE_SUPPORTS_USN_JOURNAL", 

1645 0x01000000: "FILE_SUPPORTS_OPEN_BY_FILE_ID", 

1646 0x00800000: "FILE_SUPPORTS_EXTENDED_ATTRIBUTES", 

1647 0x00400000: "FILE_SUPPORTS_HARD_LINKS", 

1648 0x00200000: "FILE_SUPPORTS_TRANSACTIONS", 

1649 0x00100000: "FILE_SEQUENTIAL_WRITE_ONCE", 

1650 0x00080000: "FILE_READ_ONLY_VOLUME", 

1651 0x00040000: "FILE_NAMED_STREAMS", 

1652 0x00020000: "FILE_SUPPORTS_ENCRYPTION", 

1653 0x00010000: "FILE_SUPPORTS_OBJECT_IDS", 

1654 0x00008000: "FILE_VOLUME_IS_COMPRESSED", 

1655 0x00000100: "FILE_SUPPORTS_REMOTE_STORAGE", 

1656 0x00000080: "FILE_SUPPORTS_REPARSE_POINTS", 

1657 0x00000040: "FILE_SUPPORTS_SPARSE_FILES", 

1658 0x00000020: "FILE_VOLUME_QUOTAS", 

1659 0x00000010: "FILE_FILE_COMPRESSION", 

1660 0x00000008: "FILE_PERSISTENT_ACLS", 

1661 0x00000004: "FILE_UNICODE_ON_DISK", 

1662 0x00000002: "FILE_CASE_PRESERVED_NAMES", 

1663 0x00000001: "FILE_CASE_SENSITIVE_SEARCH", 

1664 0x04000000: "FILE_SUPPORT_INTEGRITY_STREAMS", 

1665 0x08000000: "FILE_SUPPORTS_BLOCK_REFCOUNTING", 

1666 0x10000000: "FILE_SUPPORTS_SPARSE_VDL", 

1667 }, 

1668 ), 

1669 LEIntField("MaximumComponentNameLength", 255), 

1670 FieldLenField( 

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

1672 ), 

1673 StrLenFieldUtf16( 

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

1675 ), 

1676 ] 

1677 

1678 

1679# [MS-FSCC] 2.5.8 FileFsSizeInformation 

1680 

1681 

1682class FileFsSizeInformation(Packet): 

1683 fields_desc = [ 

1684 LELongField("TotalAllocationUnits", 10485760), 

1685 LELongField("AvailableAllocationUnits", 1048576), 

1686 LEIntField("SectorsPerAllocationUnit", 8), 

1687 LEIntField("BytesPerSector", 512), 

1688 ] 

1689 

1690 

1691# [MS-FSCC] 2.5.9 FileFsVolumeInformation 

1692 

1693 

1694class FileFsVolumeInformation(Packet): 

1695 fields_desc = [ 

1696 UTCTimeField( 

1697 "VolumeCreationTime", 

1698 None, 

1699 fmt="<Q", 

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

1701 custom_scaling=1e7, 

1702 ), 

1703 LEIntField("VolumeSerialNumber", 0), 

1704 LEIntField("VolumeLabelLength", 0), 

1705 ByteField("SupportsObjects", 1), 

1706 ByteField("Reserved", 0), 

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

1708 ] 

1709 

1710 

1711# [MS-FSCC] 2.7.1 FILE_NOTIFY_INFORMATION 

1712 

1713 

1714class FILE_NOTIFY_INFORMATION(Packet): 

1715 fields_desc = [ 

1716 IntField("NextEntryOffset", 0), 

1717 LEIntEnumField( 

1718 "Action", 

1719 0, 

1720 { 

1721 0x00000001: "FILE_ACTION_ADDED", 

1722 0x00000002: "FILE_ACTION_REMOVED", 

1723 0x00000003: "FILE_ACTION_MODIFIED", 

1724 0x00000004: "FILE_ACTION_RENAMED_OLD_NAME", 

1725 0x00000005: "FILE_ACTION_RENAMED_NEW_NAME", 

1726 0x00000006: "FILE_ACTION_ADDED_STREAM", 

1727 0x00000007: "FILE_ACTION_REMOVED_STREAM", 

1728 0x00000008: "FILE_ACTION_MODIFIED_STREAM", 

1729 0x00000009: "FILE_ACTION_REMOVED_BY_DELETE", 

1730 0x0000000A: "FILE_ACTION_ID_NOT_TUNNELLED", 

1731 0x0000000B: "FILE_ACTION_TUNNELLED_ID_COLLISION", 

1732 }, 

1733 ), 

1734 FieldLenField( 

1735 "FileNameLength", 

1736 None, 

1737 length_of="FileName", 

1738 fmt="<I", 

1739 ), 

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

1741 StrLenField( 

1742 "pad", 

1743 b"", 

1744 length_from=lambda x: ( 

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

1746 ), 

1747 ), 

1748 ] 

1749 

1750 def default_payload_class(self, s): 

1751 return conf.padding_layer 

1752 

1753 

1754_SMB2_CONFIG = [ 

1755 ("BufferOffset", _NTLM_ENUM.OFFSET), 

1756 ("Len", _NTLM_ENUM.LEN), 

1757] 

1758 

1759 

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

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

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

1763 

1764 

1765# SMB2 sect 2.1 

1766 

1767 

1768class DirectTCP(NBTSession): 

1769 name = "Direct TCP" 

1770 MAXLENGTH = 0xFFFFFF 

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

1772 

1773 

1774# SMB2 sect 2.2.1.1 

1775 

1776 

1777class SMB2_Header(Packet): 

1778 __slots__ = ["_decrypted"] 

1779 

1780 name = "SMB2 Header" 

1781 fields_desc = [ 

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

1783 LEShortField("StructureSize", 64), 

1784 LEShortField("CreditCharge", 0), 

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

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

1787 LEShortField("CreditRequest", 0), 

1788 FlagsField( 

1789 "Flags", 

1790 0, 

1791 -32, 

1792 { 

1793 0x00000001: "SMB2_FLAGS_SERVER_TO_REDIR", 

1794 0x00000002: "SMB2_FLAGS_ASYNC_COMMAND", 

1795 0x00000004: "SMB2_FLAGS_RELATED_OPERATIONS", 

1796 0x00000008: "SMB2_FLAGS_SIGNED", 

1797 0x10000000: "SMB2_FLAGS_DFS_OPERATIONS", 

1798 0x20000000: "SMB2_FLAGS_REPLAY_OPERATION", 

1799 }, 

1800 ), 

1801 XLEIntField("NextCommand", 0), 

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

1803 # ASYNC 

1804 ConditionalField( 

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

1806 ), 

1807 # SYNC 

1808 ConditionalField( 

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

1810 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND, 

1811 ), 

1812 ConditionalField( 

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

1814 lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND, 

1815 ), 

1816 # COMMON 

1817 LELongField("SessionId", 0), 

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

1819 ] 

1820 

1821 _SMB2_OK_RETURNCODES = ( 

1822 # sect 3.3.4.4 

1823 (0xC0000016, 0x0001), # STATUS_MORE_PROCESSING_REQUIRED 

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

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

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

1827 (0xC000000D, 0x000B), # STATUS_INVALID_PARAMETER 

1828 (0x0000010C, 0x000F), # STATUS_NOTIFY_ENUM_DIR 

1829 ) 

1830 

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

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

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

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

1835 

1836 def guess_payload_class(self, payload): 

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

1838 # Check status for responses 

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

1840 return SMB2_Error_Response 

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

1842 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1843 return SMB2_Negotiate_Protocol_Response 

1844 return SMB2_Negotiate_Protocol_Request 

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

1846 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1847 return SMB2_Session_Setup_Response 

1848 return SMB2_Session_Setup_Request 

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

1850 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1851 return SMB2_Session_Logoff_Response 

1852 return SMB2_Session_Logoff_Request 

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

1854 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1855 return SMB2_Tree_Connect_Response 

1856 return SMB2_Tree_Connect_Request 

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

1858 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1859 return SMB2_Tree_Disconnect_Response 

1860 return SMB2_Tree_Disconnect_Request 

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

1862 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1863 return SMB2_Create_Response 

1864 return SMB2_Create_Request 

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

1866 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1867 return SMB2_Close_Response 

1868 return SMB2_Close_Request 

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

1870 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1871 return SMB2_Read_Response 

1872 return SMB2_Read_Request 

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

1874 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1875 return SMB2_Write_Response 

1876 return SMB2_Write_Request 

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

1878 return SMB2_Cancel_Request 

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

1880 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1881 return SMB2_Echo_Response 

1882 return SMB2_Echo_Request 

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

1884 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1885 return SMB2_Query_Directory_Response 

1886 return SMB2_Query_Directory_Request 

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

1888 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1889 return SMB2_Change_Notify_Response 

1890 return SMB2_Change_Notify_Request 

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

1892 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1893 return SMB2_Query_Info_Response 

1894 return SMB2_Query_Info_Request 

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

1896 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1897 return SMB2_Set_Info_Response 

1898 return SMB2_Set_Info_Request 

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

1900 if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR: 

1901 return SMB2_IOCTL_Response 

1902 return SMB2_IOCTL_Request 

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

1904 

1905 def _calc_signature( 

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

1907 ): 

1908 """ 

1909 This function calculates the signature of a SMB2 packet. 

1910 Detail is from [MS-SMB2] 3.1.4.1 

1911 """ 

1912 if len(s) <= 64: 

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

1914 return s 

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

1916 if dialect == 0x0311: # SMB 3.1.1 

1917 if IsClient is None: 

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

1919 if SigningAlgorithmId is None: 

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

1921 else: 

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

1923 if "GMAC" in SigningAlgorithmId: 

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

1925 

1926 aesgcm = AESGCM(SigningSessionKey) 

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

1928 "<I", 

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

1930 ) 

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

1932 elif "CMAC" in SigningAlgorithmId: 

1933 from cryptography.hazmat.primitives import cmac 

1934 from cryptography.hazmat.primitives.ciphers import algorithms 

1935 

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

1937 c.update(s) 

1938 sig = c.finalize() 

1939 elif "HMAC" in SigningAlgorithmId: 

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

1941 

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

1943 sig = sig[:16] 

1944 else: 

1945 raise ValueError("Unknown SigningAlgorithmId") 

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

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

1948 

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

1950 sig = sig[:16] 

1951 else: 

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

1953 sig = b"\x00" * 16 

1954 return sig 

1955 

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

1957 """ 

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

1959 """ 

1960 # Set the current signature to nul 

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

1962 # Calculate the signature 

1963 s = bytes(self) 

1964 self.SecuritySignature = self._calc_signature( 

1965 s, 

1966 dialect=dialect, 

1967 SigningSessionKey=SigningSessionKey, 

1968 SigningAlgorithmId=SigningAlgorithmId, 

1969 IsClient=IsClient, 

1970 ) 

1971 # we make sure the payload is static 

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

1973 

1974 def verify( 

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

1976 ): 

1977 """ 

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

1979 """ 

1980 s = bytes(self) 

1981 # Set SecuritySignature to nul 

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

1983 # Calculate the signature 

1984 sig = self._calc_signature( 

1985 s, 

1986 dialect=dialect, 

1987 SigningSessionKey=SigningSessionKey, 

1988 SigningAlgorithmId=SigningAlgorithmId, 

1989 IsClient=IsClient, 

1990 ) 

1991 if self.SecuritySignature != sig: 

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

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

1994 

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

1996 """ 

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

1998 """ 

1999 if dialect < 0x0300: 

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

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

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

2003 

2004 data = bytes(self) 

2005 smbt = SMB2_Transform_Header( 

2006 OriginalMessageSize=len(self), 

2007 SessionId=self.SessionId, 

2008 Flags=0x0001, 

2009 ) 

2010 if "GCM" in CipherId: 

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

2012 

2013 nonce = os.urandom(12) 

2014 cipher = AESGCM(EncryptionKey) 

2015 elif "CCM" in CipherId: 

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

2017 

2018 nonce = os.urandom(11) 

2019 cipher = AESCCM(EncryptionKey) 

2020 else: 

2021 raise Exception("Unknown CipherId !") 

2022 

2023 # Add nonce to header and build the auth data 

2024 smbt.Nonce = nonce 

2025 aad = bytes(smbt)[20:] 

2026 

2027 # Perform the actual encryption 

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

2029 

2030 # Put the auth tag in the Signature field 

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

2032 

2033 return smbt / data 

2034 

2035 

2036class _SMB2_Payload(Packet): 

2037 def do_dissect_payload(self, s): 

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

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

2040 if self.underlayer.NextCommand: 

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

2042 if padlen: 

2043 self.add_payload(s[:padlen]) 

2044 s = s[padlen:] 

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

2046 

2047 def answers(self, other): 

2048 return ( 

2049 isinstance(other, _SMB2_Payload) 

2050 and self.__class__ != other.__class__ 

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

2052 ) 

2053 

2054 def guess_payload_class(self, s): 

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

2056 if self.underlayer.NextCommand: 

2057 return SMB2_Header 

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

2059 

2060 

2061# sect 2.2.2 

2062 

2063 

2064class SMB2_Error_Response(_SMB2_Payload): 

2065 Command = -1 

2066 __slots__ = ["NTStatus"] # extra info 

2067 name = "SMB2 Error Response" 

2068 fields_desc = [ 

2069 XLEShortField("StructureSize", 0x09), 

2070 ByteField("ErrorContextCount", 0), 

2071 ByteField("Reserved", 0), 

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

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

2074 ] 

2075 

2076 

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

2078 

2079# sect 2.2.2.2.2 

2080 

2081 

2082class MOVE_DST_IPADDR(Packet): 

2083 fields_desc = [ 

2084 # Wireshark appears to get this wrong 

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

2086 IntField("Reserved", 0), 

2087 MultipleTypeField( 

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

2089 IPField("IPAddress", None), 

2090 ), 

2091 ConditionalField( 

2092 # For IPv4 

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

2094 lambda pkt: pkt.Type == 1, 

2095 ), 

2096 ] 

2097 

2098 def default_payload_class(self, payload): 

2099 return conf.padding_layer 

2100 

2101 

2102class SMB2_Error_Share_Redirect_Context_Response(_NTLMPayloadPacket): 

2103 name = "Share Redirect Error Context Response" 

2104 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2105 fields_desc = [ 

2106 XLEIntField("StructureSize", 0x30), 

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

2108 XLEIntField("ResourceNameBufferOffset", None), 

2109 LEIntField("ResourceNameLen", None), 

2110 ShortField("Reserved", 0), 

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

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

2113 PacketListField( 

2114 "IPAddrMoveList", 

2115 [], 

2116 MOVE_DST_IPADDR, 

2117 count_from=lambda pkt: pkt.IPAddrCount, 

2118 ), 

2119 _NTLMPayloadField( 

2120 "Buffer", 

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

2122 [ 

2123 StrLenFieldUtf16( 

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

2125 ), 

2126 ], 

2127 ), 

2128 ] 

2129 

2130 def post_build(self, pkt, pay): 

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

2132 return ( 

2133 _SMB2_post_build( 

2134 self, 

2135 pkt, 

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

2137 { 

2138 "ResourceName": 8, 

2139 }, 

2140 ) 

2141 + pay 

2142 ) 

2143 

2144 

2145# sect 2.2.2.1 

2146 

2147 

2148class SMB2_Error_ContextResponse(Packet): 

2149 fields_desc = [ 

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

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

2152 MultipleTypeField( 

2153 [ 

2154 ( 

2155 PacketField( 

2156 "ErrorContextData", 

2157 SMB2_Error_Share_Redirect_Context_Response(), 

2158 SMB2_Error_Share_Redirect_Context_Response, 

2159 ), 

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

2161 ) 

2162 ], 

2163 XStrLenField( 

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

2165 ), 

2166 ), 

2167 ] 

2168 

2169 

2170# sect 2.2.3 

2171 

2172 

2173class SMB2_Negotiate_Context(Packet): 

2174 name = "SMB2 Negotiate Context" 

2175 fields_desc = [ 

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

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

2178 IntField("Reserved", 0), 

2179 ] 

2180 

2181 def default_payload_class(self, payload): 

2182 return conf.padding_layer 

2183 

2184 

2185class SMB2_Negotiate_Protocol_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2186 name = "SMB2 Negotiate Protocol Request" 

2187 Command = 0x0000 

2188 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2189 fields_desc = [ 

2190 XLEShortField("StructureSize", 0x24), 

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

2192 # SecurityMode 

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

2194 LEShortField("Reserved", 0), 

2195 # Capabilities 

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

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

2198 XLEIntField("NegotiateContextsBufferOffset", None), 

2199 LEShortField("NegotiateContextsCount", None), 

2200 ShortField("Reserved2", 0), 

2201 FieldListField( 

2202 "Dialects", 

2203 [0x0202], 

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

2205 count_from=lambda pkt: pkt.DialectCount, 

2206 ), 

2207 _NTLMPayloadField( 

2208 "Buffer", 

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

2210 [ 

2211 # Field only exists if Dialects contains 0x0311 

2212 FieldListField( 

2213 "NegotiateContexts", 

2214 [], 

2215 ReversePadField( 

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

2217 8, 

2218 ), 

2219 count_from=lambda pkt: pkt.NegotiateContextsCount, 

2220 ), 

2221 ], 

2222 ), 

2223 ] 

2224 

2225 def post_build(self, pkt, pay): 

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

2227 return ( 

2228 _NTLM_post_build( 

2229 self, 

2230 pkt, 

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

2232 { 

2233 "NegotiateContexts": 28, 

2234 }, 

2235 config=[ 

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

2237 ("Count", _NTLM_ENUM.COUNT), 

2238 ], 

2239 ) 

2240 + pay 

2241 ) 

2242 

2243 

2244bind_top_down( 

2245 SMB2_Header, 

2246 SMB2_Negotiate_Protocol_Request, 

2247 Command=0x0000, 

2248) 

2249 

2250# sect 2.2.3.1.1 

2251 

2252 

2253class SMB2_Preauth_Integrity_Capabilities(Packet): 

2254 name = "SMB2 Preauth Integrity Capabilities" 

2255 fields_desc = [ 

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

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

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

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

2260 FieldListField( 

2261 "HashAlgorithms", 

2262 [0x0001], 

2263 LEShortEnumField( 

2264 "", 

2265 0x0, 

2266 SMB2_HASH_ALGORITHMS, 

2267 ), 

2268 count_from=lambda pkt: pkt.HashAlgorithmCount, 

2269 ), 

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

2271 ] 

2272 

2273 def default_payload_class(self, payload): 

2274 return conf.padding_layer 

2275 

2276 

2277bind_layers( 

2278 SMB2_Negotiate_Context, SMB2_Preauth_Integrity_Capabilities, ContextType=0x0001 

2279) 

2280 

2281# sect 2.2.3.1.2 

2282 

2283 

2284class SMB2_Encryption_Capabilities(Packet): 

2285 name = "SMB2 Encryption Capabilities" 

2286 fields_desc = [ 

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

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

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

2290 FieldListField( 

2291 "Ciphers", 

2292 [0x0001], 

2293 LEShortEnumField( 

2294 "", 

2295 0x0, 

2296 SMB2_ENCRYPTION_CIPHERS, 

2297 ), 

2298 count_from=lambda pkt: pkt.CipherCount, 

2299 ), 

2300 ] 

2301 

2302 def default_payload_class(self, payload): 

2303 return conf.padding_layer 

2304 

2305 

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

2307 

2308# sect 2.2.3.1.3 

2309 

2310 

2311class SMB2_Compression_Capabilities(Packet): 

2312 name = "SMB2 Compression Capabilities" 

2313 fields_desc = [ 

2314 FieldLenField( 

2315 "CompressionAlgorithmCount", 

2316 None, 

2317 fmt="<H", 

2318 count_of="CompressionAlgorithms", 

2319 ), 

2320 ShortField("Padding", 0x0), 

2321 LEIntEnumField( 

2322 "Flags", 

2323 0x0, 

2324 { 

2325 0x00000000: "SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE", 

2326 0x00000001: "SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED", 

2327 }, 

2328 ), 

2329 FieldListField( 

2330 "CompressionAlgorithms", 

2331 None, 

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

2333 count_from=lambda pkt: pkt.CompressionAlgorithmCount, 

2334 ), 

2335 ] 

2336 

2337 def default_payload_class(self, payload): 

2338 return conf.padding_layer 

2339 

2340 

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

2342 

2343# sect 2.2.3.1.4 

2344 

2345 

2346class SMB2_Netname_Negotiate_Context_ID(Packet): 

2347 name = "SMB2 Netname Negotiate Context ID" 

2348 fields_desc = [ 

2349 StrLenFieldUtf16( 

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

2351 ) 

2352 ] 

2353 

2354 def default_payload_class(self, payload): 

2355 return conf.padding_layer 

2356 

2357 

2358bind_layers( 

2359 SMB2_Negotiate_Context, SMB2_Netname_Negotiate_Context_ID, ContextType=0x0005 

2360) 

2361 

2362# sect 2.2.3.1.5 

2363 

2364 

2365class SMB2_Transport_Capabilities(Packet): 

2366 name = "SMB2 Transport Capabilities" 

2367 fields_desc = [ 

2368 FlagsField( 

2369 "Flags", 

2370 0x0, 

2371 -32, 

2372 { 

2373 0x00000001: "SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY", 

2374 }, 

2375 ), 

2376 ] 

2377 

2378 def default_payload_class(self, payload): 

2379 return conf.padding_layer 

2380 

2381 

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

2383 

2384# sect 2.2.3.1.6 

2385 

2386 

2387class SMB2_RDMA_Transform_Capabilities(Packet): 

2388 name = "SMB2 RDMA Transform Capabilities" 

2389 fields_desc = [ 

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

2391 LEShortField("Reserved1", 0), 

2392 LEIntField("Reserved2", 0), 

2393 FieldListField( 

2394 "RDMATransformIds", 

2395 None, 

2396 LEShortEnumField( 

2397 "", 

2398 0x0, 

2399 { 

2400 0x0000: "SMB2_RDMA_TRANSFORM_NONE", 

2401 0x0001: "SMB2_RDMA_TRANSFORM_ENCRYPTION", 

2402 0x0002: "SMB2_RDMA_TRANSFORM_SIGNING", 

2403 }, 

2404 ), 

2405 count_from=lambda pkt: pkt.TransformCount, 

2406 ), 

2407 ] 

2408 

2409 def default_payload_class(self, payload): 

2410 return conf.padding_layer 

2411 

2412 

2413bind_layers( 

2414 SMB2_Negotiate_Context, SMB2_RDMA_Transform_Capabilities, ContextType=0x0007 

2415) 

2416 

2417# sect 2.2.3.1.7 

2418 

2419 

2420class SMB2_Signing_Capabilities(Packet): 

2421 name = "SMB2 Signing Capabilities" 

2422 fields_desc = [ 

2423 FieldLenField( 

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

2425 ), 

2426 FieldListField( 

2427 "SigningAlgorithms", 

2428 None, 

2429 LEShortEnumField( 

2430 "", 

2431 0x0, 

2432 SMB2_SIGNING_ALGORITHMS, 

2433 ), 

2434 count_from=lambda pkt: pkt.SigningAlgorithmCount, 

2435 ), 

2436 ] 

2437 

2438 def default_payload_class(self, payload): 

2439 return conf.padding_layer 

2440 

2441 

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

2443 

2444# sect 2.2.4 

2445 

2446 

2447class SMB2_Negotiate_Protocol_Response(_SMB2_Payload, _NTLMPayloadPacket): 

2448 name = "SMB2 Negotiate Protocol Response" 

2449 Command = 0x0000 

2450 OFFSET = 64 + 64 

2451 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2452 fields_desc = [ 

2453 XLEShortField("StructureSize", 0x41), 

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

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

2456 LEShortField("NegotiateContextsCount", None), 

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

2458 # Capabilities 

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

2460 LEIntField("MaxTransactionSize", 65536), 

2461 LEIntField("MaxReadSize", 65536), 

2462 LEIntField("MaxWriteSize", 65536), 

2463 UTCTimeField( 

2464 "ServerTime", 

2465 None, 

2466 fmt="<Q", 

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

2468 custom_scaling=1e7, 

2469 ), 

2470 UTCTimeField( 

2471 "ServerStartTime", 

2472 None, 

2473 fmt="<Q", 

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

2475 custom_scaling=1e7, 

2476 ), 

2477 XLEShortField("SecurityBlobBufferOffset", None), 

2478 LEShortField("SecurityBlobLen", None), 

2479 XLEIntField("NegotiateContextsBufferOffset", None), 

2480 _NTLMPayloadField( 

2481 "Buffer", 

2482 OFFSET, 

2483 [ 

2484 PacketLenField( 

2485 "SecurityBlob", 

2486 None, 

2487 GSSAPI_BLOB, 

2488 length_from=lambda x: x.SecurityBlobLen, 

2489 ), 

2490 # Field only exists if Dialect is 0x0311 

2491 FieldListField( 

2492 "NegotiateContexts", 

2493 [], 

2494 ReversePadField( 

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

2496 8, 

2497 ), 

2498 count_from=lambda pkt: pkt.NegotiateContextsCount, 

2499 ), 

2500 ], 

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

2502 ), 

2503 ] 

2504 

2505 def post_build(self, pkt, pay): 

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

2507 pkt = _NTLM_post_build( 

2508 self, 

2509 pkt, 

2510 self.OFFSET, 

2511 { 

2512 "SecurityBlob": 56, 

2513 "NegotiateContexts": 60, 

2514 }, 

2515 config=[ 

2516 ( 

2517 "BufferOffset", 

2518 { 

2519 "SecurityBlob": _NTLM_ENUM.OFFSET, 

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

2521 }, 

2522 ), 

2523 ], 

2524 ) 

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

2526 if self.SecurityBlobLen is None: 

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

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

2529 if self.NegotiateContextsCount is None: 

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

2531 return pkt + pay 

2532 

2533 

2534bind_top_down( 

2535 SMB2_Header, 

2536 SMB2_Negotiate_Protocol_Response, 

2537 Command=0x0000, 

2538 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

2539) 

2540 

2541# sect 2.2.5 

2542 

2543 

2544class SMB2_Session_Setup_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2545 name = "SMB2 Session Setup Request" 

2546 Command = 0x0001 

2547 OFFSET = 24 + 64 

2548 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2549 fields_desc = [ 

2550 XLEShortField("StructureSize", 0x19), 

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

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

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

2554 LEIntField("Channel", 0), 

2555 XLEShortField("SecurityBlobBufferOffset", None), 

2556 LEShortField("SecurityBlobLen", None), 

2557 XLELongField("PreviousSessionId", 0), 

2558 _NTLMPayloadField( 

2559 "Buffer", 

2560 OFFSET, 

2561 [ 

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

2563 ], 

2564 ), 

2565 ] 

2566 

2567 def post_build(self, pkt, pay): 

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

2569 return ( 

2570 _SMB2_post_build( 

2571 self, 

2572 pkt, 

2573 self.OFFSET, 

2574 { 

2575 "SecurityBlob": 12, 

2576 }, 

2577 ) 

2578 + pay 

2579 ) 

2580 

2581 

2582bind_top_down( 

2583 SMB2_Header, 

2584 SMB2_Session_Setup_Request, 

2585 Command=0x0001, 

2586) 

2587 

2588# sect 2.2.6 

2589 

2590 

2591class SMB2_Session_Setup_Response(_SMB2_Payload, _NTLMPayloadPacket): 

2592 name = "SMB2 Session Setup Response" 

2593 Command = 0x0001 

2594 OFFSET = 8 + 64 

2595 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2596 fields_desc = [ 

2597 XLEShortField("StructureSize", 0x9), 

2598 FlagsField( 

2599 "SessionFlags", 

2600 0, 

2601 -16, 

2602 { 

2603 0x0001: "IS_GUEST", 

2604 0x0002: "IS_NULL", 

2605 0x0004: "ENCRYPT_DATA", 

2606 }, 

2607 ), 

2608 XLEShortField("SecurityBufferOffset", None), 

2609 LEShortField("SecurityLen", None), 

2610 _NTLMPayloadField( 

2611 "Buffer", 

2612 OFFSET, 

2613 [ 

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

2615 ], 

2616 ), 

2617 ] 

2618 

2619 def __getattr__(self, attr): 

2620 # Ease SMB1 backward compatibility 

2621 if attr == "SecurityBlob": 

2622 return ( 

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

2624 or [(None, None)] 

2625 )[0][1] 

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

2627 

2628 def setfieldval(self, attr, val): 

2629 if attr == "SecurityBlob": 

2630 return super(SMB2_Session_Setup_Response, self).setfieldval( 

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

2632 ) 

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

2634 

2635 def post_build(self, pkt, pay): 

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

2637 return ( 

2638 _SMB2_post_build( 

2639 self, 

2640 pkt, 

2641 self.OFFSET, 

2642 { 

2643 "Security": 4, 

2644 }, 

2645 ) 

2646 + pay 

2647 ) 

2648 

2649 

2650bind_top_down( 

2651 SMB2_Header, 

2652 SMB2_Session_Setup_Response, 

2653 Command=0x0001, 

2654 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

2655) 

2656 

2657# sect 2.2.7 

2658 

2659 

2660class SMB2_Session_Logoff_Request(_SMB2_Payload): 

2661 name = "SMB2 LOGOFF Request" 

2662 Command = 0x0002 

2663 fields_desc = [ 

2664 XLEShortField("StructureSize", 0x4), 

2665 ShortField("reserved", 0), 

2666 ] 

2667 

2668 

2669bind_top_down( 

2670 SMB2_Header, 

2671 SMB2_Session_Logoff_Request, 

2672 Command=0x0002, 

2673) 

2674 

2675# sect 2.2.8 

2676 

2677 

2678class SMB2_Session_Logoff_Response(_SMB2_Payload): 

2679 name = "SMB2 LOGOFF Request" 

2680 Command = 0x0002 

2681 fields_desc = [ 

2682 XLEShortField("StructureSize", 0x4), 

2683 ShortField("reserved", 0), 

2684 ] 

2685 

2686 

2687bind_top_down( 

2688 SMB2_Header, 

2689 SMB2_Session_Logoff_Response, 

2690 Command=0x0002, 

2691 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

2692) 

2693 

2694# sect 2.2.9 

2695 

2696 

2697class SMB2_Tree_Connect_Request(_SMB2_Payload, _NTLMPayloadPacket): 

2698 name = "SMB2 TREE_CONNECT Request" 

2699 Command = 0x0003 

2700 OFFSET = 8 + 64 

2701 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2702 fields_desc = [ 

2703 XLEShortField("StructureSize", 0x9), 

2704 FlagsField( 

2705 "Flags", 

2706 0, 

2707 -16, 

2708 ["CLUSTER_RECONNECT", "REDIRECT_TO_OWNER", "EXTENSION_PRESENT"], 

2709 ), 

2710 XLEShortField("PathBufferOffset", None), 

2711 LEShortField("PathLen", None), 

2712 _NTLMPayloadField( 

2713 "Buffer", 

2714 OFFSET, 

2715 [ 

2716 StrFieldUtf16("Path", b""), 

2717 ], 

2718 ), 

2719 ] 

2720 

2721 def post_build(self, pkt, pay): 

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

2723 return ( 

2724 _SMB2_post_build( 

2725 self, 

2726 pkt, 

2727 self.OFFSET, 

2728 { 

2729 "Path": 4, 

2730 }, 

2731 ) 

2732 + pay 

2733 ) 

2734 

2735 

2736bind_top_down( 

2737 SMB2_Header, 

2738 SMB2_Tree_Connect_Request, 

2739 Command=0x0003, 

2740) 

2741 

2742# sect 2.2.10 

2743 

2744 

2745class SMB2_Tree_Connect_Response(_SMB2_Payload): 

2746 name = "SMB2 TREE_CONNECT Response" 

2747 Command = 0x0003 

2748 fields_desc = [ 

2749 XLEShortField("StructureSize", 0x10), 

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

2751 ByteField("Reserved", 0), 

2752 FlagsField( 

2753 "ShareFlags", 

2754 0x30, 

2755 -32, 

2756 { 

2757 0x00000010: "AUTO_CACHING", 

2758 0x00000020: "VDO_CACHING", 

2759 0x00000030: "NO_CACHING", 

2760 0x00000001: "DFS", 

2761 0x00000002: "DFS_ROOT", 

2762 0x00000100: "RESTRICT_EXCLUSIVE_OPENS", 

2763 0x00000200: "FORCE_SHARED_DELETE", 

2764 0x00000400: "ALLOW_NAMESPACE_CACHING", 

2765 0x00000800: "ACCESS_BASED_DIRECTORY_ENUM", 

2766 0x00001000: "FORCE_LEVELII_OPLOCK", 

2767 0x00002000: "ENABLE_HASH_V1", 

2768 0x00004000: "ENABLE_HASH_V2", 

2769 0x00008000: "ENCRYPT_DATA", 

2770 0x00040000: "IDENTITY_REMOTING", 

2771 0x00100000: "COMPRESS_DATA", 

2772 }, 

2773 ), 

2774 FlagsField( 

2775 "Capabilities", 

2776 0, 

2777 -32, 

2778 { 

2779 0x00000008: "DFS", 

2780 0x00000010: "CONTINUOUS_AVAILABILITY", 

2781 0x00000020: "SCALEOUT", 

2782 0x00000040: "CLUSTER", 

2783 0x00000080: "ASYMMETRIC", 

2784 0x00000100: "REDIRECT_TO_OWNER", 

2785 }, 

2786 ), 

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

2788 ] 

2789 

2790 

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

2792 

2793# sect 2.2.11 

2794 

2795 

2796class SMB2_Tree_Disconnect_Request(_SMB2_Payload): 

2797 name = "SMB2 TREE_DISCONNECT Request" 

2798 Command = 0x0004 

2799 fields_desc = [ 

2800 XLEShortField("StructureSize", 0x4), 

2801 XLEShortField("Reserved", 0), 

2802 ] 

2803 

2804 

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

2806 

2807# sect 2.2.12 

2808 

2809 

2810class SMB2_Tree_Disconnect_Response(_SMB2_Payload): 

2811 name = "SMB2 TREE_DISCONNECT Response" 

2812 Command = 0x0004 

2813 fields_desc = [ 

2814 XLEShortField("StructureSize", 0x4), 

2815 XLEShortField("Reserved", 0), 

2816 ] 

2817 

2818 

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

2820 

2821 

2822# sect 2.2.14.1 

2823 

2824 

2825class SMB2_FILEID(Packet): 

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

2827 

2828 def __hash__(self): 

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

2830 

2831 def default_payload_class(self, payload): 

2832 return conf.padding_layer 

2833 

2834 

2835# sect 2.2.14.2 

2836 

2837 

2838class SMB2_CREATE_DURABLE_HANDLE_RESPONSE(Packet): 

2839 fields_desc = [ 

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

2841 ] 

2842 

2843 

2844class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE(Packet): 

2845 fields_desc = [ 

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

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

2848 ] 

2849 

2850 

2851class SMB2_CREATE_QUERY_ON_DISK_ID(Packet): 

2852 fields_desc = [ 

2853 XLELongField("DiskFileId", 0), 

2854 XLELongField("VolumeId", 0), 

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

2856 ] 

2857 

2858 

2859class SMB2_CREATE_RESPONSE_LEASE(Packet): 

2860 fields_desc = [ 

2861 UUIDField("LeaseKey", None), 

2862 FlagsField( 

2863 "LeaseState", 

2864 0x7, 

2865 -32, 

2866 { 

2867 0x01: "SMB2_LEASE_READ_CACHING", 

2868 0x02: "SMB2_LEASE_HANDLE_CACHING", 

2869 0x04: "SMB2_LEASE_WRITE_CACHING", 

2870 }, 

2871 ), 

2872 FlagsField( 

2873 "LeaseFlags", 

2874 0, 

2875 -32, 

2876 { 

2877 0x02: "SMB2_LEASE_FLAG_BREAK_IN_PROGRESS", 

2878 0x04: "SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET", 

2879 }, 

2880 ), 

2881 LELongField("LeaseDuration", 0), 

2882 ] 

2883 

2884 

2885class SMB2_CREATE_RESPONSE_LEASE_V2(Packet): 

2886 fields_desc = [ 

2887 SMB2_CREATE_RESPONSE_LEASE, 

2888 UUIDField("ParentLeaseKey", None), 

2889 LEShortField("Epoch", 0), 

2890 LEShortField("Reserved", 0), 

2891 ] 

2892 

2893 

2894class SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2(Packet): 

2895 fields_desc = [ 

2896 LEIntField("Timeout", 0), 

2897 FlagsField( 

2898 "Flags", 

2899 0, 

2900 -32, 

2901 { 

2902 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT", 

2903 }, 

2904 ), 

2905 ] 

2906 

2907 

2908# sect 2.2.13 

2909 

2910 

2911class SMB2_CREATE_DURABLE_HANDLE_REQUEST(Packet): 

2912 fields_desc = [ 

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

2914 ] 

2915 

2916 

2917class SMB2_CREATE_DURABLE_HANDLE_RECONNECT(Packet): 

2918 fields_desc = [ 

2919 PacketField("Data", SMB2_FILEID(), SMB2_FILEID), 

2920 ] 

2921 

2922 

2923class SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST(Packet): 

2924 fields_desc = [ 

2925 LELongField("Timestamp", 0), 

2926 ] 

2927 

2928 

2929class SMB2_CREATE_ALLOCATION_SIZE(Packet): 

2930 fields_desc = [ 

2931 LELongField("AllocationSize", 0), 

2932 ] 

2933 

2934 

2935class SMB2_CREATE_TIMEWARP_TOKEN(Packet): 

2936 fields_desc = [ 

2937 LELongField("Timestamp", 0), 

2938 ] 

2939 

2940 

2941class SMB2_CREATE_REQUEST_LEASE(Packet): 

2942 fields_desc = [ 

2943 SMB2_CREATE_RESPONSE_LEASE, 

2944 ] 

2945 

2946 

2947class SMB2_CREATE_REQUEST_LEASE_V2(Packet): 

2948 fields_desc = [ 

2949 SMB2_CREATE_RESPONSE_LEASE_V2, 

2950 ] 

2951 

2952 

2953class SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2(Packet): 

2954 fields_desc = [ 

2955 SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2, 

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

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

2958 ] 

2959 

2960 

2961class SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2(Packet): 

2962 fields_desc = [ 

2963 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

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

2965 FlagsField( 

2966 "Flags", 

2967 0, 

2968 -32, 

2969 { 

2970 0x02: "SMB2_DHANDLE_FLAG_PERSISTENT", 

2971 }, 

2972 ), 

2973 ] 

2974 

2975 

2976class SMB2_CREATE_APP_INSTANCE_ID(Packet): 

2977 fields_desc = [ 

2978 XLEShortField("StructureSize", 0x14), 

2979 LEShortField("Reserved", 0), 

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

2981 ] 

2982 

2983 

2984class SMB2_CREATE_APP_INSTANCE_VERSION(Packet): 

2985 fields_desc = [ 

2986 XLEShortField("StructureSize", 0x18), 

2987 LEShortField("Reserved", 0), 

2988 LEIntField("Padding", 0), 

2989 LELongField("AppInstanceVersionHigh", 0), 

2990 LELongField("AppInstanceVersionLow", 0), 

2991 ] 

2992 

2993 

2994class SMB2_Create_Context(_NTLMPayloadPacket): 

2995 name = "SMB2 CREATE CONTEXT" 

2996 OFFSET = 16 

2997 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

2998 fields_desc = [ 

2999 LEIntField("Next", None), 

3000 XLEShortField("NameBufferOffset", None), 

3001 LEShortField("NameLen", None), 

3002 ShortField("Reserved", 0), 

3003 XLEShortField("DataBufferOffset", None), 

3004 LEIntField("DataLen", None), 

3005 _NTLMPayloadField( 

3006 "Buffer", 

3007 OFFSET, 

3008 [ 

3009 PadField( 

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

3011 8, 

3012 ), 

3013 # Must be padded on 8-octet alignment 

3014 PacketLenField( 

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

3016 ), 

3017 ], 

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

3019 ), 

3020 StrLenField( 

3021 "pad", 

3022 b"", 

3023 length_from=lambda x: ( 

3024 ( 

3025 x.Next 

3026 - max( 

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

3028 ) 

3029 ) 

3030 if x.Next 

3031 else 0 

3032 ), 

3033 ), 

3034 ] 

3035 

3036 def post_dissect(self, s): 

3037 if not self.DataLen: 

3038 return s 

3039 try: 

3040 if isinstance(self.parent, SMB2_Create_Request): 

3041 data_cls = { 

3042 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_REQUEST, 

3043 b"DHnC": SMB2_CREATE_DURABLE_HANDLE_RECONNECT, 

3044 b"AISi": SMB2_CREATE_ALLOCATION_SIZE, 

3045 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 

3046 b"TWrp": SMB2_CREATE_TIMEWARP_TOKEN, 

3047 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID, 

3048 b"RqLs": SMB2_CREATE_REQUEST_LEASE, 

3049 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, 

3050 b"DH2C": SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, 

3051 # 3.1.1 only 

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

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

3054 }[self.Name] 

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

3056 data_cls = SMB2_CREATE_REQUEST_LEASE_V2 

3057 elif isinstance(self.parent, SMB2_Create_Response): 

3058 data_cls = { 

3059 b"DHnQ": SMB2_CREATE_DURABLE_HANDLE_RESPONSE, 

3060 b"MxAc": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE, 

3061 b"QFid": SMB2_CREATE_QUERY_ON_DISK_ID, 

3062 b"RqLs": SMB2_CREATE_RESPONSE_LEASE, 

3063 b"DH2Q": SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2, 

3064 }[self.Name] 

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

3066 data_cls = SMB2_CREATE_RESPONSE_LEASE_V2 

3067 else: 

3068 return s 

3069 except KeyError: 

3070 return s 

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

3072 return s 

3073 

3074 def default_payload_class(self, _): 

3075 return conf.padding_layer 

3076 

3077 def post_build(self, pkt, pay): 

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

3079 return ( 

3080 _NTLM_post_build( 

3081 self, 

3082 pkt, 

3083 self.OFFSET, 

3084 { 

3085 "Name": 4, 

3086 "Data": 10, 

3087 }, 

3088 config=[ 

3089 ( 

3090 "BufferOffset", 

3091 { 

3092 "Name": _NTLM_ENUM.OFFSET, 

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

3094 }, 

3095 ), 

3096 ("Len", _NTLM_ENUM.LEN), 

3097 ], 

3098 ) 

3099 + pay 

3100 ) 

3101 

3102 

3103# sect 2.2.13 

3104 

3105SMB2_OPLOCK_LEVELS = { 

3106 0x00: "SMB2_OPLOCK_LEVEL_NONE", 

3107 0x01: "SMB2_OPLOCK_LEVEL_II", 

3108 0x08: "SMB2_OPLOCK_LEVEL_EXCLUSIVE", 

3109 0x09: "SMB2_OPLOCK_LEVEL_BATCH", 

3110 0xFF: "SMB2_OPLOCK_LEVEL_LEASE", 

3111} 

3112 

3113 

3114class SMB2_Create_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3115 name = "SMB2 CREATE Request" 

3116 Command = 0x0005 

3117 OFFSET = 56 + 64 

3118 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3119 fields_desc = [ 

3120 XLEShortField("StructureSize", 0x39), 

3121 ByteField("ShareType", 0), 

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

3123 LEIntEnumField( 

3124 "ImpersonationLevel", 

3125 0, 

3126 { 

3127 0x00000000: "Anonymous", 

3128 0x00000001: "Identification", 

3129 0x00000002: "Impersonation", 

3130 0x00000003: "Delegate", 

3131 }, 

3132 ), 

3133 LELongField("SmbCreateFlags", 0), 

3134 LELongField("Reserved", 0), 

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

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

3137 FlagsField( 

3138 "ShareAccess", 

3139 0, 

3140 -32, 

3141 { 

3142 0x00000001: "FILE_SHARE_READ", 

3143 0x00000002: "FILE_SHARE_WRITE", 

3144 0x00000004: "FILE_SHARE_DELETE", 

3145 }, 

3146 ), 

3147 LEIntEnumField( 

3148 "CreateDisposition", 

3149 1, 

3150 { 

3151 0x00000000: "FILE_SUPERSEDE", 

3152 0x00000001: "FILE_OPEN", 

3153 0x00000002: "FILE_CREATE", 

3154 0x00000003: "FILE_OPEN_IF", 

3155 0x00000004: "FILE_OVERWRITE", 

3156 0x00000005: "FILE_OVERWRITE_IF", 

3157 }, 

3158 ), 

3159 FlagsField( 

3160 "CreateOptions", 

3161 0, 

3162 -32, 

3163 { 

3164 0x00000001: "FILE_DIRECTORY_FILE", 

3165 0x00000002: "FILE_WRITE_THROUGH", 

3166 0x00000004: "FILE_SEQUENTIAL_ONLY", 

3167 0x00000008: "FILE_NO_INTERMEDIATE_BUFFERING", 

3168 0x00000010: "FILE_SYNCHRONOUS_IO_ALERT", 

3169 0x00000020: "FILE_SYNCHRONOUS_IO_NONALERT", 

3170 0x00000040: "FILE_NON_DIRECTORY_FILE", 

3171 0x00000100: "FILE_COMPLETE_IF_OPLOCKED", 

3172 0x00000200: "FILE_RANDOM_ACCESS", 

3173 0x00001000: "FILE_DELETE_ON_CLOSE", 

3174 0x00002000: "FILE_OPEN_BY_FILE_ID", 

3175 0x00004000: "FILE_OPEN_FOR_BACKUP_INTENT", 

3176 0x00008000: "FILE_NO_COMPRESSION", 

3177 0x00000400: "FILE_OPEN_REMOTE_INSTANCE", 

3178 0x00010000: "FILE_OPEN_REQUIRING_OPLOCK", 

3179 0x00020000: "FILE_DISALLOW_EXCLUSIVE", 

3180 0x00100000: "FILE_RESERVE_OPFILTER", 

3181 0x00200000: "FILE_OPEN_REPARSE_POINT", 

3182 0x00400000: "FILE_OPEN_NO_RECALL", 

3183 0x00800000: "FILE_OPEN_FOR_FREE_SPACE_QUERY", 

3184 }, 

3185 ), 

3186 XLEShortField("NameBufferOffset", None), 

3187 LEShortField("NameLen", None), 

3188 XLEIntField("CreateContextsBufferOffset", None), 

3189 LEIntField("CreateContextsLen", None), 

3190 _NTLMPayloadField( 

3191 "Buffer", 

3192 OFFSET, 

3193 [ 

3194 StrFieldUtf16("Name", b""), 

3195 _NextPacketListField( 

3196 "CreateContexts", 

3197 [], 

3198 SMB2_Create_Context, 

3199 length_from=lambda pkt: pkt.CreateContextsLen, 

3200 ), 

3201 ], 

3202 ), 

3203 ] 

3204 

3205 def post_build(self, pkt, pay): 

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

3207 if len(pkt) == 0x38: 

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

3209 pkt += b"\x00" 

3210 return ( 

3211 _SMB2_post_build( 

3212 self, 

3213 pkt, 

3214 self.OFFSET, 

3215 { 

3216 "Name": 44, 

3217 "CreateContexts": 48, 

3218 }, 

3219 ) 

3220 + pay 

3221 ) 

3222 

3223 

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

3225 

3226 

3227# sect 2.2.14 

3228 

3229 

3230class SMB2_Create_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3231 name = "SMB2 CREATE Response" 

3232 Command = 0x0005 

3233 OFFSET = 88 + 64 

3234 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3235 fields_desc = [ 

3236 XLEShortField("StructureSize", 0x59), 

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

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

3239 LEIntEnumField( 

3240 "CreateAction", 

3241 1, 

3242 { 

3243 0x00000000: "FILE_SUPERSEDED", 

3244 0x00000001: "FILE_OPENED", 

3245 0x00000002: "FILE_CREATED", 

3246 0x00000003: "FILE_OVERWRITEN", 

3247 }, 

3248 ), 

3249 FileNetworkOpenInformation, 

3250 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3251 XLEIntField("CreateContextsBufferOffset", None), 

3252 LEIntField("CreateContextsLen", None), 

3253 _NTLMPayloadField( 

3254 "Buffer", 

3255 OFFSET, 

3256 [ 

3257 _NextPacketListField( 

3258 "CreateContexts", 

3259 [], 

3260 SMB2_Create_Context, 

3261 length_from=lambda pkt: pkt.CreateContextsLen, 

3262 ), 

3263 ], 

3264 ), 

3265 ] 

3266 

3267 def post_build(self, pkt, pay): 

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

3269 return ( 

3270 _SMB2_post_build( 

3271 self, 

3272 pkt, 

3273 self.OFFSET, 

3274 { 

3275 "CreateContexts": 80, 

3276 }, 

3277 ) 

3278 + pay 

3279 ) 

3280 

3281 

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

3283 

3284# sect 2.2.15 

3285 

3286 

3287class SMB2_Close_Request(_SMB2_Payload): 

3288 name = "SMB2 CLOSE Request" 

3289 Command = 0x0006 

3290 fields_desc = [ 

3291 XLEShortField("StructureSize", 0x18), 

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

3293 LEIntField("Reserved", 0), 

3294 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3295 ] 

3296 

3297 

3298bind_top_down( 

3299 SMB2_Header, 

3300 SMB2_Close_Request, 

3301 Command=0x0006, 

3302) 

3303 

3304# sect 2.2.16 

3305 

3306 

3307class SMB2_Close_Response(_SMB2_Payload): 

3308 name = "SMB2 CLOSE Response" 

3309 Command = 0x0006 

3310 FileAttributes = 0 

3311 CreationTime = 0 

3312 LastAccessTime = 0 

3313 LastWriteTime = 0 

3314 ChangeTime = 0 

3315 fields_desc = [ 

3316 XLEShortField("StructureSize", 0x3C), 

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

3318 LEIntField("Reserved", 0), 

3319 ] + FileNetworkOpenInformation.fields_desc[:7] 

3320 

3321 

3322bind_top_down( 

3323 SMB2_Header, 

3324 SMB2_Close_Response, 

3325 Command=0x0006, 

3326 Flags=1, 

3327) 

3328 

3329# sect 2.2.19 

3330 

3331 

3332class SMB2_Read_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3333 name = "SMB2 READ Request" 

3334 Command = 0x0008 

3335 OFFSET = 48 + 64 

3336 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3337 fields_desc = [ 

3338 XLEShortField("StructureSize", 0x31), 

3339 ByteField("Padding", 0x00), 

3340 FlagsField( 

3341 "Flags", 

3342 0, 

3343 -8, 

3344 { 

3345 0x01: "SMB2_READFLAG_READ_UNBUFFERED", 

3346 0x02: "SMB2_READFLAG_REQUEST_COMPRESSED", 

3347 }, 

3348 ), 

3349 LEIntField("Length", 4280), 

3350 LELongField("Offset", 0), 

3351 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3352 LEIntField("MinimumCount", 0), 

3353 LEIntEnumField( 

3354 "Channel", 

3355 0, 

3356 { 

3357 0x00000000: "SMB2_CHANNEL_NONE", 

3358 0x00000001: "SMB2_CHANNEL_RDMA_V1", 

3359 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE", 

3360 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM", 

3361 }, 

3362 ), 

3363 LEIntField("RemainingBytes", 0), 

3364 LEShortField("ReadChannelInfoBufferOffset", None), 

3365 LEShortField("ReadChannelInfoLen", None), 

3366 _NTLMPayloadField( 

3367 "Buffer", 

3368 OFFSET, 

3369 [ 

3370 StrLenField( 

3371 "ReadChannelInfo", 

3372 b"", 

3373 length_from=lambda pkt: pkt.ReadChannelInfoLen, 

3374 ) 

3375 ], 

3376 ), 

3377 ] 

3378 

3379 def post_build(self, pkt, pay): 

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

3381 if len(pkt) == 0x30: 

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

3383 pkt += b"\x00" 

3384 return ( 

3385 _SMB2_post_build( 

3386 self, 

3387 pkt, 

3388 self.OFFSET, 

3389 { 

3390 "ReadChannelInfo": 44, 

3391 }, 

3392 ) 

3393 + pay 

3394 ) 

3395 

3396 

3397bind_top_down( 

3398 SMB2_Header, 

3399 SMB2_Read_Request, 

3400 Command=0x0008, 

3401) 

3402 

3403# sect 2.2.20 

3404 

3405 

3406class SMB2_Read_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3407 name = "SMB2 READ Response" 

3408 Command = 0x0008 

3409 OFFSET = 16 + 64 

3410 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3411 fields_desc = [ 

3412 XLEShortField("StructureSize", 0x11), 

3413 LEShortField("DataBufferOffset", None), 

3414 LEIntField("DataLen", None), 

3415 LEIntField("DataRemaining", 0), 

3416 FlagsField( 

3417 "Flags", 

3418 0, 

3419 -32, 

3420 { 

3421 0x01: "SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM", 

3422 }, 

3423 ), 

3424 _NTLMPayloadField( 

3425 "Buffer", 

3426 OFFSET, 

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

3428 ), 

3429 ] 

3430 

3431 def post_build(self, pkt, pay): 

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

3433 return ( 

3434 _SMB2_post_build( 

3435 self, 

3436 pkt, 

3437 self.OFFSET, 

3438 { 

3439 "Data": 2, 

3440 }, 

3441 ) 

3442 + pay 

3443 ) 

3444 

3445 

3446bind_top_down( 

3447 SMB2_Header, 

3448 SMB2_Read_Response, 

3449 Command=0x0008, 

3450 Flags=1, 

3451) 

3452 

3453 

3454# sect 2.2.21 

3455 

3456 

3457class SMB2_Write_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3458 name = "SMB2 WRITE Request" 

3459 Command = 0x0009 

3460 OFFSET = 48 + 64 

3461 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3462 fields_desc = [ 

3463 XLEShortField("StructureSize", 0x31), 

3464 LEShortField("DataBufferOffset", None), 

3465 LEIntField("DataLen", None), 

3466 LELongField("Offset", 0), 

3467 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3468 LEIntEnumField( 

3469 "Channel", 

3470 0, 

3471 { 

3472 0x00000000: "SMB2_CHANNEL_NONE", 

3473 0x00000001: "SMB2_CHANNEL_RDMA_V1", 

3474 0x00000002: "SMB2_CHANNEL_RDMA_V1_INVALIDATE", 

3475 0x00000003: "SMB2_CHANNEL_RDMA_TRANSFORM", 

3476 }, 

3477 ), 

3478 LEIntField("RemainingBytes", 0), 

3479 LEShortField("WriteChannelInfoBufferOffset", None), 

3480 LEShortField("WriteChannelInfoLen", None), 

3481 FlagsField( 

3482 "Flags", 

3483 0, 

3484 -32, 

3485 { 

3486 0x00000001: "SMB2_WRITEFLAG_WRITE_THROUGH", 

3487 0x00000002: "SMB2_WRITEFLAG_WRITE_UNBUFFERED", 

3488 }, 

3489 ), 

3490 _NTLMPayloadField( 

3491 "Buffer", 

3492 OFFSET, 

3493 [ 

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

3495 StrLenField( 

3496 "WriteChannelInfo", 

3497 b"", 

3498 length_from=lambda pkt: pkt.WriteChannelInfoLen, 

3499 ), 

3500 ], 

3501 ), 

3502 ] 

3503 

3504 def post_build(self, pkt, pay): 

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

3506 return ( 

3507 _SMB2_post_build( 

3508 self, 

3509 pkt, 

3510 self.OFFSET, 

3511 { 

3512 "Data": 2, 

3513 "WriteChannelInfo": 40, 

3514 }, 

3515 ) 

3516 + pay 

3517 ) 

3518 

3519 

3520bind_top_down( 

3521 SMB2_Header, 

3522 SMB2_Write_Request, 

3523 Command=0x0009, 

3524) 

3525 

3526# sect 2.2.22 

3527 

3528 

3529class SMB2_Write_Response(_SMB2_Payload): 

3530 name = "SMB2 WRITE Response" 

3531 Command = 0x0009 

3532 fields_desc = [ 

3533 XLEShortField("StructureSize", 0x11), 

3534 LEShortField("Reserved", 0), 

3535 LEIntField("Count", 0), 

3536 LEIntField("Remaining", 0), 

3537 LEShortField("WriteChannelInfoBufferOffset", 0), 

3538 LEShortField("WriteChannelInfoLen", 0), 

3539 ] 

3540 

3541 

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

3543 

3544# sect 2.2.28 

3545 

3546 

3547class SMB2_Echo_Request(_SMB2_Payload): 

3548 name = "SMB2 ECHO Request" 

3549 Command = 0x000D 

3550 fields_desc = [ 

3551 XLEShortField("StructureSize", 0x4), 

3552 LEShortField("Reserved", 0), 

3553 ] 

3554 

3555 

3556bind_top_down( 

3557 SMB2_Header, 

3558 SMB2_Echo_Request, 

3559 Command=0x000D, 

3560) 

3561 

3562# sect 2.2.29 

3563 

3564 

3565class SMB2_Echo_Response(_SMB2_Payload): 

3566 name = "SMB2 ECHO Response" 

3567 Command = 0x000D 

3568 fields_desc = [ 

3569 XLEShortField("StructureSize", 0x4), 

3570 LEShortField("Reserved", 0), 

3571 ] 

3572 

3573 

3574bind_top_down( 

3575 SMB2_Header, 

3576 SMB2_Echo_Response, 

3577 Command=0x000D, 

3578 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

3579) 

3580 

3581# sect 2.2.30 

3582 

3583 

3584class SMB2_Cancel_Request(_SMB2_Payload): 

3585 name = "SMB2 CANCEL Request" 

3586 fields_desc = [ 

3587 XLEShortField("StructureSize", 0x4), 

3588 LEShortField("Reserved", 0), 

3589 ] 

3590 

3591 

3592bind_top_down( 

3593 SMB2_Header, 

3594 SMB2_Cancel_Request, 

3595 Command=0x0009, 

3596) 

3597 

3598# sect 2.2.31.4 

3599 

3600 

3601class SMB2_IOCTL_Validate_Negotiate_Info_Request(Packet): 

3602 name = "SMB2 IOCTL Validate Negotiate Info" 

3603 fields_desc = ( 

3604 SMB2_Negotiate_Protocol_Request.fields_desc[4:6] 

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

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

3607 ) 

3608 

3609 

3610# sect 2.2.31 

3611 

3612 

3613class _SMB2_IOCTL_Request_PacketLenField(PacketLenField): 

3614 def m2i(self, pkt, m): 

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

3616 return SMB2_IOCTL_Validate_Negotiate_Info_Request(m) 

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

3618 return SMB2_IOCTL_REQ_GET_DFS_Referral(m) 

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

3620 return SMB2_IOCTL_OFFLOAD_READ_Request(m) 

3621 return conf.raw_layer(m) 

3622 

3623 

3624class SMB2_IOCTL_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3625 name = "SMB2 IOCTL Request" 

3626 Command = 0x000B 

3627 OFFSET = 56 + 64 

3628 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3629 deprecated_fields = { 

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

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

3632 } 

3633 fields_desc = [ 

3634 XLEShortField("StructureSize", 0x39), 

3635 LEShortField("Reserved", 0), 

3636 LEIntEnumField( 

3637 "CtlCode", 

3638 0, 

3639 { 

3640 0x00060194: "FSCTL_DFS_GET_REFERRALS", 

3641 0x0011400C: "FSCTL_PIPE_PEEK", 

3642 0x00110018: "FSCTL_PIPE_WAIT", 

3643 0x0011C017: "FSCTL_PIPE_TRANSCEIVE", 

3644 0x001440F2: "FSCTL_SRV_COPYCHUNK", 

3645 0x00144064: "FSCTL_SRV_ENUMERATE_SNAPSHOTS", 

3646 0x00140078: "FSCTL_SRV_REQUEST_RESUME_KEY", 

3647 0x001441BB: "FSCTL_SRV_READ_HASH", 

3648 0x001480F2: "FSCTL_SRV_COPYCHUNK_WRITE", 

3649 0x001401D4: "FSCTL_LMR_REQUEST_RESILIENCY", 

3650 0x001401FC: "FSCTL_QUERY_NETWORK_INTERFACE_INFO", 

3651 0x000900A4: "FSCTL_SET_REPARSE_POINT", 

3652 0x000601B0: "FSCTL_DFS_GET_REFERRALS_EX", 

3653 0x00098208: "FSCTL_FILE_LEVEL_TRIM", 

3654 0x00140204: "FSCTL_VALIDATE_NEGOTIATE_INFO", 

3655 0x00094264: "FSCTL_OFFLOAD_READ", 

3656 }, 

3657 ), 

3658 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3659 LEIntField("InputBufferOffset", None), 

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

3661 LEIntField("MaxInputResponse", 0), 

3662 LEIntField("OutputBufferOffset", None), 

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

3664 LEIntField("MaxOutputResponse", 65535), 

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

3666 LEIntField("Reserved2", 0), 

3667 _NTLMPayloadField( 

3668 "Buffer", 

3669 OFFSET, 

3670 [ 

3671 _SMB2_IOCTL_Request_PacketLenField( 

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

3673 ), 

3674 _SMB2_IOCTL_Request_PacketLenField( 

3675 "Output", 

3676 None, 

3677 conf.raw_layer, 

3678 length_from=lambda pkt: pkt.OutputLen, 

3679 ), 

3680 ], 

3681 ), 

3682 ] 

3683 

3684 def post_build(self, pkt, pay): 

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

3686 return ( 

3687 _SMB2_post_build( 

3688 self, 

3689 pkt, 

3690 self.OFFSET, 

3691 { 

3692 "Input": 24, 

3693 "Output": 36, 

3694 }, 

3695 ) 

3696 + pay 

3697 ) 

3698 

3699 

3700bind_top_down( 

3701 SMB2_Header, 

3702 SMB2_IOCTL_Request, 

3703 Command=0x000B, 

3704) 

3705 

3706# sect 2.2.32.5 

3707 

3708 

3709class SOCKADDR_STORAGE(Packet): 

3710 fields_desc = [ 

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

3712 ShortField("Port", 0), 

3713 # IPv4 

3714 ConditionalField( 

3715 IPField("IPv4Adddress", None), 

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

3717 ), 

3718 ConditionalField( 

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

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

3721 ), 

3722 # IPv6 

3723 ConditionalField( 

3724 LEIntField("FlowInfo", 0), 

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

3726 ), 

3727 ConditionalField( 

3728 IP6Field("IPv6Address", None), 

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

3730 ), 

3731 ConditionalField( 

3732 LEIntField("ScopeId", 0), 

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

3734 ), 

3735 ] 

3736 

3737 def default_payload_class(self, _): 

3738 return conf.padding_layer 

3739 

3740 

3741class NETWORK_INTERFACE_INFO(Packet): 

3742 fields_desc = [ 

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

3744 LEIntField("IfIndex", 1), 

3745 FlagsField( 

3746 "Capability", 

3747 1, 

3748 -32, 

3749 { 

3750 0x00000001: "RSS_CAPABLE", 

3751 0x00000002: "RDMA_CAPABLE", 

3752 }, 

3753 ), 

3754 LEIntField("Reserved", 0), 

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

3756 PacketField("SockAddr_Storage", SOCKADDR_STORAGE(), SOCKADDR_STORAGE), 

3757 ] 

3758 

3759 def default_payload_class(self, _): 

3760 return conf.padding_layer 

3761 

3762 

3763class SMB2_IOCTL_Network_Interface_Info(Packet): 

3764 name = "SMB2 IOCTL Network Interface Info response" 

3765 fields_desc = [ 

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

3767 ] 

3768 

3769 

3770# sect 2.2.32.6 

3771 

3772 

3773class SMB2_IOCTL_Validate_Negotiate_Info_Response(Packet): 

3774 name = "SMB2 IOCTL Validate Negotiate Info" 

3775 fields_desc = ( 

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

3777 + SMB2_Negotiate_Protocol_Response.fields_desc[ # Cap/GUID 

3778 1:3 

3779 ] # SecMod/DialectRevision 

3780 ) 

3781 

3782 

3783# [MS-FSCC] sect 2.3.42 

3784 

3785 

3786class SMB2_IOCTL_OFFLOAD_READ_Request(Packet): 

3787 name = "SMB2 IOCTL OFFLOAD_READ Request" 

3788 fields_desc = [ 

3789 LEIntField("StructureSize", 0x20), 

3790 LEIntField("Flags", 0), 

3791 LEIntField("TokenTimeToLive", 0), 

3792 LEIntField("Reserved", 0), 

3793 LELongField("FileOffset", 0), 

3794 LELongField("CopyLength", 0), 

3795 ] 

3796 

3797 

3798# [MS-FSCC] sect 2.1.11 

3799 

3800 

3801class STORAGE_OFFLOAD_TOKEN(Packet): 

3802 fields_desc = [ 

3803 LEIntEnumField( 

3804 "TokenType", 

3805 0xFFFF0001, 

3806 { 

3807 0xFFFF0001: "STORAGE_OFFLOAD_TOKEN_TYPE_ZERO_DATA", 

3808 }, 

3809 ), 

3810 LEShortField("Reserved", 0), 

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

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

3813 ] 

3814 

3815 

3816# [MS-FSCC] sect 2.3.42 

3817 

3818 

3819class SMB2_IOCTL_OFFLOAD_READ_Response(Packet): 

3820 name = "SMB2 IOCTL OFFLOAD_READ Response" 

3821 fields_desc = [ 

3822 LEIntField("StructureSize", 0x210), 

3823 FlagsField( 

3824 "Flags", 

3825 0, 

3826 -32, 

3827 { 

3828 0x00000001: "OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE", 

3829 }, 

3830 ), 

3831 LELongField("TransferLength", 0), 

3832 PacketField("Token", STORAGE_OFFLOAD_TOKEN(), STORAGE_OFFLOAD_TOKEN), 

3833 ] 

3834 

3835 

3836# sect 2.2.32 

3837 

3838 

3839class _SMB2_IOCTL_Response_PacketLenField(PacketLenField): 

3840 def m2i(self, pkt, m): 

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

3842 return SMB2_IOCTL_Validate_Negotiate_Info_Response(m) 

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

3844 return SMB2_IOCTL_Network_Interface_Info(m) 

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

3846 return SMB2_IOCTL_RESP_GET_DFS_Referral(m) 

3847 return conf.raw_layer(m) 

3848 

3849 

3850class SMB2_IOCTL_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3851 name = "SMB2 IOCTL Response" 

3852 Command = 0x000B 

3853 OFFSET = 48 + 64 

3854 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3855 StructureSize = 0x31 

3856 MaxOutputResponse = 0 

3857 fields_desc = ( 

3858 SMB2_IOCTL_Request.fields_desc[:6] 

3859 + SMB2_IOCTL_Request.fields_desc[7:9] 

3860 + SMB2_IOCTL_Request.fields_desc[10:12] 

3861 + [ 

3862 _NTLMPayloadField( 

3863 "Buffer", 

3864 OFFSET, 

3865 [ 

3866 _SMB2_IOCTL_Response_PacketLenField( 

3867 "Input", 

3868 None, 

3869 conf.raw_layer, 

3870 length_from=lambda pkt: pkt.InputLen, 

3871 ), 

3872 _SMB2_IOCTL_Response_PacketLenField( 

3873 "Output", 

3874 None, 

3875 conf.raw_layer, 

3876 length_from=lambda pkt: pkt.OutputLen, 

3877 ), 

3878 ], 

3879 ), 

3880 ] 

3881 ) 

3882 

3883 def post_build(self, pkt, pay): 

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

3885 return ( 

3886 _SMB2_post_build( 

3887 self, 

3888 pkt, 

3889 self.OFFSET, 

3890 { 

3891 "Input": 24, 

3892 "Output": 32, 

3893 }, 

3894 ) 

3895 + pay 

3896 ) 

3897 

3898 

3899bind_top_down( 

3900 SMB2_Header, 

3901 SMB2_IOCTL_Response, 

3902 Command=0x000B, 

3903 Flags=1, # SMB2_FLAGS_SERVER_TO_REDIR 

3904) 

3905 

3906# sect 2.2.33 

3907 

3908 

3909class SMB2_Query_Directory_Request(_SMB2_Payload, _NTLMPayloadPacket): 

3910 name = "SMB2 QUERY DIRECTORY Request" 

3911 Command = 0x000E 

3912 OFFSET = 32 + 64 

3913 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3914 fields_desc = [ 

3915 XLEShortField("StructureSize", 0x21), 

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

3917 FlagsField( 

3918 "Flags", 

3919 0, 

3920 -8, 

3921 { 

3922 0x01: "SMB2_RESTART_SCANS", 

3923 0x02: "SMB2_RETURN_SINGLE_ENTRY", 

3924 0x04: "SMB2_INDEX_SPECIFIED", 

3925 0x10: "SMB2_REOPEN", 

3926 }, 

3927 ), 

3928 LEIntField("FileIndex", 0), 

3929 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

3930 LEShortField("FileNameBufferOffset", None), 

3931 LEShortField("FileNameLen", None), 

3932 LEIntField("OutputBufferLength", 65535), 

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

3934 ] 

3935 

3936 def post_build(self, pkt, pay): 

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

3938 return ( 

3939 _SMB2_post_build( 

3940 self, 

3941 pkt, 

3942 self.OFFSET, 

3943 { 

3944 "FileName": 24, 

3945 }, 

3946 ) 

3947 + pay 

3948 ) 

3949 

3950 

3951bind_top_down( 

3952 SMB2_Header, 

3953 SMB2_Query_Directory_Request, 

3954 Command=0x000E, 

3955) 

3956 

3957# sect 2.2.34 

3958 

3959 

3960class SMB2_Query_Directory_Response(_SMB2_Payload, _NTLMPayloadPacket): 

3961 name = "SMB2 QUERY DIRECTORY Response" 

3962 Command = 0x000E 

3963 OFFSET = 8 + 64 

3964 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

3965 fields_desc = [ 

3966 XLEShortField("StructureSize", 0x9), 

3967 LEShortField("OutputBufferOffset", None), 

3968 LEIntField("OutputLen", None), 

3969 _NTLMPayloadField( 

3970 "Buffer", 

3971 OFFSET, 

3972 [ 

3973 # TODO 

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

3975 ], 

3976 ), 

3977 ] 

3978 

3979 def post_build(self, pkt, pay): 

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

3981 return ( 

3982 _SMB2_post_build( 

3983 self, 

3984 pkt, 

3985 self.OFFSET, 

3986 { 

3987 "Output": 2, 

3988 }, 

3989 ) 

3990 + pay 

3991 ) 

3992 

3993 

3994bind_top_down( 

3995 SMB2_Header, 

3996 SMB2_Query_Directory_Response, 

3997 Command=0x000E, 

3998 Flags=1, 

3999) 

4000 

4001# sect 2.2.35 

4002 

4003 

4004class SMB2_Change_Notify_Request(_SMB2_Payload): 

4005 name = "SMB2 CHANGE NOTIFY Request" 

4006 Command = 0x000F 

4007 fields_desc = [ 

4008 XLEShortField("StructureSize", 0x20), 

4009 FlagsField( 

4010 "Flags", 

4011 0, 

4012 -16, 

4013 { 

4014 0x0001: "SMB2_WATCH_TREE", 

4015 }, 

4016 ), 

4017 LEIntField("OutputBufferLength", 2048), 

4018 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

4019 FlagsField( 

4020 "CompletionFilter", 

4021 0, 

4022 -32, 

4023 { 

4024 0x00000001: "FILE_NOTIFY_CHANGE_FILE_NAME", 

4025 0x00000002: "FILE_NOTIFY_CHANGE_DIR_NAME", 

4026 0x00000004: "FILE_NOTIFY_CHANGE_ATTRIBUTES", 

4027 0x00000008: "FILE_NOTIFY_CHANGE_SIZE", 

4028 0x00000010: "FILE_NOTIFY_CHANGE_LAST_WRITE", 

4029 0x00000020: "FILE_NOTIFY_CHANGE_LAST_ACCESS", 

4030 0x00000040: "FILE_NOTIFY_CHANGE_CREATION", 

4031 0x00000080: "FILE_NOTIFY_CHANGE_EA", 

4032 0x00000100: "FILE_NOTIFY_CHANGE_SECURITY", 

4033 0x00000200: "FILE_NOTIFY_CHANGE_STREAM_NAME", 

4034 0x00000400: "FILE_NOTIFY_CHANGE_STREAM_SIZE", 

4035 0x00000800: "FILE_NOTIFY_CHANGE_STREAM_WRITE", 

4036 }, 

4037 ), 

4038 LEIntField("Reserved", 0), 

4039 ] 

4040 

4041 

4042bind_top_down( 

4043 SMB2_Header, 

4044 SMB2_Change_Notify_Request, 

4045 Command=0x000F, 

4046) 

4047 

4048# sect 2.2.36 

4049 

4050 

4051class SMB2_Change_Notify_Response(_SMB2_Payload, _NTLMPayloadPacket): 

4052 name = "SMB2 CHANGE NOTIFY Response" 

4053 Command = 0x000F 

4054 OFFSET = 8 + 64 

4055 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

4056 fields_desc = [ 

4057 XLEShortField("StructureSize", 0x9), 

4058 LEShortField("OutputBufferOffset", None), 

4059 LEIntField("OutputLen", None), 

4060 _NTLMPayloadField( 

4061 "Buffer", 

4062 OFFSET, 

4063 [ 

4064 _NextPacketListField( 

4065 "Output", 

4066 [], 

4067 FILE_NOTIFY_INFORMATION, 

4068 length_from=lambda pkt: pkt.OutputLen, 

4069 max_count=1000, 

4070 ) 

4071 ], 

4072 ), 

4073 ] 

4074 

4075 def post_build(self, pkt, pay): 

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

4077 return ( 

4078 _SMB2_post_build( 

4079 self, 

4080 pkt, 

4081 self.OFFSET, 

4082 { 

4083 "Output": 2, 

4084 }, 

4085 ) 

4086 + pay 

4087 ) 

4088 

4089 

4090bind_top_down( 

4091 SMB2_Header, 

4092 SMB2_Change_Notify_Response, 

4093 Command=0x000F, 

4094 Flags=1, 

4095) 

4096 

4097# sect 2.2.37 

4098 

4099 

4100class FILE_GET_QUOTA_INFORMATION(Packet): 

4101 fields_desc = [ 

4102 IntField("NextEntryOffset", 0), 

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

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

4105 StrLenField( 

4106 "pad", 

4107 b"", 

4108 length_from=lambda x: ( 

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

4110 ), 

4111 ), 

4112 ] 

4113 

4114 

4115class SMB2_Query_Quota_Info(Packet): 

4116 fields_desc = [ 

4117 ByteField("ReturnSingle", 0), 

4118 ByteField("ReturnBoolean", 0), 

4119 ShortField("Reserved", 0), 

4120 LEIntField("SidListLength", 0), 

4121 LEIntField("StartSidLength", 0), 

4122 LEIntField("StartSidOffset", 0), 

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

4124 MultipleTypeField( 

4125 [ 

4126 ( 

4127 PacketListField( 

4128 "SidBuffer", 

4129 [], 

4130 FILE_GET_QUOTA_INFORMATION, 

4131 length_from=lambda x: x.SidListLength, 

4132 ), 

4133 lambda x: x.SidListLength, 

4134 ), 

4135 ( 

4136 StrLenField( 

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

4138 ), 

4139 lambda x: x.StartSidLength, 

4140 ), 

4141 ], 

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

4143 ), 

4144 ] 

4145 

4146 

4147SMB2_INFO_TYPE = { 

4148 0x01: "SMB2_0_INFO_FILE", 

4149 0x02: "SMB2_0_INFO_FILESYSTEM", 

4150 0x03: "SMB2_0_INFO_SECURITY", 

4151 0x04: "SMB2_0_INFO_QUOTA", 

4152} 

4153 

4154SMB2_ADDITIONAL_INFORMATION = { 

4155 0x00000001: "OWNER_SECURITY_INFORMATION", 

4156 0x00000002: "GROUP_SECURITY_INFORMATION", 

4157 0x00000004: "DACL_SECURITY_INFORMATION", 

4158 0x00000008: "SACL_SECURITY_INFORMATION", 

4159 0x00000010: "LABEL_SECURITY_INFORMATION", 

4160 0x00000020: "ATTRIBUTE_SECURITY_INFORMATION", 

4161 0x00000040: "SCOPE_SECURITY_INFORMATION", 

4162 0x00010000: "BACKUP_SECURITY_INFORMATION", 

4163} 

4164 

4165 

4166class SMB2_Query_Info_Request(_SMB2_Payload, _NTLMPayloadPacket): 

4167 name = "SMB2 QUERY INFO Request" 

4168 Command = 0x0010 

4169 OFFSET = 40 + 64 

4170 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

4171 fields_desc = [ 

4172 XLEShortField("StructureSize", 0x29), 

4173 ByteEnumField( 

4174 "InfoType", 

4175 0, 

4176 SMB2_INFO_TYPE, 

4177 ), 

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

4179 LEIntField("OutputBufferLength", 0), 

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

4181 LEIntField("InputLen", None), 

4182 FlagsField( 

4183 "AdditionalInformation", 

4184 0, 

4185 -32, 

4186 SMB2_ADDITIONAL_INFORMATION, 

4187 ), 

4188 FlagsField( 

4189 "Flags", 

4190 0, 

4191 -32, 

4192 { 

4193 0x00000001: "SL_RESTART_SCAN", 

4194 0x00000002: "SL_RETURN_SINGLE_ENTRY", 

4195 0x00000004: "SL_INDEX_SPECIFIED", 

4196 }, 

4197 ), 

4198 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

4199 _NTLMPayloadField( 

4200 "Buffer", 

4201 OFFSET, 

4202 [ 

4203 MultipleTypeField( 

4204 [ 

4205 ( 

4206 # QUOTA 

4207 PacketListField( 

4208 "Input", 

4209 None, 

4210 SMB2_Query_Quota_Info, 

4211 length_from=lambda pkt: pkt.InputLen, 

4212 ), 

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

4214 ), 

4215 ], 

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

4217 ), 

4218 ], 

4219 ), 

4220 ] 

4221 

4222 def post_build(self, pkt, pay): 

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

4224 return ( 

4225 _SMB2_post_build( 

4226 self, 

4227 pkt, 

4228 self.OFFSET, 

4229 { 

4230 "Input": 4, 

4231 }, 

4232 ) 

4233 + pay 

4234 ) 

4235 

4236 

4237bind_top_down( 

4238 SMB2_Header, 

4239 SMB2_Query_Info_Request, 

4240 Command=0x00010, 

4241) 

4242 

4243 

4244class SMB2_Query_Info_Response(_SMB2_Payload, _NTLMPayloadPacket): 

4245 name = "SMB2 QUERY INFO Response" 

4246 Command = 0x0010 

4247 OFFSET = 8 + 64 

4248 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

4249 fields_desc = [ 

4250 XLEShortField("StructureSize", 0x9), 

4251 LEShortField("OutputBufferOffset", None), 

4252 LEIntField("OutputLen", None), 

4253 _NTLMPayloadField( 

4254 "Buffer", 

4255 OFFSET, 

4256 [ 

4257 # TODO 

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

4259 ], 

4260 ), 

4261 ] 

4262 

4263 def post_build(self, pkt, pay): 

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

4265 return ( 

4266 _SMB2_post_build( 

4267 self, 

4268 pkt, 

4269 self.OFFSET, 

4270 { 

4271 "Output": 2, 

4272 }, 

4273 ) 

4274 + pay 

4275 ) 

4276 

4277 

4278bind_top_down( 

4279 SMB2_Header, 

4280 SMB2_Query_Info_Response, 

4281 Command=0x00010, 

4282 Flags=1, 

4283) 

4284 

4285 

4286# sect 2.2.39 

4287 

4288 

4289class SMB2_Set_Info_Request(_SMB2_Payload, _NTLMPayloadPacket): 

4290 name = "SMB2 SET INFO Request" 

4291 Command = 0x0011 

4292 OFFSET = 32 + 64 

4293 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

4294 fields_desc = [ 

4295 XLEShortField("StructureSize", 0x21), 

4296 ByteEnumField( 

4297 "InfoType", 

4298 0, 

4299 SMB2_INFO_TYPE, 

4300 ), 

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

4302 LEIntField("DataLen", None), 

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

4304 FlagsField( 

4305 "AdditionalInformation", 

4306 0, 

4307 -32, 

4308 SMB2_ADDITIONAL_INFORMATION, 

4309 ), 

4310 PacketField("FileId", SMB2_FILEID(), SMB2_FILEID), 

4311 _NTLMPayloadField( 

4312 "Buffer", 

4313 OFFSET, 

4314 [ 

4315 MultipleTypeField( 

4316 [ 

4317 ( 

4318 # FILE 

4319 PacketLenField( 

4320 "Data", 

4321 None, 

4322 lambda x, _parent: _FileInformationClasses.get( 

4323 _parent.FileInfoClass, conf.raw_layer 

4324 )(x), 

4325 length_from=lambda pkt: pkt.DataLen, 

4326 ), 

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

4328 ), 

4329 ( 

4330 # QUOTA 

4331 PacketListField( 

4332 "Data", 

4333 None, 

4334 SMB2_Query_Quota_Info, 

4335 length_from=lambda pkt: pkt.DataLen, 

4336 ), 

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

4338 ), 

4339 ], 

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

4341 ), 

4342 ], 

4343 ), 

4344 ] 

4345 

4346 def post_build(self, pkt, pay): 

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

4348 return ( 

4349 _SMB2_post_build( 

4350 self, 

4351 pkt, 

4352 self.OFFSET, 

4353 { 

4354 "Data": 4, 

4355 }, 

4356 ) 

4357 + pay 

4358 ) 

4359 

4360 

4361bind_top_down( 

4362 SMB2_Header, 

4363 SMB2_Set_Info_Request, 

4364 Command=0x00011, 

4365) 

4366 

4367 

4368class SMB2_Set_Info_Response(_SMB2_Payload): 

4369 name = "SMB2 SET INFO Request" 

4370 Command = 0x0011 

4371 fields_desc = [ 

4372 XLEShortField("StructureSize", 0x02), 

4373 ] 

4374 

4375 

4376bind_top_down( 

4377 SMB2_Header, 

4378 SMB2_Set_Info_Response, 

4379 Command=0x00011, 

4380 Flags=1, 

4381) 

4382 

4383 

4384# sect 2.2.41 

4385 

4386 

4387class SMB2_Transform_Header(Packet): 

4388 name = "SMB2 Transform Header" 

4389 fields_desc = [ 

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

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

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

4393 LEIntField("OriginalMessageSize", 0x0), 

4394 LEShortField("Reserved", 0), 

4395 LEShortEnumField( 

4396 "Flags", 

4397 0x1, 

4398 { 

4399 0x0001: "ENCRYPTED", 

4400 }, 

4401 ), 

4402 LELongField("SessionId", 0), 

4403 ] 

4404 

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

4406 """ 

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

4408 """ 

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

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

4411 

4412 if "GCM" in CipherId: 

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

4414 

4415 nonce = self.Nonce[:12] 

4416 cipher = AESGCM(DecryptionKey) 

4417 elif "CCM" in CipherId: 

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

4419 

4420 nonce = self.Nonce[:11] 

4421 cipher = AESCCM(DecryptionKey) 

4422 else: 

4423 raise Exception("Unknown CipherId !") 

4424 

4425 # Decrypt the data 

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

4427 data = cipher.decrypt( 

4428 nonce, 

4429 self.payload.load + self.Signature, 

4430 aad, 

4431 ) 

4432 return SMB2_Header(data, _decrypted=True) 

4433 

4434 

4435bind_layers(SMB2_Transform_Header, conf.raw_layer) 

4436 

4437 

4438# sect 2.2.42.1 

4439 

4440 

4441class SMB2_Compression_Transform_Header(Packet): 

4442 name = "SMB2 Compression Transform Header" 

4443 fields_desc = [ 

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

4445 LEIntField("OriginalCompressedSegmentSize", 0x0), 

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

4447 LEShortEnumField( 

4448 "Flags", 

4449 0x0, 

4450 { 

4451 0x0000: "SMB2_COMPRESSION_FLAG_NONE", 

4452 0x0001: "SMB2_COMPRESSION_FLAG_CHAINED", 

4453 }, 

4454 ), 

4455 XLEIntField("Offset_or_Length", 0), 

4456 ] 

4457 

4458 

4459# [MS-DFSC] sect 2.2 

4460 

4461 

4462class SMB2_IOCTL_REQ_GET_DFS_Referral(Packet): 

4463 fields_desc = [ 

4464 LEShortField("MaxReferralLevel", 0), 

4465 StrNullFieldUtf16("RequestFileName", ""), 

4466 ] 

4467 

4468 

4469class DFS_REFERRAL(Packet): 

4470 fields_desc = [ 

4471 LEShortField("Version", 1), 

4472 FieldLenField( 

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

4474 ), 

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

4476 LEShortField("ReferralEntryFlags", 0), 

4477 StrNullFieldUtf16("ShareName", ""), 

4478 ] 

4479 

4480 @classmethod 

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

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

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

4484 if version == 1: 

4485 return DFS_REFERRAL 

4486 elif version == 3: 

4487 return DFS_REFERRAL_V3 

4488 elif version == 4: 

4489 return DFS_REFERRAL_V4 

4490 return cls 

4491 

4492 def default_payload_class(self, s): 

4493 return conf.padding_layer 

4494 

4495 

4496class DFS_REFERRAL_V3(DFS_REFERRAL): 

4497 fields_desc = [ 

4498 LEShortField("Version", 3), 

4499 LEShortField("Size", None), 

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

4501 FlagsField( 

4502 "ReferralEntryFlags", 

4503 0, 

4504 -16, 

4505 { 

4506 0x0002: "NameListReferral", 

4507 0x0004: "TargetSetBoundary", 

4508 }, 

4509 ), 

4510 LEIntField("TimeToLive", 300), 

4511 # NameListReferral is 0 

4512 ConditionalField( 

4513 LEShortField("DFSPathOffset", None), 

4514 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

4515 ), 

4516 ConditionalField( 

4517 LEShortField("DFSAlternatePathOffset", None), 

4518 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

4519 ), 

4520 ConditionalField( 

4521 LEShortField("NetworkAddressOffset", None), 

4522 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

4523 ), 

4524 ConditionalField( 

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

4526 lambda pkt: not pkt.ReferralEntryFlags.NameListReferral, 

4527 ), 

4528 # NameListReferral is 1 

4529 ConditionalField( 

4530 LEShortField("SpecialNameOffset", None), 

4531 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

4532 ), 

4533 ConditionalField( 

4534 LEShortField("NumberOfExpandedNames", None), 

4535 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

4536 ), 

4537 ConditionalField( 

4538 LEShortField("ExpandedNameOffset", None), 

4539 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

4540 ), 

4541 ConditionalField( 

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

4543 lambda pkt: pkt.ReferralEntryFlags.NameListReferral, 

4544 ), 

4545 ] 

4546 

4547 def post_build(self, pkt, pay): 

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

4549 if self.Size is None: 

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

4551 return pkt + pay 

4552 

4553 

4554class DFS_REFERRAL_V4(DFS_REFERRAL_V3): 

4555 Version = 4 

4556 

4557 

4558class DFS_REFERRAL_ENTRY0(Packet): 

4559 fields_desc = [ 

4560 StrNullFieldUtf16("DFSPath", ""), 

4561 StrNullFieldUtf16("DFSAlternatePath", ""), 

4562 StrNullFieldUtf16("NetworkAddress", ""), 

4563 ] 

4564 

4565 

4566class DFS_REFERRAL_ENTRY1(Packet): 

4567 fields_desc = [ 

4568 StrNullFieldUtf16("SpecialName", ""), 

4569 FieldListField( 

4570 "ExpandedName", 

4571 [], 

4572 StrNullFieldUtf16("", ""), 

4573 ), 

4574 ] 

4575 

4576 

4577class _DFS_Referrals_BufferField(PacketListField): 

4578 def getfield(self, pkt, s): 

4579 results = [] 

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

4581 for ref in pkt.ReferralEntries: 

4582 # For every ref 

4583 if not ref.ReferralEntryFlags.NameListReferral: 

4584 cls = DFS_REFERRAL_ENTRY0 

4585 else: 

4586 cls = DFS_REFERRAL_ENTRY1 

4587 # Build the fields manually 

4588 fld = _NTLMPayloadField( 

4589 "", 

4590 offset, 

4591 cls.fields_desc, 

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

4593 offset_name="Offset", 

4594 ) 

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

4596 vals = fld.i2h(ref, vals) 

4597 # Append the entry class 

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

4599 offset -= ref.Size 

4600 return b"", results 

4601 

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

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

4604 for i, val in enumerate(vals): 

4605 try: 

4606 ref = pkt.ReferralEntries[i] 

4607 except KeyError: 

4608 ref = None 

4609 fld = _NTLMPayloadField( 

4610 "", 

4611 offset, 

4612 val.fields_desc, 

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

4614 offset_name="Offset", 

4615 ) 

4616 # Append the bytes manually 

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

4618 values = fld.h2i(ref, values) 

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

4620 offset -= len(ref) 

4621 return s 

4622 

4623 

4624class SMB2_IOCTL_RESP_GET_DFS_Referral(Packet): 

4625 fields_desc = [ 

4626 LEShortField("PathConsumed", 0), 

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

4628 FlagsField( 

4629 "ReferralHeaderFlags", 

4630 0, 

4631 -32, 

4632 { 

4633 0x00000001: "ReferralServers", 

4634 0x00000002: "StorageServers", 

4635 0x00000004: "TargetFailback", 

4636 }, 

4637 ), 

4638 PacketListField( 

4639 "ReferralEntries", 

4640 [], 

4641 DFS_REFERRAL, 

4642 count_from=lambda pkt: pkt.NumberOfReferrals, 

4643 ), 

4644 _DFS_Referrals_BufferField("ReferralBuffer", []), 

4645 ] 

4646 

4647 def post_build(self, pkt, pay): 

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

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

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

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

4652 offsets = { 

4653 # DFS_REFERRAL_ENTRY0 

4654 "DFSPath": 12, 

4655 "DFSAlternatePath": 14, 

4656 "NetworkAddress": 16, 

4657 # DFS_REFERRAL_ENTRY1 

4658 "SpecialName": 12, 

4659 "ExpandedName": 16, 

4660 } 

4661 # dataoffset = pointer in the ReferralBuffer 

4662 # entryoffset = pointer in the ReferralEntries 

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

4664 entryoffset = 8 

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

4666 for fld in buf.fields_desc: 

4667 off = entryoffset + offsets[fld.name] 

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

4669 fld.name 

4670 ): 

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

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

4673 dataoffset -= len(ref) 

4674 entryoffset += len(ref) 

4675 return pkt + pay 

4676 

4677 

4678# [MS-SMB2] various usages 

4679 

4680 

4681def SMB2computePreauthIntegrityHashValue( 

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

4683): 

4684 """ 

4685 Update the PreauthIntegrityHashValue 

4686 """ 

4687 # get hasher 

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

4689 # compute the hash of concatenation of previous and bytes 

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

4691 

4692 

4693# SMB2 socket and session 

4694 

4695 

4696class SMBStreamSocket(StreamSocket): 

4697 """ 

4698 A modified StreamSocket to dissect SMB compounded requests 

4699 [MS-SMB2] 3.3.5.2.7 

4700 """ 

4701 

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

4703 self.queue = collections.deque() 

4704 self.session = SMBSession() 

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

4706 

4707 def recv(self, x=None): 

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

4709 # this takes care of splitting compounded requests 

4710 if self.queue: 

4711 pkt = self.queue.popleft() 

4712 else: 

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

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

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

4716 if pkt is not None and ( 

4717 SMB2_Header in pkt 

4718 or SMB2_Transform_Header in pkt 

4719 or SMB2_Compression_Transform_Header in pkt 

4720 ): 

4721 pkt = self.session.in_pkt(pkt) 

4722 pay = pkt[SMB2_Header].payload 

4723 while SMB2_Header in pay: 

4724 pay = pay[SMB2_Header] 

4725 pay.underlayer.remove_payload() 

4726 self.queue.append(pay) 

4727 if not pay.NextCommand: 

4728 break 

4729 pay = pay.payload 

4730 # Verify the signature if required. 

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

4732 smbh = pkt.getlayer(SMB2_Header) 

4733 if ( 

4734 smbh 

4735 and self.session.Dialect 

4736 and self.session.SigningKey 

4737 and self.session.SigningRequired 

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

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

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

4741 and not smbh._decrypted 

4742 # - MessageId is 0xFFFFFFFFFFFFFFFF 

4743 and smbh.MID != 0xFFFFFFFFFFFFFFFF 

4744 # - Status in the SMB2 header is STATUS_PENDING 

4745 and smbh.Status != 0x00000103 

4746 ): 

4747 smbh.verify( 

4748 self.session.Dialect, 

4749 self.session.SigningKey, 

4750 # SMB 3.1.1 parameters: 

4751 SigningAlgorithmId=self.session.SigningAlgorithmId, 

4752 IsClient=False, 

4753 ) 

4754 return pkt 

4755 

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

4757 for pkt in self.session.out_pkt( 

4758 x, Compounded=Compounded, ForceSign=ForceSign, ForceEncrypt=ForceEncrypt 

4759 ): 

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

4761 

4762 @staticmethod 

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

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

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

4766 return select_objects(sockets, remain=remain) 

4767 

4768 

4769class SMBSession(DefaultSession): 

4770 """ 

4771 A SMB session within a TCP socket. 

4772 """ 

4773 

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

4775 self.smb_header = None 

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

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

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

4779 # SMB session parameters 

4780 self.CompoundQueue = [] 

4781 self.Dialect = 0x0202 # Updated by parent 

4782 self.Credits = 0 

4783 self.IsGuest = False 

4784 self.MaxTransactionSize = 0 

4785 self.MaxReadSize = 0 

4786 self.MaxWriteSize = 0 

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

4788 self.SigningRequired = True 

4789 self.SupportsEncryption = False 

4790 self.EncryptData = False 

4791 self.TreeEncryptData = False 

4792 self.SigningKey = None 

4793 self.EncryptionKey = None 

4794 self.DecryptionKey = None 

4795 self.PreauthIntegrityHashId = "SHA-512" 

4796 self.SupportedCipherIds = [ 

4797 "AES-128-CCM", 

4798 "AES-128-GCM", 

4799 "AES-256-CCM", 

4800 "AES-256-GCM", 

4801 ] 

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

4803 self.SupportedSigningAlgorithmIds = [ 

4804 "AES-CMAC", 

4805 "HMAC-SHA256", 

4806 ] 

4807 self.SigningAlgorithmId = None 

4808 self.Salt = os.urandom(32) 

4809 self.ConnectionPreauthIntegrityHashValue = None 

4810 self.SessionPreauthIntegrityHashValue = None 

4811 # SMB 3.1.1 

4812 self.SessionPreauthIntegrityHashValue = None 

4813 if conf.winssps_passive: 

4814 for ssp in conf.winssps_passive: 

4815 self.sniffsspcontexts[ssp] = None 

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

4817 

4818 # SMB crypto functions 

4819 

4820 @crypto_validator 

4821 def computeSMBSessionKeys(self, IsClient=None): 

4822 """ 

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

4824 """ 

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

4826 # no signing key, no session key 

4827 return 

4828 # [MS-SMB2] sect 3.3.5.5.3 

4829 # SigningKey 

4830 if self.Dialect >= 0x0300: 

4831 if self.Dialect == 0x0311: 

4832 label = b"SMBSigningKey\x00" 

4833 context = self.SessionPreauthIntegrityHashValue 

4834 else: 

4835 label = b"SMB2AESCMAC\x00" 

4836 context = b"SmbSign\x00" 

4837 # [MS-SMB2] sect 3.1.4.2 

4838 if "256" in self.CipherId: 

4839 L = 256 

4840 elif "128" in self.CipherId: 

4841 L = 128 

4842 else: 

4843 raise ValueError 

4844 self.SigningKey = SP800108_KDFCTR( 

4845 self.sspcontext.SessionKey[:16], 

4846 label, 

4847 context, 

4848 L, 

4849 ) 

4850 # EncryptionKey / DecryptionKey 

4851 if self.Dialect == 0x0311: 

4852 if IsClient: 

4853 label_out = b"SMBC2SCipherKey\x00" 

4854 label_in = b"SMBS2CCipherKey\x00" 

4855 else: 

4856 label_out = b"SMBS2CCipherKey\x00" 

4857 label_in = b"SMBC2SCipherKey\x00" 

4858 context_out = context_in = self.SessionPreauthIntegrityHashValue 

4859 else: 

4860 label_out = label_in = b"SMB2AESCCM\x00" 

4861 if IsClient: 

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

4863 context_in = b"ServerOut\x00" 

4864 else: 

4865 context_out = b"ServerOut\x00" 

4866 context_in = b"ServerIn \x00" 

4867 self.EncryptionKey = SP800108_KDFCTR( 

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

4869 label_out, 

4870 context_out, 

4871 L, 

4872 ) 

4873 self.DecryptionKey = SP800108_KDFCTR( 

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

4875 label_in, 

4876 context_in, 

4877 L, 

4878 ) 

4879 elif self.Dialect <= 0x0210: 

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

4881 else: 

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

4883 

4884 def computeSMBConnectionPreauth(self, *negopkts): 

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

4886 # [MS-SMB2] 3.3.5.4 

4887 # TODO: handle SMB2_SESSION_FLAG_BINDING 

4888 if self.ConnectionPreauthIntegrityHashValue is None: 

4889 # New auth or failure 

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

4891 # Calculate the *Connection* PreauthIntegrityHashValue 

4892 for negopkt in negopkts: 

4893 self.ConnectionPreauthIntegrityHashValue = ( 

4894 SMB2computePreauthIntegrityHashValue( 

4895 self.ConnectionPreauthIntegrityHashValue, 

4896 negopkt, 

4897 HashId=self.PreauthIntegrityHashId, 

4898 ) 

4899 ) 

4900 

4901 def computeSMBSessionPreauth(self, *sesspkts): 

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

4903 # [MS-SMB2] 3.3.5.5.3 

4904 if self.SessionPreauthIntegrityHashValue is None: 

4905 # New auth or failure 

4906 self.SessionPreauthIntegrityHashValue = ( 

4907 self.ConnectionPreauthIntegrityHashValue 

4908 ) 

4909 # Calculate the *Session* PreauthIntegrityHashValue 

4910 for sesspkt in sesspkts: 

4911 self.SessionPreauthIntegrityHashValue = ( 

4912 SMB2computePreauthIntegrityHashValue( 

4913 self.SessionPreauthIntegrityHashValue, 

4914 sesspkt, 

4915 HashId=self.PreauthIntegrityHashId, 

4916 ) 

4917 ) 

4918 

4919 # I/O 

4920 

4921 def in_pkt(self, pkt): 

4922 """ 

4923 Incoming SMB packet 

4924 """ 

4925 if SMB2_Transform_Header in pkt: 

4926 # Packet is encrypted 

4927 pkt = pkt[SMB2_Transform_Header].decrypt( 

4928 self.Dialect, 

4929 self.DecryptionKey, 

4930 CipherId=self.CipherId, 

4931 ) 

4932 # Signature is verified in SMBStreamSocket 

4933 return pkt 

4934 

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

4936 """ 

4937 Outgoing SMB packet 

4938 

4939 :param pkt: the packet to send 

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

4941 un-compounded packet 

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

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

4944 

4945 Handles: 

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

4947 - handles signing and encryption (if required) 

4948 """ 

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

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

4951 if SMB2_Header in pkt: 

4952 if self.CompoundQueue: 

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

4954 pkt = pkt[SMB2_Header] 

4955 if Compounded: 

4956 # [MS-SMB2] 3.2.4.1.4 

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

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

4959 # an 8-byte boundary." 

4960 # [MS-SMB2] 3.1.4.1 

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

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

4963 # computation." 

4964 length = len(pkt[SMB2_Header]) 

4965 padlen = (-length) % 8 

4966 if padlen: 

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

4968 pkt[SMB2_Header].NextCommand = length + padlen 

4969 if ( 

4970 self.Dialect 

4971 and self.SigningKey 

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

4973 ): 

4974 # [MS-SMB2] sect 3.2.4.1.1 - Signing 

4975 smb = pkt[SMB2_Header] 

4976 smb.Flags += "SMB2_FLAGS_SIGNED" 

4977 smb.sign( 

4978 self.Dialect, 

4979 self.SigningKey, 

4980 # SMB 3.1.1 parameters: 

4981 SigningAlgorithmId=self.SigningAlgorithmId, 

4982 IsClient=False, 

4983 ) 

4984 if Compounded: 

4985 # There IS a next compound. Store in queue 

4986 self.CompoundQueue.append(pkt) 

4987 return [] 

4988 else: 

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

4990 if self.CompoundQueue: 

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

4992 self.CompoundQueue.clear() 

4993 if self.EncryptionKey and ( 

4994 ForceEncrypt or self.EncryptData or self.TreeEncryptData 

4995 ): 

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

4997 smb = pkt[SMB2_Header] 

4998 assert not smb.Flags.SMB2_FLAGS_SIGNED 

4999 smbt = smb.encrypt( 

5000 self.Dialect, 

5001 self.EncryptionKey, 

5002 CipherId=self.CipherId, 

5003 ) 

5004 if smb.underlayer: 

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

5006 smb.underlayer.payload = smbt 

5007 else: 

5008 smb = smbt 

5009 return [pkt] 

5010 

5011 def process(self, pkt: Packet): 

5012 # Called when passively sniffing 

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

5014 if pkt is not None and SMB2_Header in pkt: 

5015 return self.in_pkt(pkt) 

5016 return pkt