Source code for plaso.parsers.winreg_plugins.amcache

"""Windows Registry plugin to parse the AMCache.hve Root key."""

import re

from dfdatetime import filetime as dfdatetime_filetime
from dfdatetime import posix_time as dfdatetime_posix_time
from dfdatetime import time_elements as dfdatetime_time_elements

from dfwinreg import errors as dfwinreg_errors

from plaso.containers import events
from plaso.parsers import winreg_parser
from plaso.parsers.winreg_plugins import interface


[docs] class AMCacheFileEventData(events.EventData): """AMCache file event data. Attributes: application_key_last_written_time (dfdatetime.DateTimeValues): last written date and time of the application key. company_name (str): company name that created product file belongs to. file_creation_time (dfdatetime.DateTimeValues): file entry creation date and time. file_description (str): description of file. file_identifier (str): identifier of file (SHA-1 of the first 30 MiB (31457280 bytes) of file, preceded by "0000"). file_modification_time (dfdatetime.DateTimeValues): file entry last modification date and time. file_name (str): name of the file. file_reference (str): file system file reference, for example 9-1 (MFT entry - sequence number). file_size (int): size of file in bytes. file_version (str): version of file. full_path (str): full path of file. installation_time (dfdatetime.DateTimeValues): installation date and time. language_code (int): language code of file. last_written_time (dfdatetime.DateTimeValues): entry last written date and time. link_time (dfdatetime.DateTimeValues): link date and time. msi_installation_time (dfdatetime.DateTimeValues): MSI installation date and time. product_name (str): product name file belongs to. program_identifier (str): GUID of entry under Root/Program key file belongs to. sha1 (str): SHA-1. """ DATA_TYPE = "windows:registry:amcache"
[docs] def __init__(self): """Initializes event data.""" super().__init__(data_type=self.DATA_TYPE) self.application_key_last_written_time = None self.company_name = None self.file_creation_time = None self.file_description = None self.file_identifier = None self.file_modification_time = None self.file_reference = None self.file_name = None self.file_size = None self.file_version = None self.full_path = None self.installation_time = None self.language_code = None self.last_written_time = None self.link_time = None self.msi_installation_time = None self.product_name = None self.program_identifier = None self.sha1 = None
[docs] class AMCacheProgramEventData(events.EventData): """AMCache programs event data. Attributes: entry_type (str): type of entry (usually AddRemoveProgram). file_paths (str): file paths of installed program. files (str): list of files belonging to program. installation_time (dfdatetime.DateTimeValues): installation date and time. language_code (int): language_code of program. msi_package_code (str): MSI package code of program. msi_product_code (str): MSI product code of program. name (str): name of installed program. package_code (str): package code of program. product_code (str): product code of program. publisher (str): publisher of program. uninstall_key (str): unicode string of uninstall registry key for program. version (str): version of program. """ DATA_TYPE = "windows:registry:amcache:programs"
[docs] def __init__(self): """Initializes event data.""" super().__init__(data_type=self.DATA_TYPE) self.entry_type = None self.file_paths = None self.files = None self.installation_time = None self.language_code = None self.msi_package_code = None self.msi_product_code = None self.name = None self.package_code = None self.product_code = None self.publisher = None self.uninstall_key = None self.version = None
[docs] class AMCachePlugin(interface.WindowsRegistryPlugin): """AMCache.hve Windows Registry plugin.""" NAME = "amcache" DATA_FORMAT = "AMCache (AMCache.hve)" FILTERS = frozenset([interface.WindowsRegistryKeyPathFilter("\\Root")]) # Contains: {value name: attribute name} _APPLICATION_SUB_KEY_VALUES = { "FileId": "file_identifier", "LowerCaseLongPath": "full_path", "Name": "file_name", "ProductName": "product_name", "ProductVersion": "file_version", "ProgramId": "program_identifier", "Publisher": "company_name", "Size": "file_size", } _FILE_REFERENCE_KEY_VALUES = { "0": "product_name", "1": "company_name", "3": "language_code", "5": "file_version", "6": "file_size", "c": "file_description", "15": "full_path", "100": "program_identifier", "101": "sha1", } _AMCACHE_LINK_TIME = "f" _AMCACHE_FILE_MODIFICATION_TIME = "11" _AMCACHE_FILE_CREATION_TIME = "12" _AMCACHE_ENTRY_WRITE_TIME = "17" _AMCACHE_P_INSTALLATION_TIME = "a" _AMCACHE_P_FILES = "Files" # Date and time string formatted as: "MM/DD/YYYY hh:mm:ss" # for example "04/07/2014 15:18:49" # TODO: determine if this is true for other locales. _LINK_DATE_TIME_RE = re.compile( r"([0-9][0-9])/([0-9][0-9])/([0-9][0-9][0-9][0-9]) " r"([0-9][0-9]):([0-9][0-9]):([0-9][0-9])" ) _PRODUCT_KEY_VALUES = { "0": "name", "1": "version", "2": "publisher", "3": "language_code", "6": "entry_type", "7": "uninstall_key", "d": "file_paths", "f": "product_code", "10": "package_code", "11": "msi_product_code", "12": "msi_package_code", } def _GetValueDataAsObject( self, parser_mediator, key_path, value_name, registry_value ): """Retrieves the value data as an object from a Windows Registry value. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. key_path (str): key path. value_name (str): name of the value. registry_value (dfwinreg.WinRegistryValue): Windows Registry value. Returns: object: value data or None when the value data cannot be determined. """ if registry_value.data is None: return "(empty)" try: value_object = registry_value.GetDataAsObject() if registry_value.DataIsMultiString(): value_object = list(value_object) elif ( not registry_value.DataIsInteger() and not registry_value.DataIsString() ): # Represent remaining types like REG_BINARY and # REG_RESOURCE_REQUIREMENT_LIST. value_object = registry_value.data except dfwinreg_errors.WinRegistryValueError as exception: parser_mediator.ProduceRecoveryWarning( ( f"Unable to retrieve value data of type: " f"{registry_value.data_type_string,:s} as object from value: " f"{value_name:s} in key: {key_path:s} with error: {exception!s}" ) ) value_object = None return value_object def _ParseApplicationSubKey(self, parser_mediator, application_sub_key): """Parses a Root\\InventoryApplicationFile\\%NAME%|%IDENTIFIER% key. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. application_sub_key (dfwinreg.WinRegistryKey): application sub key of the InventoryApplicationFile Windows Registry key. """ event_data = AMCacheFileEventData() for value_name, attribute_name in self._APPLICATION_SUB_KEY_VALUES.items(): value = application_sub_key.GetValueByName(value_name) if value: value_data = self._GetValueDataAsObject( parser_mediator, application_sub_key.path, value_name, value ) setattr(event_data, attribute_name, value_data) install_date_value = application_sub_key.GetValueByName("InstallDate") if install_date_value: event_data.installation_time = self._ParseDateStringValue( parser_mediator, application_sub_key.path, install_date_value ) install_date_msi_value = application_sub_key.GetValueByName("InstallDateMsi") if install_date_msi_value: event_data.msi_installation_time = self._ParseDateStringValue( parser_mediator, application_sub_key.path, install_date_msi_value ) link_date_value = application_sub_key.GetValueByName("LinkDate") if link_date_value: event_data.link_time = self._ParseDateStringValue( parser_mediator, application_sub_key.path, link_date_value ) event_data.application_key_last_written_time = ( application_sub_key.last_written_time ) parser_mediator.ProduceEventData(event_data) def _ParseDateStringValue(self, parser_mediator, key_path, registry_value): """Parses a date and time string value. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. key_path (str): key path. registry_value (dfwinreg.WinRegistryValue): Windows Registry value. Returns: dfdatetime_time_elements.TimeElements: date and time value or None if not available. """ if not registry_value.DataIsString(): parser_mediator.ProduceExtractionWarning( ( f"unsupported {registry_value.name:s} with value data type: " f"{registry_value.data_type_string:s} in key: {key_path:s}" ) ) return None date_time_string = registry_value.GetDataAsObject() if not date_time_string: parser_mediator.ProduceExtractionWarning( f"missing {registry_value.name:s} value data in key: {key_path:s}" ) return None re_match = self._LINK_DATE_TIME_RE.match(date_time_string) if not re_match: parser_mediator.ProduceExtractionWarning( ( f"unsupported {registry_value.name:s} value data: " f"{date_time_string!s} in key: {key_path:s}" ) ) return None month, day_of_month, year, hours, minutes, seconds = re_match.groups() try: year = int(year, 10) month = int(month, 10) day_of_month = int(day_of_month, 10) hours = int(hours, 10) minutes = int(minutes, 10) seconds = int(seconds, 10) except (TypeError, ValueError): parser_mediator.ProduceExtractionWarning( ( f"invalid {registry_value.name:s} date time value: " f"{date_time_string!s} in key: {key_path:s}" ) ) return None time_elements_tuple = (year, month, day_of_month, hours, minutes, seconds) try: date_time = dfdatetime_time_elements.TimeElements( time_elements_tuple=time_elements_tuple ) except ValueError: parser_mediator.ProduceExtractionWarning( ( f"invalid {registry_value.name:s} date time value: " f"{time_elements_tuple!s} in key: {key_path:s}" ) ) return None return date_time def _ParseFileKey(self, parser_mediator, file_key): """Parses a Root\\File key. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. file_key (dfwinreg.WinRegistryKey): the File Windows Registry key. """ for volume_key in file_key.GetSubkeys(): for file_reference_key in volume_key.GetSubkeys(): self._ParseFileReferenceKey(parser_mediator, file_reference_key) def _ParseFileReferenceKey(self, parser_mediator, file_reference_key): """Parses a file reference key (sub key of Root\\File\\%VOLUME%) for events. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. file_reference_key (dfwinreg.WinRegistryKey): file reference Windows Registry key. """ event_data = AMCacheFileEventData() try: if "0000" in file_reference_key.name: # A NTFS file reference is a combination of MFT entry and sequence # number. sequence_number, mft_entry = file_reference_key.name.split("0000") mft_entry = int(mft_entry, 16) sequence_number = int(sequence_number, 16) event_data.file_reference = f"{mft_entry:d}-{sequence_number:d}" else: # A FAT file reference is the offset of the corresponding directory # entry. file_reference = int(file_reference_key.name, 16) event_data.file_reference = f"{file_reference:d}" except (ValueError, TypeError): pass for value_name, attribute_name in self._FILE_REFERENCE_KEY_VALUES.items(): value = file_reference_key.GetValueByName(value_name) if not value: continue value_data = self._GetValueDataAsObject( parser_mediator, file_reference_key.path, value_name, value ) if attribute_name == "sha1" and value_data.startswith("0000"): # Strip off the 4 leading zero's from the sha1 hash. value_data = value_data[4:] setattr(event_data, attribute_name, value_data) write_time_value = file_reference_key.GetValueByName( self._AMCACHE_ENTRY_WRITE_TIME ) if write_time_value: timestamp = write_time_value.GetDataAsObject() event_data.last_written_time = dfdatetime_filetime.Filetime( timestamp=timestamp ) creation_time_value = file_reference_key.GetValueByName( self._AMCACHE_FILE_CREATION_TIME ) if creation_time_value: timestamp = creation_time_value.GetDataAsObject() event_data.file_creation_time = dfdatetime_filetime.Filetime( timestamp=timestamp ) modification_time_value = file_reference_key.GetValueByName( self._AMCACHE_FILE_MODIFICATION_TIME ) if modification_time_value: timestamp = modification_time_value.GetDataAsObject() event_data.file_modification_time = dfdatetime_filetime.Filetime( timestamp=timestamp ) link_time_value = file_reference_key.GetValueByName(self._AMCACHE_LINK_TIME) if link_time_value: timestamp = link_time_value.GetDataAsObject() event_data.link_time = dfdatetime_posix_time.PosixTime(timestamp=timestamp) parser_mediator.ProduceEventData(event_data) def _ParseInventoryApplicationFileKey( self, parser_mediator, inventory_application_file_key ): """Parses a Root\\InventoryApplicationFile key. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. inventory_application_file_key (dfwinreg.WinRegistryKey): the InventoryApplicationFile Windows Registry key. """ for application_sub_key in inventory_application_file_key.GetSubkeys(): self._ParseApplicationSubKey(parser_mediator, application_sub_key) def _ParseProgramKey(self, parser_mediator, program_key): """Parses a program key (a sub key of Root\\Programs) for events. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. program_key (dfwinreg.WinRegistryKey): program Windows Registry key. """ event_data = AMCacheProgramEventData() for value_name, attribute_name in self._PRODUCT_KEY_VALUES.items(): value = program_key.GetValueByName(value_name) if value: value_data = self._GetValueDataAsObject( parser_mediator, program_key.path, value_name, value ) setattr(event_data, attribute_name, value_data) installation_time_value = program_key.GetValueByName( self._AMCACHE_P_INSTALLATION_TIME ) if installation_time_value: timestamp = installation_time_value.GetDataAsObject() event_data.installation_time = dfdatetime_posix_time.PosixTime( timestamp=timestamp ) parser_mediator.ProduceEventData(event_data) def _ParseProgramsKey(self, parser_mediator, programs_key): """Parses a Root\\Programs key. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. programs_key (dfwinreg.WinRegistryKey): the Programs Windows Registry key. """ for program_key in programs_key.GetSubkeys(): self._ParseProgramKey(parser_mediator, program_key) def _ParseRootKey(self, parser_mediator, root_key): """Parses a Root key. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. root_key (dfwinreg.WinRegistryKey): the Root Windows Registry key. """ self._ProduceDefaultWindowsRegistryEvent(parser_mediator, root_key) for sub_key in root_key.GetSubkeys(): self._ParseSubKey(parser_mediator, sub_key) if sub_key.name == "File": self._ParseFileKey(parser_mediator, sub_key) elif sub_key.name == "InventoryApplicationFile": self._ParseInventoryApplicationFileKey(parser_mediator, sub_key) elif sub_key.name == "Programs": self._ParseProgramsKey(parser_mediator, sub_key) def _ParseSubKey(self, parser_mediator, registry_key): """Parses a sub key. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. registry_key (dfwinreg.WinRegistryKey): the Windows Registry key. """ self._ProduceDefaultWindowsRegistryEvent(parser_mediator, registry_key) for sub_key in registry_key.GetSubkeys(): self._ParseSubKey(parser_mediator, sub_key)
[docs] def ExtractEvents(self, parser_mediator, registry_key, **kwargs): """Extracts events from a Windows Registry key. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. registry_key (dfwinreg.WinRegistryKey): Windows Registry key. """ self._ParseRootKey(parser_mediator, registry_key)
winreg_parser.WinRegistryParser.RegisterPlugin(AMCachePlugin)