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

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

280 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) Philippe Biondi <phil@secdev.org> 

5# Copyright (C) Gabriel Potter 

6 

7""" 

8SMB 1.0 (Server Message Block), also known as CIFS. 

9 

10.. note:: 

11 You will find more complete documentation for this layer over at 

12 `SMB <https://scapy.readthedocs.io/en/latest/layers/smb.html>`_ 

13 

14Specs: 

15 

16- [MS-CIFS] (base) 

17- [MS-SMB] (extension of CIFS - SMB v1) 

18""" 

19 

20import struct 

21 

22from scapy.config import conf 

23from scapy.packet import Packet, bind_layers, bind_top_down 

24from scapy.fields import ( 

25 ByteEnumField, 

26 ByteField, 

27 ConditionalField, 

28 FieldLenField, 

29 FieldListField, 

30 FlagsField, 

31 IPField, 

32 LEFieldLenField, 

33 LEIntEnumField, 

34 LEIntField, 

35 LELongField, 

36 LEShortEnumField, 

37 LEShortField, 

38 MultipleTypeField, 

39 PacketField, 

40 PacketLenField, 

41 PacketListField, 

42 ReversePadField, 

43 ScalingField, 

44 ShortField, 

45 StrFixedLenField, 

46 StrNullField, 

47 StrNullFieldUtf16, 

48 UTCTimeField, 

49 UUIDField, 

50 XLEShortField, 

51 XStrLenField, 

52) 

53 

54from scapy.layers.dns import ( 

55 DNSStrField, 

56 DNSCompressedPacket, 

57) 

58from scapy.layers.ntlm import ( 

59 _NTLMPayloadPacket, 

60 _NTLMPayloadField, 

61 _NTLM_ENUM, 

62 _NTLM_post_build, 

63) 

64from scapy.layers.netbios import NBTSession, NBTDatagram 

65from scapy.layers.gssapi import ( 

66 GSSAPI_BLOB, 

67) 

68from scapy.layers.smb2 import ( 

69 STATUS_ERREF, 

70 SMB2_Compression_Transform_Header, 

71 SMB2_Header, 

72 SMB2_Transform_Header, 

73) 

74 

75 

76SMB_COM = { 

77 0x00: "SMB_COM_CREATE_DIRECTORY", 

78 0x01: "SMB_COM_DELETE_DIRECTORY", 

79 0x02: "SMB_COM_OPEN", 

80 0x03: "SMB_COM_CREATE", 

81 0x04: "SMB_COM_CLOSE", 

82 0x05: "SMB_COM_FLUSH", 

83 0x06: "SMB_COM_DELETE", 

84 0x07: "SMB_COM_RENAME", 

85 0x08: "SMB_COM_QUERY_INFORMATION", 

86 0x09: "SMB_COM_SET_INFORMATION", 

87 0x0A: "SMB_COM_READ", 

88 0x0B: "SMB_COM_WRITE", 

89 0x0C: "SMB_COM_LOCK_BYTE_RANGE", 

90 0x0D: "SMB_COM_UNLOCK_BYTE_RANGE", 

91 0x0E: "SMB_COM_CREATE_TEMPORARY", 

92 0x0F: "SMB_COM_CREATE_NEW", 

93 0x10: "SMB_COM_CHECK_DIRECTORY", 

94 0x11: "SMB_COM_PROCESS_EXIT", 

95 0x12: "SMB_COM_SEEK", 

96 0x13: "SMB_COM_LOCK_AND_READ", 

97 0x14: "SMB_COM_WRITE_AND_UNLOCK", 

98 0x1A: "SMB_COM_READ_RAW", 

99 0x1B: "SMB_COM_READ_MPX", 

100 0x1C: "SMB_COM_READ_MPX_SECONDARY", 

101 0x1D: "SMB_COM_WRITE_RAW", 

102 0x1E: "SMB_COM_WRITE_MPX", 

103 0x1F: "SMB_COM_WRITE_MPX_SECONDARY", 

104 0x20: "SMB_COM_WRITE_COMPLETE", 

105 0x21: "SMB_COM_QUERY_SERVER", 

106 0x22: "SMB_COM_SET_INFORMATION2", 

107 0x23: "SMB_COM_QUERY_INFORMATION2", 

108 0x24: "SMB_COM_LOCKING_ANDX", 

109 0x25: "SMB_COM_TRANSACTION", 

110 0x26: "SMB_COM_TRANSACTION_SECONDARY", 

111 0x27: "SMB_COM_IOCTL", 

112 0x28: "SMB_COM_IOCTL_SECONDARY", 

113 0x29: "SMB_COM_COPY", 

114 0x2A: "SMB_COM_MOVE", 

115 0x2B: "SMB_COM_ECHO", 

116 0x2C: "SMB_COM_WRITE_AND_CLOSE", 

117 0x2D: "SMB_COM_OPEN_ANDX", 

118 0x2E: "SMB_COM_READ_ANDX", 

119 0x2F: "SMB_COM_WRITE_ANDX", 

120 0x30: "SMB_COM_NEW_FILE_SIZE", 

121 0x31: "SMB_COM_CLOSE_AND_TREE_DISC", 

122 0x32: "SMB_COM_TRANSACTION2", 

123 0x33: "SMB_COM_TRANSACTION2_SECONDARY", 

124 0x34: "SMB_COM_FIND_CLOSE2", 

125 0x35: "SMB_COM_FIND_NOTIFY_CLOSE", 

126 0x70: "SMB_COM_TREE_CONNECT", 

127 0x71: "SMB_COM_TREE_DISCONNECT", 

128 0x72: "SMB_COM_NEGOTIATE", 

129 0x73: "SMB_COM_SESSION_SETUP_ANDX", 

130 0x74: "SMB_COM_LOGOFF_ANDX", 

131 0x75: "SMB_COM_TREE_CONNECT_ANDX", 

132 0x7E: "SMB_COM_SECURITY_PACKAGE_ANDX", 

133 0x80: "SMB_COM_QUERY_INFORMATION_DISK", 

134 0x81: "SMB_COM_SEARCH", 

135 0x82: "SMB_COM_FIND", 

136 0x83: "SMB_COM_FIND_UNIQUE", 

137 0x84: "SMB_COM_FIND_CLOSE", 

138 0xA0: "SMB_COM_NT_TRANSACT", 

139 0xA1: "SMB_COM_NT_TRANSACT_SECONDARY", 

140 0xA2: "SMB_COM_NT_CREATE_ANDX", 

141 0xA4: "SMB_COM_NT_CANCEL", 

142 0xA5: "SMB_COM_NT_RENAME", 

143 0xC0: "SMB_COM_OPEN_PRINT_FILE", 

144 0xC1: "SMB_COM_WRITE_PRINT_FILE", 

145 0xC2: "SMB_COM_CLOSE_PRINT_FILE", 

146 0xC3: "SMB_COM_GET_PRINT_QUEUE", 

147 0xD8: "SMB_COM_READ_BULK", 

148 0xD9: "SMB_COM_WRITE_BULK", 

149 0xDA: "SMB_COM_WRITE_BULK_DATA", 

150 0xFE: "SMB_COM_INVALID", 

151 0xFF: "SMB_COM_NO_ANDX_COMMAND", 

152} 

153 

154 

155class SMB_Header(Packet): 

156 name = "SMB 1 Protocol Request Header" 

157 fields_desc = [ 

158 StrFixedLenField("Start", b"\xffSMB", 4), 

159 ByteEnumField("Command", 0x72, SMB_COM), 

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

161 FlagsField( 

162 "Flags", 

163 0x18, 

164 8, 

165 [ 

166 "LOCK_AND_READ_OK", 

167 "BUF_AVAIL", 

168 "res", 

169 "CASE_INSENSITIVE", 

170 "CANONICALIZED_PATHS", 

171 "OPLOCK", 

172 "OPBATCH", 

173 "REPLY", 

174 ], 

175 ), 

176 FlagsField( 

177 "Flags2", 

178 0x0000, 

179 -16, 

180 [ 

181 "LONG_NAMES", 

182 "EAS", 

183 "SMB_SECURITY_SIGNATURE", 

184 "COMPRESSED", 

185 "SMB_SECURITY_SIGNATURE_REQUIRED", 

186 "res", 

187 "IS_LONG_NAME", 

188 "res", 

189 "res", 

190 "res", 

191 "REPARSE_PATH", 

192 "EXTENDED_SECURITY", 

193 "DFS", 

194 "PAGING_IO", 

195 "NT_STATUS", 

196 "UNICODE", 

197 ], 

198 ), 

199 LEShortField("PIDHigh", 0x0000), 

200 StrFixedLenField("SecuritySignature", b"", length=8), 

201 LEShortField("Reserved", 0x0), 

202 LEShortField("TID", 0), 

203 LEShortField("PIDLow", 0), 

204 LEShortField("UID", 0), 

205 LEShortField("MID", 0), 

206 ] 

207 

208 def guess_payload_class(self, payload): 

209 # type: (bytes) -> Packet 

210 if not payload: 

211 return super(SMB_Header, self).guess_payload_class(payload) 

212 WordCount = ord(payload[:1]) 

213 if self.Command == 0x72: 

214 if self.Flags.REPLY: 

215 if self.Flags2.EXTENDED_SECURITY: 

216 return SMBNegotiate_Response_Extended_Security 

217 else: 

218 return SMBNegotiate_Response_Security 

219 else: 

220 return SMBNegotiate_Request 

221 elif self.Command == 0x73: 

222 if WordCount == 0: 

223 return SMBSession_Null 

224 if self.Flags.REPLY: 

225 if WordCount == 0x04: 

226 return SMBSession_Setup_AndX_Response_Extended_Security 

227 elif WordCount == 0x03: 

228 return SMBSession_Setup_AndX_Response 

229 if self.Flags2.EXTENDED_SECURITY: 

230 return SMBSession_Setup_AndX_Response_Extended_Security 

231 else: 

232 return SMBSession_Setup_AndX_Response 

233 else: 

234 if WordCount == 0x0C: 

235 return SMBSession_Setup_AndX_Request_Extended_Security 

236 elif WordCount == 0x0D: 

237 return SMBSession_Setup_AndX_Request 

238 if self.Flags2.EXTENDED_SECURITY: 

239 return SMBSession_Setup_AndX_Request_Extended_Security 

240 else: 

241 return SMBSession_Setup_AndX_Request 

242 elif self.Command == 0x25: 

243 if self.Flags.REPLY: 

244 if WordCount == 0x11: 

245 return SMBMailslot_Write 

246 else: 

247 return SMBTransaction_Response 

248 else: 

249 if WordCount == 0x11: 

250 return SMBMailslot_Write 

251 else: 

252 return SMBTransaction_Request 

253 return super(SMB_Header, self).guess_payload_class(payload) 

254 

255 def answers(self, pkt): 

256 return SMB_Header in pkt 

257 

258 

259# SMB Negotiate Request 

260 

261 

262class SMB_Dialect(Packet): 

263 name = "SMB Dialect" 

264 fields_desc = [ 

265 ByteField("BufferFormat", 0x02), 

266 StrNullField("DialectString", "NT LM 0.12"), 

267 ] 

268 

269 def default_payload_class(self, payload): 

270 return conf.padding_layer 

271 

272 

273class SMBNegotiate_Request(Packet): 

274 name = "SMB Negotiate Request" 

275 fields_desc = [ 

276 ByteField("WordCount", 0), 

277 LEFieldLenField("ByteCount", None, length_of="Dialects"), 

278 PacketListField( 

279 "Dialects", 

280 [SMB_Dialect()], 

281 SMB_Dialect, 

282 length_from=lambda pkt: pkt.ByteCount, 

283 ), 

284 ] 

285 

286 

287bind_layers(SMB_Header, SMBNegotiate_Request, Command=0x72) 

288 

289# SMBNegociate Protocol Response 

290 

291 

292def _SMBStrNullField(name, default): 

293 """ 

294 Returns a StrNullField that is either normal or UTF-16 depending 

295 on the SMB headers. 

296 """ 

297 

298 def _isUTF16(pkt): 

299 while not hasattr(pkt, "Flags2") and pkt.underlayer: 

300 pkt = pkt.underlayer 

301 return hasattr(pkt, "Flags2") and pkt.Flags2.UNICODE 

302 

303 return MultipleTypeField( 

304 [(StrNullFieldUtf16(name, default), _isUTF16)], 

305 StrNullField(name, default), 

306 ) 

307 

308 

309def _len(pkt, name): 

310 """ 

311 Returns the length of a field, works with Unicode strings. 

312 """ 

313 fld, v = pkt.getfield_and_val(name) 

314 return len(fld.addfield(pkt, v, b"")) 

315 

316 

317class _SMBNegotiate_Response(Packet): 

318 @classmethod 

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

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

321 # Yes this is inspired by 

322 # https://github.com/wireshark/wireshark/blob/925e01b23fd5aad2fa929fafd894128a88832e74/epan/dissectors/packet-smb.c#L2902 

323 wc = struct.unpack("<H", _pkt[:1]) 

324 # dialect = struct.unpack("<H", _pkt[1:3]) 

325 if wc == 1: 

326 # Core Protocol 

327 return SMBNegotiate_Response_NoSecurity 

328 elif wc == 0xD: 

329 # LAN Manager 1.0 - LAN Manager 2.1 

330 # TODO 

331 pass 

332 elif wc == 0x11: 

333 # NT LAN Manager 

334 return cls 

335 return cls 

336 

337 

338_SMB_ServerCapabilities = [ 

339 "RAW_MODE", 

340 "MPX_MODE", 

341 "UNICODE", 

342 "LARGE_FILES", 

343 "NT_SMBS", 

344 "RPC_REMOTE_APIS", 

345 "STATUS32", 

346 "LEVEL_II_OPLOCKS", 

347 "LOCK_AND_READ", 

348 "NT_FIND", 

349 "res", 

350 "res", 

351 "DFS", 

352 "INFOLEVEL_PASSTHRU", 

353 "LARGE_READX", 

354 "LARGE_WRITEX", 

355 "LWIO", 

356 "res", 

357 "res", 

358 "res", 

359 "res", 

360 "res", 

361 "res", 

362 "UNIX", 

363 "res", 

364 "COMPRESSED_DATA", 

365 "res", 

366 "res", 

367 "res", 

368 "DYNAMIC_REAUTH", 

369 "PERSISTENT_HANDLES", 

370 "EXTENDED_SECURITY", 

371] 

372 

373 

374# CIFS sect 2.2.4.52.2 

375 

376 

377class SMBNegotiate_Response_NoSecurity(_SMBNegotiate_Response): 

378 name = "SMB Negotiate No-Security Response (CIFS)" 

379 fields_desc = [ 

380 ByteField("WordCount", 0x1), 

381 LEShortField("DialectIndex", 7), 

382 FlagsField( 

383 "SecurityMode", 

384 0x03, 

385 8, 

386 [ 

387 "USER_SECURITY", 

388 "ENCRYPT_PASSWORDS", 

389 "SECURITY_SIGNATURES_ENABLED", 

390 "SECURITY_SIGNATURES_REQUIRED", 

391 ], 

392 ), 

393 LEShortField("MaxMpxCount", 50), 

394 LEShortField("MaxNumberVC", 1), 

395 LEIntField("MaxBufferSize", 16144), # Windows: 4356 

396 LEIntField("MaxRawSize", 65536), 

397 LEIntField("SessionKey", 0x0000), 

398 FlagsField("ServerCapabilities", 0xF3F9, -32, _SMB_ServerCapabilities), 

399 UTCTimeField( 

400 "ServerTime", 

401 None, 

402 fmt="<Q", 

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

404 custom_scaling=1e7, 

405 ), 

406 ScalingField("ServerTimeZone", 0x3C, fmt="<h", unit="min-UTC"), 

407 FieldLenField( 

408 "ChallengeLength", 

409 None, 

410 # aka EncryptionKeyLength 

411 length_of="Challenge", 

412 fmt="<B", 

413 ), 

414 LEFieldLenField( 

415 "ByteCount", 

416 None, 

417 length_of="DomainName", 

418 adjust=lambda pkt, x: x + len(pkt.Challenge), 

419 ), 

420 XStrLenField( 

421 "Challenge", 

422 b"", # aka EncryptionKey 

423 length_from=lambda pkt: pkt.ChallengeLength, 

424 ), 

425 StrNullField("DomainName", "WORKGROUP"), 

426 ] 

427 

428 

429bind_top_down(SMB_Header, SMBNegotiate_Response_NoSecurity, Command=0x72, Flags=0x80) 

430 

431# SMB sect 2.2.4.5.2.1 

432 

433 

434class SMBNegotiate_Response_Extended_Security(_SMBNegotiate_Response): 

435 name = "SMB Negotiate Extended Security Response (SMB)" 

436 WordCount = 0x11 

437 fields_desc = SMBNegotiate_Response_NoSecurity.fields_desc[:12] + [ 

438 LEFieldLenField( 

439 "ByteCount", None, length_of="SecurityBlob", adjust=lambda _, x: x + 16 

440 ), 

441 SMBNegotiate_Response_NoSecurity.fields_desc[13], 

442 UUIDField("GUID", None, uuid_fmt=UUIDField.FORMAT_LE), 

443 PacketLenField( 

444 "SecurityBlob", None, GSSAPI_BLOB, length_from=lambda x: x.ByteCount - 16 

445 ), 

446 ] 

447 

448 

449bind_top_down( 

450 SMB_Header, 

451 SMBNegotiate_Response_Extended_Security, 

452 Command=0x72, 

453 Flags=0x80, 

454 Flags2=0x800, 

455) 

456 

457# SMB sect 2.2.4.5.2.2 

458 

459 

460class SMBNegotiate_Response_Security(_SMBNegotiate_Response): 

461 name = "SMB Negotiate Non-Extended Security Response (SMB)" 

462 WordCount = 0x11 

463 fields_desc = SMBNegotiate_Response_NoSecurity.fields_desc[:12] + [ 

464 LEFieldLenField( 

465 "ByteCount", 

466 None, 

467 length_of="DomainName", 

468 adjust=lambda pkt, x: x 

469 + 2 

470 + _len(pkt, "Challenge") 

471 + _len(pkt, "ServerName"), 

472 ), 

473 XStrLenField( 

474 "Challenge", 

475 b"", # aka EncryptionKey 

476 length_from=lambda pkt: pkt.ChallengeLength, 

477 ), 

478 _SMBStrNullField("DomainName", "WORKGROUP"), 

479 _SMBStrNullField("ServerName", "RMFF1"), 

480 ] 

481 

482 

483bind_top_down(SMB_Header, SMBNegotiate_Response_Security, Command=0x72, Flags=0x80) 

484 

485# Session Setup AndX Request 

486 

487# CIFS sect 2.2.4.53 

488 

489 

490class SMBSession_Setup_AndX_Request(Packet): 

491 name = "Session Setup AndX Request (CIFS)" 

492 fields_desc = [ 

493 ByteField("WordCount", 0x0D), 

494 ByteEnumField("AndXCommand", 0xFF, SMB_COM), 

495 ByteField("AndXReserved", 0), 

496 LEShortField("AndXOffset", None), 

497 LEShortField("MaxBufferSize", 16144), # Windows: 4356 

498 LEShortField("MaxMPXCount", 50), 

499 LEShortField("VCNumber", 0), 

500 LEIntField("SessionKey", 0), 

501 LEFieldLenField("OEMPasswordLength", None, length_of="OEMPassword"), 

502 LEFieldLenField("UnicodePasswordLength", None, length_of="UnicodePassword"), 

503 LEIntField("Reserved", 0), 

504 FlagsField("ServerCapabilities", 0x05, -32, _SMB_ServerCapabilities), 

505 LEShortField("ByteCount", None), 

506 XStrLenField("OEMPassword", "Pass", length_from=lambda x: x.OEMPasswordLength), 

507 XStrLenField( 

508 "UnicodePassword", "Pass", length_from=lambda x: x.UnicodePasswordLength 

509 ), 

510 ReversePadField(_SMBStrNullField("AccountName", "GUEST"), 2, b"\0"), 

511 _SMBStrNullField("PrimaryDomain", ""), 

512 _SMBStrNullField("NativeOS", "Windows 4.0"), 

513 _SMBStrNullField("NativeLanMan", "Windows 4.0"), 

514 ] 

515 

516 def post_build(self, pkt, pay): 

517 if self.AndXOffset is None and self.AndXCommand != 0xFF: 

518 pkt = pkt[:3] + struct.pack("<H", len(pkt) + 32) + pkt[5:] 

519 if self.ByteCount is None: 

520 pkt = pkt[:27] + struct.pack("<H", len(pkt) - 29) + pkt[29:] 

521 if self.payload and hasattr(self.payload, "AndXOffset") and pay: 

522 pay = pay[:3] + struct.pack("<H", len(pkt) + len(pay) + 32) + pay[5:] 

523 return pkt + pay 

524 

525 

526bind_top_down(SMB_Header, SMBSession_Setup_AndX_Request, Command=0x73) 

527 

528# SMB sect 2.2.4.7 

529 

530 

531class SMBTree_Connect_AndX(Packet): 

532 name = "Session Tree Connect AndX" 

533 WordCount = 0x04 

534 fields_desc = SMBSession_Setup_AndX_Request.fields_desc[:4] + [ 

535 FlagsField( 

536 "Flags", 

537 "", 

538 -16, 

539 ["DISCONNECT_TID", "r2", "EXTENDED_SIGNATURES", "EXTENDED_RESPONSE"], 

540 ), 

541 FieldLenField("PasswordLength", None, length_of="Password", fmt="<H"), 

542 LEShortField("ByteCount", None), 

543 XStrLenField("Password", b"", length_from=lambda pkt: pkt.PasswordLength), 

544 ReversePadField(_SMBStrNullField("Path", "\\\\WIN2K\\IPC$"), 2), 

545 StrNullField("Service", "?????"), 

546 ] 

547 

548 def post_build(self, pkt, pay): 

549 pkt += pay 

550 if self.ByteCount is None: 

551 pkt = pkt[:9] + struct.pack("<H", len(pkt) - 11) + pkt[11:] 

552 return pkt 

553 

554 

555bind_layers(SMB_Header, SMBTree_Connect_AndX, Command=0x75) 

556bind_layers(SMBSession_Setup_AndX_Request, SMBTree_Connect_AndX, AndXCommand=0x75) 

557 

558# SMB sect 2.2.4.6.1 

559 

560 

561class SMBSession_Setup_AndX_Request_Extended_Security(Packet): 

562 name = "Session Setup AndX Extended Security Request (SMB)" 

563 WordCount = 0x0C 

564 fields_desc = ( 

565 SMBSession_Setup_AndX_Request.fields_desc[:8] 

566 + [ 

567 LEFieldLenField("SecurityBlobLength", None, length_of="SecurityBlob"), 

568 ] 

569 + SMBSession_Setup_AndX_Request.fields_desc[10:12] 

570 + [ 

571 LEShortField("ByteCount", None), 

572 PacketLenField( 

573 "SecurityBlob", 

574 None, 

575 GSSAPI_BLOB, 

576 length_from=lambda x: x.SecurityBlobLength, 

577 ), 

578 ReversePadField( 

579 _SMBStrNullField("NativeOS", "Windows 4.0"), 

580 2, 

581 b"\0", 

582 ), 

583 _SMBStrNullField("NativeLanMan", "Windows 4.0"), 

584 ] 

585 ) 

586 

587 def post_build(self, pkt, pay): 

588 if self.ByteCount is None: 

589 pkt = pkt[:25] + struct.pack("<H", len(pkt) - 27) + pkt[27:] 

590 return pkt + pay 

591 

592 

593bind_top_down( 

594 SMB_Header, 

595 SMBSession_Setup_AndX_Request_Extended_Security, 

596 Command=0x73, 

597 Flags2=0x800, 

598) 

599 

600# Session Setup AndX Response 

601 

602 

603# CIFS sect 2.2.4.53.2 

604 

605 

606class SMBSession_Setup_AndX_Response(Packet): 

607 name = "Session Setup AndX Response (CIFS)" 

608 fields_desc = [ 

609 ByteField("WordCount", 0x3), 

610 ByteEnumField("AndXCommand", 0xFF, SMB_COM), 

611 ByteField("AndXReserved", 0), 

612 LEShortField("AndXOffset", None), 

613 FlagsField( 

614 "Action", 

615 0, 

616 -16, 

617 { 

618 0x0001: "SMB_SETUP_GUEST", 

619 0x0002: "SMB_SETUP_USE_LANMAN_KEY", 

620 }, 

621 ), 

622 LEShortField("ByteCount", 25), 

623 _SMBStrNullField("NativeOS", "Windows 4.0"), 

624 _SMBStrNullField("NativeLanMan", "Windows 4.0"), 

625 _SMBStrNullField("PrimaryDomain", ""), 

626 # Off spec? 

627 ByteField("WordCount2", 3), 

628 ByteEnumField("AndXCommand2", 0xFF, SMB_COM), 

629 ByteField("Reserved3", 0), 

630 LEShortField("AndXOffset2", 80), 

631 LEShortField("OptionalSupport", 0x01), 

632 LEShortField("ByteCount2", 5), 

633 StrNullField("Service", "IPC"), 

634 StrNullField("NativeFileSystem", ""), 

635 ] 

636 

637 def post_build(self, pkt, pay): 

638 if self.AndXOffset is None: 

639 pkt = pkt[:3] + struct.pack("<H", len(pkt) + 32) + pkt[5:] 

640 return pkt + pay 

641 

642 

643bind_top_down(SMB_Header, SMBSession_Setup_AndX_Response, Command=0x73, Flags=0x80) 

644 

645# SMB sect 2.2.4.6.2 

646 

647 

648class SMBSession_Setup_AndX_Response_Extended_Security( 

649 SMBSession_Setup_AndX_Response 

650): # noqa: E501 

651 name = "Session Setup AndX Extended Security Response (SMB)" 

652 WordCount = 0x4 

653 fields_desc = ( 

654 SMBSession_Setup_AndX_Response.fields_desc[:5] 

655 + [SMBSession_Setup_AndX_Request_Extended_Security.fields_desc[8]] 

656 + SMBSession_Setup_AndX_Request_Extended_Security.fields_desc[11:] 

657 ) 

658 

659 def post_build(self, pkt, pay): 

660 if self.ByteCount is None: 

661 pkt = pkt[:9] + struct.pack("<H", len(pkt) - 11) + pkt[11:] 

662 return super(SMBSession_Setup_AndX_Response_Extended_Security, self).post_build( 

663 pkt, pay 

664 ) 

665 

666 

667bind_top_down( 

668 SMB_Header, 

669 SMBSession_Setup_AndX_Response_Extended_Security, 

670 Command=0x73, 

671 Flags=0x80, 

672 Flags2=0x800, 

673) 

674 

675# SMB null (no wordcount) 

676 

677 

678class SMBSession_Null(Packet): 

679 fields_desc = [ByteField("WordCount", 0), LEShortField("ByteCount", 0)] 

680 

681 

682bind_top_down(SMB_Header, SMBSession_Null, Command=0x73) 

683 

684# [MS-CIFS] sect 2.2.4.33.1 

685 

686_SMB_CONFIG = [ 

687 ("Len", _NTLM_ENUM.LEN), 

688 ("BufferOffset", _NTLM_ENUM.OFFSET), 

689] 

690 

691 

692class _SMB_TransactionRequest_Data(PacketLenField): 

693 def m2i(self, pkt, m): 

694 if pkt.Name == b"\\MAILSLOT\\NET\\NETLOGON": 

695 return NETLOGON(m) 

696 elif pkt.Name == b"\\MAILSLOT\\BROWSE" or pkt.name == b"\\MAILSLOT\\LANMAN": 

697 return BRWS(m) 

698 return conf.raw_layer(m) 

699 

700 

701def _optlen(pkt, x): 

702 try: 

703 return len(getattr(pkt, x)) 

704 except AttributeError: 

705 return 0 

706 

707 

708class SMBTransaction_Request(_NTLMPayloadPacket): 

709 name = "SMB COM Transaction Request" 

710 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

711 

712 fields_desc = [ 

713 FieldLenField( 

714 "WordCount", 

715 None, 

716 length_of="SetupCount", 

717 adjust=lambda pkt, x: x + 0x0E, 

718 fmt="B", 

719 ), 

720 FieldLenField( 

721 "TotalParamCount", 

722 None, 

723 length_of="Buffer", 

724 fmt="<H", 

725 adjust=lambda pkt, _: _optlen(pkt, "Parameter"), 

726 ), 

727 FieldLenField( 

728 "TotalDataCount", 

729 None, 

730 length_of="Buffer", 

731 fmt="<H", 

732 adjust=lambda pkt, _: _optlen(pkt, "Data"), 

733 ), 

734 LEShortField("MaxParamCount", 0), 

735 LEShortField("MaxDataCount", 0), 

736 ByteField("MaxSetupCount", 0), 

737 ByteField("Reserved1", 0), 

738 FlagsField("Flags", 0, -16, {0x1: "DISCONNECT_TID", 0x2: "NO_RESPONSE"}), 

739 LEIntField("Timeout", 1000), 

740 ShortField("Reserved2", 0), 

741 LEShortField("ParameterLen", None), 

742 LEShortField("ParameterBufferOffset", None), 

743 LEShortField("DataLen", None), 

744 LEShortField("DataBufferOffset", None), 

745 FieldLenField("SetupCount", 3, count_of="Setup", fmt="B"), 

746 ByteField("Reserved3", 0), 

747 FieldListField( 

748 "Setup", 

749 [1, 1, 2], 

750 LEShortField("", 0), 

751 count_from=lambda pkt: pkt.SetupCount, 

752 ), 

753 # SMB Data 

754 FieldLenField( 

755 "ByteCount", 

756 None, 

757 length_of="Name", 

758 fmt="<H", 

759 adjust=lambda pkt, x: x + _optlen(pkt, "Parameter") + _optlen(pkt, "Data"), 

760 ), 

761 StrNullField("Name", "\\MAILSLOT\\NET\\NETLOGON"), 

762 _NTLMPayloadField( 

763 "Buffer", 

764 lambda pkt: 32 + 31 + len(pkt.Setup) * 2 + len(pkt.Name) + 1, 

765 [ 

766 XStrLenField( 

767 "Parameter", b"", length_from=lambda pkt: pkt.ParameterLen 

768 ), 

769 _SMB_TransactionRequest_Data( 

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

771 ), 

772 ], 

773 ), 

774 ] 

775 

776 def post_build(self, pkt, pay): 

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

778 return ( 

779 _NTLM_post_build( 

780 self, 

781 pkt, 

782 32 + 31 + len(self.Setup) * 2 + len(self.Name) + 1, 

783 { 

784 "Parameter": 19, 

785 "Data": 23, 

786 }, 

787 config=_SMB_CONFIG, 

788 ) 

789 + pay 

790 ) 

791 

792 def mysummary(self): 

793 if getattr(self, "Data", None) is not None: 

794 return self.sprintf("Tran %Name% ") + self.Data.mysummary() 

795 return self.sprintf("Tran %Name%") 

796 

797 

798bind_top_down(SMB_Header, SMBTransaction_Request, Command=0x25) 

799 

800 

801class SMBMailslot_Write(SMBTransaction_Request): 

802 WordCount = 0x11 

803 

804 

805# [MS-CIFS] sect 2.2.4.33.2 

806 

807 

808class SMBTransaction_Response(_NTLMPayloadPacket): 

809 name = "SMB COM Transaction Response" 

810 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

811 fields_desc = [ 

812 FieldLenField( 

813 "WordCount", 

814 None, 

815 length_of="SetupCount", 

816 adjust=lambda pkt, x: x + 0x0A, 

817 fmt="B", 

818 ), 

819 FieldLenField( 

820 "TotalParamCount", 

821 None, 

822 length_of="Buffer", 

823 fmt="<H", 

824 adjust=lambda pkt, _: _optlen(pkt, "Parameter"), 

825 ), 

826 FieldLenField( 

827 "TotalDataCount", 

828 None, 

829 length_of="Buffer", 

830 fmt="<H", 

831 adjust=lambda pkt, _: _optlen(pkt, "Data"), 

832 ), 

833 LEShortField("Reserved1", None), 

834 LEShortField("ParameterLen", None), 

835 LEShortField("ParameterBufferOffset", None), 

836 LEShortField("ParameterDisplacement", 0), 

837 LEShortField("DataLen", None), 

838 LEShortField("DataBufferOffset", None), 

839 LEShortField("DataDisplacement", 0), 

840 FieldLenField("SetupCount", 3, count_of="Setup", fmt="B"), 

841 ByteField("Reserved2", 0), 

842 FieldListField( 

843 "Setup", 

844 [1, 1, 2], 

845 LEShortField("", 0), 

846 count_from=lambda pkt: pkt.SetupCount, 

847 ), 

848 # SMB Data 

849 FieldLenField( 

850 "ByteCount", 

851 None, 

852 length_of="Buffer", 

853 fmt="<H", 

854 adjust=lambda pkt, x: _optlen(pkt, "Parameter") + _optlen(pkt, "Data"), 

855 ), 

856 _NTLMPayloadField( 

857 "Buffer", 

858 lambda pkt: 32 + 22 + len(pkt.Setup) * 2, 

859 [ 

860 XStrLenField( 

861 "Parameter", b"", length_from=lambda pkt: pkt.ParameterLen 

862 ), 

863 XStrLenField("Data", b"", length_from=lambda pkt: pkt.DataLen), 

864 ], 

865 ), 

866 ] 

867 

868 def post_build(self, pkt, pay): 

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

870 return ( 

871 _NTLM_post_build( 

872 self, 

873 pkt, 

874 32 + 22 + len(self.Setup) * 2, 

875 { 

876 "Parameter": 7, 

877 "Data": 13, 

878 }, 

879 config=_SMB_CONFIG, 

880 ) 

881 + pay 

882 ) 

883 

884 

885bind_top_down(SMB_Header, SMBTransaction_Response, Command=0x25, Flags=0x80) 

886 

887 

888# [MS-ADTS] sect 6.3.1.4 

889 

890_NETLOGON_opcodes = { 

891 0x7: "LOGON_PRIMARY_QUERY", 

892 0x12: "LOGON_SAM_LOGON_REQUEST", 

893 0x13: "LOGON_SAM_LOGON_RESPONSE", 

894 0x15: "LOGON_SAM_USER_UNKNOWN", 

895 0x17: "LOGON_SAM_LOGON_RESPONSE_EX", 

896 0x19: "LOGON_SAM_USER_UNKNOWN_EX", 

897} 

898 

899_NV_VERSION = { 

900 0x00000001: "V1", 

901 0x00000002: "V5", 

902 0x00000004: "V5EX", 

903 0x00000008: "V5EX_WITH_IP", 

904 0x00000010: "V5EX_WITH_CLOSEST_SITE", 

905 0x01000000: "AVOID_NT4EMUL", 

906 0x10000000: "PDC", 

907 0x20000000: "IP", 

908 0x40000000: "LOCAL", 

909 0x80000000: "GC", 

910} 

911 

912 

913class NETLOGON(Packet): 

914 @classmethod 

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

916 if _pkt: 

917 if _pkt[0] == 0x07: # LOGON_PRIMARY_QUERY 

918 return NETLOGON_LOGON_QUERY 

919 elif _pkt[0] == 0x12: # LOGON_SAM_LOGON_REQUEST 

920 return NETLOGON_SAM_LOGON_REQUEST 

921 elif _pkt[0] == 0x13: # LOGON_SAM_USER_RESPONSE 

922 try: 

923 i = _pkt.index(b"\xff\xff\xff\xff") 

924 NtVersion = NETLOGON_SAM_LOGON_RESPONSE_NT40.fields_desc[ 

925 -3 

926 ].getfield(None, _pkt[i - 4 : i])[1] 

927 if NtVersion.V1 and not NtVersion.V5: 

928 return NETLOGON_SAM_LOGON_RESPONSE_NT40 

929 except Exception: 

930 pass 

931 return NETLOGON_SAM_LOGON_RESPONSE 

932 elif _pkt[0] == 0x15: # LOGON_SAM_USER_UNKNOWN 

933 return NETLOGON_SAM_LOGON_RESPONSE 

934 elif _pkt[0] == 0x17: # LOGON_SAM_LOGON_RESPONSE_EX 

935 return NETLOGON_SAM_LOGON_RESPONSE_EX 

936 elif _pkt[0] == 0x19: # LOGON_SAM_USER_UNKNOWN_EX 

937 return NETLOGON_SAM_LOGON_RESPONSE 

938 return cls 

939 

940 

941class NETLOGON_LOGON_QUERY(NETLOGON): 

942 fields_desc = [ 

943 LEShortEnumField("OpCode", 0x7, _NETLOGON_opcodes), 

944 StrNullField("ComputerName", ""), 

945 StrNullField("MailslotName", ""), 

946 StrNullFieldUtf16("UnicodeComputerName", ""), 

947 FlagsField("NtVersion", 0xB, -32, _NV_VERSION), 

948 XLEShortField("LmNtToken", 0xFFFF), 

949 XLEShortField("Lm20Token", 0xFFFF), 

950 ] 

951 

952 

953# [MS-ADTS] sect 6.3.1.6 

954 

955 

956class NETLOGON_SAM_LOGON_REQUEST(NETLOGON): 

957 fields_desc = [ 

958 LEShortEnumField("OpCode", 0x12, _NETLOGON_opcodes), 

959 LEShortField("RequestCount", 0), 

960 StrNullFieldUtf16("UnicodeComputerName", ""), 

961 StrNullFieldUtf16("UnicodeUserName", ""), 

962 StrNullField("MailslotName", "\\MAILSLOT\\NET\\GETDC701253F9"), 

963 LEIntField("AllowableAccountControlBits", 0), 

964 FieldLenField("DomainSidSize", None, fmt="<I", length_of="DomainSid"), 

965 XStrLenField("DomainSid", b"", length_from=lambda pkt: pkt.DomainSidSize), 

966 FlagsField("NtVersion", 0xB, -32, _NV_VERSION), 

967 XLEShortField("LmNtToken", 0xFFFF), 

968 XLEShortField("Lm20Token", 0xFFFF), 

969 ] 

970 

971 

972# [MS-ADTS] sect 6.3.1.7 

973 

974 

975class NETLOGON_SAM_LOGON_RESPONSE_NT40(NETLOGON): 

976 fields_desc = [ 

977 LEShortEnumField("OpCode", 0x13, _NETLOGON_opcodes), 

978 StrNullFieldUtf16("UnicodeLogonServer", ""), 

979 StrNullFieldUtf16("UnicodeUserName", ""), 

980 StrNullFieldUtf16("UnicodeDomainName", ""), 

981 FlagsField("NtVersion", 0x1, -32, _NV_VERSION), 

982 XLEShortField("LmNtToken", 0xFFFF), 

983 XLEShortField("Lm20Token", 0xFFFF), 

984 ] 

985 

986 

987# [MS-ADTS] sect 6.3.1.2 

988 

989 

990_NETLOGON_FLAGS = { 

991 0x00000001: "PDC", 

992 0x00000004: "GC", 

993 0x00000008: "LDAP", 

994 0x00000010: "DC", 

995 0x00000020: "KDC", 

996 0x00000040: "TIMESERV", 

997 0x00000080: "CLOSEST", 

998 0x00000100: "RODC", 

999 0x00000200: "GOOD_TIMESERV", 

1000 0x00000400: "NC", 

1001 0x00000800: "SELECT_SECRET_DOMAIN_6", 

1002 0x00001000: "FULL_SECRET_DOMAIN_6", 

1003 0x00002000: "WS", 

1004 0x00004000: "DS_8", 

1005 0x00008000: "DS_9", 

1006 0x00010000: "DS_10", # guess 

1007 0x00020000: "DS_11", # guess 

1008 0x20000000: "DNS_CONTROLLER", 

1009 0x40000000: "DNS_DOMAIN", 

1010 0x80000000: "DNS_FOREST", 

1011} 

1012 

1013 

1014# [MS-ADTS] sect 6.3.1.8 

1015 

1016 

1017class NETLOGON_SAM_LOGON_RESPONSE(NETLOGON, DNSCompressedPacket): 

1018 fields_desc = [ 

1019 LEShortEnumField("OpCode", 0x17, _NETLOGON_opcodes), 

1020 StrNullFieldUtf16("UnicodeLogonServer", ""), 

1021 StrNullFieldUtf16("UnicodeUserName", ""), 

1022 StrNullFieldUtf16("UnicodeDomainName", ""), 

1023 UUIDField("DomainGuid", None, uuid_fmt=UUIDField.FORMAT_LE), 

1024 UUIDField("NullGuid", None, uuid_fmt=UUIDField.FORMAT_LE), 

1025 DNSStrField("DnsForestName", ""), 

1026 DNSStrField("DnsDomainName", ""), 

1027 DNSStrField("DnsHostName", ""), 

1028 IPField("DcIpAddress", "0.0.0.0"), 

1029 FlagsField("Flags", 0, -32, _NETLOGON_FLAGS), 

1030 FlagsField("NtVersion", 0x1, -32, _NV_VERSION), 

1031 XLEShortField("LmNtToken", 0xFFFF), 

1032 XLEShortField("Lm20Token", 0xFFFF), 

1033 ] 

1034 

1035 def get_full(self): 

1036 return self.original 

1037 

1038 

1039# [MS-ADTS] sect 6.3.1.9 

1040 

1041 

1042class DcSockAddr(Packet): 

1043 fields_desc = [ 

1044 LEShortField("sin_family", 2), 

1045 LEShortField("sin_port", 0), 

1046 IPField("sin_addr", None), 

1047 LELongField("sin_zero", 0), 

1048 ] 

1049 

1050 def default_payload_class(self, payload): 

1051 return conf.padding_layer 

1052 

1053 

1054class NETLOGON_SAM_LOGON_RESPONSE_EX(NETLOGON, DNSCompressedPacket): 

1055 fields_desc = [ 

1056 LEShortEnumField("OpCode", 0x17, _NETLOGON_opcodes), 

1057 LEShortField("Sbz", 0), 

1058 FlagsField("Flags", 0, -32, _NETLOGON_FLAGS), 

1059 UUIDField("DomainGuid", None, uuid_fmt=UUIDField.FORMAT_LE), 

1060 DNSStrField("DnsForestName", ""), 

1061 DNSStrField("DnsDomainName", ""), 

1062 DNSStrField("DnsHostName", ""), 

1063 DNSStrField("NetbiosDomainName", ""), 

1064 DNSStrField("NetbiosComputerName", ""), 

1065 DNSStrField("UserName", ""), 

1066 DNSStrField("DcSiteName", "Default-First-Site-Name"), 

1067 DNSStrField("ClientSiteName", "Default-First-Site-Name"), 

1068 ConditionalField( 

1069 ByteField("DcSockAddrSize", 0x10), 

1070 lambda pkt: pkt.NtVersion.V5EX_WITH_IP, 

1071 ), 

1072 ConditionalField( 

1073 PacketField("DcSockAddr", DcSockAddr(), DcSockAddr), 

1074 lambda pkt: pkt.NtVersion.V5EX_WITH_IP, 

1075 ), 

1076 ConditionalField( 

1077 DNSStrField("NextClosestSiteName", ""), 

1078 lambda pkt: pkt.NtVersion.V5EX_WITH_CLOSEST_SITE, 

1079 ), 

1080 FlagsField("NtVersion", 0xB, -32, _NV_VERSION), 

1081 XLEShortField("LmNtToken", 0xFFFF), 

1082 XLEShortField("Lm20Token", 0xFFFF), 

1083 ] 

1084 

1085 def pre_dissect(self, s): 

1086 try: 

1087 i = s.index(b"\xff\xff\xff\xff") 

1088 self.fields["NtVersion"] = self.fields_desc[-3].getfield( 

1089 self, s[i - 4 : i] 

1090 )[1] 

1091 except Exception: 

1092 self.NtVersion = 0xB 

1093 return s 

1094 

1095 def get_full(self): 

1096 return self.original 

1097 

1098 

1099# [MS-BRWS] sect 2.2 

1100 

1101 

1102class BRWS(Packet): 

1103 fields_desc = [ 

1104 ByteEnumField( 

1105 "OpCode", 

1106 0x00, 

1107 { 

1108 0x01: "HostAnnouncement", 

1109 0x02: "AnnouncementRequest", 

1110 0x08: "RequestElection", 

1111 0x09: "GetBackupListRequest", 

1112 0x0A: "GetBackupListResponse", 

1113 0x0B: "BecomeBackup", 

1114 0x0C: "DomainAnnouncement", 

1115 0x0D: "MasterAnnouncement", 

1116 0x0E: "ResetStateRequest", 

1117 0x0F: "LocalMasterAnnouncement", 

1118 }, 

1119 ), 

1120 ] 

1121 

1122 def mysummary(self): 

1123 return self.sprintf("%OpCode%") 

1124 

1125 registered_opcodes = {} 

1126 

1127 @classmethod 

1128 def register_variant(cls): 

1129 cls.registered_opcodes[cls.OpCode.default] = cls 

1130 

1131 @classmethod 

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

1133 if _pkt: 

1134 return cls.registered_opcodes.get(_pkt[0], cls) 

1135 return cls 

1136 

1137 def default_payload_class(self, payload): 

1138 return conf.padding_layer 

1139 

1140 

1141# [MS-BRWS] sect 2.2.1 

1142 

1143 

1144class BRWS_HostAnnouncement(BRWS): 

1145 OpCode = 0x01 

1146 fields_desc = [ 

1147 BRWS, 

1148 ByteField("UpdateCount", 0), 

1149 LEIntField("Periodicity", 128000), 

1150 StrFixedLenField("ServerName", b"", length=16), 

1151 ByteField("OSVersionMajor", 6), 

1152 ByteField("OSVersionMinor", 1), 

1153 LEIntField("ServerType", 4611), 

1154 ByteField("BrowserConfigVersionMajor", 21), 

1155 ByteField("BrowserConfigVersionMinor", 1), 

1156 XLEShortField("Signature", 0xAA55), 

1157 StrNullField("Comment", ""), 

1158 ] 

1159 

1160 def mysummary(self): 

1161 return self.sprintf("%OpCode% for %ServerName%") 

1162 

1163 

1164# [MS-BRWS] sect 2.2.6 

1165 

1166 

1167class BRWS_BecomeBackup(BRWS): 

1168 OpCode = 0x0B 

1169 fields_desc = [ 

1170 BRWS, 

1171 StrNullField("BrowserToPromote", b""), 

1172 ] 

1173 

1174 def mysummary(self): 

1175 return self.sprintf("%OpCode% from %BrowserToPromote%") 

1176 

1177 

1178# [MS-BRWS] sect 2.2.10 

1179 

1180 

1181class BRWS_LocalMasterAnnouncement(BRWS_HostAnnouncement): 

1182 OpCode = 0x0F 

1183 

1184 

1185# SMB dispatcher 

1186 

1187 

1188class _SMBGeneric(Packet): 

1189 name = "SMB Generic dispatcher" 

1190 fields_desc = [StrFixedLenField("Start", b"\xffSMB", 4)] 

1191 

1192 @classmethod 

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

1194 """ 

1195 Depending on the first 4 bytes of the packet, 

1196 dispatch to the correct version of Header 

1197 (either SMB or SMB2) 

1198 """ 

1199 if _pkt and len(_pkt) >= 4: 

1200 if _pkt[:4] == b"\xffSMB": 

1201 return SMB_Header 

1202 if _pkt[:4] == b"\xfeSMB": 

1203 return SMB2_Header 

1204 if _pkt[:4] == b"\xfdSMB": 

1205 return SMB2_Transform_Header 

1206 if _pkt[:4] == b"\xfcSMB": 

1207 return SMB2_Compression_Transform_Header 

1208 return cls 

1209 

1210 

1211bind_layers(NBTSession, _SMBGeneric) 

1212bind_layers(NBTDatagram, _SMBGeneric)