Skip to content

Commit 7d61ce0

Browse files
committed
Update ACE module
1 parent 773cda1 commit 7d61ce0

2 files changed

Lines changed: 72 additions & 70 deletions

File tree

wconv/ace.py

Lines changed: 58 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -281,19 +281,18 @@ class Ace:
281281
The Ace class represents a single ACE entry inside a SDDL string.
282282
'''
283283

284-
def __init__(self, ace_type: int, ace_flags: list[str], permissions: list[str], object_type: str,
285-
inherited_object_type: str, trustee: str, numeric: int) -> None:
284+
def __init__(self, ace_type: int, ace_flags: list[str], permissions: int, object_type: str,
285+
inherited_object_type: str, trustee: str | SecurityIdentifier) -> None:
286286
'''
287287
The init function takes the six different ACE components and constructs an object out of them.
288288
289289
Parameters:
290290
ace_type integer that specifies the ACE type (see ACE_TYPES)
291291
ace_flags ace_flags according to the ACE specifications
292-
permissions permissions defined inside the ACE as strings
292+
permissions ACE permissions as integer
293293
object_type object_type according to the sddl specifications
294294
i_object_type inherited_object_type according to the sddl specifications
295295
trustee trustee the ACE applies to
296-
numeric Integer ace value
297296
298297
Returns:
299298
None
@@ -304,11 +303,11 @@ def __init__(self, ace_type: int, ace_flags: list[str], permissions: list[str],
304303
self.object_type = object_type
305304
self.inherited_object_type = inherited_object_type
306305
self.trustee = trustee
307-
self.numeric = numeric
308306

309307
def __str__(self) -> str:
310308
'''
311-
Outputs a simple string represenation of the ACE. Only used for debugging purposes.
309+
Outputs a simple string represenation of the ACE.
310+
Only used for debugging purposes.
312311
313312
Paramaters:
314313
None
@@ -317,29 +316,35 @@ def __str__(self) -> str:
317316
String representation of ACE
318317
'''
319318
result = f'ACE Type:\t {ACE_TYPES[self.ace_type]}\n'
319+
permissions = self.get_permissions()
320320

321321
if self.trustee:
322322
result += f'Trustee:\t {self.trustee}\n'
323323

324-
if self.permissions:
324+
if permissions:
325+
325326
result += 'Permissions:\n'
326-
for perm in self.permissions:
327+
328+
for perm in permissions:
327329
result += f'\t\t+ {perm}\n'
328330

329331
if self.ace_flags:
332+
330333
result += 'ACE Flags:\n'
334+
331335
for flag in self.ace_flags:
332336
result += f'\t\t+ {flag}\n'
333337

334338
return result[:-1]
335339

336-
def pretty_print(self, indent: str = ' ') -> None:
340+
def pretty_print(self, indent: str = ' ', perm_type: str = 'file') -> None:
337341
'''
338342
Prints some formatted and colored output that represents the ACE. Probably not really
339343
ideal to be placed inside a library, but for now we can live with that.
340344
341345
Parameters:
342346
indent Spaces after the '[+]' prefix
347+
perm_type which resource the ACE is attached to
343348
344349
Returns:
345350
None
@@ -377,44 +382,68 @@ def pretty_print(self, indent: str = ' ') -> None:
377382
print_blue(f'[+]{indent}IObj Type:\t', end='')
378383
self.inherited_object_type.pretty_print()
379384

380-
if self.permissions:
385+
permissions = self.get_permissions(perm_type)
386+
387+
if permissions:
381388

382389
print_blue(f'[+]{indent}Permissions:')
383-
for perm in self.permissions:
390+
391+
for perm in permissions:
384392
print_blue('[+]', end='')
385393
print_yellow(f'{indent}\t\t+ {perm}')
386394

387-
def toggle_permission(self, permissions: list[str], perm_type: str = 'file') -> None:
395+
def get_permissions(self, perm_type: str = 'file') -> list[str]:
396+
'''
397+
Returns the permissions contained within the ACE as a list
398+
of strings.
399+
400+
Parameters:
401+
None
402+
403+
Returns:
404+
list of permissions as strings
405+
'''
406+
perm_dict = get_permission_dict(perm_type)
407+
permissions = []
408+
409+
for key, value in ACCESS_MASK_HEX.items():
410+
411+
if key & self.permissions:
412+
413+
try:
414+
permission = perm_dict[value]
415+
permissions.append(permission)
416+
417+
except KeyError:
418+
pass
419+
420+
return permissions
421+
422+
def toggle_permission(self, permissions: list[str]) -> None:
388423
'''
389424
Toggles the specified permissions for this ACE.
390425
391426
Parameters:
392427
permissions List of permission to toggle (GA, GR, GW, GE, CC, ...)
393-
perm_type Object type the sddl applies to (file, service, ...)
394428
395429
Returns:
396430
None
397431
'''
398-
perm_dict = get_permission_dict(perm_type)
399-
400432
for permission in permissions:
401433

402434
try:
403435
hex_value = wconv.sddl.ACCESS_MASK_HEX[permission]
404-
405-
self.numeric = self.numeric ^ hex_value
406-
self.permissions.append(perm_dict[hex_value])
436+
self.permissions ^= hex_value
407437

408438
except KeyError:
409439
raise WConvException(f'Ace.toggle_permission(... - Unknown permission name: {permission}')
410440

411-
def from_sddl(ace_string: str, perm_type: str = 'file') -> Ace:
441+
def from_sddl(ace_string: str) -> Ace:
412442
'''
413443
Parses an ace from a string in SDDL representation (e.g. A;OICI;FA;;;BA).
414444
415445
Parameters:
416446
ace_string ACE string in sddl format
417-
perm_type Object type the sddl applies to (file, service, ...)
418447
419448
Returns:
420449
ace_object
@@ -428,7 +457,7 @@ def from_sddl(ace_string: str, perm_type: str = 'file') -> Ace:
428457

429458
ace_type = wconv.sddl.SDDL_ACE_TYPES[ace_type]
430459
ace_flags = wconv.sddl.map_ace_flags(ace_flags)
431-
permissions = wconv.sddl.get_ace_permissions(perms, perm_type)
460+
permissions = wconv.sddl.get_ace_numeric(perms)
432461
ace_int = wconv.sddl.get_ace_numeric(perms)
433462

434463
if object_type:
@@ -440,44 +469,28 @@ def from_sddl(ace_string: str, perm_type: str = 'file') -> Ace:
440469
if trustee in wconv.sddl.TRUSTEES:
441470
trustee = wconv.sddl.TRUSTEES[trustee]
442471

443-
return Ace(ace_type, ace_flags, permissions, object_type, inherited_object_type, trustee, ace_int)
472+
return Ace(ace_type, ace_flags, permissions, object_type, inherited_object_type, trustee)
444473

445-
def from_int(integer: str | int, perm_type: str = 'file') -> Ace:
474+
def from_int(integer: str | int) -> Ace:
446475
'''
447476
Parses an ace from an integer value in string representation.
448477
449478
Parameters:
450479
integer Integer value as string (hex also allowed)
451-
perm_type Object type the sddl applies to (file, service, ...)
452480
453481
Returns:
454482
ace_object
455483
'''
456-
ace_int = get_int(integer)
457-
458-
perm_dict = get_permission_dict(perm_type)
459-
permissions = []
460-
461-
for key, value in perm_dict.items():
462-
463-
if key & ace_int:
464-
465-
try:
466-
permissions.append(value)
467-
468-
except KeyError:
469-
# Ignore matches on grouped permissions like FA, FR, FW...
470-
pass
484+
permissions = get_int(integer)
471485

472-
return Ace(None, None, permissions, None, None, None, ace_int)
486+
return Ace(None, None, permissions, None, None, None)
473487

474-
def from_bytes(byte_data: bytes, perm_type: str = 'file') -> Ace:
488+
def from_bytes(byte_data: bytes) -> Ace:
475489
'''
476490
Parses an ACE from a bytes object.
477491
478492
Parameters:
479493
byte_data byte data of the ACE
480-
perm_type Object type the ACE applies to (file, service, ...)
481494
482495
Returns:
483496
ace_object
@@ -512,36 +525,21 @@ def from_bytes(byte_data: bytes, perm_type: str = 'file') -> Ace:
512525
ace_perms = struct.unpack('<I', byte_data[4:8])[0]
513526
trustee = SecurityIdentifier(byte_data[position:], False)
514527

515-
perm_dict = get_permission_dict(perm_type)
516-
permissions = []
517-
518-
for key, value in ACCESS_MASK_HEX.items():
519-
520-
if key & ace_perms:
521-
522-
try:
523-
permission = perm_dict[value]
524-
permissions.append(permission)
525-
526-
except KeyError:
527-
pass
528-
529-
return Ace(ace_type, ace_flag_list, permissions, object_type, object_type_inherited, trustee, ace_perms)
528+
return Ace(ace_type, ace_flag_list, ace_perms, object_type, object_type_inherited, trustee)
530529

531-
def from_hex(hex_str: str, perm_type: str = 'file') -> Ace:
530+
def from_hex(hex_str: str) -> Ace:
532531
'''
533532
Parses an ACE from a hex string.
534533
535534
Parameters:
536535
hex_string hex string representing an ACE
537-
perm_type Object type the ACE applies to (file, service, ...)
538536
539537
Returns:
540538
ace_object
541539
'''
542540
try:
543541
data = binascii.unhexlify(hex_str)
544-
return Ace.from_bytes(data, perm_type)
542+
return Ace.from_bytes(data)
545543

546544
except binascii.Error:
547545
raise WConvException(f'Ace.from_hex(... - Invalid hex string: {hex_string}')

wconv/main.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import wconv.sid
99
import wconv.objecttype
1010

11-
from wconv.helpers import print_yellow, print_blue, file_to_dict
11+
from wconv.helpers import print_yellow, print_blue, file_to_dict, get_max
1212

1313

1414
typelist = [
@@ -92,6 +92,7 @@ def main():
9292
if args.permissions:
9393

9494
perm_dict = wconv.ace.get_permission_dict(args.type)
95+
result_list = []
9596

9697
for hex_value, name in perm_dict.items():
9798

@@ -102,8 +103,11 @@ def main():
102103
sddl_name = sddl
103104

104105
hex_value = '{:08x}'.format(hex_value)
105-
print_blue(f'[+] {hex_value} - {sddl_name} - ', end='')
106-
print_yellow(name)
106+
result_list.append((hex_value, sddl_name, name))
107+
108+
for result in sorted(result_list, key = lambda x: x[0]):
109+
print_blue(f'[+] 0x{result[0]} - {result[1]} - ', end='')
110+
print_yellow(result[2])
107111

108112
elif args.trustees:
109113

@@ -114,30 +118,30 @@ def main():
114118
elif args.flags:
115119

116120
for key, value in wconv.ace.ACE_FLAGS.items():
117-
print_blue(f'[+] {key} - ', end='')
121+
print_blue(f'[+] {str(key).ljust(3)} - ', end='')
118122
print_yellow(value)
119123

120124
elif args.types:
121125

122126
for key, value in wconv.ace.ACE_TYPES.items():
123-
print_blue(f'[+] {key} - ', end='')
127+
print_blue(f'[+] {str(key).ljust(2)} - ', end='')
124128
print_yellow(value)
125129

126130
elif args.ace is not None:
127131

128132
if args.sddl:
129-
ace = wconv.ace.Ace.from_sddl(args.ace, args.type)
133+
ace = wconv.ace.Ace.from_sddl(args.ace)
130134

131135
elif args.hex:
132-
ace = wconv.ace.Ace.from_hex(args.ace, args.type)
136+
ace = wconv.ace.Ace.from_hex(args.ace)
133137

134138
else:
135-
ace = wconv.ace.Ace.from_int(args.ace, args.type)
139+
ace = wconv.ace.Ace.from_int(args.ace)
136140

137141
if args.toggle:
138-
ace.toggle_permission(args.toggle, args.type)
142+
ace.toggle_permission(args.toggle)
139143

140-
ace.pretty_print()
144+
ace.pretty_print(args.type)
141145

142146
else:
143147
parser_ace.print_usage()

0 commit comments

Comments
 (0)