Source code for winregrc.userassist

# -*- coding: utf-8 -*-
"""Windows UserAssist information collector."""

import codecs
import logging

from winregrc import data_format
from winregrc import errors
from winregrc import interface


[docs] class UserAssistEntry(object): """UserAssist entry. Attributes: guid (str): GUID. name (str): name. value_name (str): name of the Windows Registry value. """
[docs] def __init__(self, guid=None, name=None, value_name=None): """Initializes an UserAssist entry. Args: guid (Optional[str]): GUID. name (Optional[str]): name. value_name (Optional[str]): name of the Windows Registry value. """ super(UserAssistEntry, self).__init__() self.guid = guid self.name = name self.value_name = value_name
[docs] class UserAssistDataParser(data_format.BinaryDataFormat): """UserAssist data parser.""" _DEFINITION_FILE = 'userassist.yaml' # pylint: disable=missing-type-doc def _DebugPrintEntry(self, format_version, user_assist_entry): """Prints UserAssist entry value debug information. Args: format_version (int): format version. user_assist_entry (user_assist_entry_v3|user_assist_entry_v5): UserAssist entry. """ self._DebugPrintValue('Unknown1', f'0x{user_assist_entry.unknown1:08x}') self._DebugPrintDecimalValue( 'Number of executions', user_assist_entry.number_of_executions) if format_version == 5: self._DebugPrintDecimalValue( 'Application focus count', user_assist_entry.application_focus_count) self._DebugPrintDecimalValue( 'Application focus duration', user_assist_entry.application_focus_duration) self._DebugPrintValue('Unknown2', f'{user_assist_entry.unknown2:.2f}') self._DebugPrintValue('Unknown3', f'{user_assist_entry.unknown3:.2f}') self._DebugPrintValue('Unknown4', f'{user_assist_entry.unknown4:.2f}') self._DebugPrintValue('Unknown5', f'{user_assist_entry.unknown5:.2f}') self._DebugPrintValue('Unknown6', f'{user_assist_entry.unknown6:.2f}') self._DebugPrintValue('Unknown7', f'{user_assist_entry.unknown7:.2f}') self._DebugPrintValue('Unknown8', f'{user_assist_entry.unknown8:.2f}') self._DebugPrintValue('Unknown9', f'{user_assist_entry.unknown9:.2f}') self._DebugPrintValue('Unknown10', f'{user_assist_entry.unknown10:.2f}') self._DebugPrintValue('Unknown11', f'{user_assist_entry.unknown11:.2f}') self._DebugPrintValue('Unknown12', f'0x{user_assist_entry.unknown12:08x}') self._DebugPrintFiletimeValue( 'Last execution time', user_assist_entry.last_execution_time) if format_version == 5: self._DebugPrintValue('Unknown13', '0x{user_assist_entry.unknown13:08x}') self._DebugPrintText('\n') # pylint: disable=missing-return-type-doc
[docs] def ParseEntry(self, format_version, entry_data): """Parses an UserAssist entry. Args: format_version (int): format version. entry_data (bytes): entry data. Returns: user_assist_entry_v3|user_assist_entry_v5: UserAssist entry. Raises: ParseError: if the value data could not be parsed. """ if format_version == 3: data_type_map = self._GetDataTypeMap('user_assist_entry_v3') expected_entry_data_size = 16 elif format_version == 5: data_type_map = self._GetDataTypeMap('user_assist_entry_v5') expected_entry_data_size = 72 if expected_entry_data_size != len(entry_data): entry_data_size = len(entry_data) raise errors.ParseError(( f'Version: {format_version:d} size mismatch (calculated: ' f'{expected_entry_data_size:d}, stored: {entry_data_size:d}).')) try: user_assist_entry = self._ReadStructureFromByteStream( entry_data, 0, data_type_map, 'UserAssist entry') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse UserAssist entry value with error: {exception!s}') if self._debug: self._DebugPrintEntry(format_version, user_assist_entry) return user_assist_entry
[docs] class UserAssistCollector(interface.WindowsRegistryKeyCollector): """Windows UserAssist information collector. Returns: user_assist_entries (list[UserAssistEntry]): UserAssist entries. """ _USER_ASSIST_KEY = ( 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\UserAssist')
[docs] def __init__(self, debug=False, output_writer=None): """Initializes a Windows UserAssist information collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super(UserAssistCollector, self).__init__(debug=debug) self._output_writer = output_writer self._parser = UserAssistDataParser( debug=debug, output_writer=output_writer) self.user_assist_entries = []
def _CollectUserAssistFromKey(self, guid_subkey): """Collects the UserAssist information from a GUID sub key. Args: guid_subkey (dfwinreg.WinRegistryKey): UserAssist GUID Registry key. """ version_value = guid_subkey.GetValueByName('Version') if not version_value: logging.warning(f'Missing Version value in sub key: {guid_subkey.name:s}') return format_version = version_value.GetDataAsObject() if self._debug: self._output_writer.WriteValue('GUID', guid_subkey.name) self._output_writer.WriteIntegerValueAsDecimal( 'Format version', format_version) self._output_writer.WriteText('\n') count_subkey = guid_subkey.GetSubkeyByName('Count') for value in count_subkey.GetValues(): if self._debug: self._output_writer.WriteValue('Original name', value.name) try: # Note that Python 2 codecs.decode() does not support keyword arguments # such as encodings='rot-13'. value_name = codecs.decode(value.name, 'rot-13') except UnicodeEncodeError: characters = [] for character in value.name: if ord(character) < 128: try: character = codecs.decode(character, 'rot-13') characters.append(character) except UnicodeEncodeError: characters.append(character) else: characters.append(character) value_name = ''.join(characters) if self._debug: self._output_writer.WriteValue('Converted name', value_name) self._output_writer.WriteDebugData('Value data:', value.data) if value_name != 'UEME_CTLSESSION': user_assist_entry = self._parser.ParseEntry(format_version, value.data) user_assist_entry = UserAssistEntry( guid=guid_subkey.name, name=value_name, value_name=value.name) self.user_assist_entries.append(user_assist_entry)
[docs] def Collect(self, registry): # pylint: disable=arguments-differ """Collects the UserAssist information. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the UserAssist key was found, False if not. """ user_assist_key = registry.GetKeyByPath(self._USER_ASSIST_KEY) if not user_assist_key: return False for guid_subkey in user_assist_key.GetSubkeys(): self._CollectUserAssistFromKey(guid_subkey) return True