Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/windows/security.py: 56%

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

156 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""" 

7Python objects for Microsoft Windows security structures. 

8""" 

9 

10import re 

11import struct 

12 

13from scapy.config import conf 

14from scapy.packet import Packet, bind_layers 

15from scapy.fields import ( 

16 ByteEnumField, 

17 ByteField, 

18 ConditionalField, 

19 FieldLenField, 

20 FieldListField, 

21 FlagsField, 

22 FlagValue, 

23 LEIntField, 

24 LELongField, 

25 LenField, 

26 LEShortEnumField, 

27 LEShortField, 

28 MultipleTypeField, 

29 PacketField, 

30 PacketListField, 

31 ShortField, 

32 StrFieldUtf16, 

33 StrFixedLenField, 

34 StrLenField, 

35 StrLenFieldUtf16, 

36 UUIDField, 

37) 

38 

39from scapy.layers.ntlm import ( 

40 _NTLM_ENUM, 

41 _NTLM_post_build, 

42 _NTLMPayloadField, 

43 _NTLMPayloadPacket, 

44) 

45 

46# [MS-DTYP] sect 2.4.1 

47 

48 

49class WINNT_SID_IDENTIFIER_AUTHORITY(Packet): 

50 

51 fields_desc = [ 

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

53 ] 

54 

55 def default_payload_class(self, payload: bytes) -> Packet: 

56 return conf.padding_layer 

57 

58 

59# [MS-DTYP] sect 2.4.2 

60 

61 

62class WINNT_SID(Packet): 

63 fields_desc = [ 

64 ByteField("Revision", 1), 

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

66 PacketField( 

67 "IdentifierAuthority", 

68 WINNT_SID_IDENTIFIER_AUTHORITY(), 

69 WINNT_SID_IDENTIFIER_AUTHORITY, 

70 ), 

71 FieldListField( 

72 "SubAuthority", 

73 [0], 

74 LEIntField("", 0), 

75 count_from=lambda pkt: pkt.SubAuthorityCount, 

76 ), 

77 ] 

78 

79 def default_payload_class(self, payload: bytes) -> Packet: 

80 return conf.padding_layer 

81 

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

83 

84 @staticmethod 

85 def fromstr(x: str): 

86 """ 

87 Helper to create a SID from its string representation. 

88 

89 :param x: string representation of the SID like "S-1-5-18" 

90 :type x: str 

91 

92 Example: 

93 

94 >>> from scapy.layers.windows.security import WINNT_SID 

95 >>> WINNT_SID.fromstr("S-1-5-18") 

96 <WINNT_SID Revision=1 IdentifierAuthority=<WINNT_SID_IDENTIFIER_AUTHORITY 

97 Value=b'\x00\x00\x00\x00\x00\x05' |> SubAuthority=[18] |> 

98 >>> _.summary() 

99 >>> 'S-1-5-18' 

100 """ 

101 

102 m = WINNT_SID._SID_REG.match(x) 

103 if not m: 

104 raise ValueError("Invalid SID format !") 

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

106 return WINNT_SID( 

107 Revision=int(rev), 

108 IdentifierAuthority=WINNT_SID_IDENTIFIER_AUTHORITY( 

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

110 ), 

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

112 ) 

113 

114 def summary(self) -> str: 

115 """ 

116 Return the string representation of the SID. 

117 """ 

118 return "S-%s-%s%s" % ( 

119 self.Revision, 

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

121 ( 

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

123 if self.SubAuthority 

124 else "" 

125 ), 

126 ) 

127 

128 

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

130 

131WELL_KNOWN_SIDS = { 

132 # Universal well-known SID 

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

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

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

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

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

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

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

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

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

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

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

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

145 # NT well-known SIDs 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

203} 

204 

205 

206# [MS-DTYP] sect 2.4.3 

207 

208_WINNT_ACCESS_MASK = { 

209 0x80000000: "GENERIC_READ", 

210 0x40000000: "GENERIC_WRITE", 

211 0x20000000: "GENERIC_EXECUTE", 

212 0x10000000: "GENERIC_ALL", 

213 0x02000000: "MAXIMUM_ALLOWED", 

214 0x01000000: "ACCESS_SYSTEM_SECURITY", 

215 0x00100000: "SYNCHRONIZE", 

216 0x00080000: "WRITE_OWNER", 

217 0x00040000: "WRITE_DACL", 

218 0x00020000: "READ_CONTROL", 

219 0x00010000: "DELETE", 

220} 

221 

222 

223# [MS-DTYP] sect 2.4.4.1 

224 

225 

226WINNT_ACE_FLAGS = { 

227 0x01: "OBJECT_INHERIT", 

228 0x02: "CONTAINER_INHERIT", 

229 0x04: "NO_PROPAGATE_INHERIT", 

230 0x08: "INHERIT_ONLY", 

231 0x10: "INHERITED_ACE", 

232 0x40: "SUCCESSFUL_ACCESS", 

233 0x80: "FAILED_ACCESS", 

234} 

235 

236 

237class WINNT_ACE_HEADER(Packet): 

238 """ 

239 Access Control Entry (ACE) Header 

240 It is composed of 3 fields, followed by ACE-specific data: 

241 

242 - AceType (1 byte): see below for standard values 

243 - AceFlags (1 byte): see WINNT_ACE_FLAGS 

244 - AceSize (2 bytes): total size of the ACE, including the header 

245 and the ACE-specific data. 

246 """ 

247 

248 fields_desc = [ 

249 ByteEnumField( 

250 "AceType", 

251 0, 

252 { 

253 0x00: "ACCESS_ALLOWED", 

254 0x01: "ACCESS_DENIED", 

255 0x02: "SYSTEM_AUDIT", 

256 0x03: "SYSTEM_ALARM", 

257 0x04: "ACCESS_ALLOWED_COMPOUND", 

258 0x05: "ACCESS_ALLOWED_OBJECT", 

259 0x06: "ACCESS_DENIED_OBJECT", 

260 0x07: "SYSTEM_AUDIT_OBJECT", 

261 0x08: "SYSTEM_ALARM_OBJECT", 

262 0x09: "ACCESS_ALLOWED_CALLBACK", 

263 0x0A: "ACCESS_DENIED_CALLBACK", 

264 0x0B: "ACCESS_ALLOWED_CALLBACK_OBJECT", 

265 0x0C: "ACCESS_DENIED_CALLBACK_OBJECT", 

266 0x0D: "SYSTEM_AUDIT_CALLBACK", 

267 0x0E: "SYSTEM_ALARM_CALLBACK", 

268 0x0F: "SYSTEM_AUDIT_CALLBACK_OBJECT", 

269 0x10: "SYSTEM_ALARM_CALLBACK_OBJECT", 

270 0x11: "SYSTEM_MANDATORY_LABEL", 

271 0x12: "SYSTEM_RESOURCE_ATTRIBUTE", 

272 0x13: "SYSTEM_SCOPED_POLICY_ID", 

273 }, 

274 ), 

275 FlagsField( 

276 "AceFlags", 

277 0, 

278 8, 

279 WINNT_ACE_FLAGS, 

280 ), 

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

282 ] 

283 

284 def extract_padding(self, p): 

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

286 

287 # fmt: off 

288 def extractData(self, accessMask=None): 

289 """ 

290 Return the ACE data as usable data. 

291 

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

293 """ 

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

295 mask = self.payload.Mask 

296 if accessMask is not None: 

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

298 ace_flag_string = str( 

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

300 ) 

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

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

303 # ApplicationData -> conditional expression 

304 cond_expr = None 

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

306 # Parse tokens 

307 res = [] 

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

309 if ct.TokenType in [ 

310 # binary operators 

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

312 0xa0, 0xa1 

313 ]: 

314 t1 = res.pop(-1) 

315 t0 = res.pop(-1) 

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

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

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

319 else: 

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

321 elif ct.TokenType in [ 

322 # unary operators 

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

324 ]: 

325 t0 = res.pop(-1) 

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

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

328 elif ct.TokenType in [ 

329 # values 

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

331 0xfa, 0xfb 

332 ]: 

333 def lit(ct): 

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

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

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

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

338 else: 

339 return str(ct.value) 

340 res.append(lit(ct)) 

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

342 pass 

343 else: 

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

345 if len(res) != 1: 

346 raise ValueError("Incomplete SDDL !") 

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

348 return { 

349 "ace-flags-string": ace_flag_string, 

350 "sid-string": sid_string, 

351 "mask": mask, 

352 "object-guid": object_guid, 

353 "inherited-object-guid": inherit_object_guid, 

354 "cond-expr": cond_expr, 

355 } 

356 # fmt: on 

357 

358 def toSDDL(self, accessMask=None): 

359 """ 

360 Return SDDL 

361 """ 

362 data = self.extractData(accessMask=accessMask) 

363 ace_rights = "" # TODO 

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

365 conditional_ace_type = { 

366 0x09: "XA", 

367 0x0A: "XD", 

368 0x0B: "XU", 

369 0x0D: "ZA", 

370 }[self.AceType] 

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

372 ";".join( 

373 x 

374 for x in [ 

375 conditional_ace_type, 

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

377 ace_rights, 

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

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

380 data["sid-string"], 

381 data["cond-expr"], 

382 ] 

383 if x is not None 

384 ) 

385 ) 

386 else: 

387 ace_type = { 

388 0x00: "A", 

389 0x01: "D", 

390 0x02: "AU", 

391 0x05: "OA", 

392 0x06: "OD", 

393 0x07: "OU", 

394 0x11: "ML", 

395 0x13: "SP", 

396 }[self.AceType] 

397 return "(%s)" % ( 

398 ";".join( 

399 x 

400 for x in [ 

401 ace_type, 

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

403 ace_rights, 

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

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

406 data["sid-string"], 

407 data["cond-expr"], 

408 ] 

409 if x is not None 

410 ) 

411 ) 

412 

413 

414# [MS-DTYP] sect 2.4.4.2 

415 

416 

417class WINNT_ACCESS_ALLOWED_ACE(Packet): 

418 fields_desc = [ 

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

420 PacketField("Sid", WINNT_SID(), WINNT_SID), 

421 ] 

422 

423 

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

425 

426 

427# [MS-DTYP] sect 2.4.4.3 

428 

429 

430class WINNT_ACCESS_ALLOWED_OBJECT_ACE(Packet): 

431 fields_desc = [ 

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

433 FlagsField( 

434 "Flags", 

435 0, 

436 -32, 

437 { 

438 0x00000001: "OBJECT_TYPE_PRESENT", 

439 0x00000002: "INHERITED_OBJECT_TYPE_PRESENT", 

440 }, 

441 ), 

442 ConditionalField( 

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

444 lambda pkt: pkt.Flags.OBJECT_TYPE_PRESENT, 

445 ), 

446 ConditionalField( 

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

448 lambda pkt: pkt.Flags.INHERITED_OBJECT_TYPE_PRESENT, 

449 ), 

450 PacketField("Sid", WINNT_SID(), WINNT_SID), 

451 ] 

452 

453 

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

455 

456 

457# [MS-DTYP] sect 2.4.4.4 

458 

459 

460class WINNT_ACCESS_DENIED_ACE(Packet): 

461 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

462 

463 

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

465 

466 

467# [MS-DTYP] sect 2.4.4.5 

468 

469 

470class WINNT_ACCESS_DENIED_OBJECT_ACE(Packet): 

471 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc 

472 

473 

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

475 

476 

477# [MS-DTYP] sect 2.4.4.17.4+ 

478 

479 

480class WINNT_APPLICATION_DATA_LITERAL_TOKEN(Packet): 

481 def default_payload_class(self, payload): 

482 return conf.padding_layer 

483 

484 

485# fmt: off 

486WINNT_APPLICATION_DATA_LITERAL_TOKEN.fields_desc = [ 

487 ByteEnumField( 

488 "TokenType", 

489 0, 

490 { 

491 # [MS-DTYP] sect 2.4.4.17.5 

492 0x00: "Padding token", 

493 0x01: "Signed int8", 

494 0x02: "Signed int16", 

495 0x03: "Signed int32", 

496 0x04: "Signed int64", 

497 0x10: "Unicode", 

498 0x18: "Octet String", 

499 0x50: "Composite", 

500 0x51: "SID", 

501 # [MS-DTYP] sect 2.4.4.17.6 

502 0x80: "==", 

503 0x81: "!=", 

504 0x82: "<", 

505 0x83: "<=", 

506 0x84: ">", 

507 0x85: ">=", 

508 0x86: "Contains", 

509 0x88: "Any_of", 

510 0x8e: "Not_Contains", 

511 0x8f: "Not_Any_of", 

512 0x89: "Member_of", 

513 0x8a: "Device_Member_of", 

514 0x8b: "Member_of_Any", 

515 0x8c: "Device_Member_of_Any", 

516 0x90: "Not_Member_of", 

517 0x91: "Not_Device_Member_of", 

518 0x92: "Not_Member_of_Any", 

519 0x93: "Not_Device_Member_of_Any", 

520 # [MS-DTYP] sect 2.4.4.17.7 

521 0x87: "Exists", 

522 0x8d: "Not_Exists", 

523 0xa0: "&&", 

524 0xa1: "||", 

525 0xa2: "!", 

526 # [MS-DTYP] sect 2.4.4.17.8 

527 0xf8: "Local attribute", 

528 0xf9: "User Attribute", 

529 0xfa: "Resource Attribute", 

530 0xfb: "Device Attribute", 

531 } 

532 ), 

533 ConditionalField( 

534 # Strings 

535 LEIntField("length", 0), 

536 lambda pkt: pkt.TokenType in [ 

537 0x10, # Unicode string 

538 0x18, # Octet string 

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

540 0x50, # Composite 

541 ] 

542 ), 

543 ConditionalField( 

544 MultipleTypeField( 

545 [ 

546 ( 

547 LELongField("value", 0), 

548 lambda pkt: pkt.TokenType in [ 

549 0x01, # signed int8 

550 0x02, # signed int16 

551 0x03, # signed int32 

552 0x04, # signed int64 

553 ] 

554 ), 

555 ( 

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

557 lambda pkt: pkt.TokenType in [ 

558 0x10, # Unicode string 

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

560 ] 

561 ), 

562 ( 

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

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

565 ), 

566 ( 

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

568 length_from=lambda pkt: pkt.length), 

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

570 ), 

571 

572 ], 

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

574 ), 

575 lambda pkt: pkt.TokenType in [ 

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

577 ] 

578 ), 

579 ConditionalField( 

580 # Literal 

581 ByteEnumField("sign", 0, { 

582 0x01: "+", 

583 0x02: "-", 

584 0x03: "None", 

585 }), 

586 lambda pkt: pkt.TokenType in [ 

587 0x01, # signed int8 

588 0x02, # signed int16 

589 0x03, # signed int32 

590 0x04, # signed int64 

591 ] 

592 ), 

593 ConditionalField( 

594 # Literal 

595 ByteEnumField("base", 0, { 

596 0x01: "Octal", 

597 0x02: "Decimal", 

598 0x03: "Hexadecimal", 

599 }), 

600 lambda pkt: pkt.TokenType in [ 

601 0x01, # signed int8 

602 0x02, # signed int16 

603 0x03, # signed int32 

604 0x04, # signed int64 

605 ] 

606 ), 

607] 

608# fmt: on 

609 

610 

611class WINNT_APPLICATION_DATA(Packet): 

612 fields_desc = [ 

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

614 PacketListField( 

615 "Tokens", 

616 [], 

617 WINNT_APPLICATION_DATA_LITERAL_TOKEN, 

618 ), 

619 ] 

620 

621 def default_payload_class(self, payload): 

622 return conf.padding_layer 

623 

624 

625# [MS-DTYP] sect 2.4.4.6 

626 

627 

628class WINNT_ACCESS_ALLOWED_CALLBACK_ACE(Packet): 

629 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [ 

630 PacketField( 

631 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

632 ), 

633 ] 

634 

635 

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

637 

638 

639# [MS-DTYP] sect 2.4.4.7 

640 

641 

642class WINNT_ACCESS_DENIED_CALLBACK_ACE(Packet): 

643 fields_desc = WINNT_ACCESS_ALLOWED_CALLBACK_ACE.fields_desc 

644 

645 

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

647 

648 

649# [MS-DTYP] sect 2.4.4.8 

650 

651 

652class WINNT_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE(Packet): 

653 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc + [ 

654 PacketField( 

655 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

656 ), 

657 ] 

658 

659 

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

661 

662 

663# [MS-DTYP] sect 2.4.4.9 

664 

665 

666class WINNT_ACCESS_DENIED_CALLBACK_OBJECT_ACE(Packet): 

667 fields_desc = WINNT_ACCESS_DENIED_OBJECT_ACE.fields_desc + [ 

668 PacketField( 

669 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

670 ), 

671 ] 

672 

673 

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

675 

676 

677# [MS-DTYP] sect 2.4.4.10 

678 

679 

680class WINNT_SYSTEM_AUDIT_ACE(Packet): 

681 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

682 

683 

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

685 

686 

687# [MS-DTYP] sect 2.4.4.11 

688 

689 

690class WINNT_SYSTEM_AUDIT_OBJECT_ACE(Packet): 

691 # doc is wrong. 

692 fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc 

693 

694 

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

696 

697 

698# [MS-DTYP] sect 2.4.4.12 

699 

700 

701class WINNT_SYSTEM_AUDIT_CALLBACK_ACE(Packet): 

702 fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc + [ 

703 PacketField( 

704 "ApplicationData", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA 

705 ), 

706 ] 

707 

708 

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

710 

711 

712# [MS-DTYP] sect 2.4.4.13 

713 

714 

715class WINNT_SYSTEM_MANDATORY_LABEL_ACE(Packet): 

716 fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc 

717 

718 

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

720 

721 

722# [MS-DTYP] sect 2.4.4.14 

723 

724 

725class WINNT_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE(Packet): 

726 fields_desc = WINNT_SYSTEM_AUDIT_OBJECT_ACE.fields_desc 

727 

728 

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

730 

731# [MS-DTYP] sect 2.4.10.1 

732 

733 

734class CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(_NTLMPayloadPacket): 

735 _NTLM_PAYLOAD_FIELD_NAME = "Data" 

736 fields_desc = [ 

737 LEIntField("NameOffset", 0), 

738 LEShortEnumField( 

739 "ValueType", 

740 0, 

741 { 

742 0x0001: "CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64", 

743 0x0002: "CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64", 

744 0x0003: "CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING", 

745 0x0005: "CLAIM_SECURITY_ATTRIBUTE_TYPE_SID", 

746 0x0006: "CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN", 

747 0x0010: "CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING", 

748 }, 

749 ), 

750 LEShortField("Reserved", 0), 

751 FlagsField( 

752 "Flags", 

753 0, 

754 -32, 

755 { 

756 0x0001: "CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE", 

757 0x0002: "CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE", 

758 0x0004: "CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY", 

759 0x0008: "CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT", 

760 0x0010: "CLAIM_SECURITY_ATTRIBUTE_DISABLED", 

761 0x0020: "CLAIM_SECURITY_ATTRIBUTE_MANDATORY", 

762 }, 

763 ), 

764 LEIntField("ValueCount", 0), 

765 FieldListField( 

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

767 ), 

768 _NTLMPayloadField( 

769 "Data", 

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

771 [ 

772 ConditionalField( 

773 StrFieldUtf16("Name", b""), 

774 lambda pkt: pkt.NameOffset, 

775 ), 

776 # TODO: Values 

777 ], 

778 offset_name="Offset", 

779 ), 

780 ] 

781 

782 

783# [MS-DTYP] sect 2.4.4.15 

784 

785 

786class WINNT_SYSTEM_RESOURCE_ATTRIBUTE_ACE(Packet): 

787 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [ 

788 PacketField( 

789 "AttributeData", 

790 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(), 

791 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1, 

792 ) 

793 ] 

794 

795 

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

797 

798# [MS-DTYP] sect 2.4.4.16 

799 

800 

801class WINNT_SYSTEM_SCOPED_POLICY_ID_ACE(Packet): 

802 fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc 

803 

804 

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

806 

807# [MS-DTYP] sect 2.4.5 

808 

809 

810class WINNT_ACL(Packet): 

811 fields_desc = [ 

812 ByteField("AclRevision", 2), 

813 ByteField("Sbz1", 0x00), 

814 # Total size including header: 

815 # AclRevision(1) + Sbz1(1) + AclSize(2) + AceCount(2) + Sbz2(2) 

816 FieldLenField( 

817 "AclSize", 

818 None, 

819 length_of="Aces", 

820 adjust=lambda _, x: x + 8, 

821 fmt="<H", 

822 ), 

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

824 ShortField("Sbz2", 0), 

825 PacketListField( 

826 "Aces", 

827 [], 

828 WINNT_ACE_HEADER, 

829 count_from=lambda pkt: pkt.AceCount, 

830 ), 

831 ] 

832 

833 def toSDDL(self): 

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

835 

836 

837# [MS-DTYP] 2.4.6 SECURITY_DESCRIPTOR 

838 

839 

840class SECURITY_DESCRIPTOR(_NTLMPayloadPacket): 

841 OFFSET = 20 

842 _NTLM_PAYLOAD_FIELD_NAME = "Data" 

843 fields_desc = [ 

844 ByteField("Revision", 0x01), 

845 ByteField("Sbz1", 0x00), 

846 FlagsField( 

847 "Control", 

848 0x00, 

849 -16, 

850 [ 

851 "OWNER_DEFAULTED", 

852 "GROUP_DEFAULTED", 

853 "DACL_PRESENT", 

854 "DACL_DEFAULTED", 

855 "SACL_PRESENT", 

856 "SACL_DEFAULTED", 

857 "DACL_TRUSTED", 

858 "SERVER_SECURITY", 

859 "DACL_COMPUTED", 

860 "SACL_COMPUTED", 

861 "DACL_AUTO_INHERITED", 

862 "SACL_AUTO_INHERITED", 

863 "DACL_PROTECTED", 

864 "SACL_PROTECTED", 

865 "RM_CONTROL_VALID", 

866 "SELF_RELATIVE", 

867 ], 

868 ), 

869 LEIntField("OwnerSidOffset", None), 

870 LEIntField("GroupSidOffset", None), 

871 LEIntField("SACLOffset", None), 

872 LEIntField("DACLOffset", None), 

873 _NTLMPayloadField( 

874 "Data", 

875 OFFSET, 

876 [ 

877 ConditionalField( 

878 PacketField("OwnerSid", WINNT_SID(), WINNT_SID), 

879 lambda pkt: pkt.OwnerSidOffset != 0, 

880 ), 

881 ConditionalField( 

882 PacketField("GroupSid", WINNT_SID(), WINNT_SID), 

883 lambda pkt: pkt.GroupSidOffset != 0, 

884 ), 

885 ConditionalField( 

886 PacketField("SACL", WINNT_ACL(), WINNT_ACL), 

887 lambda pkt: pkt.Control.SACL_PRESENT, 

888 ), 

889 ConditionalField( 

890 PacketField("DACL", WINNT_ACL(), WINNT_ACL), 

891 lambda pkt: pkt.Control.DACL_PRESENT, 

892 ), 

893 ], 

894 offset_name="Offset", 

895 ), 

896 ] 

897 

898 def post_build(self, pkt, pay): 

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

900 return ( 

901 _NTLM_post_build( 

902 self, 

903 pkt, 

904 self.OFFSET, 

905 { 

906 "OwnerSid": 4, 

907 "GroupSid": 8, 

908 "SACL": 12, 

909 "DACL": 16, 

910 }, 

911 config=[ 

912 ("Offset", _NTLM_ENUM.OFFSET), 

913 ], 

914 ) 

915 + pay 

916 ) 

917 

918 def show_print(self): 

919 """ 

920 Print the SECURITY_DESCRIPTOR in a human format 

921 """ 

922 print("Owner:", self.OwnerSid.summary()) 

923 print("Group:", self.GroupSid.summary()) 

924 if getattr(self, "DACL", None): 

925 print("DACL:") 

926 for ace in self.DACL.Aces: 

927 print(" - ", ace.toSDDL()) 

928 if getattr(self, "SACL", None): 

929 print("SACL:") 

930 for ace in self.SACL.Aces: 

931 print(" - ", ace.toSDDL())