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

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

275 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_Header, 

71) 

72 

73 

74SMB_COM = { 

75 0x00: "SMB_COM_CREATE_DIRECTORY", 

76 0x01: "SMB_COM_DELETE_DIRECTORY", 

77 0x02: "SMB_COM_OPEN", 

78 0x03: "SMB_COM_CREATE", 

79 0x04: "SMB_COM_CLOSE", 

80 0x05: "SMB_COM_FLUSH", 

81 0x06: "SMB_COM_DELETE", 

82 0x07: "SMB_COM_RENAME", 

83 0x08: "SMB_COM_QUERY_INFORMATION", 

84 0x09: "SMB_COM_SET_INFORMATION", 

85 0x0A: "SMB_COM_READ", 

86 0x0B: "SMB_COM_WRITE", 

87 0x0C: "SMB_COM_LOCK_BYTE_RANGE", 

88 0x0D: "SMB_COM_UNLOCK_BYTE_RANGE", 

89 0x0E: "SMB_COM_CREATE_TEMPORARY", 

90 0x0F: "SMB_COM_CREATE_NEW", 

91 0x10: "SMB_COM_CHECK_DIRECTORY", 

92 0x11: "SMB_COM_PROCESS_EXIT", 

93 0x12: "SMB_COM_SEEK", 

94 0x13: "SMB_COM_LOCK_AND_READ", 

95 0x14: "SMB_COM_WRITE_AND_UNLOCK", 

96 0x1A: "SMB_COM_READ_RAW", 

97 0x1B: "SMB_COM_READ_MPX", 

98 0x1C: "SMB_COM_READ_MPX_SECONDARY", 

99 0x1D: "SMB_COM_WRITE_RAW", 

100 0x1E: "SMB_COM_WRITE_MPX", 

101 0x1F: "SMB_COM_WRITE_MPX_SECONDARY", 

102 0x20: "SMB_COM_WRITE_COMPLETE", 

103 0x21: "SMB_COM_QUERY_SERVER", 

104 0x22: "SMB_COM_SET_INFORMATION2", 

105 0x23: "SMB_COM_QUERY_INFORMATION2", 

106 0x24: "SMB_COM_LOCKING_ANDX", 

107 0x25: "SMB_COM_TRANSACTION", 

108 0x26: "SMB_COM_TRANSACTION_SECONDARY", 

109 0x27: "SMB_COM_IOCTL", 

110 0x28: "SMB_COM_IOCTL_SECONDARY", 

111 0x29: "SMB_COM_COPY", 

112 0x2A: "SMB_COM_MOVE", 

113 0x2B: "SMB_COM_ECHO", 

114 0x2C: "SMB_COM_WRITE_AND_CLOSE", 

115 0x2D: "SMB_COM_OPEN_ANDX", 

116 0x2E: "SMB_COM_READ_ANDX", 

117 0x2F: "SMB_COM_WRITE_ANDX", 

118 0x30: "SMB_COM_NEW_FILE_SIZE", 

119 0x31: "SMB_COM_CLOSE_AND_TREE_DISC", 

120 0x32: "SMB_COM_TRANSACTION2", 

121 0x33: "SMB_COM_TRANSACTION2_SECONDARY", 

122 0x34: "SMB_COM_FIND_CLOSE2", 

123 0x35: "SMB_COM_FIND_NOTIFY_CLOSE", 

124 0x70: "SMB_COM_TREE_CONNECT", 

125 0x71: "SMB_COM_TREE_DISCONNECT", 

126 0x72: "SMB_COM_NEGOTIATE", 

127 0x73: "SMB_COM_SESSION_SETUP_ANDX", 

128 0x74: "SMB_COM_LOGOFF_ANDX", 

129 0x75: "SMB_COM_TREE_CONNECT_ANDX", 

130 0x7E: "SMB_COM_SECURITY_PACKAGE_ANDX", 

131 0x80: "SMB_COM_QUERY_INFORMATION_DISK", 

132 0x81: "SMB_COM_SEARCH", 

133 0x82: "SMB_COM_FIND", 

134 0x83: "SMB_COM_FIND_UNIQUE", 

135 0x84: "SMB_COM_FIND_CLOSE", 

136 0xA0: "SMB_COM_NT_TRANSACT", 

137 0xA1: "SMB_COM_NT_TRANSACT_SECONDARY", 

138 0xA2: "SMB_COM_NT_CREATE_ANDX", 

139 0xA4: "SMB_COM_NT_CANCEL", 

140 0xA5: "SMB_COM_NT_RENAME", 

141 0xC0: "SMB_COM_OPEN_PRINT_FILE", 

142 0xC1: "SMB_COM_WRITE_PRINT_FILE", 

143 0xC2: "SMB_COM_CLOSE_PRINT_FILE", 

144 0xC3: "SMB_COM_GET_PRINT_QUEUE", 

145 0xD8: "SMB_COM_READ_BULK", 

146 0xD9: "SMB_COM_WRITE_BULK", 

147 0xDA: "SMB_COM_WRITE_BULK_DATA", 

148 0xFE: "SMB_COM_INVALID", 

149 0xFF: "SMB_COM_NO_ANDX_COMMAND", 

150} 

151 

152 

153class SMB_Header(Packet): 

154 name = "SMB 1 Protocol Request Header" 

155 fields_desc = [ 

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

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

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

159 FlagsField( 

160 "Flags", 

161 0x18, 

162 8, 

163 [ 

164 "LOCK_AND_READ_OK", 

165 "BUF_AVAIL", 

166 "res", 

167 "CASE_INSENSITIVE", 

168 "CANONICALIZED_PATHS", 

169 "OPLOCK", 

170 "OPBATCH", 

171 "REPLY", 

172 ], 

173 ), 

174 FlagsField( 

175 "Flags2", 

176 0x0000, 

177 -16, 

178 [ 

179 "LONG_NAMES", 

180 "EAS", 

181 "SMB_SECURITY_SIGNATURE", 

182 "COMPRESSED", 

183 "SMB_SECURITY_SIGNATURE_REQUIRED", 

184 "res", 

185 "IS_LONG_NAME", 

186 "res", 

187 "res", 

188 "res", 

189 "REPARSE_PATH", 

190 "EXTENDED_SECURITY", 

191 "DFS", 

192 "PAGING_IO", 

193 "NT_STATUS", 

194 "UNICODE", 

195 ], 

196 ), 

197 LEShortField("PIDHigh", 0x0000), 

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

199 LEShortField("Reserved", 0x0), 

200 LEShortField("TID", 0), 

201 LEShortField("PIDLow", 0), 

202 LEShortField("UID", 0), 

203 LEShortField("MID", 0), 

204 ] 

205 

206 def guess_payload_class(self, payload): 

207 # type: (bytes) -> Packet 

208 if not payload: 

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

210 WordCount = ord(payload[:1]) 

211 if self.Command == 0x72: 

212 if self.Flags.REPLY: 

213 if self.Flags2.EXTENDED_SECURITY: 

214 return SMBNegotiate_Response_Extended_Security 

215 else: 

216 return SMBNegotiate_Response_Security 

217 else: 

218 return SMBNegotiate_Request 

219 elif self.Command == 0x73: 

220 if WordCount == 0: 

221 return SMBSession_Null 

222 if self.Flags.REPLY: 

223 if WordCount == 0x04: 

224 return SMBSession_Setup_AndX_Response_Extended_Security 

225 elif WordCount == 0x03: 

226 return SMBSession_Setup_AndX_Response 

227 if self.Flags2.EXTENDED_SECURITY: 

228 return SMBSession_Setup_AndX_Response_Extended_Security 

229 else: 

230 return SMBSession_Setup_AndX_Response 

231 else: 

232 if WordCount == 0x0C: 

233 return SMBSession_Setup_AndX_Request_Extended_Security 

234 elif WordCount == 0x0D: 

235 return SMBSession_Setup_AndX_Request 

236 if self.Flags2.EXTENDED_SECURITY: 

237 return SMBSession_Setup_AndX_Request_Extended_Security 

238 else: 

239 return SMBSession_Setup_AndX_Request 

240 elif self.Command == 0x25: 

241 if self.Flags.REPLY: 

242 if WordCount == 0x11: 

243 return SMBMailslot_Write 

244 else: 

245 return SMBTransaction_Response 

246 else: 

247 if WordCount == 0x11: 

248 return SMBMailslot_Write 

249 else: 

250 return SMBTransaction_Request 

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

252 

253 def answers(self, pkt): 

254 return SMB_Header in pkt 

255 

256 

257# SMB Negotiate Request 

258 

259 

260class SMB_Dialect(Packet): 

261 name = "SMB Dialect" 

262 fields_desc = [ 

263 ByteField("BufferFormat", 0x02), 

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

265 ] 

266 

267 def default_payload_class(self, payload): 

268 return conf.padding_layer 

269 

270 

271class SMBNegotiate_Request(Packet): 

272 name = "SMB Negotiate Request" 

273 fields_desc = [ 

274 ByteField("WordCount", 0), 

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

276 PacketListField( 

277 "Dialects", 

278 [SMB_Dialect()], 

279 SMB_Dialect, 

280 length_from=lambda pkt: pkt.ByteCount, 

281 ), 

282 ] 

283 

284 

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

286 

287# SMBNegociate Protocol Response 

288 

289 

290def _SMBStrNullField(name, default): 

291 """ 

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

293 on the SMB headers. 

294 """ 

295 

296 def _isUTF16(pkt): 

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

298 pkt = pkt.underlayer 

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

300 

301 return MultipleTypeField( 

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

303 StrNullField(name, default), 

304 ) 

305 

306 

307def _len(pkt, name): 

308 """ 

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

310 """ 

311 fld, v = pkt.getfield_and_val(name) 

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

313 

314 

315class _SMBNegotiate_Response(Packet): 

316 @classmethod 

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

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

319 # Yes this is inspired by 

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

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

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

323 if wc == 1: 

324 # Core Protocol 

325 return SMBNegotiate_Response_NoSecurity 

326 elif wc == 0xD: 

327 # LAN Manager 1.0 - LAN Manager 2.1 

328 # TODO 

329 pass 

330 elif wc == 0x11: 

331 # NT LAN Manager 

332 return cls 

333 return cls 

334 

335 

336_SMB_ServerCapabilities = [ 

337 "RAW_MODE", 

338 "MPX_MODE", 

339 "UNICODE", 

340 "LARGE_FILES", 

341 "NT_SMBS", 

342 "RPC_REMOTE_APIS", 

343 "STATUS32", 

344 "LEVEL_II_OPLOCKS", 

345 "LOCK_AND_READ", 

346 "NT_FIND", 

347 "res", 

348 "res", 

349 "DFS", 

350 "INFOLEVEL_PASSTHRU", 

351 "LARGE_READX", 

352 "LARGE_WRITEX", 

353 "LWIO", 

354 "res", 

355 "res", 

356 "res", 

357 "res", 

358 "res", 

359 "res", 

360 "UNIX", 

361 "res", 

362 "COMPRESSED_DATA", 

363 "res", 

364 "res", 

365 "res", 

366 "DYNAMIC_REAUTH", 

367 "PERSISTENT_HANDLES", 

368 "EXTENDED_SECURITY", 

369] 

370 

371 

372# CIFS sect 2.2.4.52.2 

373 

374 

375class SMBNegotiate_Response_NoSecurity(_SMBNegotiate_Response): 

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

377 fields_desc = [ 

378 ByteField("WordCount", 0x1), 

379 LEShortField("DialectIndex", 7), 

380 FlagsField( 

381 "SecurityMode", 

382 0x03, 

383 8, 

384 [ 

385 "USER_SECURITY", 

386 "ENCRYPT_PASSWORDS", 

387 "SECURITY_SIGNATURES_ENABLED", 

388 "SECURITY_SIGNATURES_REQUIRED", 

389 ], 

390 ), 

391 LEShortField("MaxMpxCount", 50), 

392 LEShortField("MaxNumberVC", 1), 

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

394 LEIntField("MaxRawSize", 65536), 

395 LEIntField("SessionKey", 0x0000), 

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

397 UTCTimeField( 

398 "ServerTime", 

399 None, 

400 fmt="<Q", 

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

402 custom_scaling=1e7, 

403 ), 

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

405 FieldLenField( 

406 "ChallengeLength", 

407 None, 

408 # aka EncryptionKeyLength 

409 length_of="Challenge", 

410 fmt="<B", 

411 ), 

412 LEFieldLenField( 

413 "ByteCount", 

414 None, 

415 length_of="DomainName", 

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

417 ), 

418 XStrLenField( 

419 "Challenge", 

420 b"", # aka EncryptionKey 

421 length_from=lambda pkt: pkt.ChallengeLength, 

422 ), 

423 StrNullField("DomainName", "WORKGROUP"), 

424 ] 

425 

426 

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

428 

429# SMB sect 2.2.4.5.2.1 

430 

431 

432class SMBNegotiate_Response_Extended_Security(_SMBNegotiate_Response): 

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

434 WordCount = 0x11 

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

436 LEFieldLenField( 

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

438 ), 

439 SMBNegotiate_Response_NoSecurity.fields_desc[13], 

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

441 PacketLenField( 

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

443 ), 

444 ] 

445 

446 

447bind_top_down( 

448 SMB_Header, 

449 SMBNegotiate_Response_Extended_Security, 

450 Command=0x72, 

451 Flags=0x80, 

452 Flags2=0x800, 

453) 

454 

455# SMB sect 2.2.4.5.2.2 

456 

457 

458class SMBNegotiate_Response_Security(_SMBNegotiate_Response): 

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

460 WordCount = 0x11 

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

462 LEFieldLenField( 

463 "ByteCount", 

464 None, 

465 length_of="DomainName", 

466 adjust=lambda pkt, x: x 

467 + 2 

468 + _len(pkt, "Challenge") 

469 + _len(pkt, "ServerName"), 

470 ), 

471 XStrLenField( 

472 "Challenge", 

473 b"", # aka EncryptionKey 

474 length_from=lambda pkt: pkt.ChallengeLength, 

475 ), 

476 _SMBStrNullField("DomainName", "WORKGROUP"), 

477 _SMBStrNullField("ServerName", "RMFF1"), 

478 ] 

479 

480 

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

482 

483# Session Setup AndX Request 

484 

485# CIFS sect 2.2.4.53 

486 

487 

488class SMBSession_Setup_AndX_Request(Packet): 

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

490 fields_desc = [ 

491 ByteField("WordCount", 0x0D), 

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

493 ByteField("AndXReserved", 0), 

494 LEShortField("AndXOffset", None), 

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

496 LEShortField("MaxMPXCount", 50), 

497 LEShortField("VCNumber", 0), 

498 LEIntField("SessionKey", 0), 

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

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

501 LEIntField("Reserved", 0), 

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

503 LEShortField("ByteCount", None), 

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

505 XStrLenField( 

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

507 ), 

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

509 _SMBStrNullField("PrimaryDomain", ""), 

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

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

512 ] 

513 

514 def post_build(self, pkt, pay): 

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

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

517 if self.ByteCount is None: 

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

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

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

521 return pkt + pay 

522 

523 

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

525 

526# SMB sect 2.2.4.7 

527 

528 

529class SMBTree_Connect_AndX(Packet): 

530 name = "Session Tree Connect AndX" 

531 WordCount = 0x04 

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

533 FlagsField( 

534 "Flags", 

535 "", 

536 -16, 

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

538 ), 

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

540 LEShortField("ByteCount", None), 

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

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

543 StrNullField("Service", "?????"), 

544 ] 

545 

546 def post_build(self, pkt, pay): 

547 pkt += pay 

548 if self.ByteCount is None: 

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

550 return pkt 

551 

552 

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

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

555 

556# SMB sect 2.2.4.6.1 

557 

558 

559class SMBSession_Setup_AndX_Request_Extended_Security(Packet): 

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

561 WordCount = 0x0C 

562 fields_desc = ( 

563 SMBSession_Setup_AndX_Request.fields_desc[:8] 

564 + [ 

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

566 ] 

567 + SMBSession_Setup_AndX_Request.fields_desc[10:12] 

568 + [ 

569 LEShortField("ByteCount", None), 

570 PacketLenField( 

571 "SecurityBlob", 

572 None, 

573 GSSAPI_BLOB, 

574 length_from=lambda x: x.SecurityBlobLength, 

575 ), 

576 ReversePadField( 

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

578 2, 

579 b"\0", 

580 ), 

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

582 ] 

583 ) 

584 

585 def post_build(self, pkt, pay): 

586 if self.ByteCount is None: 

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

588 return pkt + pay 

589 

590 

591bind_top_down( 

592 SMB_Header, 

593 SMBSession_Setup_AndX_Request_Extended_Security, 

594 Command=0x73, 

595 Flags2=0x800, 

596) 

597 

598# Session Setup AndX Response 

599 

600 

601# CIFS sect 2.2.4.53.2 

602 

603 

604class SMBSession_Setup_AndX_Response(Packet): 

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

606 fields_desc = [ 

607 ByteField("WordCount", 0x3), 

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

609 ByteField("AndXReserved", 0), 

610 LEShortField("AndXOffset", None), 

611 FlagsField( 

612 "Action", 

613 0, 

614 -16, 

615 { 

616 0x0001: "SMB_SETUP_GUEST", 

617 0x0002: "SMB_SETUP_USE_LANMAN_KEY", 

618 }, 

619 ), 

620 LEShortField("ByteCount", 25), 

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

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

623 _SMBStrNullField("PrimaryDomain", ""), 

624 # Off spec? 

625 ByteField("WordCount2", 3), 

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

627 ByteField("Reserved3", 0), 

628 LEShortField("AndXOffset2", 80), 

629 LEShortField("OptionalSupport", 0x01), 

630 LEShortField("ByteCount2", 5), 

631 StrNullField("Service", "IPC"), 

632 StrNullField("NativeFileSystem", ""), 

633 ] 

634 

635 def post_build(self, pkt, pay): 

636 if self.AndXOffset is None: 

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

638 return pkt + pay 

639 

640 

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

642 

643# SMB sect 2.2.4.6.2 

644 

645 

646class SMBSession_Setup_AndX_Response_Extended_Security( 

647 SMBSession_Setup_AndX_Response 

648): # noqa: E501 

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

650 WordCount = 0x4 

651 fields_desc = ( 

652 SMBSession_Setup_AndX_Response.fields_desc[:5] 

653 + [SMBSession_Setup_AndX_Request_Extended_Security.fields_desc[8]] 

654 + SMBSession_Setup_AndX_Request_Extended_Security.fields_desc[11:] 

655 ) 

656 

657 def post_build(self, pkt, pay): 

658 if self.ByteCount is None: 

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

660 return super(SMBSession_Setup_AndX_Response_Extended_Security, self).post_build( 

661 pkt, pay 

662 ) 

663 

664 

665bind_top_down( 

666 SMB_Header, 

667 SMBSession_Setup_AndX_Response_Extended_Security, 

668 Command=0x73, 

669 Flags=0x80, 

670 Flags2=0x800, 

671) 

672 

673# SMB null (no wordcount) 

674 

675 

676class SMBSession_Null(Packet): 

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

678 

679 

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

681 

682# [MS-CIFS] sect 2.2.4.33.1 

683 

684_SMB_CONFIG = [ 

685 ("Len", _NTLM_ENUM.LEN), 

686 ("BufferOffset", _NTLM_ENUM.OFFSET), 

687] 

688 

689 

690class _SMB_TransactionRequest_Data(PacketLenField): 

691 def m2i(self, pkt, m): 

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

693 return NETLOGON(m) 

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

695 return BRWS(m) 

696 return conf.raw_layer(m) 

697 

698 

699def _optlen(pkt, x): 

700 try: 

701 return len(getattr(pkt, x)) 

702 except AttributeError: 

703 return 0 

704 

705 

706class SMBTransaction_Request(_NTLMPayloadPacket): 

707 name = "SMB COM Transaction Request" 

708 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

709 

710 fields_desc = [ 

711 FieldLenField( 

712 "WordCount", 

713 None, 

714 length_of="SetupCount", 

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

716 fmt="B", 

717 ), 

718 FieldLenField( 

719 "TotalParamCount", 

720 None, 

721 length_of="Buffer", 

722 fmt="<H", 

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

724 ), 

725 FieldLenField( 

726 "TotalDataCount", 

727 None, 

728 length_of="Buffer", 

729 fmt="<H", 

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

731 ), 

732 LEShortField("MaxParamCount", 0), 

733 LEShortField("MaxDataCount", 0), 

734 ByteField("MaxSetupCount", 0), 

735 ByteField("Reserved1", 0), 

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

737 LEIntField("Timeout", 1000), 

738 ShortField("Reserved2", 0), 

739 LEShortField("ParameterLen", None), 

740 LEShortField("ParameterBufferOffset", None), 

741 LEShortField("DataLen", None), 

742 LEShortField("DataBufferOffset", None), 

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

744 ByteField("Reserved3", 0), 

745 FieldListField( 

746 "Setup", 

747 [1, 1, 2], 

748 LEShortField("", 0), 

749 count_from=lambda pkt: pkt.SetupCount, 

750 ), 

751 # SMB Data 

752 FieldLenField( 

753 "ByteCount", 

754 None, 

755 length_of="Name", 

756 fmt="<H", 

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

758 ), 

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

760 _NTLMPayloadField( 

761 "Buffer", 

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

763 [ 

764 XStrLenField( 

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

766 ), 

767 _SMB_TransactionRequest_Data( 

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

769 ), 

770 ], 

771 ), 

772 ] 

773 

774 def post_build(self, pkt, pay): 

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

776 return ( 

777 _NTLM_post_build( 

778 self, 

779 pkt, 

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

781 { 

782 "Parameter": 19, 

783 "Data": 23, 

784 }, 

785 config=_SMB_CONFIG, 

786 ) 

787 + pay 

788 ) 

789 

790 def mysummary(self): 

791 if self.DataLen: 

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

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

794 

795 

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

797 

798 

799class SMBMailslot_Write(SMBTransaction_Request): 

800 WordCount = 0x11 

801 

802 

803# [MS-CIFS] sect 2.2.4.33.2 

804 

805 

806class SMBTransaction_Response(_NTLMPayloadPacket): 

807 name = "SMB COM Transaction Response" 

808 _NTLM_PAYLOAD_FIELD_NAME = "Buffer" 

809 fields_desc = [ 

810 FieldLenField( 

811 "WordCount", 

812 None, 

813 length_of="SetupCount", 

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

815 fmt="B", 

816 ), 

817 FieldLenField( 

818 "TotalParamCount", 

819 None, 

820 length_of="Buffer", 

821 fmt="<H", 

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

823 ), 

824 FieldLenField( 

825 "TotalDataCount", 

826 None, 

827 length_of="Buffer", 

828 fmt="<H", 

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

830 ), 

831 LEShortField("Reserved1", None), 

832 LEShortField("ParameterLen", None), 

833 LEShortField("ParameterBufferOffset", None), 

834 LEShortField("ParameterDisplacement", 0), 

835 LEShortField("DataLen", None), 

836 LEShortField("DataBufferOffset", None), 

837 LEShortField("DataDisplacement", 0), 

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

839 ByteField("Reserved2", 0), 

840 FieldListField( 

841 "Setup", 

842 [1, 1, 2], 

843 LEShortField("", 0), 

844 count_from=lambda pkt: pkt.SetupCount, 

845 ), 

846 # SMB Data 

847 FieldLenField( 

848 "ByteCount", 

849 None, 

850 length_of="Buffer", 

851 fmt="<H", 

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

853 ), 

854 _NTLMPayloadField( 

855 "Buffer", 

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

857 [ 

858 XStrLenField( 

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

860 ), 

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

862 ], 

863 ), 

864 ] 

865 

866 def post_build(self, pkt, pay): 

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

868 return ( 

869 _NTLM_post_build( 

870 self, 

871 pkt, 

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

873 { 

874 "Parameter": 7, 

875 "Data": 13, 

876 }, 

877 config=_SMB_CONFIG, 

878 ) 

879 + pay 

880 ) 

881 

882 

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

884 

885 

886# [MS-ADTS] sect 6.3.1.4 

887 

888_NETLOGON_opcodes = { 

889 0x7: "LOGON_PRIMARY_QUERY", 

890 0x12: "LOGON_SAM_LOGON_REQUEST", 

891 0x13: "LOGON_SAM_LOGON_RESPONSE", 

892 0x15: "LOGON_SAM_USER_UNKNOWN", 

893 0x17: "LOGON_SAM_LOGON_RESPONSE_EX", 

894 0x19: "LOGON_SAM_USER_UNKNOWN_EX", 

895} 

896 

897_NV_VERSION = { 

898 0x00000001: "V1", 

899 0x00000002: "V5", 

900 0x00000004: "V5EX", 

901 0x00000008: "V5EX_WITH_IP", 

902 0x00000010: "V5EX_WITH_CLOSEST_SITE", 

903 0x01000000: "AVOID_NT4EMUL", 

904 0x10000000: "PDC", 

905 0x20000000: "IP", 

906 0x40000000: "LOCAL", 

907 0x80000000: "GC", 

908} 

909 

910 

911class NETLOGON(Packet): 

912 @classmethod 

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

914 if _pkt: 

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

916 return NETLOGON_LOGON_QUERY 

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

918 return NETLOGON_SAM_LOGON_REQUEST 

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

920 try: 

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

922 NtVersion = ( 

923 NETLOGON_SAM_LOGON_RESPONSE_NT40.fields_desc[-3].getfield( 

924 None, _pkt[i - 4:i] 

925 )[1] 

926 ) 

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 

1016class NETLOGON_SAM_LOGON_RESPONSE(NETLOGON, DNSCompressedPacket): 

1017 fields_desc = [ 

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

1019 StrNullFieldUtf16("UnicodeLogonServer", ""), 

1020 StrNullFieldUtf16("UnicodeUserName", ""), 

1021 StrNullFieldUtf16("UnicodeDomainName", ""), 

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

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

1024 DNSStrField("DnsForestName", ""), 

1025 DNSStrField("DnsDomainName", ""), 

1026 DNSStrField("DnsHostName", ""), 

1027 IPField("DcIpAddress", "0.0.0.0"), 

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

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

1030 XLEShortField("LmNtToken", 0xFFFF), 

1031 XLEShortField("Lm20Token", 0xFFFF), 

1032 ] 

1033 

1034 def get_full(self): 

1035 return self.original 

1036 

1037 

1038# [MS-ADTS] sect 6.3.1.9 

1039 

1040 

1041class DcSockAddr(Packet): 

1042 fields_desc = [ 

1043 LEShortField("sin_family", 2), 

1044 LEShortField("sin_port", 0), 

1045 IPField("sin_addr", None), 

1046 LELongField("sin_zero", 0), 

1047 ] 

1048 

1049 def default_payload_class(self, payload): 

1050 return conf.padding_layer 

1051 

1052 

1053class NETLOGON_SAM_LOGON_RESPONSE_EX(NETLOGON, DNSCompressedPacket): 

1054 fields_desc = [ 

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

1056 LEShortField("Sbz", 0), 

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

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

1059 DNSStrField("DnsForestName", ""), 

1060 DNSStrField("DnsDomainName", ""), 

1061 DNSStrField("DnsHostName", ""), 

1062 DNSStrField("NetbiosDomainName", ""), 

1063 DNSStrField("NetbiosComputerName", ""), 

1064 DNSStrField("UserName", ""), 

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

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

1067 ConditionalField( 

1068 ByteField("DcSockAddrSize", 0x10), 

1069 lambda pkt: pkt.NtVersion.V5EX_WITH_IP, 

1070 ), 

1071 ConditionalField( 

1072 PacketField("DcSockAddr", DcSockAddr(), DcSockAddr), 

1073 lambda pkt: pkt.NtVersion.V5EX_WITH_IP, 

1074 ), 

1075 ConditionalField( 

1076 DNSStrField("NextClosestSiteName", ""), 

1077 lambda pkt: pkt.NtVersion.V5EX_WITH_CLOSEST_SITE, 

1078 ), 

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

1080 XLEShortField("LmNtToken", 0xFFFF), 

1081 XLEShortField("Lm20Token", 0xFFFF), 

1082 ] 

1083 

1084 def pre_dissect(self, s): 

1085 try: 

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

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

1088 self, 

1089 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 

1101class BRWS(Packet): 

1102 fields_desc = [ 

1103 ByteEnumField("OpCode", 0x00, { 

1104 0x01: "HostAnnouncement", 

1105 0x02: "AnnouncementRequest", 

1106 0x08: "RequestElection", 

1107 0x09: "GetBackupListRequest", 

1108 0x0A: "GetBackupListResponse", 

1109 0x0B: "BecomeBackup", 

1110 0x0C: "DomainAnnouncement", 

1111 0x0D: "MasterAnnouncement", 

1112 0x0E: "ResetStateRequest", 

1113 0x0F: "LocalMasterAnnouncement", 

1114 }), 

1115 ] 

1116 

1117 def mysummary(self): 

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

1119 

1120 registered_opcodes = {} 

1121 

1122 @classmethod 

1123 def register_variant(cls): 

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

1125 

1126 @classmethod 

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

1128 if _pkt: 

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

1130 return cls 

1131 

1132 def default_payload_class(self, payload): 

1133 return conf.padding_layer 

1134 

1135 

1136# [MS-BRWS] sect 2.2.1 

1137 

1138class BRWS_HostAnnouncement(BRWS): 

1139 OpCode = 0x01 

1140 fields_desc = [ 

1141 BRWS, 

1142 ByteField("UpdateCount", 0), 

1143 LEIntField("Periodicity", 128000), 

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

1145 ByteField("OSVersionMajor", 6), 

1146 ByteField("OSVersionMinor", 1), 

1147 LEIntField("ServerType", 4611), 

1148 ByteField("BrowserConfigVersionMajor", 21), 

1149 ByteField("BrowserConfigVersionMinor", 1), 

1150 XLEShortField("Signature", 0xAA55), 

1151 StrNullField("Comment", ""), 

1152 ] 

1153 

1154 def mysummary(self): 

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

1156 

1157 

1158# [MS-BRWS] sect 2.2.6 

1159 

1160class BRWS_BecomeBackup(BRWS): 

1161 OpCode = 0x0B 

1162 fields_desc = [ 

1163 BRWS, 

1164 StrNullField("BrowserToPromote", b""), 

1165 ] 

1166 

1167 def mysummary(self): 

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

1169 

1170 

1171# [MS-BRWS] sect 2.2.10 

1172 

1173class BRWS_LocalMasterAnnouncement(BRWS_HostAnnouncement): 

1174 OpCode = 0x0F 

1175 

1176 

1177# SMB dispatcher 

1178 

1179 

1180class _SMBGeneric(Packet): 

1181 name = "SMB Generic dispatcher" 

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

1183 

1184 @classmethod 

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

1186 """ 

1187 Depending on the first 4 bytes of the packet, 

1188 dispatch to the correct version of Header 

1189 (either SMB or SMB2) 

1190 """ 

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

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

1193 return SMB_Header 

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

1195 return SMB2_Header 

1196 return cls 

1197 

1198 

1199bind_layers(NBTSession, _SMBGeneric) 

1200bind_layers(NBTDatagram, _SMBGeneric)