def toggle_permission(integer, permissions): ''' Takes an ace in integer format and toggles the specified permissions on it. Parameters: integer (string) Integer value as string (hex also allowed) permissions (list[string]) List of permission to toggle (GA, GR, GW, GE, CC, ...) Returns: integer (string) Resulting ace value as integer in hex format ''' try: ace_int = int(integer, 0) except ValueError: raise WConvException( f"from_int(... - Specified value '{integer}' is not an integer." ) for permission in permissions: try: hex_value = ACCESS_MASK_HEX_REVERSE[permission] ace_int = ace_int ^ hex_value except KeyError: raise WConvException( f"toggle_permission(... - Unknown permission name '{permission}'" ) return "0x{:08x}".format(ace_int)
def parse_binary(binary): ''' Parse the different components of a binary SID and return them as an array of integers. Parameters: binary (bytes) binary representation of a SID Returns: items (list[int]) list of integer components of the SID ''' revision = binary[0] if revision != 1: raise WConvException( f"parse_sid(... - Unknown SID version '{revision}'.") dash_count = binary[1] if dash_count * 4 + 8 != len(binary): raise WConvException("parse_sid(... - SID has an invalid length.") authority = int.from_bytes(binary[2:8], 'big') items = [revision, authority] for count in range(0, dash_count * 4, 4): item = binary[8 + count:8 + count + 4] item = int.from_bytes(item, 'little') items.append(item) return items
def from_int(integer, perm_type='file'): ''' Parses an ace from an integer value in string representation. Parameters: integer (string) Integer value as string (hex also allowed) perm_type (string) Object type the sddl applies to (file, service, ...) Returns: ace_object (Ace) ''' try: ace_int = int(integer, 0) except ValueError: raise WConvException( f"from_int(... - Specified value '{integer}' is not an integer." ) perm_dict = get_permission_dict(perm_type) permissions = [] for key, value in ACCESS_MASK_HEX.items(): if key & ace_int: try: permission = perm_dict[value] permissions.append(permission) except KeyError: # Ignore matches on grouped permissions like FA, FR, FW... pass return Ace(None, None, permissions, None, None, None, ace_int)
def get_ace_numeric(ace_permission_string): ''' Takes the ACE portion containing the permission and returns the corresponding integer value. Paramaters: ace_permission_string (string) String containing the ACE permissions Returns: ace_int (int) Corresponding integer value ''' ace_int = 0 for ctr in range(0, len(ace_permission_string), 2): permission = ace_permission_string[ctr:ctr + 2] try: ace_int += ACCESS_MASK_HEX_REVERSE[permission] except KeyError: raise WConvException( f"from_string(... - Unknown permission name '{permission}'." ) return ace_int
def get_ace_permissions(ace_permission_string, perm_type='file'): ''' Takes the ACE portion containing the permission and returns a list of the corresponding parsed permissions. Paramaters: ace_permission_string (string) String containing the ACE permissions perm_type (string) Permission type (file, service, ...) Returns: permissions (list[string]) List of corresponding permissions ''' permissions = [] perm_dict = get_permission_dict(perm_type) for ctr in range(0, len(ace_permission_string), 2): permission = ace_permission_string[ctr:ctr + 2] try: if permission in GROUPED_PERMISSIONS: permission = GROUPED_PERMISSIONS[permission] permission = permission.split(",") permissions += permission else: permission = perm_dict[permission] permissions.append(permission) except KeyError: raise WConvException( f"from_string(... - Unknown permission name '{permission}'." ) return permissions
def get_ace_flags(ace_flag_string): ''' Parses the flag-portion of an ACE string and returns a list of the corresponding ACE flags. Paramaters: ace_flag_string (string) String containing the ACE flags Returns: ace_flags (list[string]) List containing the parsed ACE flags ''' ace_flags = [] for ctr in range(0, len(ace_flag_string), 2): try: ace_flag = ace_flag_string[ctr:ctr + 2] ace_flag = ACE_FLAGS[ace_flag] ace_flags.append(ace_flag) except KeyError: raise WConvException( f"get_ace_flags(... - Unknown ACE flag '{ace_flag}'.") return ace_flags
def from_string(sddl_string, perm_type='file'): ''' Parses an SDDL string an creates the corresponding Sddl object out of it. Parameters: sddl_string (string) String that represents the sddl perm_type (string) Type of the corresponding object (file, service, ...) Returns: sddl_object (Sddl) ''' # Split sddl header from ace strings try: header_index = sddl_string.index('(') sddl_header_string = sddl_string[:header_index] sddl_ace_string = sddl_string[header_index:] except ValueError: raise WConvException( "parse_sddl(... - Input string is no valid SDDL.") # Extract the acl type and the corresponding acl flags match = Sddl.re_acl_type.search(sddl_header_string) if not match: raise WConvException( "parse_sddl(... - Input string is no valid SDDL.") # Save acl type acl_type_split = match.group(0).split(':') if acl_type_split[0] == 'D': acl_type = 'DACL' else: raise WConvException( "parse_sddl(... - Input string describes no DACL. Other formarts are not supported." ) acl_flags = Sddl.get_acl_flags(acl_type_split[1]) owner = Sddl.get_owner(sddl_header_string) group = Sddl.get_group(sddl_header_string) ace_list = Sddl.get_ace_list(sddl_ace_string) return Sddl(owner, group, acl_type, acl_flags, ace_list)
def from_formatted(sid_string): ''' Creates an SecurityIdentifier object from an SID string. Paramaters: sid_string (string) SID in string format Returns: object (SecurityIdentifier) ''' if sid_string[0:2] != 'S-': raise WConvException( f"from_formatted(... - Specified string '{sid_string}' is not a valid SID." ) split = sid_string.split('-') split = split[1:] if split[0] != '1': raise WConvException( f"from_formatted(... - Unknown SID version '{split[0]}'.") revision = int(split[0]) dash_count = len(split) - 2 if dash_count < 0: raise WConvException( f"from_formatted(... - Specified string '{sid_string}' is not a valid SID." ) binary = int.to_bytes(revision, 1, 'big') binary += int.to_bytes(dash_count, 1, 'big') try: binary += int.to_bytes(int(split[1]), 6, 'big') for count in range(2, len(split)): binary += int.to_bytes(int(split[count]), 4, 'little') except (ValueError, OverflowError) as e: raise WConvException( f"from_formatted(... - Specified string '{sid_string}' contains invalid value: {str(e)}." ) return SecurityIdentifier(binary)
def from_string(ace_string, perm_type='file'): ''' Parses an ace from a string in SDDL representation (e.g. A;OICI;FA;;;BA). Parameters: ace_string (string) ACE string in sddl format perm_type (string) Object type the sddl applies to (file, service, ...) Returns: ace_object (Ace) ''' ace_string = Ace.clear_parentheses(ace_string) ace_split = ace_string.split(';') if len(ace_split) != 6: raise WConvException( f"from_string(... - Specified value '{ace_string}' is not a valid ACE string." ) try: ace_type = ACE_TYPES[ace_split[0]] except KeyError: raise WConvException( f"from_string(... - Unknown ACE type '{ace_split[0]}'.") ace_flags = Ace.get_ace_flags(ace_split[1]) permissions = Ace.get_ace_permissions(ace_split[2], perm_type) ace_int = Ace.get_ace_numeric(ace_split[2]) object_type = ace_split[3] inherited_object_type = ace_split[4] trustee = ace_split[5] if trustee in TRUSTEES: trustee = TRUSTEES[trustee] return Ace(ace_type, ace_flags, permissions, object_type, inherited_object_type, trustee, ace_int)
def __init__(self, uac_value): ''' Consrutcs a new UserAccountControl object from an UAC integer in string representation. Paramaters: uac_value (string) UAC integer value in string format Returns: UserAccountControl (UserAccountControl) ''' try: uac_int = int(uac_value, 0) except ValueError: raise WConvException(f"__init__(... - Specified UAC value '{uac_value}' is not an integer.") self.uac_value = uac_int self.flags = UserAccountControl.parse_flags(uac_int)
def from_hex(hex_sid): ''' Creates an SecurityIdentifier object from a hex string. Paramaters: hex_sid (string) SID in hex format Returns: object (SecurityIdentifier) ''' try: binary = binascii.unhexlify(hex_sid) except binascii.Error as e: raise WConvException( f"from_hex(... - Specified hex string is malformed: '{str(e)}'." ) return SecurityIdentifier(binary)
def from_b64(b64_sid): ''' Creates an SecurityIdentifier object from a base64 string. Paramaters: b64_sid (string) SID in base64 format Returns: object (SecurityIdentifier) ''' try: binary = base64.b64decode(b64_sid) except Exception as e: raise WConvException( f"from_b64(... - Specified base64 string is malformed: '{str(e)}'." ) return SecurityIdentifier(binary)
def toggle_flag(self, flags): ''' Toggles the specified UAC flag on the UserAccountControl object. Parameters: flags (list[str]) List of flags to enable on the UAC object Returns: None ''' for flag in flags: try: numeric = UAC_DICT_REVERSE[flag] self.uac_value = self.uac_value ^ numeric self.flags = UserAccountControl.parse_flags(self.uac_value) except KeyError: raise WConvException(f"toggle_flag(... - Specified UAC flag '{flag}' does not exist.")
def get_permission_dict(permission_type): ''' The meaning of permission shortnames like 'CC' change depending on the resource they are assigned to. This function returns the corresponding dictionary for the requested permission type. Parameters: permission_type (string) Permission type (file, service, ...) Returns: permission_dict (dict) Dictionary containing permission map ''' try: mapping = PERM_TYPE_MAPPING[permission_type] return mapping except KeyError: raise WConvException( f"get_permissions_dict(... - Unknown permission type '{permission_type}'" )