From 4516c69f80e8dfa491a4f5005f8ed0eccb173556 Mon Sep 17 00:00:00 2001 From: Joachim Metz Date: Mon, 27 Dec 2021 10:11:04 +0100 Subject: [PATCH] Worked on Security Account Manager (SAM) script and documentation --- docs/index.rst | 2 +- .../Terminal-server-client.md | 21 +++ docs/sources/application-keys/index.rst | 1 + .../{Feature-controls.md => Policies.md} | 56 +++++-- docs/sources/internet-explorer-keys/index.rst | 2 +- .../Domains.md} | 44 ++---- .../Security-accounts-manager.md | 46 ++++++ .../security-accounts-manager-keys/index.rst | 9 ++ documentation/Internet Explorer keys.asciidoc | 35 ----- .../Terminal Server Client keys.asciidoc | 24 --- winregrc/data_format.py | 135 +++++++++++++++- winregrc/sam.py | 147 ++++++++++-------- winregrc/sam.yaml | 30 ++++ 13 files changed, 384 insertions(+), 168 deletions(-) create mode 100644 docs/sources/application-keys/Terminal-server-client.md rename docs/sources/internet-explorer-keys/{Feature-controls.md => Policies.md} (79%) rename docs/sources/{Security-accounts-manager-keys.md => security-accounts-manager-keys/Domains.md} (96%) create mode 100644 docs/sources/security-accounts-manager-keys/Security-accounts-manager.md create mode 100644 docs/sources/security-accounts-manager-keys/index.rst delete mode 100644 documentation/Internet Explorer keys.asciidoc delete mode 100644 documentation/Terminal Server Client keys.asciidoc diff --git a/docs/index.rst b/docs/index.rst index ddd73e1..a3b8910 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,7 +21,7 @@ The source code is available from the `project page + sources/security-accounts-manager-keys/index .. toctree:: :maxdepth: 2 diff --git a/docs/sources/application-keys/Terminal-server-client.md b/docs/sources/application-keys/Terminal-server-client.md new file mode 100644 index 0000000..8f58f1f --- /dev/null +++ b/docs/sources/application-keys/Terminal-server-client.md @@ -0,0 +1,21 @@ +# Terminal server client + +The most recent used (MRU) connnections of the Terminal server client can +be found in the key: + +``` +HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default +``` + +Values: + +Name | Data type | Description +--- | --- | --- +MRU# | REG_SZ | The most recently used connection.
Where # is a string in the form: "[0-9]+" + +The contents of MRU# is either an IP address, e.g. 192.168.16.60, or a hostname, e.g. computer.domain.com. + +## External Links + +* [How to Remove Entries from the Remote Desktop Connection Computer Box](https://docs.microsoft.com/en-US/troubleshoot/windows-server/remote/remove-entries-from-remote-desktop-connection-computer) + diff --git a/docs/sources/application-keys/index.rst b/docs/sources/application-keys/index.rst index 87e3b7e..059a709 100644 --- a/docs/sources/application-keys/index.rst +++ b/docs/sources/application-keys/index.rst @@ -7,4 +7,5 @@ Application keys 7-Zip <7-Zip> Microsoft Office + Terminal server client WinRAR diff --git a/docs/sources/internet-explorer-keys/Feature-controls.md b/docs/sources/internet-explorer-keys/Policies.md similarity index 79% rename from docs/sources/internet-explorer-keys/Feature-controls.md rename to docs/sources/internet-explorer-keys/Policies.md index 84661df..954f611 100644 --- a/docs/sources/internet-explorer-keys/Feature-controls.md +++ b/docs/sources/internet-explorer-keys/Policies.md @@ -1,4 +1,6 @@ -# Feature controls +# Policies + +The Internet Explorer polices are stored in multiple keys. Order of application: @@ -24,7 +26,34 @@ WoW64: 1. HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl 1. HKEY_LOCAL_MACHINE\\Wow6432Node\\Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl -## Security Zones +## Policies + +``` +HKEY_CURRENT_USER\Software\Policies\Microsoft\Internet Explorer +``` + +Values: + +Value | Data type | Description +--- | --- | --- +Download Directory | REG_SZ | The user specific download directory + +### Download policies + +``` +HKEY_CURRENT_USER\Software\Policies\Microsoft\Internet Explorer\Download +``` + +Values: + +Value | Data type | Description +--- | --- | --- +CheckExeSignatures | REG_SZ | +RunInvalidSignatures | REG_DOWRD | + +## Feature controls + +### Security Zones Value | Description --- | --- @@ -36,7 +65,7 @@ Value | Description Also stored in "Description" Registry value in zone-specific Registry key. -## Local Machine Zone Lockdown +### Local Machine Zone Lockdown Applies the Lockdown Zones instead of the Zones. @@ -52,7 +81,7 @@ Add a REG_DWORD value to this key named for your application (for example, MyApplication.exe) and set it to 1. Any other setting for this value will disable Local Machine Zone Lockdown for the application. -## Network Protocol Lockdown +### Network Protocol Lockdown ``` HKEY_LOCAL_MACHINE\Software\(Policies)\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_PROTOCOL_LOCKDOWN @@ -62,19 +91,28 @@ HKEY_CURRENT_USER\Software\(Policies)\Microsoft\Internet Explorer\Main\FeatureCo HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_PROTOCOL_LOCKDOWN ``` -## HTML from CD +### HTML from CD ``` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_LOCALMACHINE_LOCKDOWN\Settings\LOCALMACHINE_CD_UNLOCK ``` +## Notes + +``` +HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy +HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy +``` + ## External Links -* [Introduction to Feature Controls](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms537184(v=vs.85)) -* [Internet Feature Controls](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/general-info/ee330720(v=vs.85)) * [About URL Security Zones](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms537183(v=vs.85)) -* [Understanding and Working in Protected Mode Internet Explorer](https://docs.microsoft.com/en-US/troubleshoot/browsers/ie-security-zones-registry-entries) -* [Internet Explorer security zones registry entries for advanced users](https://docs.microsoft.com/en-US/troubleshoot/browsers/ie-security-zones-registry-entries) * [Internet Explorer Local Machine Zone Lockdown](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc782928(v=ws.10)) * [Internet Explorer Network Protocol Lockdown](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc737488(v=ws.10)) * [Internet Explorer Protected Mode Elevation Policy and Administrative Templates](https://docs.microsoft.com/en-us/archive/blogs/juanand/internet-explorer-protected-mode-elevation-policy-and-administrative-templates) +* [Internet Explorer security zones registry entries for advanced users](https://docs.microsoft.com/en-US/troubleshoot/browsers/ie-security-zones-registry-entries) +* [Internet Feature Controls](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/general-info/ee330720(v=vs.85)) +* [Introduction to Feature Controls](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms537184(v=vs.85)) +* [Understanding and Working in Protected Mode Internet Explorer](https://docs.microsoft.com/en-US/troubleshoot/browsers/ie-security-zones-registry-entries) +* [Understanding user-agent strings](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/ms537503(v=vs.85)) + diff --git a/docs/sources/internet-explorer-keys/index.rst b/docs/sources/internet-explorer-keys/index.rst index 39063e7..d19e4ba 100644 --- a/docs/sources/internet-explorer-keys/index.rst +++ b/docs/sources/internet-explorer-keys/index.rst @@ -6,5 +6,5 @@ Internet explorer keys :maxdepth: 1 Browser helper objects - Feature controls + Policies Typed URLs diff --git a/docs/sources/Security-accounts-manager-keys.md b/docs/sources/security-accounts-manager-keys/Domains.md similarity index 96% rename from docs/sources/Security-accounts-manager-keys.md rename to docs/sources/security-accounts-manager-keys/Domains.md index 990d107..097d40f 100644 --- a/docs/sources/Security-accounts-manager-keys.md +++ b/docs/sources/security-accounts-manager-keys/Domains.md @@ -1,40 +1,17 @@ -# Security Accounts Manager (SAM) keys +# Domains -The Security Accounts Manager (SAM) is stored in the key: +The Security Accounts Manager (SAM) domains are stored in the key: ``` -HKEY_LOCAL_MACHINE\SAM +HKEY_LOCAL_MACHINE\SAM\SAM\Domains ``` -## SAM key - Sub keys: Name | Description --- | --- -Domains | -RXACT | - -Values: - -Name | Data type | Description ---- | --- | --- -C | REG_BINARY | - -### C value data - -Offset | Size | Value | Description ---- | --- | --- | --- -0 | ... | | *TODO* - -## Domains key - -Sub keys: - -Name | Description ---- | --- -Account | -Builtin | +Account | user, group, and local group accounts. +Builtin | (built-in) default local groups, such as the Administrators and Users groups, that are established when the operating system is installed. Values: @@ -344,13 +321,14 @@ Value | Identifier | Description ## External Links -* [userAccountControl Mapping Table](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/8a193181-a7a2-49df-a8b1-f689aaa6987c) -* [Security Account Manager (SAM)](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc756748(v=ws.10)) * [ACCOUNT_TYPE Values](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/e742be45-665d-4576-b872-0bc99d1e1fbe) -* [SAMPR_USER_ALL_INFORMATION](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/dc966b81-da27-4dae-a28c-ec16534f1cb9) +* [Built-in and Account Domains](https://docs.microsoft.com/en-us/windows/win32/secmgmt/built-in-and-account-domains) * [Predefined RIDs](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/565a6584-3061-4ede-a531-f5c53826504b) -* [USER_ALL_INFORMATION structure](https://docs.microsoft.com/en-us/windows/win32/api/subauth/ns-subauth-user_all_information) +* [SAMPR_USER_ALL_INFORMATION](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/dc966b81-da27-4dae-a28c-ec16534f1cb9) +* [Security Account Manager (SAM)](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc756748(v=ws.10)) +* [SysKey and the SAM](http://moyix.blogspot.com/2008/02/syskey-and-sam.html), by Brendan Dolan-Gavitt, February 21, 2008 * [USER_ACCOUNT Codes](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/b10cfda1-f24f-441b-8f43-80cb93e786ec) +* [userAccountControl Mapping Table](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/8a193181-a7a2-49df-a8b1-f689aaa6987c) +* [USER_ALL_INFORMATION structure](https://docs.microsoft.com/en-us/windows/win32/api/subauth/ns-subauth-user_all_information) * [Well-known SIDs](https://docs.microsoft.com/en-us/windows/win32/secauthz/well-known-sids) -* [SysKey and the SAM](http://moyix.blogspot.com/2008/02/syskey-and-sam.html), by Brendan Dolan-Gavitt, February 21, 2008 diff --git a/docs/sources/security-accounts-manager-keys/Security-accounts-manager.md b/docs/sources/security-accounts-manager-keys/Security-accounts-manager.md new file mode 100644 index 0000000..483aa9d --- /dev/null +++ b/docs/sources/security-accounts-manager-keys/Security-accounts-manager.md @@ -0,0 +1,46 @@ +# Security Accounts Manager (SAM) + +The Security Accounts Manager (SAM) is stored in the key: + +``` +HKEY_LOCAL_MACHINE\SAM\SAM +``` + +Sub keys: + +Name | Description +--- | --- +Domains | Built-in and account domains +RXACT | + +Values: + +Name | Data type | Description +--- | --- | --- +C | REG_BINARY | + +### C value data + +The C value data is variable of size and consists of: + +Offset | Size | Value | Description +--- | --- | --- | --- +0 | 2 | | **Unknown (Format version?)** +2 | 2 | | **Unknown** +4 | 4 | | **Unknown (empty?)** +8 | 4 | | **Unknown data size** +12 | 2 | | **Unknown** +14 | 2 | | **Unknown** +16 | ... | | **Unknown data (security descriptor?)** + +#### Format version + +Value | Description +--- | --- +1 | Used in Windows NT 3.1 +2 | Used in Windows NT 3.5 +3 | Used in Windows NT 4 +6 | Used in Windows 2000 +7 | Used in Windows XP and later +9 | Used in Windows Windows 11 + diff --git a/docs/sources/security-accounts-manager-keys/index.rst b/docs/sources/security-accounts-manager-keys/index.rst new file mode 100644 index 0000000..ebe7051 --- /dev/null +++ b/docs/sources/security-accounts-manager-keys/index.rst @@ -0,0 +1,9 @@ +############################## +Security accounts manager keys +############################## + +.. toctree:: + :maxdepth: 1 + + Security accounts manager + Domains diff --git a/documentation/Internet Explorer keys.asciidoc b/documentation/Internet Explorer keys.asciidoc deleted file mode 100644 index 40c27e8..0000000 --- a/documentation/Internet Explorer keys.asciidoc +++ /dev/null @@ -1,35 +0,0 @@ -*NOTE this page largely contains some notes for now* - -== Microsoft Internet Explorer (MSIE) keys - -=== Notes -.... -HKEY_CURRENT_USER\Software\Policies\Microsoft\Internet Explorer -.... - -[cols="1,1,5",options="header"] -|=== -| Value | Data type | Description -| Download Directory | REG_SZ | The user specific download directory -|=== - -.... -HKEY_CURRENT_USER\Software\Policies\Microsoft\Internet Explorer\Download -.... - -[cols="1,1,5",options="header"] -|=== -| Value | Data type | Description -| CheckExeSignatures | REG_SZ | -| RunInvalidSignatures | REG_DOWRD | -|=== - -.... -HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy -HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy -.... - -=== External Links - -* http://msdn.microsoft.com/en-us/library/cc232625.aspx[MSDN: InternetSettings] -* http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx#UARegistry[MSDN: Understanding user-agent strings - User-agent registry keys] diff --git a/documentation/Terminal Server Client keys.asciidoc b/documentation/Terminal Server Client keys.asciidoc deleted file mode 100644 index db1bc7c..0000000 --- a/documentation/Terminal Server Client keys.asciidoc +++ /dev/null @@ -1,24 +0,0 @@ -*NOTE this page largely contains some notes for now* - -:toc: -:toclevels: 4 - -== Terminal Server Client keys -MRU Connnections: -.... -HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default -.... - -Values: -[cols="1,1,5",options="header"] -|=== -| Value | Data type | Description -| MRU# | REG_SZ | The Most Recently Used Connection. + -Where # is a string in the form: "[0-9]+" -|=== - -The contents of MRU# is either an IP address, e.g. 192.168.16.60, or a hostname, e.g. computer.domain.com. - -== External Links -* http://support.microsoft.com/kb/312169[kb312169: How to Remove Entries from the Remote Desktop Connection Computer Box] - diff --git a/winregrc/data_format.py b/winregrc/data_format.py index 884478e..9991a12 100644 --- a/winregrc/data_format.py +++ b/winregrc/data_format.py @@ -21,6 +21,9 @@ class BinaryDataFormat(object): # at run-time. _DEFINITION_FILES_PATH = os.path.dirname(__file__) + _HEXDUMP_CHARACTER_MAP = [ + '.' if byte < 0x20 or byte > 0x7e else chr(byte) for byte in range(256)] + def __init__(self, debug=False, output_writer=None): """Initializes a binary data format. @@ -42,7 +45,8 @@ def _DebugPrintData(self, description, data): data (bytes): data. """ if self._output_writer: - self._output_writer.DebugPrintData(description, data) + self._output_writer.WriteText('{0:s}:\n'.format(description)) + self._output_writer.WriteText(self._FormatDataInHexadecimal(data)) def _DebugPrintDecimalValue(self, description, value): """Prints a decimal value for debugging. @@ -71,7 +75,7 @@ def _DebugPrintFiletimeValue(self, description, value): if date_time_string: date_time_string = '{0:s} UTC'.format(date_time_string) else: - date_time_string = '0x{08:x}'.format(value) + date_time_string = '0x{0:08x}'.format(value) self._DebugPrintValue(description, date_time_string) @@ -102,7 +106,71 @@ def _DebugPrintValue(self, description, value): value (object): value. """ if self._output_writer: - self._output_writer.DebugPrintValue(description, value) + text = self._FormatValue(description, value) + self._output_writer.WriteText(text) + + def _FormatDataInHexadecimal(self, data): + """Formats data in a hexadecimal representation. + + Args: + data (bytes): data. + + Returns: + str: hexadecimal representation of the data. + """ + in_group = False + previous_hexadecimal_string = None + + lines = [] + data_size = len(data) + for block_index in range(0, data_size, 16): + data_string = data[block_index:block_index + 16] + + hexadecimal_byte_values = [] + printable_values = [] + for byte_value in data_string: + if isinstance(byte_value, str): + byte_value = ord(byte_value) + + hexadecimal_byte_value = '{0:02x}'.format(byte_value) + hexadecimal_byte_values.append(hexadecimal_byte_value) + + printable_value = self._HEXDUMP_CHARACTER_MAP[byte_value] + printable_values.append(printable_value) + + remaining_size = 16 - len(data_string) + if remaining_size == 0: + whitespace = '' + elif remaining_size >= 8: + whitespace = ' ' * ((3 * remaining_size) - 1) + else: + whitespace = ' ' * (3 * remaining_size) + + hexadecimal_string_part1 = ' '.join(hexadecimal_byte_values[0:8]) + hexadecimal_string_part2 = ' '.join(hexadecimal_byte_values[8:16]) + hexadecimal_string = '{0:s} {1:s}{2:s}'.format( + hexadecimal_string_part1, hexadecimal_string_part2, whitespace) + + if (previous_hexadecimal_string is not None and + previous_hexadecimal_string == hexadecimal_string and + block_index + 16 < data_size): + + if not in_group: + in_group = True + + lines.append('...') + + else: + printable_string = ''.join(printable_values) + + lines.append('0x{0:08x} {1:s} {2:s}'.format( + block_index, hexadecimal_string, printable_string)) + + in_group = False + previous_hexadecimal_string = hexadecimal_string + + lines.extend(['', '']) + return '\n'.join(lines) def _FormatIntegerAsDecimal(self, integer): """Formats an integer as a decimal. @@ -115,6 +183,61 @@ def _FormatIntegerAsDecimal(self, integer): """ return '{0:d}'.format(integer) + def _FormatIntegerAsFiletime(self, integer): + """Formats an integer as a FILETIME date and time value. + + Args: + integer (int): integer. + + Returns: + str: integer formatted as a FILETIME date and time value. + """ + if integer == 0: + return 'Not set (0)' + + if integer == 0x7fffffffffffffff: + return 'Never (0x7fffffffffffffff)' + + date_time = dfdatetime_filetime.Filetime(timestamp=integer) + date_time_string = date_time.CopyToDateTimeString() + if not date_time_string: + return '0x{0:08x}'.format(integer) + + return '{0:s} UTC'.format(date_time_string) + + def _FormatIntegerAsHexadecimal2(self, integer): + """Formats an integer as an 2-digit hexadecimal. + + Args: + integer (int): integer. + + Returns: + str: integer formatted as an 2-digit hexadecimal. + """ + return '0x{0:02x}'.format(integer) + + def _FormatIntegerAsHexadecimal4(self, integer): + """Formats an integer as an 4-digit hexadecimal. + + Args: + integer (int): integer. + + Returns: + str: integer formatted as an 4-digit hexadecimal. + """ + return '0x{0:04x}'.format(integer) + + def _FormatIntegerAsHexadecimal8(self, integer): + """Formats an integer as an 8-digit hexadecimal. + + Args: + integer (int): integer. + + Returns: + str: integer formatted as an 8-digit hexadecimal. + """ + return '0x{0:08x}'.format(integer) + def _FormatStructureObject(self, structure_object, debug_info): """Formats a structure object debug information. @@ -140,7 +263,11 @@ def _FormatStructureObject(self, structure_object, debug_info): attribute_value = value_format_function(attribute_value) if isinstance(attribute_value, str) and '\n' in attribute_value: - text = '{0:s}:\n{1:s}'.format(description, attribute_value) + text = '' + if description is not None: + text = '{0:s}:\n'.format(description) + text = ''.join([text, attribute_value]) + else: text = self._FormatValue(description, attribute_value) diff --git a/winregrc/sam.py b/winregrc/sam.py index 2cd2453..461d624 100644 --- a/winregrc/sam.py +++ b/winregrc/sam.py @@ -101,70 +101,86 @@ class SecurityAccountManagerDataParser(data_format.BinaryDataFormat): 0x00100000: 'USER_PARTIAL_SECRETS_ACCOUNT', 0x00200000: 'USER_USE_AES_KEYS'} - def _DebugPrintFValue(self, f_value): - """Prints F value debug information. + _DEBUG_INFO_C_VALUE = [ + ('format_version', 'Format version', '_FormatIntegerAsDecimal'), + ('unknown1', 'Unknown1', '_FormatIntegerAsHexadecimal2'), + ('unknown2', 'Unknown1', '_FormatIntegerAsHexadecimal4'), + ('security_descriptor_size', 'Security descriptor size', + '_FormatIntegerAsDecimal'), + ('unknown3', 'Unknown1', '_FormatIntegerAsHexadecimal2'), + ('unknown4', 'Unknown1', '_FormatIntegerAsHexadecimal2'), + ('security_descriptor', 'Security descriptor', + '_FormatDataInHexadecimal')] + + _DEBUG_INFO_F_VALUE = [ + ('major_version', 'Major version', '_FormatIntegerAsDecimal'), + ('minor_version', 'Minor version', '_FormatIntegerAsDecimal'), + ('unknown1', 'Unknown1', '_FormatIntegerAsHexadecimal8'), + ('last_login_time', 'Last login time', '_FormatIntegerAsFiletime'), + ('unknown2', 'Unknown2', '_FormatIntegerAsHexadecimal8'), + ('last_password_set_time', 'Last password set time', + '_FormatIntegerAsFiletime'), + ('account_expiration_time', 'Account expiration time', + '_FormatIntegerAsFiletime'), + ('last_password_failure_time', 'Last password failure time', + '_FormatIntegerAsFiletime'), + ('rid', 'Relative identifier (RID)', '_FormatIntegerAsDecimal'), + ('primary_gid', 'Primary group identifier (GID)', + '_FormatIntegerAsDecimal'), + ('user_account_control_flags', 'User account control flags', + '_FormatIntegerAsHexadecimal8'), + ('user_account_control_flags', None, '_FormatUserAccountControlFlags'), + ('country_code', 'Country code', '_FormatIntegerAsHexadecimal4'), + ('codepage', 'Codepage', '_FormatIntegerAsDecimal'), + ('number_of_password_failures', 'Number of password failures', + '_FormatIntegerAsDecimal'), + ('number_of_logons', 'Number of logons', '_FormatIntegerAsDecimal'), + ('unknown6', 'Unknown6', '_FormatIntegerAsHexadecimal8'), + ('unknown7', 'Unknown7', '_FormatIntegerAsHexadecimal8'), + ('unknown8', 'Unknown8', '_FormatIntegerAsHexadecimal8')] + + def _FormatUserAccountControlFlags(self, user_account_control_flags): + """Formats user account control flags. Args: - f_value (f_value): F value. - """ - self._DebugPrintDecimalValue('Major version', f_value.major_version) - - self._DebugPrintDecimalValue('Minor version', f_value.minor_version) - - value_string = '0x{0:08x}'.format(f_value.unknown1) - self._DebugPrintValue('Unknown1', value_string) - - self._DebugPrintFiletimeValue('Last login time', f_value.last_login_time) - - value_string = '0x{0:08x}'.format(f_value.unknown2) - self._DebugPrintValue('Unknown2', value_string) - - self._DebugPrintFiletimeValue( - 'Last password set time', f_value.last_password_set_time) - - self._DebugPrintFiletimeValue( - 'Account expiration time', f_value.account_expiration_time) - - self._DebugPrintFiletimeValue( - 'Last password failure time', f_value.last_password_failure_time) + user_account_control_flags (int): user account control flags. - self._DebugPrintDecimalValue('Relative identifier (RID)', f_value.rid) - - self._DebugPrintDecimalValue( - 'Primary group identifier (GID)', f_value.primary_gid) - - value_string = '0x{0:08x}'.format(f_value.user_account_control_flags) - self._DebugPrintValue('User account control flags', value_string) - - if f_value.user_account_control_flags: + Returns: + str: formatted user account control flags. + """ + value_strings = [] + if user_account_control_flags: for flag, identifier in sorted( self._USER_ACCOUNT_CONTROL_FLAGS.items()): - if flag & f_value.user_account_control_flags: + if flag & user_account_control_flags: value_string = '\t{0:s} (0x{1:08x})'.format(identifier, flag) - self._DebugPrintText(value_string) - - self._DebugPrintText('\n') - - value_string = '0x{0:04x}'.format(f_value.country_code) - self._DebugPrintValue('Country code', value_string) + value_strings.append(value_string) - self._DebugPrintDecimalValue('Codepage', f_value.codepage) + value_strings.append('') - self._DebugPrintDecimalValue( - 'Number of password failures', f_value.number_of_password_failures) + value_strings.append('') + return '\n'.join(value_strings) - self._DebugPrintDecimalValue('Number of logons', f_value.number_of_logons) + def ParseCValue(self, value_data): + """Parses the C value data. - value_string = '0x{0:08x}'.format(f_value.unknown6) - self._DebugPrintValue('Unknown6', value_string) + Args: + value_data (bytes): F value data. - value_string = '0x{0:08x}'.format(f_value.unknown7) - self._DebugPrintValue('Unknown7', value_string) + Raises: + ParseError: if the value data could not be parsed. + """ + data_type_map = self._GetDataTypeMap('c_value') - value_string = '0x{0:08x}'.format(f_value.unknown8) - self._DebugPrintValue('Unknown8', value_string) + try: + c_value = self._ReadStructureFromByteStream( + value_data, 0, data_type_map, 'C value') + except (ValueError, errors.ParseError) as exception: + raise errors.ParseError( + 'Unable to parse C value with error: {0!s}'.format(exception)) - self._DebugPrintText('\n') + if self._debug: + self._DebugPrintStructureObject(c_value, self._DEBUG_INFO_C_VALUE) def _ParseFiletime(self, filetime): """Parses a FILETIME timestamp value. @@ -219,7 +235,7 @@ def ParseFValue(self, value_data, user_account): user_account.number_of_logons = f_value.number_of_logons if self._debug: - self._DebugPrintFValue(f_value) + self._DebugPrintStructureObject(f_value, self._DEBUG_INFO_F_VALUE) def ParseVValue(self, value_data, user_account): """Parses the V value data. @@ -265,7 +281,7 @@ def ParseVValue(self, value_data, user_account): value_string = '0x{0:08x}'.format(user_information_descriptor.unknown1) self._DebugPrintValue(unknown1_string, value_string) - data_string = 'Descriptor: {0:d} data:'.format(index + 1) + data_string = 'Descriptor: {0:d} data'.format(index + 1) self._DebugPrintData(data_string, descriptor_data) if index == 1: @@ -312,6 +328,9 @@ class SecurityAccountManagerCollector(interface.WindowsRegistryKeyCollector): user_accounts (list[UserAccount]): user accounts. """ + _USERS_KEY_PATH = ( + 'HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account\\Users') + def __init__(self, debug=False, output_writer=None): """Initializes a Security Accounts Manager (SAM) collector. @@ -320,7 +339,9 @@ def __init__(self, debug=False, output_writer=None): output_writer (Optional[OutputWriter]): output writer. """ super(SecurityAccountManagerCollector, self).__init__(debug=debug) - self._output_writer = output_writer + self._parser = SecurityAccountManagerDataParser( + debug=debug, output_writer=output_writer) + self.user_accounts = [] def Collect(self, registry): # pylint: disable=arguments-differ @@ -333,13 +354,17 @@ def Collect(self, registry): # pylint: disable=arguments-differ bool: True if the Security Accounts Manager (SAM) information key was found, False if not. """ - key_path = 'HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account\\Users' - users_key = registry.GetKeyByPath(key_path) - if not users_key: + main_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\SAM\\SAM') + if not main_key: return False - parser = SecurityAccountManagerDataParser( - debug=self._debug, output_writer=self._output_writer) + c_value = main_key.GetValueByName('C') + if c_value: + self._parser.ParseCValue(c_value.data) + + users_key = registry.GetKeyByPath(self._USERS_KEY_PATH) + if not users_key: + return False for subkey in users_key.GetSubkeys(): if subkey.name == 'Names': @@ -349,11 +374,11 @@ def Collect(self, registry): # pylint: disable=arguments-differ f_value = subkey.GetValueByName('F') if f_value: - parser.ParseFValue(f_value.data, user_account) + self._parser.ParseFValue(f_value.data, user_account) v_value = subkey.GetValueByName('V') if v_value: - parser.ParseVValue(v_value.data, user_account) + self._parser.ParseVValue(v_value.data, user_account) self.user_accounts.append(user_account) diff --git a/winregrc/sam.yaml b/winregrc/sam.yaml index 324bcd1..7a0142e 100644 --- a/winregrc/sam.yaml +++ b/winregrc/sam.yaml @@ -2,6 +2,13 @@ name: sam type: format description: Security Accounts Manager (SAM) format --- +name: byte +type: integer +attributes: + format: unsigned + size: 1 + units: bytes +--- name: uint16 type: integer attributes: @@ -23,6 +30,29 @@ attributes: size: 8 units: bytes --- +name: c_value +type: structure +description: Security Accounts Manager C value. +attributes: + byte_order: little-endian +members: +- name: format_version + data_type: uint16 +- name: unknown1 + data_type: uint16 +- name: unknown2 + data_type: uint32 +- name: security_descriptor_size + data_type: uint32 +- name: unknown3 + data_type: uint16 +- name: unknown4 + data_type: uint16 +- name: security_descriptor + type: stream + element_data_type: byte + elements_data_size: c_value.security_descriptor_size +--- name: f_value type: structure description: Security Accounts Manager F value.