diff --git a/config/dpkg/changelog b/config/dpkg/changelog index f621c1871a..edc9342b49 100644 --- a/config/dpkg/changelog +++ b/config/dpkg/changelog @@ -2,4 +2,4 @@ python-plaso (1.3.1-1) unstable; urgency=low * Auto-generated - -- Log2Timeline Tue, 15 Sep 2015 20:56:42 +0200 + -- Log2Timeline Thu, 17 Sep 2015 19:44:25 +0200 diff --git a/docs/plaso.dfwinreg.rst b/docs/plaso.dfwinreg.rst index ed8844f9d4..d1688520ce 100644 --- a/docs/plaso.dfwinreg.rst +++ b/docs/plaso.dfwinreg.rst @@ -12,6 +12,22 @@ plaso.dfwinreg.definitions module :undoc-members: :show-inheritance: +plaso.dfwinreg.errors module +---------------------------- + +.. automodule:: plaso.dfwinreg.errors + :members: + :undoc-members: + :show-inheritance: + +plaso.dfwinreg.fake module +-------------------------- + +.. automodule:: plaso.dfwinreg.fake + :members: + :undoc-members: + :show-inheritance: + plaso.dfwinreg.interface module ------------------------------- diff --git a/docs/plaso.formatters.rst b/docs/plaso.formatters.rst index d5f36f3839..c46cb1a3cc 100644 --- a/docs/plaso.formatters.rst +++ b/docs/plaso.formatters.rst @@ -68,6 +68,14 @@ plaso.formatters.bsm module :undoc-members: :show-inheritance: +plaso.formatters.ccleaner module +-------------------------------- + +.. automodule:: plaso.formatters.ccleaner + :members: + :undoc-members: + :show-inheritance: + plaso.formatters.chrome module ------------------------------ diff --git a/plaso/__init__.py b/plaso/__init__.py index 7628d33351..1cd0d5d4bf 100644 --- a/plaso/__init__.py +++ b/plaso/__init__.py @@ -3,7 +3,7 @@ __version__ = '1.3.1' VERSION_DEV = True -VERSION_DATE = '20150915' +VERSION_DATE = '20150917' def GetVersion(): diff --git a/plaso/dfwinreg/definitions.py b/plaso/dfwinreg/definitions.py index 551e825cfe..0ea9fe7229 100644 --- a/plaso/dfwinreg/definitions.py +++ b/plaso/dfwinreg/definitions.py @@ -26,7 +26,9 @@ REG_BINARY = 3 REG_DWORD = 4 REG_DWORD_LITTLE_ENDIAN = 4 +REG_DWORD_LE = REG_DWORD_LITTLE_ENDIAN REG_DWORD_BIG_ENDIAN = 5 +REG_DWORD_BE = REG_DWORD_BIG_ENDIAN REG_LINK = 6 REG_MULTI_SZ = 7 REG_RESOURCE_LIST = 8 diff --git a/plaso/dfwinreg/errors.py b/plaso/dfwinreg/errors.py new file mode 100644 index 0000000000..38e177f20d --- /dev/null +++ b/plaso/dfwinreg/errors.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +"""This file contains the error classes.""" + +class Error(Exception): + """Base error class.""" + + +class WinRegistryValueError(Error): + """Raised when a Windows Registry value cannot be read.""" diff --git a/plaso/dfwinreg/fake.py b/plaso/dfwinreg/fake.py new file mode 100644 index 0000000000..c883691a64 --- /dev/null +++ b/plaso/dfwinreg/fake.py @@ -0,0 +1,514 @@ +# -*- coding: utf-8 -*- +"""Fake Windows Registry objects implementation.""" + +import calendar + +import construct + +from plaso import dependencies +from plaso.dfwinreg import definitions +from plaso.dfwinreg import errors +from plaso.dfwinreg import interface + + +dependencies.CheckModuleVersion(u'construct') + + +# TODO: give this class a place of its own when dfwinreg is split off. +class Filetime(object): + """Class that implements a FILETIME timestamp. + + The FILETIME timestamp is a 64-bit integer that contains the number + of 100th nano seconds since 1601-01-01 00:00:00. + + Do not confuse this with the FILETIME structure that consists of + 2 x 32-bit integers and is presumed to be unsigned. + + Attributes: + timestamp: the FILETIME timestamp. + """ + + # The difference between Jan 1, 1601 and Jan 1, 1970 in seconds. + _FILETIME_TO_POSIX_BASE = 11644473600L + _INT64_MAX = (1 << 63L) - 1 + + def __init__(self, timestamp=None): + """Initializes the FILETIME object. + + Args: + timestamp: optional FILETIME timestamp. + """ + super(Filetime, self).__init__() + self.timestamp = timestamp + + def CopyFromString(self, time_string): + """Copies a FILETIME from a string containing a date and time value. + + Args: + time_string: A string containing a date and time value formatted as: + YYYY-MM-DD hh:mm:ss.######[+-]##:## + Where # are numeric digits ranging from 0 to 9 and the + seconds fraction can be either 3 or 6 digits. The time + of day, seconds fraction and timezone offset are optional. + The default timezone is UTC. + + Returns: + An integer containing the timestamp. + + Raises: + ValueError: if the time string is invalid or not supported. + """ + if not time_string: + raise ValueError(u'Invalid time string.') + + time_string_length = len(time_string) + + # The time string should at least contain 'YYYY-MM-DD'. + if (time_string_length < 10 or time_string[4] != u'-' or + time_string[7] != u'-'): + raise ValueError(u'Invalid time string.') + + # If a time of day is specified the time string it should at least + # contain 'YYYY-MM-DD hh:mm:ss'. + if (time_string_length > 10 and ( + time_string_length < 19 or time_string[10] != u' ' or + time_string[13] != u':' or time_string[16] != u':')): + raise ValueError(u'Invalid time string.') + + try: + year = int(time_string[0:4], 10) + except ValueError: + raise ValueError(u'Unable to parse year.') + + try: + month = int(time_string[5:7], 10) + except ValueError: + raise ValueError(u'Unable to parse month.') + + if month not in range(1, 13): + raise ValueError(u'Month value out of bounds.') + + try: + day_of_month = int(time_string[8:10], 10) + except ValueError: + raise ValueError(u'Unable to parse day of month.') + + if day_of_month not in range(1, 32): + raise ValueError(u'Day of month value out of bounds.') + + hours = 0 + minutes = 0 + seconds = 0 + + if time_string_length > 10: + try: + hours = int(time_string[11:13], 10) + except ValueError: + raise ValueError(u'Unable to parse hours.') + + if hours not in range(0, 24): + raise ValueError(u'Hours value out of bounds.') + + try: + minutes = int(time_string[14:16], 10) + except ValueError: + raise ValueError(u'Unable to parse minutes.') + + if minutes not in range(0, 60): + raise ValueError(u'Minutes value out of bounds.') + + try: + seconds = int(time_string[17:19], 10) + except ValueError: + raise ValueError(u'Unable to parse day of seconds.') + + if seconds not in range(0, 60): + raise ValueError(u'Seconds value out of bounds.') + + micro_seconds = 0 + timezone_offset = 0 + + if time_string_length > 19: + if time_string[19] != u'.': + timezone_index = 19 + else: + for timezone_index in range(19, time_string_length): + if time_string[timezone_index] in [u'+', u'-']: + break + + # The calculation that follow rely on the timezone index to point + # beyond the string in case no timezone offset was defined. + if timezone_index == time_string_length - 1: + timezone_index += 1 + + if timezone_index > 19: + fraction_of_seconds_length = timezone_index - 20 + if fraction_of_seconds_length not in [3, 6]: + raise ValueError(u'Invalid time string.') + + try: + micro_seconds = int(time_string[20:timezone_index], 10) + except ValueError: + raise ValueError(u'Unable to parse fraction of seconds.') + + if fraction_of_seconds_length == 3: + micro_seconds *= 1000 + + if timezone_index < time_string_length: + if (time_string_length - timezone_index != 6 or + time_string[timezone_index + 3] != u':'): + raise ValueError(u'Invalid time string.') + + try: + timezone_offset = int(time_string[ + timezone_index + 1:timezone_index + 3]) + except ValueError: + raise ValueError(u'Unable to parse timezone hours offset.') + + if timezone_offset not in range(0, 24): + raise ValueError(u'Timezone hours offset value out of bounds.') + + # Note that when the sign of the timezone offset is negative + # the difference needs to be added. We do so by flipping the sign. + if time_string[timezone_index] == u'-': + timezone_offset *= 60 + else: + timezone_offset *= -60 + + try: + timezone_offset += int(time_string[ + timezone_index + 4:timezone_index + 6]) + except ValueError: + raise ValueError(u'Unable to parse timezone minutes offset.') + + timezone_offset *= 60 + + self.timestamp = int(calendar.timegm(( + year, month, day_of_month, hours, minutes, seconds))) + + self.timestamp += timezone_offset + self._FILETIME_TO_POSIX_BASE + self.timestamp = (self.timestamp * 1000000) + micro_seconds + self.timestamp *= 10 + + +class FakeWinRegistryKey(interface.WinRegistryKey): + """Fake implementation of a Windows Registry key.""" + + def __init__( + self, name, key_path=u'', last_written_time=None, offset=0, subkeys=None, + values=None): + """Initializes a Windows Registry key object. + + Subkeys and values with duplicate names are silenty ignored. + + Args: + name: the name of the Windows Registry key. + key_path: optional Windows Registry key path. + last_written_time: optional last written time (contains + a FILETIME timestamp). + offset: optional offset of the key within the Windows Registry file. + subkeys: optional list of subkeys (instances of FakeWinRegistryKey). + values: optional list of values (instances of FakeWinRegistryValue). + """ + super(FakeWinRegistryKey, self).__init__(key_path=key_path) + self._last_written_time = last_written_time + self._name = name + self._offset = offset + self._subkeys = {} + self._values = {} + + if subkeys: + for registry_key in subkeys: + name = registry_key.name.upper() + if name in self._subkeys: + continue + self._subkeys[name] = registry_key + + registry_key._key_path = self._JoinKeyPath([ + self._key_path, registry_key.name]) + + if values: + for registry_value in values: + name = registry_value.name.upper() + if name in self._values: + continue + self._values[name] = registry_value + + @property + def last_written_time(self): + """The last written time of the key (contains a FILETIME timestamp).""" + return self._last_written_time + + @property + def name(self): + """The name of the key.""" + return self._name + + @property + def number_of_subkeys(self): + """The number of subkeys within the key.""" + return len(self._sub_keys) + + @property + def number_of_values(self): + """The number of values within the key.""" + return len(self._values) + + @property + def offset(self): + """The offset of the key within the Windows Registry file.""" + return self._offset + + def AddSubkey(self, registry_key): + """Adds a subkey. + + Args: + registry_key: the Windows Registry subkey (instance of + FakeWinRegistryKey). + + Raises: + KeyError: if the subkey already exists. + """ + name = registry_key.name.upper() + if name in self._subkeys: + raise KeyError( + u'Subkey: {0:s} already exists.'.format(registry_key.name)) + + self._subkeys[name] = registry_key + registry_key._key_path = self._JoinKeyPath([ + self._key_path, registry_key.name]) + + def AddValue(self, registry_value): + """Adds a value. + + Args: + registry_value: the Windows Registry value (instance of + FakeWinRegistryValue). + + Raises: + KeyError: if the value already exists. + """ + name = registry_value.name.upper() + if name in self._values: + raise KeyError( + u'Value: {0:s} already exists.'.format(registry_value.name)) + + self._values[name] = registry_value + + def GetSubkeyByName(self, name): + """Retrieves a subkey by name. + + Args: + name: The name of the subkey. + + Returns: + The Windows Registry subkey (instances of WinRegistryKey) or + None if not found. + """ + return self._subkeys.get(name.upper(), None) + + def GetSubkeys(self): + """Retrieves all subkeys within the key. + + Yields: + Windows Registry key objects (instances of WinRegistryKey) that represent + the subkeys stored within the key. + """ + for registry_key in iter(self._subkeys.values()): + yield registry_key + + def GetValueByName(self, name): + """Retrieves a value by name. + + Value names are not unique and pyregf provides first match for + the value. + + Args: + name: Name of the value or an empty string for the default value. + + Returns: + A Windows Registry value object (instance of WinRegistryValue) if + a corresponding value was found or None if not. + """ + return self._values.get(name.upper(), None) + + def GetValues(self): + """Retrieves all values within the key. + + Yields: + Windows Registry value objects (instances of WinRegistryValue) that + represent the values stored within the key. + """ + for registry_value in iter(self._values.values()): + yield registry_value + + +class FakeWinRegistryValue(interface.WinRegistryValue): + """Fake implementation of a Windows Registry value.""" + + _INT32_BIG_ENDIAN = construct.SBInt32(u'value') + _INT32_LITTLE_ENDIAN = construct.SLInt32(u'value') + _INT64_LITTLE_ENDIAN = construct.SLInt64(u'value') + + def __init__(self, name, data=b'', data_type=0, offset=0): + """Initializes a Windows Registry value object. + + Args: + name: the name of the Windows Registry value. + data: optional binary string containing the value data. + data_type: optional integer containing the value data type. + offset: optional offset of the value within the Windows Registry file. + """ + super(FakeWinRegistryValue, self).__init__() + self._data = data + self._data_type = data_type + self._data_size = len(data) + self._name = name + self._offset = offset + + @property + def data(self): + """The value data as a native Python object. + + Raises: + WinRegistryValueError: if the value data cannot be read. + """ + if not self._data: + return None + + if self._data_type in self._STRING_VALUE_TYPES: + try: + return self._data.decode(u'utf-16-le') + + except UnicodeError as exception: + raise errors.WinRegistryValueError( + u'Unable to read data from value: {0:s} with error: {1:s}'.format( + self._name, exception)) + + elif (self._data_type == definitions.REG_DWORD and + self._data_size == 4): + return self._INT32_LITTLE_ENDIAN.parse(self._data) + + elif (self._data_type == definitions.REG_DWORD_BIG_ENDIAN and + self._data_size == 4): + return self._INT32_BIG_ENDIAN.parse(self._data) + + elif (self._data_type == definitions.REG_QWORD and + self._data_size == 8): + return self._INT64_LITTLE_ENDIAN.parse(self._data) + + elif self._data_type == definitions.REG_MULTI_SZ: + try: + utf16_string = self._data.decode(u'utf-16-le') + return filter(None, utf16_string.split(u'\x00')) + + except UnicodeError as exception: + raise errors.WinRegistryValueError( + u'Unable to read data from value: {0:s} with error: {1:s}'.format( + self._name, exception)) + + return self._data + + @property + def data_type(self): + """Numeric value that contains the data type.""" + return self._data_type + + @property + def name(self): + """The name of the value.""" + return self._name + + @property + def offset(self): + """The offset of the value within the Windows Registry file.""" + return self._pyregf_value.offset + + @property + def raw_data(self): + """The value data as a byte string.""" + return self._data + + +class FakeWinRegistryFile(interface.WinRegistryFile): + """Fake implementation of a Windows Registry file.""" + + def __init__(self): + """Initializes the Windows Registry file.""" + super(FakeWinRegistryFile, self).__init__() + self._root_key = None + + def AddKeyByPath(self, key_path, registry_key): + """Adds a Windows Registry for a specific key path. + + Args: + key_path: the Windows Registry key path to add the key. + registry_key: the Windows Registry key (instance of FakeWinRegistryKey). + + Returns: + A boolean containing True if successful or False if not. + """ + if not key_path.startswith(self._KEY_PATH_SEPARATOR): + return False + + if not self._root_key: + self._root_key = FakeWinRegistryKey(u'') + + path_segments = self._SplitKeyPath(key_path) + parent_key = self._root_key + for path_segment in path_segments: + subkey = FakeWinRegistryKey(path_segment) + if not parent_key.AddSubkey(subkey): + return False + + return parent_key.AddSubkey(registry_key) + + def Close(self): + """Closes the Windows Registry file.""" + return + + def GetKeyByPath(self, key_path): + """Retrieves the key for a specific path. + + Args: + key_path: the Windows Registry key path. + + Returns: + A Registry key (instance of WinRegistryKey) or None if not available. + """ + if not key_path.startswith(self._KEY_PATH_SEPARATOR): + return + + path_segments = self._SplitKeyPath(key_path) + registry_key = self._root_key + for path_segment in path_segments: + if not registry_key: + return + + registry_key = registry_key.GetSubkeyByName(path_segment) + + return registry_key + + def GetRootKey(self, key_path_prefix=u''): + """Retrieves the root key. + + Args: + key_path_prefix: optional Windows Registry key path prefix. + + Returns: + The Windows Registry root key (instance of WinRegistryKey) or + None if not available. + """ + # TODO: handle key_path_prefix. + return self._root_key + + def Open(self, unused_file_object): + """Opens the Windows Registry file using a file-like object. + + Args: + file_object: the file-like object. + + Returns: + A boolean containing True if successful or False if not. + """ + return True diff --git a/plaso/dfwinreg/interface.py b/plaso/dfwinreg/interface.py index 00d4fb5589..fe562c75d9 100644 --- a/plaso/dfwinreg/interface.py +++ b/plaso/dfwinreg/interface.py @@ -1,17 +1,127 @@ # -*- coding: utf-8 -*- -"""The interface for Windows Registry related objects.""" +"""The interface for Windows Registry objects.""" import abc +from plaso.dfwinreg import definitions -class WinRegKey(object): - """Abstract class to represent the Windows Registry key interface.""" - PATH_SEPARATOR = u'\\' +class WinRegistryFile(object): + """Class that defines a Windows Registry file.""" + + _KEY_PATH_SEPARATOR = u'\\' + + def __init__(self, ascii_codepage=u'cp1252'): + """Initializes the Windows Registry file. + + Args: + ascii_codepage: optional ASCII string codepage. The default is cp1252 + (or windows-1252). + """ + super(WinRegistryFile, self).__init__() + self._ascii_codepage = ascii_codepage + + def _SplitKeyPath(self, path): + """Splits the key path into path segments. + + Args: + path: a string containing the path. + + Returns: + A list of path segements without the root path segment, which is an + empty string. + """ + # Split the path with the path separator and remove empty path segments. + return filter(None, path.split(self._KEY_PATH_SEPARATOR)) + + @abc.abstractmethod + def Close(self): + """Closes the Windows Registry file.""" + + @abc.abstractmethod + def GetKeyByPath(self, key_path): + """Retrieves the key for a specific path. + + Args: + key_path: the Windows Registry key path. + + Returns: + A Windows Registry key (instance of WinRegistryKey) or None if + not available. + """ + + @abc.abstractmethod + def GetRootKey(self, key_path_prefix=u''): + """Retrieves the root key. + + Args: + key_path_prefix: optional Windows Registry key path prefix. + + Returns: + The Windows Registry root key (instance of WinRegistryKey) or + None if not available. + """ + + @abc.abstractmethod + def Open(self, file_object): + """Opens the Windows Registry file using a file-like object. + + Args: + file_object: the file-like object. + + Returns: + A boolean containing True if successful or False if not. + """ + + def RecurseKeys(self): + """Recurses the Windows Registry keys starting with the root key. + + Yields: + A Windows Registry key (instance of WinRegistryKey). + """ + root_key = self.GetRootKey() + if root_key: + for registry_key in root_key.RecurseKeys(): + yield registry_key + + +class WinRegistryFileReader(object): + """Class to represent the Windows Registry file reader interface.""" + + @abc.abstractmethod + def Open(self, path, ascii_codepage=u'cp1252'): + """Opens the Windows Registry file specificed by the path. + + Args: + path: string containing the path of the Windows Registry file. The path + is a Windows path relative to the root of the file system that + contains the specfic Windows Registry file. E.g. + C:\\Windows\\System32\\config\\SYSTEM + ascii_codepage: optional ASCII string codepage. The default is cp1252 + (or windows-1252). + + Returns: + The Windows Registry file (instance of WinRegistryFile) or None. + """ + + +class WinRegistryKey(object): + """Class to represent the Windows Registry key interface.""" + + _PATH_SEPARATOR = u'\\' + + def __init__(self, key_path=u''): + """Initializes a Windows Registry key object. + + Args: + key_path: optional Windows Registry key path. + """ + super(WinRegistryKey, self).__init__() + self._key_path = self._JoinKeyPath([key_path]) @abc.abstractproperty - def last_written_timestamp(self): - """The last written time of the key represented as a timestamp.""" + def last_written_time(self): + """The last written time of the key (contains a FILETIME timestamp).""" @abc.abstractproperty def name(self): @@ -29,71 +139,91 @@ def number_of_values(self): def offset(self): """The offset of the key within the Windows Registry file.""" - @abc.abstractproperty + @property def path(self): - """The path of the key.""" + """The Windows Registry key path.""" + return self._key_path + + def _JoinKeyPath(self, path_segments): + """Joins the path segments into key path. + + Args: + path_segment: list of Windows Registry key path segments. + """ + # This is an optimized way to combine the path segments into a single path + # and combine multiple successive path separators to one. + + # Split all the path segments based on the path (segment) separator. + path_segments = [ + segment.split(self._PATH_SEPARATOR) for segment in path_segments] + + # Flatten the sublists into one list. + path_segments = [ + element for sublist in path_segments for element in sublist] + + # Remove empty path segments. + path_segments = filter(None, path_segments) + + return u'{0:s}{1:s}'.format( + self._PATH_SEPARATOR, self._PATH_SEPARATOR.join(path_segments)) @abc.abstractmethod - def GetValue(self, name): - """Retrieves a value by name. + def GetSubkeyByName(self, name): + """Retrieves a subkey by name. Args: - name: Name of the value or an empty string for the default value. + name: The name of the subkey. Returns: - An instance of a Windows Registry value object (WinRegValue) if - a corresponding value was found or None if not. + The Windows Registry subkey (instances of WinRegistryKey) or + None if not found. """ @abc.abstractmethod - def GetValues(self): - """Retrieves all values within the key. + def GetSubkeys(self): + """Retrieves all subkeys within the key. Yields: - Windows Registry value objects (instances of WinRegValue) that represent - the values stored within the key. + Windows Registry key objects (instances of WinRegistryKey) that represent + the subkeys stored within the key. """ @abc.abstractmethod - def GetSubkey(self, name): - """Retrive a subkey by name. + def GetValueByName(self, name): + """Retrieves a value by name. Args: - name: The relative path of the current key to the desired one. + name: the name of the value or an empty string for the default value. Returns: - The subkey with the relative path of name or None if not found. + A Windows Registry value object (instance of WinRegistryValue) if + a corresponding value was found or None if not. """ @abc.abstractmethod - def GetSubkeys(self): - """Retrieves all subkeys within the key. + def GetValues(self): + """Retrieves all values within the key. Yields: - Windows Registry key objects (instances of WinRegKey) that represent - the subkeys stored within the key. + Windows Registry value objects (instances of WinRegistryValue) that + represent the values stored within the key. """ + def RecurseKeys(self): + """Recurses the subkeys starting with the key. + + Yields: + A Windows Registry key (instance of WinRegistryKey). + """ + yield self + for subkey in self.GetSubkeys(): + for key in subkey.RecurseKeys(): + yield key -class WinRegValue(object): - """Abstract class to represent the Windows Registry value interface.""" - # TODO: move to definitions, currently kept for backwards compatibility. - REG_NONE = 0 - REG_SZ = 1 - REG_EXPAND_SZ = 2 - REG_BINARY = 3 - REG_DWORD = 4 - REG_DWORD_LITTLE_ENDIAN = 4 - REG_DWORD_BIG_ENDIAN = 5 - REG_LINK = 6 - REG_MULTI_SZ = 7 - REG_RESOURCE_LIST = 8 - REG_FULL_RESOURCE_DESCRIPTOR = 9 - REG_RESOURCE_REQUIREMENT_LIST = 10 - REG_QWORD = 11 +class WinRegistryValue(object): + """Class to represent the Windows Registry value interface.""" - # TODO: move to definitions, currently kept for backwards compatibility. _DATA_TYPE_STRINGS = { 0: u'REG_NONE', 1: u'REG_SZ', @@ -109,17 +239,17 @@ class WinRegValue(object): 11: u'REG_QWORD' } - def __init__(self): - """Default constructor for the Windows Registry value.""" - self._data = u'' + _INTEGER_VALUE_TYPES = frozenset([ + definitions.REG_DWORD, definitions.REG_DWORD_BIG_ENDIAN, + definitions.REG_QWORD]) - @abc.abstractproperty - def name(self): - """The name of the value.""" + _STRING_VALUE_TYPES = frozenset([ + definitions.REG_SZ, definitions.REG_EXPAND_SZ, definitions.REG_LINK]) + # TODO: move data to GetData() and raw_data to data. @abc.abstractproperty - def offset(self): - """The offset of the value within the Windows Registry file.""" + def data(self): + """The value data as a Python object.""" @abc.abstractproperty def data_type(self): @@ -131,12 +261,16 @@ def data_type_string(self): return self._DATA_TYPE_STRINGS.get(self.data_type, u'UNKNOWN') @abc.abstractproperty - def raw_data(self): - """The value data as a byte string.""" + def name(self): + """The name of the value.""" @abc.abstractproperty - def data(self): - """The value data as a native Python object.""" + def offset(self): + """The offset of the value within the Windows Registry file.""" + + @abc.abstractproperty + def raw_data(self): + """The value data as a byte string.""" def DataIsInteger(self): """Determines, based on the data type, if the data is an integer. @@ -148,27 +282,8 @@ def DataIsInteger(self): True if the data is an integer, false otherwise. """ return self.data_type in [ - self.REG_DWORD, self.REG_DWORD_BIG_ENDIAN, self.REG_QWORD] - - def DataIsString(self): - """Determines, based on the data type, if the data is a string. - - The data types considered strings are: REG_SZ and REG_EXPAND_SZ. - - Returns: - True if the data is a string, false otherwise. - """ - return self.data_type in [self.REG_SZ, self.REG_EXPAND_SZ] - - def DataIsMultiString(self): - """Determines, based on the data type, if the data is a multi string. - - The data types considered multi strings are: REG_MULTI_SZ. - - Returns: - True if the data is a multi string, false otherwise. - """ - return self.data_type == self.REG_MULTI_SZ + definitions.REG_DWORD, definitions.REG_DWORD_BIG_ENDIAN, + definitions.REG_QWORD] def DataIsBinaryData(self): """Determines, based on the data type, if the data is binary data. @@ -178,55 +293,24 @@ def DataIsBinaryData(self): Returns: True if the data is a multi string, false otherwise. """ - return self.data_type == self.REG_BINARY + return self.data_type == definitions.REG_BINARY + def DataIsMultiString(self): + """Determines, based on the data type, if the data is a multi string. -class WinRegistryFile(object): - """Class that defines a Windows Registry file.""" - - def __init__(self, ascii_codepage=u'cp1252'): - """Initializes the Windows Registry file. - - Args: - ascii_codepage: optional ASCII string codepage. The default is cp1252 - (or windows-1252). - """ - super(WinRegistryFile, self).__init__() - self._ascii_codepage = ascii_codepage - - @abc.abstractmethod - def Close(self): - """Closes the Windows Registry file.""" - - @abc.abstractmethod - def GetKeyByPath(self, key_path): - """Retrieves the key for a specific path. - - Args: - key_path: the Registry key path. + The data types considered multi strings are: REG_MULTI_SZ. Returns: - A Registry key (instance of WinRegistryKey) or None if not available. - """ - - @abc.abstractmethod - def GetRootKey(self): - """Retrieves the root key. - - Yields: - A Registry key (instance of WinRegistryKey). + True if the data is a multi string, false otherwise. """ + return self.data_type == definitions.REG_MULTI_SZ - @abc.abstractmethod - def Open(self, file_object): - """Opens the Windows Registry file using a file-like object. + def DataIsString(self): + """Determines, based on the data type, if the data is a string. - Args: - file_object: the file-like object. + The data types considered strings are: REG_SZ and REG_EXPAND_SZ. Returns: - A boolean containing True if successful or False if not. + True if the data is a string, false otherwise. """ - - -# TODO: add WinRegistryFileReader. + return self.data_type in [definitions.REG_SZ, definitions.REG_EXPAND_SZ] diff --git a/plaso/dfwinreg/regf.py b/plaso/dfwinreg/regf.py index d9ed428eec..b106476c97 100644 --- a/plaso/dfwinreg/regf.py +++ b/plaso/dfwinreg/regf.py @@ -1,48 +1,34 @@ # -*- coding: utf-8 -*- -"""Pyregf specific implementation for the Windows Registry file access.""" - -import logging +"""REGF Windows Registry objects implementation using pyregf.""" import pyregf from plaso import dependencies +from plaso.dfwinreg import definitions +from plaso.dfwinreg import errors from plaso.dfwinreg import interface -from plaso.lib import errors -from plaso.lib import timelib dependencies.CheckModuleVersion(u'pyregf') -class WinPyregfKey(interface.WinRegKey): +class REGFWinRegistryKey(interface.WinRegistryKey): """Implementation of a Windows Registry key using pyregf.""" - def __init__(self, pyregf_key, parent_path=u'', root=False): + def __init__(self, pyregf_key, key_path=u''): """Initializes a Windows Registry key object. Args: - pyregf_key: An instance of a pyregf.key object. - parent_path: The path of the parent key. - root: A boolean value indicating we are dealing with a root key. + pyregf_key: a pyreg key object (instance of a pyregf.key). + key_path: optional Windows Registry key path. """ - super(WinPyregfKey, self).__init__() + super(REGFWinRegistryKey, self).__init__(key_path=key_path) self._pyregf_key = pyregf_key - # Adding few checks to make sure the root key is not - # invalid in plugin checks (root key is equal to the - # path separator). - if parent_path == self.PATH_SEPARATOR: - parent_path = u'' - if root: - self._path = self.PATH_SEPARATOR - else: - self._path = self.PATH_SEPARATOR.join([ - parent_path, self._pyregf_key.name]) @property - def last_written_timestamp(self): - """The last written time of the key represented as a timestamp.""" - return timelib.Timestamp.FromFiletime( - self._pyregf_key.get_last_written_time_as_integer()) + def last_written_time(self): + """The last written time of the key (contains a FILETIME timestamp).""" + return self._pyregf_key.get_last_written_time_as_integer() @property def name(self): @@ -64,78 +50,33 @@ def offset(self): """The offset of the key within the Windows Registry file.""" return self._pyregf_key.offset - @property - def path(self): - """The path of the key.""" - return self._path - - # pylint: disable=arguments-differ - @path.setter - def path(self, value): - """Set the value of the path explicitly.""" - self._path = value - - def GetSubkey(self, name): - """Retrive a subkey by name. + def GetSubkeyByName(self, name): + """Retrieves a subkey by name. Args: - name: The relative path of the current key to the desired one. + name: The name of the subkey. Returns: - The subkey with the relative path of name or None if not found. + The Windows Registry subkey (instances of WinRegistryKey) or + None if not found. """ - subkey = self._pyregf_key.get_sub_key_by_name(name) - if subkey: - return WinPyregfKey(subkey, self.path) - - path_subkey = self._pyregf_key.get_sub_key_by_path(name) - if path_subkey: - # Split all the path segments based on the path (segment) separator. - path_segments = self.path.split(self.PATH_SEPARATOR) - path_segments.extend(name.split(self.PATH_SEPARATOR)) - - # Flatten the sublists into one list. - path_segments = [ - element for sublist in path_segments for element in sublist] - - # Remove empty path segments. - path_segments = filter(None, path_segments) - - path = u'{0:s}{1:s}'.format( - self.PATH_SEPARATOR, self.PATH_SEPARATOR.join(path_segments)) + pyregf_key = self._pyregf_key.get_sub_key_by_name(name) + if not pyregf_key: + return - return WinPyregfKey(path_subkey, path) + key_path = self._JoinKeyPath([self._key_path, pyregf_key.name]) + return REGFWinRegistryKey(pyregf_key, key_path=key_path) def GetSubkeys(self): """Retrieves all subkeys within the key. Yields: - Windows Registry key objects (instances of WinRegKey) that represent + Windows Registry key objects (instances of WinRegistryKey) that represent the subkeys stored within the key. """ for pyregf_key in self._pyregf_key.sub_keys: - yield WinPyregfKey(pyregf_key, self.path) - - # TODO: in the process of being deprecated. - def GetValue(self, name): - """Retrieves a value by name. - - Args: - name: Name of the value or an empty string for the default value. - - Returns: - A Windows Registry value object (instance of WinRegValue) if - a corresponding value was found or None if not. - """ - # Value names are not unique and pyregf provides first match for - # the value. If this becomes problematic this method needs to - # be changed into a generator, iterating through all returned value - # for a given name. - pyregf_value = self._pyregf_key.get_value_by_name(name) - if not pyregf_value: - return - - return WinPyregfValue(pyregf_value) + key_path = self._JoinKeyPath([self._key_path, pyregf_key.name]) + yield REGFWinRegistryKey(pyregf_key, key_path=key_path) def GetValueByName(self, name): """Retrieves a value by name. @@ -147,27 +88,27 @@ def GetValueByName(self, name): name: Name of the value or an empty string for the default value. Returns: - A Windows Registry value object (instance of WinRegValue) if + A Windows Registry value object (instance of WinRegistryValue) if a corresponding value was found or None if not. """ pyregf_value = self._pyregf_key.get_value_by_name(name) if not pyregf_value: return - return WinPyregfValue(pyregf_value) + return REGFWinRegistryValue(pyregf_value) def GetValues(self): """Retrieves all values within the key. Yields: - Windows Registry value objects (instances of WinRegValue) that represent - the values stored within the key. + Windows Registry value objects (instances of WinRegistryValue) that + represent the values stored within the key. """ for pyregf_value in self._pyregf_key.values: - yield WinPyregfValue(pyregf_value) + yield REGFWinRegistryValue(pyregf_value) -class WinPyregfValue(interface.WinRegValue): +class REGFWinRegistryValue(interface.WinRegistryValue): """Implementation of a Windows Registry value using pyregf.""" def __init__(self, pyregf_value): @@ -176,219 +117,79 @@ def __init__(self, pyregf_value): Args: pyregf_value: An instance of a pyregf.value object. """ - super(WinPyregfValue, self).__init__() + super(REGFWinRegistryValue, self).__init__() self._pyregf_value = pyregf_value - self._type_str = u'' - - @property - def name(self): - """The name of the value.""" - return self._pyregf_value.name - - @property - def offset(self): - """The offset of the value within the Windows Registry file.""" - return self._pyregf_value.offset - - @property - def data_type(self): - """Numeric value that contains the data type.""" - return self._pyregf_value.type - - @property - def raw_data(self): - """The value data as a byte string.""" - try: - return self._pyregf_value.data - except IOError: - raise errors.WinRegistryValueError( - u'Unable to read data from value: {0:s}'.format( - self._pyregf_value.name)) @property def data(self): - """The value data as a native Python object.""" - if self._pyregf_value.type in [ - self.REG_SZ, self.REG_EXPAND_SZ, self.REG_LINK]: + """The value data as a native Python object. + + Raises: + WinRegistryValueError: if the value data cannot be read. + """ + if self._pyregf_value.type in self._STRING_VALUE_TYPES: try: - return self._pyregf_value.data_as_string - except IOError: - pass + return self._pyregf_value.get_data_as_string() + except IOError as exception: + raise errors.WinRegistryValueError( + u'Unable to read data from value: {0:s} with error: {1:s}'.format( + self._pyregf_value.name, exception)) - elif self._pyregf_value.type in [ - self.REG_DWORD, self.REG_DWORD_BIG_ENDIAN, self.REG_QWORD]: + elif self._pyregf_value.type in self._INTEGER_VALUE_TYPES: try: - return self._pyregf_value.data_as_integer + return self._pyregf_value.get_data_as_integer() except (IOError, OverflowError): - # TODO: Rethink this approach. The value is not -1, but we cannot - # return the raw data, since the calling plugin expects an integer - # here. - return -1 + raise errors.WinRegistryValueError( + u'Unable to read data from value: {0:s} with error: {1:s}'.format( + self._pyregf_value.name, exception)) # TODO: Add support for REG_MULTI_SZ to pyregf. - elif self._pyregf_value.type == self.REG_MULTI_SZ: + elif self._pyregf_value.type == definitions.REG_MULTI_SZ: if self._pyregf_value.data is None: - return u'' + return [] try: utf16_string = unicode(self._pyregf_value.data.decode(u'utf-16-le')) return filter(None, utf16_string.split(b'\x00')) - except UnicodeError: - pass + except (IOError, UnicodeError) as exception: + raise errors.WinRegistryValueError( + u'Unable to read data from value: {0:s} with error: {1:s}'.format( + self._pyregf_value.name, exception)) return self._pyregf_value.data + @property + def data_type(self): + """Numeric value that contains the data type.""" + return self._pyregf_value.type -class WinPyregfFile(interface.WinRegistryFile): - """Implementation of a Windows Registry file pyregf. - - Attributes: - name: the name of the Windows Registry file. - """ - - def __init__(self, ascii_codepage=u'cp1252'): - """Initializes the Windows Registry file. - - Args: - ascii_codepage: optional ASCII string codepage. The default is cp1252 - (or windows-1252). - """ - super(WinPyregfFile, self).__init__() - self._ascii_codepage = ascii_codepage - self._base_key = None - self._file_object = None - self._regf_file = pyregf.file() - - self.name = u'' - - def Close(self): - """Closes the Windows Registry file.""" - self._base_key = None - self.name = u'' - - if self._file_object: - self._regf_file.close() - self._file_object.close() - self._file_object = None - - def GetKeyByPath(self, key_path): - """Retrieves a specific key defined by the Registry path. - - Args: - key_path: the Registry key path. - - Returns: - The key (instance of WinRegKey) if available or None otherwise. - """ - if not key_path: - return None - - if not self._base_key: - return None - - pyregf_key = self._base_key.get_sub_key_by_path(key_path) - if not pyregf_key: - return None - - if pyregf_key.name == self._base_key.name: - root = True - else: - root = False - - parent_key_path, _, _ = key_path.rpartition( - interface.WinRegKey.PATH_SEPARATOR) - return WinPyregfKey(pyregf_key, parent_key_path, root=root) - - def GetRootKey(self): - """Retrieves the root keys. - - Returns: - A Registry key (instance of WinRegistryKey) or None if not available. - """ - regf_key = self._regf_file.get_root_key() - if not regf_key: - return - - return WinPyregfKey(regf_key, u'', root=True) - - def Open(self, file_object): - """Opens the Windows Registry file. - - Args: - file_object: the file-like object. - - Raises: - IOError: if there is an error opening or reading the Registry file. - """ - # TODO: Add a more elegant error handling to this issue. There are some - # code pages that are not supported by the parent library. However we - # need to properly set the codepage so the library can properly interpret - # values in the Registry. - try: - self._regf_file.set_ascii_codepage(self._ascii_codepage) - - except (TypeError, IOError): - logging.error(( - u'Unable to set the Windows Registry file codepage: {0:s}. ' - u'Ignoring provided value.').format(self._ascii_codepage)) - - self._regf_file.open_file_object(file_object) - self._base_key = self._regf_file.get_root_key() - self._file_object = file_object + @property + def name(self): + """The name of the value.""" + return self._pyregf_value.name - def OpenFileEntry(self, file_entry): - """Opens the Windows Registry file. + @property + def offset(self): + """The offset of the value within the Windows Registry file.""" + return self._pyregf_value.offset - Args: - file_entry: The file entry object (instance of dfvfs.FileEntry). + @property + def raw_data(self): + """The value data as a byte string. Raises: - IOError: if there is an error opening or reading the Registry file. + WinRegistryValueError: if the value data cannot be read. """ - file_object = file_entry.GetFileObject() try: - self.Open(file_object) - - # TODO: move to a dfVFS like Registry sub-system. - self.name = file_entry.name - - except IOError: - file_object.close() - raise - - # TODO: move to key. - def _RecurseKey(self, key): - """Recurses a Registry key. - - Yields: - A Registry key (instance of WinPyregfKey). - """ - if key: - yield key - - for subkey in key.GetSubkeys(): - for recursed_key in self._RecurseKey(subkey): - yield recursed_key - - def RecurseKeys(self): - """Recurses the Registry file keys starting with the root key. - - Yields: - A Registry key (instance of WinPyregfKey) generator. - - Raises: - StopIteration: when there is no root key to signal the generator is empty. - """ - root_key = self.GetRootKey() - if not root_key: - raise StopIteration - - for key in self._RecurseKey(root_key): - yield key + return self._pyregf_value.data + except IOError as exception: + raise errors.WinRegistryValueError( + u'Unable to read data from value: {0:s} with error: {1:s}'.format( + self._pyregf_value.name, exception)) -class WinRegistryFileREGF(object): - """Class that defines a Windows Registry file using pyregf.""" +class REGFWinRegistryFile(interface.WinRegistryFile): + """Implementation of a Windows Registry file using pyregf.""" def __init__(self, ascii_codepage=u'cp1252'): """Initializes the Windows Registry file. @@ -397,7 +198,7 @@ def __init__(self, ascii_codepage=u'cp1252'): ascii_codepage: optional ASCII string codepage. The default is cp1252 (or windows-1252). """ - super(WinRegistryFileREGF, self).__init__() + super(REGFWinRegistryFile, self).__init__() self._file_object = None self._regf_file = pyregf.file() self._regf_file.set_ascii_codepage(ascii_codepage) @@ -412,26 +213,35 @@ def GetKeyByPath(self, key_path): """Retrieves the key for a specific path. Args: - key_path: the Registry key path. + key_path: the Windows Registry key path. Returns: A Registry key (instance of WinRegistryKey) or None if not available. """ - return self._regf_file.get_key_by_path(key_path) + try: + regf_key = self._regf_file.get_key_by_path(key_path) + except IOError: + regf_key = None + if not regf_key: + return - def GetRootKey(self): - """Retrieves the root keys. + return REGFWinRegistryKey(regf_key, key_path=key_path) + + def GetRootKey(self, key_path_prefix=u''): + """Retrieves the root key. + + Args: + key_path_prefix: optional Windows Registry key path prefix. Returns: - A Registry key (instance of WinRegistryKey) or None if not available. + The Windows Registry root key (instance of WinRegistryKey) or + None if not available. """ regf_key = self._regf_file.get_root_key() if not regf_key: return - # TODO: refactor to WinRegistryKey, also remove parent key path or - # use WinRegistry path. - return WinPyregfKey(regf_key, u'', root=True) + return REGFWinRegistryKey(regf_key, key_path=key_path_prefix) def Open(self, file_object): """Opens the Windows Registry file using a file-like object. diff --git a/plaso/dfwinreg/registry.py b/plaso/dfwinreg/registry.py index eb94499e02..e980496545 100644 --- a/plaso/dfwinreg/registry.py +++ b/plaso/dfwinreg/registry.py @@ -6,6 +6,7 @@ from dfvfs.helpers import file_system_searcher from plaso.dfwinreg import definitions +from plaso.dfwinreg import interface from plaso.dfwinreg import path_expander from plaso.dfwinreg import regf @@ -14,16 +15,18 @@ class WinRegistryFileMapping(object): """Class that defines a Windows Registry file mapping. Attributes: - key_path_prefix: the Registry key path prefix. - windows_path: the Windows path to the Registry file. + key_path_prefix: the Windows Registry key path prefix. + windows_path: the Windows path to the Windows Registry file. E.g. + C:\\Windows\\System32\\config\\SYSTEM """ def __init__(self, key_path_prefix, windows_path): """Initializes the Windows Registry file mapping. Args: - key_path_prefix: the Registry key path prefix. - windows_path: the Windows path to the Registry file. + key_path_prefix: the Windows Registry key path prefix. + windows_path: the Windows path to the Windows Registry file. E.g. + C:\\Windows\\System32\\config\\SYSTEM """ super(WinRegistryFileMapping, self).__init__() self.key_path_prefix = key_path_prefix.upper() @@ -31,7 +34,7 @@ def __init__(self, key_path_prefix, windows_path): class WinRegistry(object): - """Class to provided a uniform way to access the Windows Registry.""" + """Class to provide a uniform way to access the Windows Registry.""" _KEY_PATHS_PER_REGISTRY_TYPE = { definitions.REGISTRY_FILE_TYPE_NTUSER: frozenset([ @@ -123,10 +126,10 @@ def __init__( Args: ascii_codepage: optional ASCII string codepage. The default is cp1252 (or windows-1252). - backend: The back-end to use to read the Registry structures, the + backend: The back-end to use to read the Windows Registry structures, the default is 1 (pyregf). - registry_file_reader: optional Registry file reader (instance of - RegistryFileReader). The default is None. + registry_file_reader: optional Windows Registry file reader (instance of + WinRegistryFileReader). The default is None. """ super(WinRegistry, self).__init__() self._ascii_codepage = ascii_codepage @@ -142,15 +145,15 @@ def __del__(self): registry_file.Close() def _GetCachedFileByPath(self, safe_key_path): - """Retrieves a cached Registry file for a specific path. + """Retrieves a cached Windows Registry file for a specific path. Args: - safe_key_path: the Registry key path, in upper case with a resolved - root key alias. + safe_key_path: the Windows Registry key path, in upper case with + a resolved root key alias. Returns: - A tuple of the key path prefix and the corresponding Registry file object - (instance of RegistryFile) or None if not available. + A tuple of the key path prefix and the corresponding Windows Registry + file object (instance of WinRegistryFile) or None if not available. """ longest_key_path_prefix = u'' longest_key_path_prefix_length = len(longest_key_path_prefix) @@ -200,25 +203,25 @@ def _GetCurrentControlSet(self): return u'HKEY_LOCAL_MACHINE\\System\\ControlSet{0:03d}'.format(control_set) def _GetFileByPath(self, safe_key_path): - """Retrieves the Registry file for a specific path. + """Retrieves a Windows Registry file for a specific path. Args: - safe_key_path: the Registry key path, in upper case with a resolved - root key alias. + safe_key_path: the Windows Registry key path, in upper case with + a resolved root key alias. Returns: - A tuple of the key path prefix and the corresponding Registry file object - (instance of RegistryFile) or None if not available. + A tuple of the key path prefix and the corresponding Windows Registry + file object (instance of WinRegistryFile) or None if not available. """ + if not self._registry_file_reader: + return None, None + # TODO: handle HKEY_USERS in both 9X and NT. key_path_prefix, registry_file = self._GetCachedFileByPath(safe_key_path) if not registry_file: for mapping in self._GetFileMappingsByPath(safe_key_path): - # TODO: refactor to pass single path. - path, _, filename = mapping.windows_path.rpartition(u'/') - registry_file = self._registry_file_reader.Open( - path, filename, ascii_codepage=self._ascii_codepage) + registry_file = self.OpenFile(mapping.windows_path) if registry_file: if not key_path_prefix: key_path_prefix = mapping.key_path_prefix @@ -230,14 +233,14 @@ def _GetFileByPath(self, safe_key_path): return key_path_prefix, registry_file def _GetFileMappingsByPath(self, safe_key_path): - """Retrieves the Registry file mappings for a specific path. + """Retrieves the Windows Registry file mappings for a specific path. Args: - safe_key_path: the Registry key path, in upper case with a resolved - root key alias. + safe_key_path: the Windows Registry key path, in upper case with + a resolved root key alias. Yields: - Registry file mapping objects (instances of RegistryFileMapping). + Registry file mapping objects (instances of WinRegistryFileMapping). """ candidate_mappings = [] for mapping in self._REGISTRY_FILE_MAPPINGS_NT: @@ -251,26 +254,26 @@ def _GetFileMappingsByPath(self, safe_key_path): yield mapping def ExpandKeyPath(self, key_path, path_attributes): - """Expand a Registry key path based on path attributes. + """Expand a Windows Registry key path based on path attributes. - A Registry key path may contain path attributes. A path attribute is - defined as anything within a curly bracket, e.g. + A Windows Registry key path may contain path attributes. A path + attribute is defined as anything within a curly bracket, e.g. "\\System\\{my_attribute}\\Path\\Keyname". If the path attribute my_attribute is defined it's value will be replaced with the attribute name, e.g. "\\System\\MyValue\\Path\\Keyname". - If the Registry path needs to have curly brackets in the path then - they need to be escaped with another curly bracket, e.g. + If the Windows Registry key path needs to have curly brackets in the path + then they need to be escaped with another curly bracket, e.g. "\\System\\{my_attribute}\\{{123-AF25-E523}}\\KeyName". In this case the {{123-AF25-E523}} will be replaced with "{123-AF25-E523}". Args: - key_path: the Registry key path before being expanded. + key_path: the Windows Registry key path before being expanded. path_attributes: a dictionary containing the path attributes. Returns: - A Registry key path that's expanded based on attribute values. + A Windows Registry key path that's expanded based on attribute values. Raises: KeyError: If an attribute name is in the key path not set in @@ -291,10 +294,11 @@ def GetKeyByPath(self, key_path): """Retrieves the key for a specific path. Args: - key_path: the Registry key path. + key_path: the Windows Registry key path. Returns: - A Registry key (instance of RegistryKey) or None if not available. + A Windows Registry key (instance of WinRegistryKey) or None if + not available. Raises: RuntimeError: if the root key is not supported. @@ -337,10 +341,11 @@ def GetKeyByPath(self, key_path): return registry_file.GetKeyByPath(key_path) def GetRegistryFileType(self, registry_file): - """Determines the Registry type based on keys present in the file. + """Determines the Windows Registry type based on keys present in the file. Args: - registry_file: the Registry file object (instance of WinRegistyFile). + registry_file: the Windows Registry file object (instance of + WinRegistyFile). Returns: The Windows Registry file type, e.g. NTUSER, SOFTWARE. @@ -353,7 +358,8 @@ def GetRegistryFileType(self, registry_file): # Registry type. match = True for key_path in key_paths: - if not registry_file.GetKeyByPath(key_path): + registry_key = registry_file.GetKeyByPath(key_path) + if not registry_key: match = False if match: @@ -361,59 +367,80 @@ def GetRegistryFileType(self, registry_file): return registry_file_type - # TODO: in the process of being deprecated. - def OpenFileEntry(self, file_entry, codepage=u'cp1252'): - """Opens a Registry file. + def OpenFile(self, path): + """Opens a Windows Registry file. Args: - file_entry: The file entry object (instance of dfvfs.FileEntry). - codepage: Optional extended ASCII string codepage. The default is cp1252. + path: the Windows Registry file path. Returns: - The a Windows Registry file (instance of WinRegistyFile) if successful - or None otherwise. + A corresponding Windows Registry file object (instance of + WinRegistryFile) or None if not available. Raises: - ValueError: if the back-end is not supported. + RuntimeError: if no Registry file reader is set. + """ + if not self._registry_file_reader: + raise RuntimeError(u'Missing Registry file reader.') + + return self._registry_file_reader.Open( + path, ascii_codepage=self._ascii_codepage) + + # TODO: deprecate usage of this method. + def OpenFileEntry(self, file_entry): + """Opens a Windows Registry file entry. + + Args: + file_entry: the file entry (instance of dfvfs.FileEntry). + + Returns: + A corresponding Windows Registry file object (instance of + WinRegistryFile) or None if not available. """ - if self._backend != self.BACKEND_PYREGF: - raise ValueError(u'Unsupported back-end') + registry_file = regf.REGFWinRegistryFile() + file_object = file_entry.GetFileObject() + + try: + registry_file.Open(file_object) + except IOError: + file_object.close() + registry_file = None - registry_file = regf.WinPyregfFile(ascii_codepage=codepage) - registry_file.OpenFileEntry(file_entry) return registry_file -class WinRegistryFileReader(object): - """Class to read a Windows Registry file.""" +class SearcherWinRegistryFileReader(interface.WinRegistryFileReader): + """A file system searcher-based Windows Registry file reader.""" def __init__(self, searcher, pre_obj=None): - """Initializes the Windows Registry file reader. + """Initializes a Windows Registry file reader object. Args: - searcher: The file system searcher object (instance of + searcher: the file system searcher object (instance of dfvfs.FileSystemSearcher). - pre_obj: Optional preprocess object that contains stored values from + pre_obj: optional preprocess object that contains stored values from the image. """ - super(WinRegistryFileReader, self).__init__() + super(SearcherWinRegistryFileReader, self).__init__() self._file_path_expander = path_expander.WinRegistryKeyPathExpander() self._pre_obj = pre_obj self._searcher = searcher - def _FindPathSpec(self, path, filename): - """Searches for a path specification of the path. + def _FindPathSpec(self, path): + """Searches for a path specification. Args: - path: the path of the Registry file. - filename: the name of the Registry file. + path: the path of the Windows Registry file. Returns: - A path specification (instance of dfvfs.PathSpec) of the Registry file. + A path specification (instance of dfvfs.PathSpec) of + the Windows Registry file. Raises: - IOError: If the preprocessing failed. + IOError: If the Windows Registry file cannot be found. """ + path, _, filename = path.rpartition(u'/') + # TODO: determine why this first find is used add comment or remove. # It does not appear to help with making sure path segment separate # is correct. @@ -455,18 +482,16 @@ def _FindPathSpec(self, path, filename): return path_specs[0] - # TODO: refactor to single path. - def Open(self, path, filename, ascii_codepage=u'cp1252'): - """Opens the Registry file specificed by the path. + def Open(self, path, ascii_codepage=u'cp1252'): + """Opens the Windows Registry file specificed by the path. Args: - path: the path of the Registry file. - filename: the name of the Registry file. + path: the path of the Windows Registry file. ascii_codepage: optional ASCII string codepage. The default is cp1252 (or windows-1252). Returns: - The Registry file (instance of WinRegistryFile) or None. + The Windows Registry file (instance of WinRegistryFile) or None. """ try: # TODO: do not pass the full pre_obj here but just @@ -480,7 +505,7 @@ def Open(self, path, filename, ascii_codepage=u'cp1252'): path, exception)) expanded_path = path - path_spec = self._FindPathSpec(expanded_path, filename) + path_spec = self._FindPathSpec(expanded_path) if not path_spec: return @@ -492,16 +517,49 @@ def Open(self, path, filename, ascii_codepage=u'cp1252'): if file_object is None: return - registry_file = regf.WinPyregfFile(ascii_codepage=ascii_codepage) - # TODO: replace by: - # registry_file = regf.WinRegistryFileREGF(ascii_codepage=ascii_codepage) + registry_file = regf.REGFWinRegistryFile(ascii_codepage=ascii_codepage) try: registry_file.Open(file_object) - except IOError: - logging.warning( - u'Unable to open Registry file: {0:s} with error: {1:s}'.format( - path, exception)) + except IOError as exception: + logging.warning(( + u'Unable to open Windows Registry file: {0:s} with error: ' + u'{1:s}').format(path, exception)) file_object.close() return return registry_file + + +class SingleWinRegistryFileReader(interface.WinRegistryFileReader): + """A single file Windows Registry file reader.""" + + def __init__(self, file_object): + """Initializes a Windows Registry file reader object. + + Args: + file_object: the Windows Registry file-like object. + """ + super(SingleWinRegistryFileReader, self).__init__() + self._file_object = file_object + + def Open(self, unused_path, ascii_codepage=u'cp1252'): + """Opens the Windows Registry file specificed by the path. + + Args: + path: the path of the Windows Registry file. + ascii_codepage: optional ASCII string codepage. The default is cp1252 + (or windows-1252). + + Returns: + The Windows Registry file (instance of WinRegistryFile) or None. + """ + registry_file = regf.REGFWinRegistryFile(ascii_codepage=ascii_codepage) + try: + registry_file.Open(self._file_object) + except IOError as exception: + logging.warning( + u'Unable to open Windows Registry file with error: {0:s}'.format( + exception)) + return + + return registry_file diff --git a/plaso/events/text_events.py b/plaso/events/text_events.py index 8c0b4600db..6731693710 100644 --- a/plaso/events/text_events.py +++ b/plaso/events/text_events.py @@ -24,7 +24,7 @@ def __init__(self, timestamp, offset, attributes): self.offset = offset - for name, value in attributes.iteritems(): + for name, value in iter(attributes.items()): # TODO: Revisit this constraints and see if we can implement # it using a more sane solution. if isinstance(value, basestring) and not value: diff --git a/plaso/events/time_events.py b/plaso/events/time_events.py index 3aafe66b01..f8f739d175 100644 --- a/plaso/events/time_events.py +++ b/plaso/events/time_events.py @@ -96,9 +96,9 @@ def __init__(self, filetime, timestamp_description, data_type=None): data_type: optional event data type. If not set data_type is derived from the DATA_TYPE attribute. """ + timestamp = timelib.Timestamp.FromFiletime(filetime) super(FiletimeEvent, self).__init__( - timelib.Timestamp.FromFiletime(filetime), timestamp_description, - data_type=data_type) + timestamp, timestamp_description, data_type=data_type) class JavaTimeEvent(TimestampEvent): diff --git a/plaso/events/windows_events.py b/plaso/events/windows_events.py index faaf0852c2..be9d19069a 100644 --- a/plaso/events/windows_events.py +++ b/plaso/events/windows_events.py @@ -23,40 +23,40 @@ def __init__(self, uuid, origin): self.origin = origin -class WindowsRegistryEvent(time_events.TimestampEvent): +class WindowsRegistryEvent(time_events.FiletimeEvent): """Convenience class for a Windows Registry-based event.""" DATA_TYPE = 'windows:registry:key_value' def __init__( - self, timestamp, key_name, value_dict, usage=None, offset=None, - registry_file_type=None, urls=None, source_append=None): + self, filetime, key_path, values_dict, usage=None, offset=None, + registry_file_type=None, source_append=None, urls=None): """Initializes a Windows registry event. Args: - timestamp: The timestamp time value. The timestamp contains the - number of microseconds since Jan 1, 1970 00:00:00 UTC. - key_name: The name of the Registry key being parsed. - value_dict: The interpreted value of the key, stored as a dictionary. + filetime: the FILETIME timestamp value. + key_path: the Windows Registry key path. + values_dict: Dictionary object containing values of the key. usage: Optional description of the usage of the time value. The default is None. offset: Optional (data) offset of the Registry key or value. The default is None. registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - urls: Optional list of URLs. The default is None. source_append: Optional string to append to the source_long of the event. The default is None. + urls: Optional list of URLs. The default is None. """ if usage is None: usage = eventdata.EventTimestamp.WRITTEN_TIME - super(WindowsRegistryEvent, self).__init__(timestamp, usage) + super(WindowsRegistryEvent, self).__init__(filetime, usage) - if key_name: - self.keyname = key_name + if key_path: + # TODO: rename keyname to key_path + self.keyname = key_path - self.regvalue = value_dict + self.regvalue = values_dict if offset or isinstance(offset, (int, long)): self.offset = offset @@ -64,11 +64,46 @@ def __init__( if registry_file_type: self.registry_file_type = registry_file_type + if source_append: + self.source_append = source_append + if urls: self.url = u' - '.join(urls) - if source_append: - self.source_append = source_append + +class WindowsRegistryInstallationEvent(time_events.PosixTimeEvent): + """Convenience class for a Windows installation event. + + Attributes: + key_path: the Windows Registry key path. + owner: string containing the owner. + product_name: string containing the produce name. + service_pack: string containing service pack. + version: string containing the version. + """ + + DATA_TYPE = 'windows:registry:installation' + + def __init__( + self, posix_time, key_path, owner, product_name, service_pack, version): + """Initializes an event object. + + Args: + posix_time: the POSIX time value. + key_path: the Windows Registry key path. + owner: string containing the owner. + product_name: string containing the produce name. + service_pack: string containing service pack. + version: string containing the version. + """ + super(WindowsRegistryInstallationEvent, self).__init__( + posix_time, eventdata.EventTimestamp.INSTALLATION_TIME) + + self.key_path = key_path + self.owner = owner + self.product_name = product_name + self.service_pack = service_pack + self.version = version class WindowsRegistryServiceEvent(WindowsRegistryEvent): diff --git a/plaso/formatters/__init__.py b/plaso/formatters/__init__.py index 8a196b666b..b2f2780a7d 100644 --- a/plaso/formatters/__init__.py +++ b/plaso/formatters/__init__.py @@ -9,6 +9,7 @@ from plaso.formatters import asl from plaso.formatters import bencode_parser from plaso.formatters import bsm +from plaso.formatters import ccleaner from plaso.formatters import chrome from plaso.formatters import chrome_cache from plaso.formatters import chrome_cookies diff --git a/plaso/formatters/ccleaner.py b/plaso/formatters/ccleaner.py new file mode 100644 index 0000000000..4968b003cc --- /dev/null +++ b/plaso/formatters/ccleaner.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +"""The CCleaner event formatter.""" + +from plaso.formatters import interface +from plaso.formatters import manager + + +class CCleanerUpdateEventFormatter(interface.ConditionalEventFormatter): + """Formatter for a CCleaner update event.""" + + DATA_TYPE = u'ccleaner:update' + + FORMAT_STRING_PIECES = [ + u'Origin: {key_path}'] + + FORMAT_STRING_SHORT_PIECES = [ + u'Origin: {key_path}'] + + SOURCE_LONG = u'System' + SOURCE_SHORT = u'LOG' + + +manager.FormattersManager.RegisterFormatter( + CCleanerUpdateEventFormatter) diff --git a/plaso/formatters/windows.py b/plaso/formatters/windows.py index ff60fa6b58..62fe044de3 100644 --- a/plaso/formatters/windows.py +++ b/plaso/formatters/windows.py @@ -24,6 +24,29 @@ class WindowsDistributedLinkTrackingCreationEventFormatter( SOURCE_SHORT = u'LOG' +class WindowsRegistryInstallationEventFormatter( + interface.ConditionalEventFormatter): + """Formatter for a Windows installation event.""" + + DATA_TYPE = u'windows:registry:installation' + + FORMAT_STRING_PIECES = [ + u'{product_name}', + u'{version}', + u'{service_pack}', + u'Owner: owner', + u'Origin: {key_path}'] + + FORMAT_STRING_SHORT_PIECES = [ + u'{product_name}', + u'{version}', + u'{service_pack}', + u'Origin: {key_path}'] + + SOURCE_LONG = u'System' + SOURCE_SHORT = u'LOG' + + class WindowsVolumeCreationEventFormatter(interface.ConditionalEventFormatter): """Formatter for a Windows volume creation event.""" @@ -44,4 +67,5 @@ class WindowsVolumeCreationEventFormatter(interface.ConditionalEventFormatter): manager.FormattersManager.RegisterFormatters([ WindowsDistributedLinkTrackingCreationEventFormatter, + WindowsRegistryInstallationEventFormatter, WindowsVolumeCreationEventFormatter]) diff --git a/plaso/frontend/preg.py b/plaso/frontend/preg.py index 40265fa6bd..3e8e018131 100644 --- a/plaso/frontend/preg.py +++ b/plaso/frontend/preg.py @@ -394,7 +394,8 @@ def GetRegistryFilePaths(self, plugin_name=None, registry_file_type=None): paths.append(u'/Users/.+/AppData/Local/Microsoft/Windows/UsrClass.dat') # Expand all the paths. - win_registry = dfwinreg_registry.WinRegistry() + win_registry = dfwinreg_registry.WinRegistry( + backend=dfwinreg_registry.WinRegistry.BACKEND_PYREGF) # TODO: deprecate usage of pre_obj. path_attributes = self.knowledge_base_object.pre_obj.__dict__ @@ -549,8 +550,9 @@ def ParseRegistryFile( Returns: A dict that contains the following structure: key_path: - key: a Registry key (instance of WinRegKey) - subkeys: a list of Registry keys (instance of WinRegKey). + key: a Registry key (instance of dfwinreg.WinRegistryKey) + subkeys: a list of Registry keys (instance of + dfwinreg.WinRegistryKey). data: plugin: a plugin object (instance of RegistryPlugin) event_objects: List of event objects extracted. @@ -594,8 +596,8 @@ def ParseRegistryKey(self, key, registry_helper, use_plugins=None): all available plugins. Args: - key: the Registry key to parse (instance of WinRegKey or a string - containing key path). + key: the Registry key to parse (instance of dfwinreg.WinRegistryKey or + a string containing key path). registry_helper: the Registry helper object (instance of PregRegistryHelper). use_plugins: optional list of plugin names to use. The default is None @@ -697,6 +699,9 @@ def __init__( self._codepage = codepage self._collector_name = collector_name self._knowledge_base_object = knowledge_base_object + self._registry_file = None + self._registry_file_name = None + self._registry_file_type = dfwinreg_definitions.REGISTRY_FILE_TYPE_UNKNOWN self._win_registry = dfwinreg_registry.WinRegistry( backend=dfwinreg_registry.WinRegistry.BACKEND_PYREGF) @@ -723,7 +728,7 @@ def file_type(self): @property def name(self): """The name of the Registry file.""" - return getattr(self._registry_file, u'name', u'N/A') + return self._registry_file_name @property def path(self): @@ -744,6 +749,7 @@ def _Reset(self): """Reset all attributes of the Registry helper.""" self._currently_loaded_registry_key = u'' self._registry_file = None + self._registry_file_name = None self._registry_file_type = dfwinreg_definitions.REGISTRY_FILE_TYPE_UNKNOWN def Close(self): @@ -793,7 +799,8 @@ def GetKeyByPath(self, key_path): key_path: the Registry key path. Returns: - The key (instance of WinRegKey) if available or None otherwise. + The key (instance of dfwinreg.WinRegistryKey) if available or + None otherwise. """ if not key_path: return @@ -815,20 +822,24 @@ def GetKeyByPath(self, key_path): return key def Open(self): - """Open the Registry file.""" + """Opens a Windows Registry file. + + Raises: + IOError: if the Windows Registry file cannot be opened. + """ if self._registry_file: raise IOError(u'Registry file already open.') - try: - self._registry_file = self._win_registry.OpenFileEntry( - self.file_entry, codepage=self._codepage) - except IOError: + self._registry_file = self._win_registry.OpenFileEntry(self.file_entry) + if not self._registry_file: logging.error( u'Unable to open Registry file: {0:s} [{1:s}]'.format( self.path, self._collector_name)) + self.Close() - raise + raise IOError(u'Unable to open Registry file.') + self._registry_file_name = self.file_entry.name self._registry_file_type = self._win_registry.GetRegistryFileType( self._registry_file) diff --git a/plaso/lib/errors.py b/plaso/lib/errors.py index 29f11b3f4b..9d1520397b 100644 --- a/plaso/lib/errors.py +++ b/plaso/lib/errors.py @@ -130,7 +130,3 @@ class WrongPlugin(Error): class WrongProtobufEntry(Error): """Raised when an EventObject cannot be serialized as a protobuf.""" - - -class WinRegistryValueError(Error): - """Raised when there is an issue reading a registry value.""" diff --git a/plaso/lib/eventdata.py b/plaso/lib/eventdata.py index cc48e02702..3ba49f52a5 100644 --- a/plaso/lib/eventdata.py +++ b/plaso/lib/eventdata.py @@ -19,6 +19,8 @@ class EventTimestamp(object): LAST_RUNTIME = u'Last Time Executed' DELETED_TIME = u'Content Deletion Time' + INSTALLATION_TIME = u'Installation Time' + FILE_DOWNLOADED = u'File Downloaded' PAGE_VISITED = u'Page Visited' # TODO: change page visited into last visited time. @@ -29,6 +31,7 @@ class EventTimestamp(object): EXPIRATION_TIME = u'Expiration Time' START_TIME = u'Start Time' END_TIME = u'End Time' + UPDATE_TIME = u'Update Time' LAST_SHUTDOWN = u'Last Shutdown Time' diff --git a/plaso/parsers/winreg.py b/plaso/parsers/winreg.py index bf4ffc07f1..731925947b 100644 --- a/plaso/parsers/winreg.py +++ b/plaso/parsers/winreg.py @@ -3,6 +3,7 @@ import logging +from plaso.dfwinreg import regf as dfwinreg_regf from plaso.dfwinreg import registry as dfwinreg_registry from plaso.lib import errors from plaso.lib import specification @@ -132,7 +133,7 @@ def GetTypes(self): return set(self._plugins) -class WinRegistryParser(interface.BaseParser): +class WinRegistryParser(interface.SingleFileBaseParser): """Parses Windows NT Registry (REGF) files.""" NAME = u'winreg' @@ -147,31 +148,14 @@ def __init__(self): self._win_registry = dfwinreg_registry.WinRegistry( backend=dfwinreg_registry.WinRegistry.BACKEND_PYREGF) - def _CheckSignature(self, parser_mediator): - """Checks if the file matches the signature of a REGF file. - - Args: - parser_mediator: A parser mediator object (instance of ParserMediator). - - Returns: - A boolean value indicating if the file matches the signature of - a REGF file. - """ - file_object = parser_mediator.GetFileObject() - try: - data = file_object.read(4) - finally: - file_object.close() - - return data == b'regf' - def _ParseRegistryFile( self, parser_mediator, winreg_file, registry_file_type): """Parses a Windows Registry file. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - winreg_file: A Windows Registry file (instance of dfwinreg.WinRegFile). + winreg_file: A Windows Registry file (instance of + dfwinreg.WinRegistryFile). registry_file_type: The Registry file type. """ plugins = self._plugins.GetPluginObjects(registry_file_type) @@ -213,43 +197,34 @@ def GetPluginList(cls): plugins_list.AddPlugin(plugin_class.REG_TYPE, plugin_class) return plugins_list - def Parse(self, parser_mediator, **kwargs): - """Parses a Windows Registry file. + def ParseFileObject(self, parser_mediator, file_object, **kwargs): + """Parses a Windows Registry file-like object. Args: parser_mediator: A parser mediator object (instance of ParserMediator). + file_object: A file-like object. + + Raises: + UnableToParseFile: when the file cannot be parsed. """ display_name = parser_mediator.GetDisplayName() - # TODO: Remove this magic reads when the classifier has been - # implemented, until then we need to make sure we are dealing with - # a Windows NT Registry file before proceeding. - - if not self._CheckSignature(parser_mediator): - raise errors.UnableToParseFile(( - u'[{0:s}] unable to parse file: {1:s} with error: invalid ' - u'signature.').format(self.NAME, display_name)) + winreg_file = dfwinreg_regf.REGFWinRegistryFile( + ascii_codepage=parser_mediator.codepage) - # TODO: refactor this. - file_entry = parser_mediator.GetFileEntry() try: - winreg_file = self._win_registry.OpenFileEntry( - file_entry, codepage=parser_mediator.codepage) + winreg_file.Open(file_object) except IOError as exception: raise errors.UnableToParseFile( u'[{0:s}] unable to parse file: {1:s} with error: {2:s}'.format( self.NAME, display_name, exception)) - try: - registry_file_type = self._win_registry.GetRegistryFileType(winreg_file) - logging.debug( - u'Windows Registry file {0:s}: detected as: {1:s}'.format( - display_name, registry_file_type)) - - self._ParseRegistryFile(parser_mediator, winreg_file, registry_file_type) + registry_file_type = self._win_registry.GetRegistryFileType(winreg_file) + logging.debug( + u'Windows Registry file {0:s}: detected as: {1:s}'.format( + display_name, registry_file_type)) - finally: - winreg_file.Close() + self._ParseRegistryFile(parser_mediator, winreg_file, registry_file_type) manager.ParsersManager.RegisterParser(WinRegistryParser) diff --git a/plaso/parsers/winreg_plugins/appcompatcache.py b/plaso/parsers/winreg_plugins/appcompatcache.py index 3edef89e1f..dc4d4cd083 100644 --- a/plaso/parsers/winreg_plugins/appcompatcache.py +++ b/plaso/parsers/winreg_plugins/appcompatcache.py @@ -17,22 +17,21 @@ class AppCompatCacheEvent(time_events.FiletimeEvent): DATA_TYPE = u'windows:registry:appcompatcache' def __init__( - self, filetime, usage, key, entry_index, path, offset): + self, filetime, usage, key_name, entry_index, path, offset): """Initializes a Windows Registry event. Args: filetime: The FILETIME timestamp value. usage: The description of the usage of the time value. - key: Name of the Registry key being parsed. + key_name: The name of the corresponding Windows Registry key. entry_index: The cache entry index number for the record. path: The full path to the executable. - offset: The (data) offset of the Registry key or value. + offset: The (data) offset of the Windows Registry key or value. """ super(AppCompatCacheEvent, self).__init__(filetime, usage) - - self.keyname = key - self.offset = offset self.entry_index = entry_index + self.keyname = key_name + self.offset = offset self.path = path @@ -547,17 +546,15 @@ def _ParseCachedEntry( return cached_entry_object - def GetEntries( - self, parser_mediator, key=None, codepage=u'cp1252', **unused_kwargs): + def GetEntries(self, parser_mediator, registry_key, **kwargs): """Extracts event objects from a Application Compatibility Cache key. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). """ - value = key.GetValue(u'AppCompatCache') + value = registry_key.GetValueByName(u'AppCompatCache') if not value: return @@ -568,7 +565,7 @@ def GetEntries( if not format_type: parser_mediator.ProduceParseError( u'Unsupported signature in AppCompatCache key: {0:s}'.format( - key.path)) + registry_key.path)) return header_object = self._ParseHeader(format_type, value_data) @@ -585,7 +582,7 @@ def GetEntries( if not cached_entry_size: parser_mediator.ProduceParseError( u'Unsupported cached entry size at offset {0:d} in AppCompatCache ' - u'key: {1:s}'.format(cached_entry_offset, key.path)) + u'key: {1:s}'.format(cached_entry_offset, registry_key.path)) return cached_entry_index = 0 @@ -597,7 +594,7 @@ def GetEntries( # TODO: refactor to file modification event. event_object = AppCompatCacheEvent( cached_entry_object.last_modification_time, - u'File Last Modification Time', key.path, + u'File Last Modification Time', registry_key.path, cached_entry_index + 1, cached_entry_object.path, cached_entry_offset) parser_mediator.ProduceEvent(event_object) @@ -606,7 +603,7 @@ def GetEntries( # TODO: refactor to process run event. event_object = AppCompatCacheEvent( cached_entry_object.last_update_time, - eventdata.EventTimestamp.LAST_RUNTIME, key.path, + eventdata.EventTimestamp.LAST_RUNTIME, registry_key.path, cached_entry_index + 1, cached_entry_object.path, cached_entry_offset) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/bagmru.py b/plaso/parsers/winreg_plugins/bagmru.py index 649f21bb7e..410526e84f 100644 --- a/plaso/parsers/winreg_plugins/bagmru.py +++ b/plaso/parsers/winreg_plugins/bagmru.py @@ -34,26 +34,28 @@ class BagMRUPlugin(interface.WindowsRegistryPlugin): _MRULISTEX_ENTRY = construct.ULInt32(u'entry_number') + _SOURCE_APPEND = u': BagMRU' + def _ParseMRUListExEntryValue( - self, parser_mediator, key, entry_index, entry_number, text_dict, + self, parser_mediator, key, entry_index, entry_number, values_dict, value_strings, parent_path_segments, codepage=u'cp1252', **unused_kwargs): """Parses the MRUListEx entry value. Args: - parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey) that contains + parser_mediator: a parser mediator object (instance of ParserMediator). + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUListEx value. entry_index: integer value representing the MRUListEx entry index. entry_number: integer value representing the entry number. - text_dict: text dictionary object to append textual strings. + values_dict: dictionary object containing values of the key. value_strings: value string dictionary object to append value strings. parent_path_segments: list containing the parent shell item path segments. - codepage: Optional extended ASCII string codepage. The default is cp1252. + codepage: optional extended ASCII string codepage. Returns: The path segment of the shell item. """ - value = key.GetValue(u'{0:d}'.format(entry_number)) + value = key.GetValueByName(u'{0:d}'.format(entry_number)) path_segment = u'N/A' value_string = u'' if value is None: @@ -82,7 +84,7 @@ def _ParseMRUListExEntryValue( value_text = u'Index: {0:d} [MRU Value {1:d}]'.format( entry_index + 1, entry_number) - text_dict[value_text] = value_string + values_dict[value_text] = value_string return path_segment @@ -90,15 +92,15 @@ def _ParseMRUListExValue(self, parser_mediator, key): """Parses the MRUListEx value in a given Registry key. Args: - parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey) that contains + parser_mediator: a parser mediator object (instance of ParserMediator). + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUListEx value. Yields: A tuple of the MRUListEx index and entry number, where 0 is the first index value. """ - mru_list_value = key.GetValue(u'MRUListEx') + mru_list_value = key.GetValueByName(u'MRUListEx') if mru_list_value: mrulistex_data = mru_list_value.data data_size = len(mrulistex_data) @@ -126,20 +128,20 @@ def _ParseMRUListExValue(self, parser_mediator, key): data_offset += 4 def _ParseSubKey( - self, parser_mediator, key, parent_path_segments, registry_file_type=None, - codepage=u'cp1252'): + self, parser_mediator, key, parent_path_segments, codepage=u'cp1252', + registry_file_type=None): """Extract event objects from a MRUListEx Registry key. Args: - parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey). + parser_mediator: a parser mediator object (instance of ParserMediator). + key: the Registry key (instance of dfwinreg.WinRegistryKey). parent_path_segments: list containing the parent shell item path segments. - registry_file_type: Optional string containing the Windows Registry file + codepage: optional extended ASCII string codepage. The default is cp1252. + registry_file_type: optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ entry_numbers = {} - text_dict = {} + values_dict = {} value_strings = {} found_terminator = False @@ -157,19 +159,19 @@ def _ParseSubKey( found_terminator = False path_segment = self._ParseMRUListExEntryValue( - parser_mediator, key, index, entry_number, text_dict, value_strings, - parent_path_segments, codepage=codepage) + parser_mediator, key, index, entry_number, values_dict, + value_strings, parent_path_segments, codepage=codepage) entry_numbers[entry_number] = path_segment event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, + key.last_written_time, key.path, values_dict, offset=key.offset, registry_file_type=registry_file_type, - urls=self.URLS, source_append=u': BagMRU') + urls=self.URLS, source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) for entry_number, path_segment in entry_numbers.iteritems(): - sub_key = key.GetSubkey(u'{0:d}'.format(entry_number)) + sub_key = key.GetSubkeyByName(u'{0:d}'.format(entry_number)) if not sub_key: parser_mediator.ProduceParseError( u'Missing BagMRU sub key: {0:d} in key: {1:s}.'.format( @@ -182,21 +184,21 @@ def _ParseSubKey( _ = parent_path_segments.pop() def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, + self, parser_mediator, registry_key, registry_file_type=None, codepage=u'cp1252', **unused_kwargs): """Extract event objects from a Registry key containing a MRUListEx value. Args: - parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. - registry_file_type: Optional string containing the Windows Registry file + parser_mediator: a parser mediator object (instance of ParserMediator). + registry_key: a Windows Registry key (instance of + dfwinreg.WinRegistryKey). + codepage: optional extended ASCII string codepage. The default is cp1252. + registry_file_type: optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ self._ParseSubKey( - parser_mediator, key, [], registry_file_type=registry_file_type, - codepage=codepage) + parser_mediator, registry_key, [], codepage=codepage, + registry_file_type=registry_file_type) winreg.WinRegistryParser.RegisterPlugin(BagMRUPlugin) diff --git a/plaso/parsers/winreg_plugins/ccleaner.py b/plaso/parsers/winreg_plugins/ccleaner.py index 17f13664e4..594cde1b68 100644 --- a/plaso/parsers/winreg_plugins/ccleaner.py +++ b/plaso/parsers/winreg_plugins/ccleaner.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- """Parser for the CCleaner Registry key.""" +from plaso.events import time_events from plaso.events import windows_events from plaso.lib import errors +from plaso.lib import eventdata from plaso.lib import timelib from plaso.parsers import winreg from plaso.parsers.winreg_plugins import interface @@ -11,6 +13,29 @@ __author__ = 'Marc Seguin (segumarc@gmail.com)' +class CCleanerUpdateEvent(time_events.TimestampEvent): + """Convenience class for a Windows installation event. + + Attributes: + key_path: the Windows Registry key path. + """ + + DATA_TYPE = 'ccleaner:update' + + def __init__(self, timestamp, key_path): + """Initializes an event object. + + Args: + timestamp: The timestamp which is an integer containing the number + of micro seconds since January 1, 1970, 00:00:00 UTC. + key_path: the Windows Registry key path. + """ + super(CCleanerUpdateEvent, self).__init__( + timestamp, eventdata.EventTimestamp.UPDATE_TIME) + + self.key_path = key_path + + class CCleanerPlugin(interface.WindowsRegistryPlugin): """Gathers the CCleaner Keys for NTUSER hive.""" @@ -23,53 +48,55 @@ class CCleanerPlugin(interface.WindowsRegistryPlugin): URLS = [(u'http://cheeky4n6monkey.blogspot.com/2012/02/writing-ccleaner' u'-regripper-plugin-part_05.html')] + _SOURCE_APPEND = u': CCleaner Registry key' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, codepage=u'cp1252', + registry_file_type=None, **unused_kwargs): """Extracts event objects from a CCleaner Registry key. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). + codepage: Optional extended ASCII string codepage. The default is cp1252. registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - for value in key.GetValues(): - if not value.name or not value.data: + update_key_value = None + values_dict = {} + for registry_value in registry_key.GetValues(): + if not registry_value.name or not registry_value.data: continue - text_dict = {} - text_dict[value.name] = value.data - - if value.name == u'UpdateKey': - try: - timestamp = timelib.Timestamp.FromTimeString( - value.data, timezone=parser_mediator.timezone) - except errors.TimestampError: - parser_mediator.ProduceParseError( - u'Unable to parse time string: {0:s}'.format(value.data)) - continue - - event_object = windows_events.WindowsRegistryEvent( - timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type) - - elif value.name == u'0': - event_object = windows_events.WindowsRegistryEvent( - key.timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type) + if (registry_value.name == u'UpdateKey' and + registry_value.DataIsString()): + update_key_value = registry_value else: - # TODO: change this event not to set a timestamp of 0. - event_object = windows_events.WindowsRegistryEvent( - 0, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type) - - event_object.source_append = u': CCleaner Registry key' - - parser_mediator.ProduceEvent(event_object) + values_dict[registry_value.name] = registry_value.data + + if update_key_value: + try: + # Date and time string in the form: MM/DD/YYYY hh:mm:ss [A|P]M + # e.g. 07/13/2013 10:03:14 AM + # TODO: does this hold for other locales? + timestamp = timelib.Timestamp.FromTimeString( + update_key_value.data, timezone=parser_mediator.timezone) + except errors.TimestampError: + timestamp = None + parser_mediator.ProduceParseError( + u'unable to parse time string: {0:s}'.format(update_key_value.data)) + + if timestamp is not None: + event_object = CCleanerUpdateEvent(timestamp, registry_key.path) + parser_mediator.ProduceEvent(event_object) + + event_object = windows_events.WindowsRegistryEvent( + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) + parser_mediator.ProduceEvent(event_object) winreg.WinRegistryParser.RegisterPlugin(CCleanerPlugin) diff --git a/plaso/parsers/winreg_plugins/default.py b/plaso/parsers/winreg_plugins/default.py index 78b1e6a061..29e065526a 100644 --- a/plaso/parsers/winreg_plugins/default.py +++ b/plaso/parsers/winreg_plugins/default.py @@ -23,25 +23,23 @@ class DefaultPlugin(interface.WindowsRegistryPlugin): REG_KEYS = [] def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Returns an event object based on a Registry key name and values. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - text_dict = {} + values_dict = {} - if key.number_of_values == 0: - text_dict[u'Value'] = u'No values stored in key.' + if registry_key.number_of_values == 0: + values_dict[u'Value'] = u'No values stored in key.' else: - for value in key.GetValues(): + for value in registry_key.GetValues(): if not value.name: value_name = u'(default)' else: @@ -67,11 +65,11 @@ def GetEntries( else: value_string = u'[{0:s}]'.format(value.data_type_string) - text_dict[value_name] = value_string + values_dict[value_name] = value_string event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, - offset=key.offset, registry_file_type=registry_file_type) + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type) parser_mediator.ProduceEvent(event_object) @@ -85,13 +83,13 @@ def Process( Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). + key: Optional Registry key (instance of dfwinreg.WinRegistryKey). The default is None. registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. """ self.GetEntries( - parser_mediator, key=key, registry_file_type=registry_file_type, + parser_mediator, key, registry_file_type=registry_file_type, **kwargs) diff --git a/plaso/parsers/winreg_plugins/interface.py b/plaso/parsers/winreg_plugins/interface.py index accb235a72..5b133884b8 100644 --- a/plaso/parsers/winreg_plugins/interface.py +++ b/plaso/parsers/winreg_plugins/interface.py @@ -81,19 +81,17 @@ def ExpandKeys(self, parser_mediator): @abc.abstractmethod def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, codepage=u'cp1252', + registry_file_type=None, **kwargs): """Extracts event objects from the Windows Registry key. Args: parser_mediator: A parser context object (instance of ParserContext). - file_entry: optional file entry object (instance of dfvfs.FileEntry). - The default is None. - key: Optional Registry key (instance of dfwinreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). + codepage: Optional extended ASCII string codepage. The default is cp1252. registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ def Process( @@ -103,7 +101,7 @@ def Process( Args: parser_mediator: A parser context object (instance of ParserContext). - key: Optional Registry key (instance of dfwinreg.WinRegKey). + key: Optional Registry key (instance of dfwinreg.WinRegistryKey). The default is None. registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. @@ -125,11 +123,11 @@ def Process( values = frozenset([value.name for value in key.GetValues()]) if self.REG_VALUES.issubset(values): self.GetEntries( - parser_mediator, key=key, registry_file_type=registry_file_type, + parser_mediator, key, registry_file_type=registry_file_type, codepage=codepage, **kwargs) else: if key and key.path in self.expanded_keys: self.GetEntries( - parser_mediator, key=key, registry_file_type=registry_file_type, + parser_mediator, key, registry_file_type=registry_file_type, **kwargs) diff --git a/plaso/parsers/winreg_plugins/lfu.py b/plaso/parsers/winreg_plugins/lfu.py index f2498504ff..97184a308c 100644 --- a/plaso/parsers/winreg_plugins/lfu.py +++ b/plaso/parsers/winreg_plugins/lfu.py @@ -18,26 +18,25 @@ class BootVerificationPlugin(interface.WindowsRegistryPlugin): URLS = [u'http://technet.microsoft.com/en-us/library/cc782537(v=ws.10).aspx'] def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Gather the BootVerification key values and return one event for all. This key is rare, so its presence is suspect. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - text_dict = {} - for value in key.GetValues(): - text_dict[value.name] = value.data + values_dict = {} + for value in registry_key.GetValues(): + values_dict[value.name] = value.data event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, urls=self.URLS) + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + urls=self.URLS) parser_mediator.ProduceEvent(event_object) @@ -53,23 +52,21 @@ class BootExecutePlugin(interface.WindowsRegistryPlugin): URLS = [u'http://technet.microsoft.com/en-us/library/cc963230.aspx'] def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Gather the BootExecute Value, compare to default, return event. The rest of the values in the Session Manager key are in a separate event. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - text_dict = {} + values_dict = {} - for value in key.GetValues(): + for value in registry_key.GetValues(): if value.name == u'BootExecute': # MSDN: claims that the data type of this value is REG_BINARY # although REG_MULTI_SZ is known to be used as well. @@ -83,22 +80,25 @@ def GetEntries( value_string = u'' error_string = ( u'Key: {0:s}, value: {1:s}: unsupported value data type: ' - u'{2:s}.').format(key.path, value.name, value.data_type_string) + u'{2:s}.').format( + registry_key.path, value.name, value.data_type_string) parser_mediator.ProduceParseError(error_string) # TODO: why does this have a separate event object? Remove this. value_dict = {u'BootExecute': value_string} event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, value_dict, offset=key.offset, - registry_file_type=registry_file_type, urls=self.URLS) + registry_key.last_written_time, registry_key.path, value_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + urls=self.URLS) parser_mediator.ProduceEvent(event_object) else: - text_dict[value.name] = value.data + values_dict[value.name] = value.data event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, urls=self.URLS) + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + urls=self.URLS) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/mountpoints.py b/plaso/parsers/winreg_plugins/mountpoints.py index b8534c6561..3f6200667b 100644 --- a/plaso/parsers/winreg_plugins/mountpoints.py +++ b/plaso/parsers/winreg_plugins/mountpoints.py @@ -21,47 +21,45 @@ class MountPoints2Plugin(interface.WindowsRegistryPlugin): URLS = [u'http://support.microsoft.com/kb/932463'] def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Retrieves information from the MountPoints2 registry key. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - for subkey in key.GetSubkeys(): + for subkey in registry_key.GetSubkeys(): name = subkey.name if not name: continue - text_dict = {} - text_dict[u'Volume'] = name + values_dict = {} + values_dict[u'Volume'] = name # Get the label if it exists. - label_value = subkey.GetValue(u'_LabelFromReg') + label_value = subkey.GetValueByName(u'_LabelFromReg') if label_value: - text_dict[u'Label'] = label_value.data + values_dict[u'Label'] = label_value.data if name.startswith(u'{'): - text_dict[u'Type'] = u'Volume' + values_dict[u'Type'] = u'Volume' elif name.startswith(u'#'): # The format is: ##Server_Name#Share_Name. - text_dict[u'Type'] = u'Remote Drive' + values_dict[u'Type'] = u'Remote Drive' server_name, _, share_name = name[2:].partition(u'#') - text_dict[u'Remote_Server'] = server_name - text_dict[u'Share_Name'] = u'\\{0:s}'.format( + values_dict[u'Remote_Server'] = server_name + values_dict[u'Share_Name'] = u'\\{0:s}'.format( share_name.replace(u'#', u'\\')) else: - text_dict[u'Type'] = u'Drive' + values_dict[u'Type'] = u'Drive' event_object = windows_events.WindowsRegistryEvent( - subkey.last_written_timestamp, key.path, text_dict, + subkey.last_written_time, registry_key.path, values_dict, offset=subkey.offset, registry_file_type=registry_file_type, urls=self.URLS) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/mrulist.py b/plaso/parsers/winreg_plugins/mrulist.py index 82957910b4..e4daa6c084 100644 --- a/plaso/parsers/winreg_plugins/mrulist.py +++ b/plaso/parsers/winreg_plugins/mrulist.py @@ -18,6 +18,8 @@ class BaseMRUListPlugin(interface.WindowsRegistryPlugin): _MRULIST_STRUCT = construct.Range(1, 500, construct.ULInt16(u'entry_letter')) + _SOURCE_APPEND = u': MRU List' + @abc.abstractmethod def _ParseMRUListEntryValue( self, parser_mediator, key, entry_index, entry_letter, **kwargs): @@ -25,7 +27,7 @@ def _ParseMRUListEntryValue( Args: parser_mediator: A parser context object (instance of ParserContext). - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUList value. entry_index: integer value representing the MRUList entry index. entry_letter: character value representing the entry. @@ -38,14 +40,14 @@ def _ParseMRUListValue(self, key): """Parses the MRUList value in a given Registry key. Args: - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUList value. Returns: A MRUList value generator, which returns the MRU index number and entry value. """ - mru_list_value = key.GetValue(u'MRUList') + mru_list_value = key.GetValueByName(u'MRUList') # The key exists but does not contain a value named "MRUList". if not mru_list_value: @@ -66,12 +68,12 @@ def _ParseMRUListKey( Args: parser_mediator: A parser context object (instance of ParserContext). - key: the Registry key (instance of winreg.WinRegKey). + key: the Registry key (instance of dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. codepage: Optional extended ASCII string codepage. The default is cp1252. """ - text_dict = {} + values_dict = {} for entry_index, entry_letter in self._ParseMRUListValue(key): # TODO: detect if list ends prematurely. # MRU lists are terminated with \0 (0x0000). @@ -86,12 +88,12 @@ def _ParseMRUListKey( value_text = u'Index: {0:d} [MRU Value {1:s}]'.format( entry_index + 1, entry_letter) - text_dict[value_text] = value_string + values_dict[value_text] = value_string event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, + key.last_written_time, key.path, values_dict, offset=key.offset, registry_file_type=registry_file_type, - source_append=u': MRU List') + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) @@ -111,7 +113,7 @@ def _ParseMRUListEntryValue( Args: parser_mediator: A parser context object (instance of ParserContext). - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUList value. entry_index: integer value representing the MRUList entry index. entry_letter: character value representing the entry. @@ -121,7 +123,7 @@ def _ParseMRUListEntryValue( """ value_string = u'' - value = key.GetValue(u'{0:s}'.format(entry_letter)) + value = key.GetValueByName(u'{0:s}'.format(entry_letter)) if value is None: logging.debug( u'[{0:s}] Missing MRUList entry value: {1:s} in key: {2:s}.'.format( @@ -148,21 +150,21 @@ def _ParseMRUListEntryValue( return value_string def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key=None, codepage=u'cp1252', + registry_file_type=None, **kwargs): """Extracts event objects from a MRU list. Args: parser_mediator: A parser context object (instance of ParserContext). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. codepage: Optional extended ASCII string codepage. The default is cp1252. """ self._ParseMRUListKey( - parser_mediator, key, registry_file_type=registry_file_type, - codepage=codepage) + parser_mediator, registry_key, codepage=codepage, + registry_file_type=registry_file_type) def Process( self, parser_mediator, key=None, registry_file_type=None, @@ -171,7 +173,7 @@ def Process( Args: parser_mediator: A parser context object (instance of ParserContext). - key: Optional Registry key (instance of winreg.WinRegKey). + key: Optional Registry key (instance of dfwinreg.WinRegistryKey). The default is None. registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. @@ -206,7 +208,7 @@ def _ParseMRUListEntryValue( Args: parser_mediator: A parser context object (instance of ParserContext). - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUList value. entry_index: integer value representing the MRUList entry index. entry_letter: character value representing the entry. @@ -217,7 +219,7 @@ def _ParseMRUListEntryValue( """ value_string = u'' - value = key.GetValue(u'{0:s}'.format(entry_letter)) + value = key.GetValueByName(u'{0:s}'.format(entry_letter)) if value is None: logging.debug( u'[{0:s}] Missing MRUList entry value: {1:s} in key: {2:s}.'.format( @@ -239,21 +241,21 @@ def _ParseMRUListEntryValue( return value_string def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key=None, codepage=u'cp1252', + registry_file_type=None, **kwargs): """Extract event objects from a Registry key containing a MRUList value. Args: parser_mediator: A parser context object (instance of ParserContext). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. codepage: Optional extended ASCII string codepage. The default is cp1252. """ self._ParseMRUListKey( - parser_mediator, key, registry_file_type=registry_file_type, - codepage=codepage) + parser_mediator, registry_key, codepage=codepage, + registry_file_type=registry_file_type) winreg.WinRegistryParser.RegisterPlugins([ diff --git a/plaso/parsers/winreg_plugins/mrulistex.py b/plaso/parsers/winreg_plugins/mrulistex.py index e0b16802f1..43dc8d0f5b 100644 --- a/plaso/parsers/winreg_plugins/mrulistex.py +++ b/plaso/parsers/winreg_plugins/mrulistex.py @@ -19,6 +19,8 @@ class BaseMRUListExPlugin(interface.WindowsRegistryPlugin): _MRULISTEX_STRUCT = construct.Range( 1, 500, construct.ULInt32(u'entry_number')) + _SOURCE_APPEND = u': MRUListEx' + @abc.abstractmethod def _ParseMRUListExEntryValue( self, parser_mediator, key, entry_index, entry_number, **kwargs): @@ -26,7 +28,7 @@ def _ParseMRUListExEntryValue( Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUListEx value. entry_index: integer value representing the MRUListEx entry index. entry_number: integer value representing the entry number. @@ -39,14 +41,14 @@ def _ParseMRUListExValue(self, key): """Parses the MRUListEx value in a given Registry key. Args: - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUListEx value. Returns: A MRUListEx value generator, which returns the MRU index number and entry value. """ - mru_list_value = key.GetValue(u'MRUListEx') + mru_list_value = key.GetValueByName(u'MRUListEx') # The key exists but does not contain a value named "MRUListEx". if not mru_list_value: @@ -67,12 +69,12 @@ def _ParseMRUListExKey( Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey). + key: the Registry key (instance of dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. codepage: Optional extended ASCII string codepage. The default is cp1252. """ - text_dict = {} + values_dict = {} for entry_index, entry_number in self._ParseMRUListExValue(key): # TODO: detect if list ends prematurely. # MRU lists are terminated with 0xffffffff (-1). @@ -85,12 +87,12 @@ def _ParseMRUListExKey( value_text = u'Index: {0:d} [MRU Value {1:d}]'.format( entry_index + 1, entry_number) - text_dict[value_text] = value_string + values_dict[value_text] = value_string event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, + key.last_written_time, key.path, values_dict, offset=key.offset, registry_file_type=registry_file_type, - source_append=u': MRUListEx') + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) @@ -118,7 +120,7 @@ def _ParseMRUListExEntryValue( Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUListEx value. entry_index: integer value representing the MRUListEx entry index. entry_number: integer value representing the entry number. @@ -128,7 +130,7 @@ def _ParseMRUListExEntryValue( """ value_string = u'' - value = key.GetValue(u'{0:d}'.format(entry_number)) + value = key.GetValueByName(u'{0:d}'.format(entry_number)) if value is None: logging.debug( u'[{0:s}] Missing MRUListEx entry value: {1:d} in key: {2:s}.'.format( @@ -155,28 +157,28 @@ def _ParseMRUListExEntryValue( return value_string def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, codepage=u'cp1252', + registry_file_type=None, **kwargs): """Extract event objects from a Registry key containing a MRUListEx value. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). + codepage: Optional extended ASCII string codepage. The default is cp1252. registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ self._ParseMRUListExKey( - parser_mediator, key, registry_file_type=registry_file_type, - codepage=codepage) + parser_mediator, registry_key, codepage=codepage, + registry_file_type=registry_file_type) def Process(self, parser_mediator, key=None, codepage=u'cp1252', **kwargs): """Determine if we can process this Registry key or not. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Windows Registry key (instance of WinRegKey). + key: Optional Windows Registry key (instance of dfwinreg.WinRegistryKey). The default is None. codepage: Optional extended ASCII string codepage. The default is cp1252. """ @@ -210,7 +212,7 @@ def _ParseMRUListExEntryValue( Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUListEx value. entry_index: integer value representing the MRUListEx entry index. entry_number: integer value representing the entry number. @@ -221,7 +223,7 @@ def _ParseMRUListExEntryValue( """ value_string = u'' - value = key.GetValue(u'{0:d}'.format(entry_number)) + value = key.GetValueByName(u'{0:d}'.format(entry_number)) if value is None: logging.debug( u'[{0:s}] Missing MRUListEx entry value: {1:d} in key: {2:s}.'.format( @@ -243,30 +245,30 @@ def _ParseMRUListExEntryValue( return value_string def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, codepage=u'cp1252', + registry_file_type=None, **kwargs): """Extract event objects from a Registry key containing a MRUListEx value. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. codepage: Optional extended ASCII string codepage. The default is cp1252. """ - if key.name != u'OpenSavePidlMRU': + if registry_key.name != u'OpenSavePidlMRU': self._ParseMRUListExKey( - parser_mediator, key, registry_file_type=registry_file_type, - codepage=codepage) + parser_mediator, registry_key, codepage=codepage, + registry_file_type=registry_file_type) - if key.name == u'OpenSavePidlMRU': + if registry_key.name == u'OpenSavePidlMRU': # For the OpenSavePidlMRU MRUListEx we also need to parse its subkeys # since the Registry key path does not support wildcards yet. - for subkey in key.GetSubkeys(): + for subkey in registry_key.GetSubkeys(): self._ParseMRUListExKey( - parser_mediator, subkey, registry_file_type=registry_file_type, - codepage=codepage) + parser_mediator, subkey, codepage=codepage, + registry_file_type=registry_file_type) class MRUListExStringAndShellItemPlugin(BaseMRUListExPlugin): @@ -292,7 +294,7 @@ def _ParseMRUListExEntryValue( Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUListEx value. entry_index: integer value representing the MRUListEx entry index. entry_number: integer value representing the entry number. @@ -303,7 +305,7 @@ def _ParseMRUListExEntryValue( """ value_string = u'' - value = key.GetValue(u'{0:d}'.format(entry_number)) + value = key.GetValueByName(u'{0:d}'.format(entry_number)) if value is None: logging.debug( u'[{0:s}] Missing MRUListEx entry value: {1:d} in key: {2:s}.'.format( @@ -347,29 +349,29 @@ def _ParseMRUListExEntryValue( return value_string def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, codepage=u'cp1252', + registry_file_type=None, **kwargs): """Extract event objects from a Registry key containing a MRUListEx value. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. codepage: Optional extended ASCII string codepage. The default is cp1252. """ self._ParseMRUListExKey( - parser_mediator, key, registry_file_type=registry_file_type, - codepage=codepage) + parser_mediator, registry_key, codepage=codepage, + registry_file_type=registry_file_type) - if key.name == u'RecentDocs': + if registry_key.name == u'RecentDocs': # For the RecentDocs MRUListEx we also need to parse its subkeys # since the Registry key path does not support wildcards yet. - for subkey in key.GetSubkeys(): + for subkey in registry_key.GetSubkeys(): self._ParseMRUListExKey( - parser_mediator, subkey, registry_file_type=registry_file_type, - codepage=codepage) + parser_mediator, subkey, codepage=codepage, + registry_file_type=registry_file_type) class MRUListExStringAndShellItemListPlugin(BaseMRUListExPlugin): @@ -396,7 +398,7 @@ def _ParseMRUListExEntryValue( Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: the Registry key (instance of winreg.WinRegKey) that contains + key: the Registry key (instance of dfwinreg.WinRegistryKey) that contains the MRUListEx value. entry_index: integer value representing the MRUListEx entry index. entry_number: integer value representing the entry number. @@ -407,7 +409,7 @@ def _ParseMRUListExEntryValue( """ value_string = u'' - value = key.GetValue(u'{0:d}'.format(entry_number)) + value = key.GetValueByName(u'{0:d}'.format(entry_number)) if value is None: logging.debug( u'[{0:s}] Missing MRUListEx entry value: {1:d} in key: {2:s}.'.format( @@ -451,20 +453,20 @@ def _ParseMRUListExEntryValue( return value_string def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, codepage=u'cp1252', + registry_file_type=None, **kwargs): """Extract event objects from a Registry key containing a MRUListEx value. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. codepage: Optional extended ASCII string codepage. The default is cp1252. """ self._ParseMRUListExKey( - parser_mediator, key, registry_file_type=registry_file_type, + parser_mediator, registry_key, registry_file_type=registry_file_type, codepage=codepage) diff --git a/plaso/parsers/winreg_plugins/msie_zones.py b/plaso/parsers/winreg_plugins/msie_zones.py index fb83127885..6101d90946 100644 --- a/plaso/parsers/winreg_plugins/msie_zones.py +++ b/plaso/parsers/winreg_plugins/msie_zones.py @@ -25,7 +25,7 @@ class MsieZoneSettingsPlugin(interface.WindowsRegistryPlugin): URLS = [u'http://support.microsoft.com/kb/182569'] - ZONE_NAMES = { + _ZONE_NAMES = { u'0': u'0 (My Computer)', u'1': u'1 (Local Intranet Zone)', u'2': u'2 (Trusted sites Zone)', @@ -34,26 +34,26 @@ class MsieZoneSettingsPlugin(interface.WindowsRegistryPlugin): u'5': u'5 (Custom)' } - KNOWN_PERMISSIONS_VALUE_NAMES = [ + _KNOWN_PERMISSIONS_VALUE_NAMES = [ u'1001', u'1004', u'1200', u'1201', u'1400', u'1402', u'1405', u'1406', u'1407', u'1601', u'1604', u'1606', u'1607', u'1608', u'1609', u'1800', u'1802', u'1803', u'1804', u'1809', u'1A04', u'2000', u'2001', u'2004', u'2100', u'2101', u'2102', u'2200', u'2201', u'2300'] - CONTROL_VALUES_PERMISSIONS = { + _CONTROL_VALUES_PERMISSIONS = { 0x00000000: u'0 (Allow)', 0x00000001: u'1 (Prompt User)', 0x00000003: u'3 (Not Allowed)', 0x00010000: u'0x00010000 (Administrator approved)' } - CONTROL_VALUES_SAFETY = { + _CONTROL_VALUES_SAFETY = { 0x00010000: u'0x00010000 (High safety)', 0x00020000: u'0x00020000 (Medium safety)', 0x00030000: u'0x00030000 (Low safety)' } - CONTROL_VALUES_1A00 = { + _CONTROL_VALUES_1A00 = { 0x00000000: ( u'0x00000000 (Automatic logon with current user name and password)'), 0x00010000: u'0x00010000 (Prompt for user name and password)', @@ -61,7 +61,7 @@ class MsieZoneSettingsPlugin(interface.WindowsRegistryPlugin): 0x00030000: u'0x00030000 (Anonymous logon)' } - CONTROL_VALUES_1C00 = { + _CONTROL_VALUES_1C00 = { 0x00000000: u'0x00000000 (Disable Java)', 0x00010000: u'0x00010000 (High safety)', 0x00020000: u'0x00020000 (Medium safety)', @@ -69,7 +69,7 @@ class MsieZoneSettingsPlugin(interface.WindowsRegistryPlugin): 0x00800000: u'0x00800000 (Custom)' } - FEATURE_CONTROLS = { + _FEATURE_CONTROLS = { u'1200': u'Run ActiveX controls and plug-ins', u'1400': u'Active scripting', u'1001': u'Download signed ActiveX controls', @@ -144,8 +144,7 @@ class MsieZoneSettingsPlugin(interface.WindowsRegistryPlugin): } def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Retrieves information of the Internet Settings Zones values. The MSIE Feature controls are stored in the Zone specific subkeys in: @@ -154,18 +153,15 @@ def GetEntries( Args: parser_mediator: A parser mediator object (instance of ParserMediator). - file_entry: optional file entry object (instance of dfvfs.FileEntry). - The default is None. - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - text_dict = {} + values_dict = {} - if key.number_of_values > 0: - for value in key.GetValues(): + if registry_key.number_of_values > 0: + for value in registry_key.GetValues(): if not value.name: value_name = u'(default)' else: @@ -183,26 +179,28 @@ def GetEntries( else: value_string = u'[{0:s}]'.format(value.data_type_string) - text_dict[value_name] = value_string + values_dict[value_name] = value_string # Generate at least one event object for the key. event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, urls=self.URLS) + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + urls=self.URLS) parser_mediator.ProduceEvent(event_object) - if key.number_of_subkeys == 0: - error_string = u'Key: {0:s} missing subkeys.'.format(key.path) + if registry_key.number_of_subkeys == 0: + error_string = u'Key: {0:s} missing subkeys.'.format(registry_key.path) parser_mediator.ProduceParseError(error_string) return - for zone_key in key.GetSubkeys(): + for zone_key in registry_key.GetSubkeys(): # TODO: these values are stored in the Description value of the # zone key. This solution will break on zone values that are larger # than 5. - path = u'{0:s}\\{1:s}'.format(key.path, self.ZONE_NAMES[zone_key.name]) + path = u'{0:s}\\{1:s}'.format( + registry_key.path, self._ZONE_NAMES[zone_key.name]) - text_dict = {} + values_dict = {} # TODO: this plugin currently just dumps the values and does not # distinguish between what is a feature control or not. @@ -215,15 +213,15 @@ def GetEntries( value_string = value.data elif value.DataIsInteger(): - if value.name in self.KNOWN_PERMISSIONS_VALUE_NAMES: - value_string = self.CONTROL_VALUES_PERMISSIONS.get( + if value.name in self._KNOWN_PERMISSIONS_VALUE_NAMES: + value_string = self._CONTROL_VALUES_PERMISSIONS.get( value.data, u'UNKNOWN') elif value.name == u'1A00': - value_string = self.CONTROL_VALUES_1A00.get(value.data, u'UNKNOWN') + value_string = self._CONTROL_VALUES_1A00.get(value.data, u'UNKNOWN') elif value.name == u'1C00': - value_string = self.CONTROL_VALUES_1C00.get(value.data, u'UNKNOWN') + value_string = self._CONTROL_VALUES_1C00.get(value.data, u'UNKNOWN') elif value.name == u'1E05': - value_string = self.CONTROL_VALUES_SAFETY.get( + value_string = self._CONTROL_VALUES_SAFETY.get( value.data, u'UNKNOWN') else: value_string = u'{0:d}'.format(value.data) @@ -232,9 +230,9 @@ def GetEntries( value_string = u'[{0:s}]'.format(value.data_type_string) if len(value.name) == 4 and value.name != u'Icon': - value_description = self.FEATURE_CONTROLS.get(value.name, u'UNKNOWN') + value_description = self._FEATURE_CONTROLS.get(value.name, u'UNKNOWN') else: - value_description = self.FEATURE_CONTROLS.get(value.name, u'') + value_description = self._FEATURE_CONTROLS.get(value.name, u'') if value_description: feature_control = u'[{0:s}] {1:s}'.format( @@ -242,10 +240,10 @@ def GetEntries( else: feature_control = u'[{0:s}]'.format(value.name) - text_dict[feature_control] = value_string + values_dict[feature_control] = value_string event_object = windows_events.WindowsRegistryEvent( - zone_key.last_written_timestamp, path, text_dict, + zone_key.last_written_time, path, values_dict, offset=zone_key.offset, registry_file_type=registry_file_type, urls=self.URLS) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/officemru.py b/plaso/parsers/winreg_plugins/officemru.py index 7521222834..a883e33221 100644 --- a/plaso/parsers/winreg_plugins/officemru.py +++ b/plaso/parsers/winreg_plugins/officemru.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- """This file contains a parser for MS Office MRUs for Plaso.""" -import logging import re from plaso.events import windows_events -from plaso.lib import timelib from plaso.parsers import winreg from plaso.parsers.winreg_plugins import interface @@ -40,30 +38,32 @@ class OfficeMRUPlugin(interface.WindowsRegistryPlugin): # [F00000000][T%FILETIME%][O00000000]*%FILENAME% _RE_VALUE_DATA = re.compile(r'\[F00000000\]\[T([0-9A-Z]+)\].*\*[\\]?(.*)') + _SOURCE_APPEND = u': Microsoft Office MRU' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect Values under Office 2010 MRUs and return events for each one. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ # TODO: Test other Office versions to make sure this plugin is applicable. - for value in key.GetValues(): + mru_values_dict = {} + for registry_value in registry_key.GetValues(): # Ignore any value not in the form: 'Item [0-9]+'. - if not value.name or not self._RE_VALUE_NAME.search(value.name): + if not registry_value.name or not self._RE_VALUE_NAME.search( + registry_value.name): continue # Ignore any value that is empty or that does not contain a string. - if not value.data or not value.DataIsString(): + if not registry_value.data or not registry_value.DataIsString(): continue - values = self._RE_VALUE_DATA.findall(value.data) + values = self._RE_VALUE_DATA.findall(registry_value.data) # Values will contain a list containing a tuple containing 2 values. if len(values) != 1 or len(values[0]) != 2: @@ -72,26 +72,26 @@ def GetEntries( try: filetime = int(values[0][0], 16) except ValueError: - logging.warning(u'Unable to convert filetime string to an integer.') - filetime = 0 - - # TODO: why this behavior? Only the first Item is stored with its - # timestamp. Shouldn't this be: Store all the Item # values with - # their timestamp and store the entire MRU as one event with the - # registry key last written time? - if value.name == u'Item 1': - timestamp = timelib.Timestamp.FromFiletime(filetime) - else: - timestamp = 0 + parser_mediator.ProduceParseError(( + u'unable to convert filetime string to an integer for ' + u'value: {0:s}.').format(registry_value.name)) + continue - text_dict = {} - text_dict[value.name] = value.data + mru_values_dict[registry_value.name] = registry_value.data + # TODO: change into a separate event object. + values_dict = {registry_value.name: registry_value.data} event_object = windows_events.WindowsRegistryEvent( - timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': Microsoft Office MRU') + filetime, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) + event_object = windows_events.WindowsRegistryEvent( + registry_key.last_written_time, registry_key.path, mru_values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) + parser_mediator.ProduceEvent(event_object) + winreg.WinRegistryParser.RegisterPlugin(OfficeMRUPlugin) diff --git a/plaso/parsers/winreg_plugins/outlook.py b/plaso/parsers/winreg_plugins/outlook.py index 82257aef5d..48b34e6d98 100644 --- a/plaso/parsers/winreg_plugins/outlook.py +++ b/plaso/parsers/winreg_plugins/outlook.py @@ -33,46 +33,39 @@ class OutlookSearchMRUPlugin(interface.WindowsRegistryPlugin): REG_TYPE = u'NTUSER' + _SOURCE_APPEND = u': PST Paths' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect the values under Outlook and return event for each one. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - value_index = 0 - for value in key.GetValues(): + values_dict = {} + for registry_value in registry_key.GetValues(): # Ignore the default value. - if not value.name: + if not registry_value.name: continue # Ignore any value that is empty or that does not contain an integer. - if not value.data or not value.DataIsInteger(): + if not registry_value.data or not registry_value.DataIsInteger(): continue # TODO: change this 32-bit integer into something meaningful, for now # the value name is the most interesting part. - text_dict = {} - text_dict[value.name] = u'0x{0:08x}'.format(value.data) - - if value_index == 0: - timestamp = key.last_written_timestamp - else: - timestamp = 0 - - event_object = windows_events.WindowsRegistryEvent( - timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': PST Paths') - parser_mediator.ProduceEvent(event_object) - - value_index += 1 + values_dict[registry_value.name] = u'0x{0:08x}'.format( + registry_value.data) + + event_object = windows_events.WindowsRegistryEvent( + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) + parser_mediator.ProduceEvent(event_object) winreg.WinRegistryParser.RegisterPlugin(OutlookSearchMRUPlugin) diff --git a/plaso/parsers/winreg_plugins/run.py b/plaso/parsers/winreg_plugins/run.py index 4fe2522280..1fe8355140 100644 --- a/plaso/parsers/winreg_plugins/run.py +++ b/plaso/parsers/winreg_plugins/run.py @@ -20,20 +20,20 @@ class RunUserPlugin(interface.WindowsRegistryPlugin): URLS = [u'http://msdn.microsoft.com/en-us/library/aa376977(v=vs.85).aspx'] + _SOURCE_APPEND = u': Run Key' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect the Values under the Run Key and return an event for each one. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - for value in key.GetValues(): + for value in registry_key.GetValues(): # Ignore the default value. if not value.name: continue @@ -42,13 +42,13 @@ def GetEntries( if not value.data or not value.DataIsString(): continue - text_dict = {} - text_dict[value.name] = value.data + values_dict = {} + values_dict[value.name] = value.data event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, offset=key.offset, - urls=self.URLS, registry_file_type=registry_file_type, - source_append=': Run Key') + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND, urls=self.URLS) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/sam_users.py b/plaso/parsers/winreg_plugins/sam_users.py index d36a8ed2a2..744a45f09b 100644 --- a/plaso/parsers/winreg_plugins/sam_users.py +++ b/plaso/parsers/winreg_plugins/sam_users.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- -import construct import logging + +import construct + from plaso.events import windows_events from plaso.lib import binary from plaso.lib import eventdata -from plaso.lib import timelib from plaso.parsers import winreg from plaso.parsers.winreg_plugins import interface @@ -32,145 +33,146 @@ class UsersPlugin(interface.WindowsRegistryPlugin): construct.ULInt16(u'rid'), construct.Padding(16), construct.ULInt8(u'login_count')) + V_VALUE_HEADER = construct.Struct( u'v_header', construct.Array(11, construct.ULInt32(u'values'))) + V_VALUE_HEADER_SIZE = 0xCC + _SOURCE_APPEND = u'User Account Information' + + def _ParseFValue(self, key): + """Parses F value and returns parsed F data construct object. + + Args: + key: Registry key (instance of dfwinreg.WinRegistryKey). + + Returns: + f_data: Construct parsed F value containing rid, login count, + and timestamp information. + """ + f_value = key.GetValueByName(u'F') + if not f_value: + logging.error(u'Unable to locate F Value in key.') + return + try: + f_data = self.F_VALUE_STRUCT.parse(f_value.data) + except construct.FieldError as exception: + logging.error( + u'Unable to extract F value data: {:s}'.format(exception)) + return + return f_data + + def _ParseVValue(self, key): + """Parses V value and returns name, fullname, and comments data. + + Args: + key: Registry key (instance of dfwinreg.WinRegistryKey). + + Returns: + name: Name data parsed with name start and length values. + fullname: Fullname data parsed with fullname start and length values. + comments: Comments data parsed with comments start and length values. + """ + v_value = key.GetValueByName(u'V') + if not v_value: + logging.error(u'Unable to locate V Value in key.') + return + try: + structure = self.V_VALUE_HEADER.parse(v_value.data) + except construct.FieldError as exception: + logging.error( + u'Unable to extract V value header data with error: {0:s}'.format( + exception)) + return + name_offset = structure.values()[0][3] + self.V_VALUE_HEADER_SIZE + full_name_offset = structure.values()[0][6] + self.V_VALUE_HEADER_SIZE + comments_offset = structure.values()[0][9] + self.V_VALUE_HEADER_SIZE + name_raw = v_value.data[ + name_offset:name_offset + structure.values()[0][4]] + full_name_raw = v_value.data[ + full_name_offset:full_name_offset + structure.values()[0][7]] + comments_raw = v_value.data[ + comments_offset:comments_offset + structure.values()[0][10]] + name = binary.ReadUtf16(name_raw) + full_name = binary.ReadUtf16(full_name_raw) + comments = binary.ReadUtf16(comments_raw) + return name, full_name, comments + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect data from Users and Names and produce event objects. Args: parser_mediator: A parser context object (instance of ParserContext). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - name_dict = {} - - name_key = key.GetSubkey(u'Names') + name_key = registry_key.GetSubkeyByName(u'Names') if not name_key: parser_mediator.ProduceParseError(u'Unable to locate Names key.') return - values = [(v.name, v.last_written_timestamp) for v in name_key.GetSubkeys()] + values = [(v.name, v.last_written_time) for v in name_key.GetSubkeys()] + name_dict = dict(values) - for subkey in key.GetSubkeys(): - text_dict = {} + for subkey in registry_key.GetSubkeys(): if subkey.name == u'Names': continue - text_dict[u'user_guid'] = subkey.name + parsed_v_value = self._ParseVValue(subkey) if not parsed_v_value: parser_mediator.ProduceParseError( u'Unable to parse SAM key: {0:s} V value.'.format(subkey)) return + username = parsed_v_value[0] full_name = parsed_v_value[1] comments = parsed_v_value[2] + + values_dict = {u'user_guid': subkey.name} + if username: - text_dict[u'username'] = username + values_dict[u'username'] = username if full_name: - text_dict[u'full_name'] = full_name + values_dict[u'full_name'] = full_name if comments: - text_dict[u'comments'] = comments + values_dict[u'comments'] = comments if name_dict: - account_create_time = name_dict.get(text_dict.get(u'username'), 0) + account_create_time = name_dict.get(username, 0) else: account_create_time = 0 f_data = self._ParseFValue(subkey) - last_login_time = timelib.Timestamp.FromFiletime(f_data.last_login) - password_reset_time = timelib.Timestamp.FromFiletime( - f_data.password_reset) - text_dict[u'account_rid'] = f_data.rid - text_dict[u'login_count'] = f_data.login_count + values_dict[u'account_rid'] = f_data.rid + values_dict[u'login_count'] = f_data.login_count if account_create_time > 0: event_object = windows_events.WindowsRegistryEvent( - account_create_time, key.path, text_dict, + account_create_time, registry_key.path, values_dict, usage=eventdata.EventTimestamp.ACCOUNT_CREATED, - offset=key.offset, registry_file_type=registry_file_type, - source_append=u'User Account Information') + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) - if last_login_time > 0: + if f_data.last_login > 0: event_object = windows_events.WindowsRegistryEvent( - last_login_time, key.path, text_dict, + f_data.last_login, registry_key.path, values_dict, usage=eventdata.EventTimestamp.LAST_LOGIN_TIME, - offset=key.offset, - registry_file_type=registry_file_type, - source_append=u'User Account Information') + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) - if password_reset_time > 0: + if f_data.password_reset > 0: event_object = windows_events.WindowsRegistryEvent( - password_reset_time, key.path, text_dict, + f_data.password_reset, registry_key.path, values_dict, usage=eventdata.EventTimestamp.LAST_PASSWORD_RESET, - offset=key.offset, registry_file_type=registry_file_type, - source_append=u'User Account Information') + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) - def _ParseVValue(self, key): - """Parses V value and returns name, fullname, and comments data. - - Args: - key: Registry key (instance of winreg.WinRegKey). - - Returns: - name: Name data parsed with name start and length values. - fullname: Fullname data parsed with fullname start and length values. - comments: Comments data parsed with comments start and length values. - """ - v_value = key.GetValue(u'V') - if not v_value: - logging.error(u'Unable to locate V Value in key.') - return - try: - structure = self.V_VALUE_HEADER.parse(v_value.data) - except construct.FieldError as exception: - logging.error( - u'Unable to extract V value header data: {:s}'.format(exception)) - return - name_offset = structure.values()[0][3] + self.V_VALUE_HEADER_SIZE - full_name_offset = structure.values()[0][6] + self.V_VALUE_HEADER_SIZE - comments_offset = structure.values()[0][9] + self.V_VALUE_HEADER_SIZE - name_raw = v_value.data[ - name_offset:name_offset + structure.values()[0][4]] - full_name_raw = v_value.data[ - full_name_offset:full_name_offset + structure.values()[0][7]] - comments_raw = v_value.data[ - comments_offset:comments_offset + structure.values()[0][10]] - name = binary.ReadUtf16(name_raw) - full_name = binary.ReadUtf16(full_name_raw) - comments = binary.ReadUtf16(comments_raw) - return name, full_name, comments - - def _ParseFValue(self, key): - """Parses F value and returns parsed F data construct object. - - Args: - key: Registry key (instance of winreg.WinRegKey). - - Returns: - f_data: Construct parsed F value containing rid, login count, - and timestamp information. - """ - f_value = key.GetValue(u'F') - if not f_value: - logging.error(u'Unable to locate F Value in key.') - return - try: - f_data = self.F_VALUE_STRUCT.parse(f_value.data) - except construct.FieldError as exception: - logging.error( - u'Unable to extract F value data: {:s}'.format(exception)) - return - return f_data - winreg.WinRegistryParser.RegisterPlugin(UsersPlugin) diff --git a/plaso/parsers/winreg_plugins/services.py b/plaso/parsers/winreg_plugins/services.py index 8701a73631..95ddb8f270 100644 --- a/plaso/parsers/winreg_plugins/services.py +++ b/plaso/parsers/winreg_plugins/services.py @@ -23,55 +23,54 @@ def GetServiceDll(self, key): the Registry. Args: - key: A Windows Registry key (instance of WinRegKey). + key: A Windows Registry key (instance of dfwinreg.WinRegistryKey). """ - parameters_key = key.GetSubkey(u'Parameters') + parameters_key = key.GetSubkeyByName(u'Parameters') if parameters_key: - service_dll = parameters_key.GetValue(u'ServiceDll') + service_dll = parameters_key.GetValueByName(u'ServiceDll') if service_dll: return service_dll.data else: return None def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Create one event for each subkey under Services that has Type and Start. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - text_dict = {} + values_dict = {} - service_type_value = key.GetValue(u'Type') - service_start_value = key.GetValue(u'Start') + service_type_value = registry_key.GetValueByName(u'Type') + service_start_value = registry_key.GetValueByName(u'Start') # Grab the ServiceDLL value if it exists. if service_type_value and service_start_value: - service_dll = self.GetServiceDll(key) + service_dll = self.GetServiceDll(registry_key) if service_dll: - text_dict[u'ServiceDll'] = service_dll + values_dict[u'ServiceDll'] = service_dll # Gather all the other string and integer values and insert as they are. - for value in key.GetValues(): + for value in registry_key.GetValues(): if not value.name: continue - if value.name not in text_dict: + if value.name not in values_dict: if value.DataIsString() or value.DataIsInteger(): - text_dict[value.name] = value.data + values_dict[value.name] = value.data elif value.DataIsMultiString(): - text_dict[value.name] = u', '.join(value.data) + values_dict[value.name] = u', '.join(value.data) # Create a specific service event, so that we can recognize and expand # certain values when we're outputting the event. event_object = windows_events.WindowsRegistryServiceEvent( - key.last_written_timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, urls=self.URLS) + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + urls=self.URLS) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/shutdown.py b/plaso/parsers/winreg_plugins/shutdown.py index 70d89f6dde..95ccd756f0 100644 --- a/plaso/parsers/winreg_plugins/shutdown.py +++ b/plaso/parsers/winreg_plugins/shutdown.py @@ -4,7 +4,6 @@ from plaso.events import windows_events from plaso.lib import eventdata -from plaso.lib import timelib from plaso.parsers import winreg from plaso.parsers.winreg_plugins import interface @@ -20,26 +19,26 @@ class ShutdownPlugin(interface.WindowsRegistryPlugin): REG_KEYS = [u'\\{current_control_set}\\Control\\Windows'] REG_TYPE = u'SYSTEM' + FILETIME_STRUCT = construct.ULInt64(u'filetime_timestamp') + _SOURCE_APPEND = u'Shutdown Entry' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect ShutdownTime value under Windows and produce an event object. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - shutdown_value = key.GetValue(u'ShutdownTime') + shutdown_value = registry_key.GetValueByName(u'ShutdownTime') if not shutdown_value: return - text_dict = {} - text_dict[u'Description'] = shutdown_value.name + try: filetime = self.FILETIME_STRUCT.parse(shutdown_value.data) except construct.FieldError as exception: @@ -47,13 +46,14 @@ def GetEntries( u'Unable to extract shutdown timestamp with error: {0:s}'.format( exception)) return - timestamp = timelib.Timestamp.FromFiletime(filetime) + + values_dict = {u'Description': shutdown_value.name} event_object = windows_events.WindowsRegistryEvent( - timestamp, key.path, text_dict, - usage=eventdata.EventTimestamp.LAST_SHUTDOWN, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u'Shutdown Entry') + filetime, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + usage=eventdata.EventTimestamp.LAST_SHUTDOWN, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/task_scheduler.py b/plaso/parsers/winreg_plugins/task_scheduler.py index 3be2fecc6d..87dfc11050 100644 --- a/plaso/parsers/winreg_plugins/task_scheduler.py +++ b/plaso/parsers/winreg_plugins/task_scheduler.py @@ -57,13 +57,14 @@ def _GetIdValue(self, key): """Retrieves the Id value from Task Cache Tree key. Args: - key: A Windows Registry key (instance of WinRegKey). + key: A Windows Registry key (instance of dfwinreg.WinRegistryKey). Yields: - A tuple containing a Windows Registry Key (instance of WinRegKey) and - a Windows Registry value (instance of WinRegValue). + A tuple containing a Windows Registry Key (instance of + dfwinreg.WinRegistryKey) and a Windows Registry value (instance of + dfwinreg.WinRegistryValue). """ - id_value = key.GetValue(u'Id') + id_value = key.GetValueByName(u'Id') if id_value: yield key, id_value @@ -72,20 +73,18 @@ def _GetIdValue(self, key): yield value_key, id_value def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Parses a Task Cache Registry key. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - tasks_key = key.GetSubkey(u'Tasks') - tree_key = key.GetSubkey(u'Tree') + tasks_key = registry_key.GetSubkeyByName(u'Tasks') + tree_key = registry_key.GetSubkeyByName(u'Tree') if not tasks_key or not tree_key: parser_mediator.ProduceParseError( @@ -103,7 +102,7 @@ def GetEntries( task_guids[id_value.data] = value_key.name for sub_key in tasks_key.GetSubkeys(): - dynamic_info_value = sub_key.GetValue(u'DynamicInfo') + dynamic_info_value = sub_key.GetValueByName(u'DynamicInfo') if not dynamic_info_value: continue @@ -117,12 +116,12 @@ def GetEntries( name = task_guids.get(sub_key.name, sub_key.name) - text_dict = {} - text_dict[u'Task: {0:s}'.format(name)] = u'[ID: {0:s}]'.format( + values_dict = {} + values_dict[u'Task: {0:s}'.format(name)] = u'[ID: {0:s}]'.format( sub_key.name) event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type) + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type) parser_mediator.ProduceEvent(event_object) if dynamic_info.last_registered_time: diff --git a/plaso/parsers/winreg_plugins/terminal_server.py b/plaso/parsers/winreg_plugins/terminal_server.py index 748eb673ec..50a0f0aa23 100644 --- a/plaso/parsers/winreg_plugins/terminal_server.py +++ b/plaso/parsers/winreg_plugins/terminal_server.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- """This file contains the Terminal Server Registry plugins.""" +import re + from plaso.events import windows_events from plaso.parsers import winreg from plaso.parsers.winreg_plugins import interface @@ -20,37 +22,44 @@ class TerminalServerClientPlugin(interface.WindowsRegistryPlugin): u'\\Software\\Microsoft\\Terminal Server Client\\Servers', u'\\Software\\Microsoft\\Terminal Server Client\\Default\\AddIns\\RDPDR'] + _SOURCE_APPEND = u': RDP Connection' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect Values in Servers and return event for each one. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - for subkey in key.GetSubkeys(): - username_value = subkey.GetValue(u'UsernameHint') + mru_values_dict = {} + for subkey in registry_key.GetSubkeys(): + username_value = subkey.GetValueByName(u'UsernameHint') if (username_value and username_value.data and username_value.DataIsString()): username = username_value.data else: - username = u'None' + username = u'N/A' - text_dict = {} - text_dict[u'UsernameHint'] = username + mru_values_dict[subkey.name] = username + values_dict = {u'Username hint': username} event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': RDP Connection') + subkey.last_written_time, subkey.path, values_dict, + offset=subkey.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) + event_object = windows_events.WindowsRegistryEvent( + registry_key.last_written_time, registry_key.path, mru_values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) + parser_mediator.ProduceEvent(event_object) + class TerminalServerClientMRUPlugin(interface.WindowsRegistryPlugin): """Windows Registry plugin for Terminal Server Client Connection MRUs keys.""" @@ -63,21 +72,22 @@ class TerminalServerClientMRUPlugin(interface.WindowsRegistryPlugin): u'\\Software\\Microsoft\\Terminal Server Client\\Default', u'\\Software\\Microsoft\\Terminal Server Client\\LocalDevices'] + _RE_VALUE_DATA = re.compile(r'MRU[0-9]+') + _SOURCE_APPEND = u': RDP Connection' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect MRU Values and return event for each one. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - for value in key.GetValues(): - # TODO: add a check for the value naming scheme. + values_dict = {} + for value in registry_key.GetValues(): # Ignore the default value. if not value.name: continue @@ -86,19 +96,13 @@ def GetEntries( if not value.data or not value.DataIsString(): continue - text_dict = {} - text_dict[value.name] = value.data + values_dict[value.name] = value.data - if value.name == u'MRU0': - timestamp = key.last_written_timestamp - else: - timestamp = 0 - - event_object = windows_events.WindowsRegistryEvent( - timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': RDP Connection') - parser_mediator.ProduceEvent(event_object) + event_object = windows_events.WindowsRegistryEvent( + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) + parser_mediator.ProduceEvent(event_object) winreg.WinRegistryParser.RegisterPlugins([ diff --git a/plaso/parsers/winreg_plugins/timezone.py b/plaso/parsers/winreg_plugins/timezone.py index 99cfdfd454..36bfc28377 100644 --- a/plaso/parsers/winreg_plugins/timezone.py +++ b/plaso/parsers/winreg_plugins/timezone.py @@ -19,51 +19,53 @@ class WinRegTimezonePlugin(interface.WindowsRegistryPlugin): REG_KEYS = [u'\\{current_control_set}\\Control\\TimeZoneInformation'] URLS = [] - WIN_TIMEZONE_VALUE_NAMES = ( + _VALUE_NAMES = frozenset([ u'ActiveTimeBias', u'Bias', u'DaylightBias', u'DaylightName', u'DynamicDaylightTimeDisabled', u'StandardBias', u'StandardName', - u'TimeZoneKeyName') + u'TimeZoneKeyName']) - def _GetValue(self, value_name, key): - """Get value helper, it returns the key value if exists. + def _GetValueData(self, registry_key, value_name): + """Retrieves the value data. Given the Registry key and the value_name it returns the data in the value or None if value_name does not exist. Args: + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). value_name: the name of the value. - key: Registry key (instance of winreg.WinRegKey). Returns: - The data inside a Registry value or None. + The data inside a Windows Registry value or None. """ - value = key.GetValue(value_name) - if value: - return value.data + registry_value = registry_key.GetValueByName(value_name) + if registry_value: + return registry_value.data def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **unused_kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect values and return an event. Args: parser_mediator: A parser context object (instance of ParserContext). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - if key is None: + if registry_key is None: return - text_dict = {} - for value_name in self.WIN_TIMEZONE_VALUE_NAMES: - text_dict[value_name] = self._GetValue(value_name, key) - event_object = windows_events.WindowsRegistryEvent( - key.last_written_timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type) + values_dict = {} + for value_name in self._VALUE_NAMES: + value_data = self._GetValueData(registry_key, value_name) + if value_data is None: + continue + values_dict[value_name] = value_data + event_object = windows_events.WindowsRegistryEvent( + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/typedurls.py b/plaso/parsers/winreg_plugins/typedurls.py index 048da43a36..40bd7d1ad1 100644 --- a/plaso/parsers/winreg_plugins/typedurls.py +++ b/plaso/parsers/winreg_plugins/typedurls.py @@ -24,20 +24,21 @@ class TypedURLsPlugin(interface.WindowsRegistryPlugin): _RE_VALUE_NAME = re.compile(r'^url[0-9]+$', re.I) + _SOURCE_APPEND = u': Typed URLs' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect typed URLs values. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - for value in key.GetValues(): + values_dict = {} + for value in registry_key.GetValues(): # Ignore any value not in the form: 'url[0-9]+'. if not value.name or not self._RE_VALUE_NAME.search(value.name): continue @@ -46,21 +47,13 @@ def GetEntries( if not value.data or not value.DataIsString(): continue - # TODO: shouldn't this behavior be, put all the typed urls - # into a single event object with the last written time of the key? - if value.name == u'url1': - timestamp = key.last_written_timestamp - else: - timestamp = 0 - - text_dict = {} - text_dict[value.name] = value.data - - event_object = windows_events.WindowsRegistryEvent( - timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': Typed URLs') - parser_mediator.ProduceEvent(event_object) + values_dict[value.name] = value.data + + event_object = windows_events.WindowsRegistryEvent( + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) + parser_mediator.ProduceEvent(event_object) winreg.WinRegistryParser.RegisterPlugin(TypedURLsPlugin) diff --git a/plaso/parsers/winreg_plugins/usb.py b/plaso/parsers/winreg_plugins/usb.py index c0ad7ccbeb..db588b1924 100644 --- a/plaso/parsers/winreg_plugins/usb.py +++ b/plaso/parsers/winreg_plugins/usb.py @@ -25,22 +25,22 @@ class USBPlugin(interface.WindowsRegistryPlugin): (u'https://msdn.microsoft.com/en-us/library/windows/hardware/' u'jj649944%28v=vs.85%29.aspx')] + _SOURCE_APPEND = u': USB Entries' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect SubKeys under USB and produce an event object for each one. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - for subkey in key.GetSubkeys(): - text_dict = {} - text_dict[u'subkey_name'] = subkey.name + for subkey in registry_key.GetSubkeys(): + values_dict = {} + values_dict[u'subkey_name'] = subkey.name vendor_identification = None product_identification = None @@ -55,18 +55,18 @@ def GetEntries( subkey.name, exception)) if vendor_identification and product_identification: - text_dict[u'vendor'] = vendor_identification - text_dict[u'product'] = product_identification + values_dict[u'vendor'] = vendor_identification + values_dict[u'product'] = product_identification for devicekey in subkey.GetSubkeys(): - text_dict[u'serial'] = devicekey.name + values_dict[u'serial'] = devicekey.name # Last USB connection per USB device recorded in the Registry. event_object = windows_events.WindowsRegistryEvent( - devicekey.last_written_timestamp, key.path, text_dict, - usage=eventdata.EventTimestamp.LAST_CONNECTED, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': USB Entries') + devicekey.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + usage=eventdata.EventTimestamp.LAST_CONNECTED, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/usbstor.py b/plaso/parsers/winreg_plugins/usbstor.py index d211195288..80b6f6f530 100644 --- a/plaso/parsers/winreg_plugins/usbstor.py +++ b/plaso/parsers/winreg_plugins/usbstor.py @@ -23,29 +23,29 @@ class USBStorPlugin(interface.WindowsRegistryPlugin): URLS = [u'http://www.forensicswiki.org/wiki/USB_History_Viewing'] + _SOURCE_APPEND = u': USBStor Entries' + def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Collect Values under USBStor and return an event object for each one. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - for subkey in key.GetSubkeys(): - text_dict = {} - text_dict[u'subkey_name'] = subkey.name + for subkey in registry_key.GetSubkeys(): + values_dict = {} + values_dict[u'subkey_name'] = subkey.name # Time last USB device of this class was first inserted. event_object = windows_events.WindowsRegistryEvent( - subkey.last_written_timestamp, key.path, text_dict, - usage=eventdata.EventTimestamp.FIRST_CONNECTED, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': USBStor Entries') + subkey.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + usage=eventdata.EventTimestamp.FIRST_CONNECTED, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) name_values = subkey.name.split(u'&') @@ -57,62 +57,62 @@ def GetEntries( u'Expected 4 &-separated values in: {0:s}'.format(subkey.name)) if number_of_name_values >= 1: - text_dict[u'device_type'] = name_values[0] + values_dict[u'device_type'] = name_values[0] if number_of_name_values >= 2: - text_dict[u'vendor'] = name_values[1] + values_dict[u'vendor'] = name_values[1] if number_of_name_values >= 3: - text_dict[u'product'] = name_values[2] + values_dict[u'product'] = name_values[2] if number_of_name_values >= 4: - text_dict[u'revision'] = name_values[3] + values_dict[u'revision'] = name_values[3] for devicekey in subkey.GetSubkeys(): - text_dict[u'serial'] = devicekey.name + values_dict[u'serial'] = devicekey.name - friendly_name_value = devicekey.GetValue(u'FriendlyName') + friendly_name_value = devicekey.GetValueByName(u'FriendlyName') if friendly_name_value: - text_dict[u'friendly_name'] = friendly_name_value.data + values_dict[u'friendly_name'] = friendly_name_value.data else: - text_dict.pop(u'friendly_name', None) + values_dict.pop(u'friendly_name', None) # ParentIdPrefix applies to Windows XP Only. - parent_id_prefix_value = devicekey.GetValue(u'ParentIdPrefix') + parent_id_prefix_value = devicekey.GetValueByName(u'ParentIdPrefix') if parent_id_prefix_value: - text_dict[u'parent_id_prefix'] = parent_id_prefix_value.data + values_dict[u'parent_id_prefix'] = parent_id_prefix_value.data else: - text_dict.pop(u'parent_id_prefix', None) + values_dict.pop(u'parent_id_prefix', None) # Win7 - Last Connection. # Vista/XP - Time of an insert. event_object = windows_events.WindowsRegistryEvent( - devicekey.last_written_timestamp, key.path, text_dict, - usage=eventdata.EventTimestamp.LAST_CONNECTED, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': USBStor Entries') + devicekey.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + usage=eventdata.EventTimestamp.LAST_CONNECTED, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) # Build list of first Insertion times. first_insert = [] - device_parameter_key = devicekey.GetSubkey(u'Device Parameters') + device_parameter_key = devicekey.GetSubkeyByName(u'Device Parameters') if device_parameter_key: - first_insert.append(device_parameter_key.last_written_timestamp) + first_insert.append(device_parameter_key.last_written_time) - log_configuration_key = devicekey.GetSubkey(u'LogConf') + log_configuration_key = devicekey.GetSubkeyByName(u'LogConf') if (log_configuration_key and - log_configuration_key.last_written_timestamp not in first_insert): - first_insert.append(log_configuration_key.last_written_timestamp) + log_configuration_key.last_written_time not in first_insert): + first_insert.append(log_configuration_key.last_written_time) - properties_key = devicekey.GetSubkey(u'Properties') + properties_key = devicekey.GetSubkeyByName(u'Properties') if (properties_key and - properties_key.last_written_timestamp not in first_insert): - first_insert.append(properties_key.last_written_timestamp) + properties_key.last_written_time not in first_insert): + first_insert.append(properties_key.last_written_time) # Add first Insertion times. for timestamp in first_insert: event_object = windows_events.WindowsRegistryEvent( - timestamp, key.path, text_dict, - usage=eventdata.EventTimestamp.LAST_CONNECTED, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': USBStor Entries') + timestamp, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + usage=eventdata.EventTimestamp.LAST_CONNECTED, + source_append=self._SOURCE_APPEND) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/userassist.py b/plaso/parsers/winreg_plugins/userassist.py index e65bdfd248..c5598ddb3e 100644 --- a/plaso/parsers/winreg_plugins/userassist.py +++ b/plaso/parsers/winreg_plugins/userassist.py @@ -6,7 +6,6 @@ import construct from plaso.events import windows_events -from plaso.lib import timelib from plaso.parsers import winreg from plaso.parsers.winreg_plugins import interface from plaso.winnt import environ_expand @@ -71,20 +70,18 @@ class UserAssistPlugin(interface.WindowsRegistryPlugin): construct.Padding(4)) def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Parses a UserAssist Registry key. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - version_value = key.GetValue(u'Version') - count_subkey = key.GetSubkey(u'Count') + version_value = registry_key.GetValueByName(u'Version') + count_subkey = registry_key.GetSubkeyByName(u'Count') if not version_value: parser_mediator.ProduceParseError(u'Missing version value') @@ -157,11 +154,10 @@ def GetEntries( if count > 5: count -= 5 - text_dict = {} - text_dict[value_name] = u'[Count: {0:d}]'.format(count) + values_dict = {} + values_dict[value_name] = u'[Count: {0:d}]'.format(count) event_object = windows_events.WindowsRegistryEvent( - timelib.Timestamp.FromFiletime(filetime), count_subkey.path, - text_dict, offset=value.offset, + filetime, count_subkey.path, values_dict, offset=value.offset, registry_file_type=registry_file_type) parser_mediator.ProduceEvent(event_object) @@ -176,19 +172,18 @@ def GetEntries( count = parsed_data.get(u'count', None) app_focus_count = parsed_data.get(u'app_focus_count', None) focus_duration = parsed_data.get(u'focus_duration', None) - timestamp = parsed_data.get(u'timestamp', 0) + filetime = parsed_data.get(u'timestamp', 0) - text_dict = {} - text_dict[value_name] = ( + values_dict = {} + values_dict[value_name] = ( u'[UserAssist entry: {0:d}, Count: {1:d}, ' u'Application focus count: {2:d}, Focus duration: {3:d}]').format( userassist_entry_index, count, app_focus_count, focus_duration) event_object = windows_events.WindowsRegistryEvent( - timelib.Timestamp.FromFiletime(timestamp), count_subkey.path, - text_dict, offset=count_subkey.offset, - registry_file_type=registry_file_type) + filetime, count_subkey.path, values_dict, + offset=count_subkey.offset, registry_file_type=registry_file_type) parser_mediator.ProduceEvent(event_object) diff --git a/plaso/parsers/winreg_plugins/winrar.py b/plaso/parsers/winreg_plugins/winrar.py index 39ac67210a..8679ad054e 100644 --- a/plaso/parsers/winreg_plugins/winrar.py +++ b/plaso/parsers/winreg_plugins/winrar.py @@ -13,7 +13,6 @@ class WinRarHistoryPlugin(interface.WindowsRegistryPlugin): """Windows Registry plugin for parsing WinRAR History keys.""" - # TODO: Create NTUSER.DAT test file with WinRAR data. NAME = u'winrar_mru' DESCRIPTION = u'Parser for WinRAR History Registry data.' @@ -25,21 +24,21 @@ class WinRarHistoryPlugin(interface.WindowsRegistryPlugin): u'\\Software\\WinRAR\\ArcHistory'] _RE_VALUE_NAME = re.compile(r'^[0-9]+$', re.I) + _SOURCE_APPEND = u': WinRAR History' def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): - """Collect values under WinRAR ArcHistory and return event for each one. + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): + """Extracts event objects from a WinRAR ArcHistory key. Args: - parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. - registry_file_type: Optional string containing the Windows Registry file - type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. + parser_mediator: a parser mediator object (instance of ParserMediator). + registry_key: a Windows Registry key (instance of + dfwinreg.WinRegistryKey). + registry_file_type: optional string containing the Windows Registry file + type, e.g. NTUSER, SOFTWARE. """ - for value in key.GetValues(): + values_dict = {} + for value in registry_key.GetValues(): # Ignore any value not in the form: '[0-9]+'. if not value.name or not self._RE_VALUE_NAME.search(value.name): continue @@ -48,21 +47,13 @@ def GetEntries( if not value.data or not value.DataIsString(): continue - if value.name == u'0': - timestamp = key.last_written_timestamp - else: - timestamp = 0 - - text_dict = {} - text_dict[value.name] = value.data - - # TODO: shouldn't this behavior be, put all the values - # into a single event object with the last written time of the key? - event_object = windows_events.WindowsRegistryEvent( - timestamp, key.path, text_dict, offset=key.offset, - registry_file_type=registry_file_type, - source_append=u': WinRAR History') - parser_mediator.ProduceEvent(event_object) + values_dict[value.name] = value.data + + event_object = windows_events.WindowsRegistryEvent( + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type, + source_append=self._SOURCE_APPEND) + parser_mediator.ProduceEvent(event_object) winreg.WinRegistryParser.RegisterPlugin(WinRarHistoryPlugin) diff --git a/plaso/parsers/winreg_plugins/winver.py b/plaso/parsers/winreg_plugins/winver.py index 098e9d1493..141f886edf 100644 --- a/plaso/parsers/winreg_plugins/winver.py +++ b/plaso/parsers/winreg_plugins/winver.py @@ -1,10 +1,7 @@ # -*- coding: utf-8 -*- """Plug-in to collect information about the Windows version.""" -import construct - from plaso.events import windows_events -from plaso.lib import timelib from plaso.parsers import winreg from plaso.parsers.winreg_plugins import interface @@ -19,65 +16,73 @@ class WinVerPlugin(interface.WindowsRegistryPlugin): REG_TYPE = u'SOFTWARE' URLS = [] - INT_STRUCT = construct.ULInt32(u'install') - - # TODO: Refactor remove this function in a later CL. - def GetValueString(self, key, value_name): - """Retrieves a specific string value from the Registry key. - - Args: - key: A Windows Registry key (instance of WinRegKey). - value_name: The name of the value. - - Returns: - A string value if one is available, otherwise an empty string. - """ - value = key.GetValue(value_name) - - if not value: - return u'' - - if not value.data or not value.DataIsString(): - return u'' - return value.data + _STRING_VALUE_NAME_STRINGS = { + u'CSDVersion': u'service_pack', + u'CurrentVersion': u'version', + u'CurrentBuildNumber': u'build_number', + u'ProductName': u'product_name', + u'RegisteredOrganization': u'organization', + u'RegisteredOwner': u'owner', + } def GetEntries( - self, parser_mediator, key=None, registry_file_type=None, - codepage=u'cp1252', **kwargs): + self, parser_mediator, registry_key, registry_file_type=None, **kwargs): """Gather minimal information about system install and return an event. Args: parser_mediator: A parser mediator object (instance of ParserMediator). - key: Optional Registry key (instance of winreg.WinRegKey). - The default is None. + registry_key: A Windows Registry key (instance of + dfwinreg.WinRegistryKey). registry_file_type: Optional string containing the Windows Registry file type, e.g. NTUSER, SOFTWARE. The default is None. - codepage: Optional extended ASCII string codepage. The default is cp1252. """ - text_dict = {} - text_dict[u'Owner'] = self.GetValueString(key, u'RegisteredOwner') - text_dict[u'sp'] = self.GetValueString(key, u'CSDBuildNumber') - text_dict[u'Product name'] = self.GetValueString(key, u'ProductName') - text_dict[u' Windows Version Information'] = u'' - - install_raw = key.GetValue(u'InstallDate').raw_data - # TODO: move this to a function in utils with a more descriptive name - # e.g. CopyByteStreamToInt32BigEndian. - try: - install = self.INT_STRUCT.parse(install_raw) - except construct.FieldError: - install = 0 + installation_value = None + string_values = {} + for registry_value in registry_key.GetValues(): + # Ignore the default value. + if not registry_value.name: + continue + + if (registry_value.name == u'InstallDate' and + registry_value.DataIsInteger()): + installation_value = registry_value + continue + + # Ignore any value that is empty or that does not contain a string. + if not registry_value.data or not registry_value.DataIsString(): + continue + + string_value_name = self._STRING_VALUE_NAME_STRINGS.get( + registry_value.name, None) + if not string_value_name: + continue + + string_values[string_value_name] = registry_value.data + + owner = string_values.get(u'owner', u'') + product_name = string_values.get(u'product_name', u'') + service_pack = string_values.get(u'service_pack', u'') + version = string_values.get(u'version', u'') + + values_dict = {} + values_dict[u'Owner'] = owner + values_dict[u'Product name'] = product_name + values_dict[u'Service pack'] = service_pack + values_dict[u'Windows Version Information'] = version event_object = windows_events.WindowsRegistryEvent( - timelib.Timestamp.FromPosixTime(install), key.path, text_dict, - usage=u'OS Install Time', offset=key.offset, - registry_file_type=registry_file_type, urls=self.URLS) - - event_object.prodname = text_dict[u'Product name'] - event_object.source_long = u'SOFTWARE WinVersion key' - if text_dict[u'Owner']: - event_object.owner = text_dict[u'Owner'] + registry_key.last_written_time, registry_key.path, values_dict, + offset=registry_key.offset, registry_file_type=registry_file_type) + parser_mediator.ProduceEvent(event_object) + # TODO: if not present indicate anomaly of missing installation + # date and time. + if installation_value: + event_object = windows_events.WindowsRegistryInstallationEvent( + installation_value.data, registry_key.path, owner, product_name, + service_pack, version) + parser_mediator.ProduceEvent(event_object) + winreg.WinRegistryParser.RegisterPlugin(WinVerPlugin) diff --git a/plaso/preprocessors/manager.py b/plaso/preprocessors/manager.py index c3687a0044..77664281db 100644 --- a/plaso/preprocessors/manager.py +++ b/plaso/preprocessors/manager.py @@ -158,10 +158,9 @@ def RunPlugins(cls, platform, file_system, mount_point, knowledge_base): # TODO: do not pass the full pre_obj here but just # the necessary values. - registry_file_reader = dfwinreg_registry.WinRegistryFileReader( + registry_file_reader = dfwinreg_registry.SearcherWinRegistryFileReader( searcher, pre_obj=pre_obj) win_registry = dfwinreg_registry.WinRegistry( - backend=dfwinreg_registry.WinRegistry.BACKEND_PYREGF, registry_file_reader=registry_file_reader) for weight in cls._GetWeights(cls._registry_plugin_classes, platform): diff --git a/plaso/preprocessors/windows.py b/plaso/preprocessors/windows.py index 6202e747aa..b78bbe0372 100644 --- a/plaso/preprocessors/windows.py +++ b/plaso/preprocessors/windows.py @@ -160,7 +160,7 @@ def _ParseKey(self, registry_key): # TODO: create a proper object for this. user = {} user[u'sid'] = subkey.name - value = subkey.GetValue(u'ProfileImagePath') + value = subkey.GetValueByName(u'ProfileImagePath') if value: user[u'path'] = value.data user[u'name'] = self._GetUsernameFromPath(user[u'path']) @@ -190,7 +190,7 @@ def _ParseKey(self, registry_key): u'Registry key: {0:s} does not exist'.format(self.KEY_PATH)) return self.DEFAULT_ATTRIBUTE_VALUE - registry_value = registry_key.GetValue(self.VALUE_NAME) + registry_value = registry_key.GetValueByName(self.VALUE_NAME) if not registry_value: logging.warning( u'Registry value: {0:s} does not exist'.format(self.VALUE_NAME)) diff --git a/plaso/serializer/protobuf_serializer.py b/plaso/serializer/protobuf_serializer.py index 24c4761677..d0d182b19d 100644 --- a/plaso/serializer/protobuf_serializer.py +++ b/plaso/serializer/protobuf_serializer.py @@ -167,6 +167,9 @@ def WriteSerializedDictObject( proto_attribute: a protobuf attribute object. attribute_name: the name of the attribute. ditctobject: a dictionary object that is the value of the attribute. + + Raises: + AttributeError: if the attribute cannot be merged with the dictionary. """ dict_proto = plaso_storage_pb2.Dict() @@ -175,7 +178,12 @@ def WriteSerializedDictObject( cls.WriteSerializedObject(dict_proto_add, dict_key, dict_value) dict_attribute = getattr(proto_attribute, attribute_name) - dict_attribute.MergeFrom(dict_proto) + try: + dict_attribute.MergeFrom(dict_proto) + except AttributeError as exception: + raise AttributeError( + u'Unable to merge attribute: {0:s} with error: {1:s}'.format( + attribute_name, exception)) @classmethod def WriteSerializedListObject( @@ -186,6 +194,9 @@ def WriteSerializedListObject( proto_attribute: a protobuf attribute object. attribute_name: the name of the attribute. list_object: a list object that is the value of the attribute. + + Raises: + AttributeError: if the attribute cannot be merged with the list. """ list_proto = plaso_storage_pb2.Array() @@ -194,7 +205,12 @@ def WriteSerializedListObject( cls.WriteSerializedObject(list_proto_add, u'', list_value) list_attribute = getattr(proto_attribute, attribute_name) - list_attribute.MergeFrom(list_proto) + try: + list_attribute.MergeFrom(list_proto) + except AttributeError as exception: + raise AttributeError( + u'Unable to merge attribute: {0:s} with error: {1:s}'.format( + attribute_name, exception)) class ProtobufAnalysisReportSerializer(interface.AnalysisReportSerializer): diff --git a/tests/dfwinreg/fake.py b/tests/dfwinreg/fake.py new file mode 100644 index 0000000000..4baea10cd6 --- /dev/null +++ b/tests/dfwinreg/fake.py @@ -0,0 +1,82 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""Tests for the fake Windows Registry back-end.""" + +import unittest + +from plaso.dfwinreg import fake + +from tests.dfwinreg import test_lib + + +class FakeWinRegTestCase(test_lib.WinRegTestCase): + """The unit test case for fake Windows Registry related object.""" + + def _OpenFakeRegistryFile(self): + """Opens a fake Windows Registry file. + + Returns: + The Windows Registry file object (instance of FakeWinRegistryFileTest). + """ + registry_file = fake.FakeWinRegistryFile() + + software_key = fake.FakeWinRegistryKey(u'Software') + registry_file.AddKeyByPath(u'\\', software_key) + + registry_file.Open(None) + return registry_file + + +class FakeWinRegistryFileTest(FakeWinRegTestCase): + """Tests for the fake Windows Registry file object.""" + + def testOpenClose(self): + """Tests the Open and Close functions.""" + registry_file = self._OpenFakeRegistryFile() + registry_file.Close() + + def testGetRootKey(self): + """Tests the GetRootKey function.""" + registry_file = self._OpenFakeRegistryFile() + + registry_key = registry_file.GetRootKey() + self.assertIsNotNone(registry_key) + self.assertEqual(registry_key.path, u'\\') + + registry_file.Close() + + def testGetKeyByPath(self): + """Tests the GetKeyByPath function.""" + registry_file = self._OpenFakeRegistryFile() + + key_path = u'\\' + registry_key = registry_file.GetKeyByPath(key_path) + self.assertIsNotNone(registry_key) + self.assertEqual(registry_key.path, key_path) + + key_path = u'\\Software' + registry_key = registry_file.GetKeyByPath(key_path) + self.assertIsNotNone(registry_key) + self.assertEqual(registry_key.path, key_path) + + key_path = u'\\Bogus' + registry_key = registry_file.GetKeyByPath(key_path) + self.assertIsNone(registry_key) + + registry_file.Close() + + def testRecurseKeys(self): + """Tests the RecurseKeys function.""" + registry_file = self._OpenFakeRegistryFile() + + registry_keys = list(registry_file.RecurseKeys()) + registry_file.Close() + + self.assertEqual(len(registry_keys), 2) + +# TODO: add key tests. +# TODO: add value tests. + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/dfwinreg/regf.py b/tests/dfwinreg/regf.py index b59bd38f45..6901c56a96 100644 --- a/tests/dfwinreg/regf.py +++ b/tests/dfwinreg/regf.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -"""Tests for the pyregf Windows Registry back-end.""" +"""Tests for the REGF Windows Registry back-end.""" import unittest @@ -9,45 +9,267 @@ from tests.dfwinreg import test_lib -class WinPyregfFileTest(test_lib.WinRegTestCase): - """Tests for the pyregf Windows Registry File object.""" +class REGFWinRegTestCase(test_lib.WinRegTestCase): + """The unit test case for REGF Windows Registry related object.""" - def _KeyPathCompare(self, winreg_file, key_path): - """Retrieves a key from the file and checks if the path key matches. + def _OpenREGFRegistryFile(self, filename): + """Opens a REGF Windows Registry file. Args: - winreg_file: the Windows Registry file (instance of WinPyregfFile). - key_path: the key path to retrieve and compare. + filename: the name of the file relative to the test file path. + + Returns: + The Windows Registry file object (instance of REGFWinRegistryFileTest) or + None. """ - key = winreg_file.GetKeyByPath(key_path) - self.assertEqual(key.path, key_path) + test_file = self._GetTestFilePath([filename]) + file_entry = self._GetTestFileEntry(test_file) + file_object = file_entry.GetFileObject() + + registry_file = regf.REGFWinRegistryFile() + registry_file.Open(file_object) + + return registry_file + + +class REGFWinRegistryFileTest(REGFWinRegTestCase): + """Tests for the REGF Windows Registry file object.""" def testOpenClose(self): """Tests the Open and Close functions.""" - test_file = self._GetTestFilePath([u'NTUSER.DAT']) - file_entry = self._GetTestFileEntry(test_file) - winreg_file = regf.WinPyregfFile() - winreg_file.OpenFileEntry(file_entry) + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + registry_file.Close() - self._KeyPathCompare(winreg_file, u'\\') - self._KeyPathCompare(winreg_file, u'\\Printers') - self._KeyPathCompare(winreg_file, u'\\Printers\\Connections') - self._KeyPathCompare(winreg_file, u'\\Software') + def testGetRootKey(self): + """Tests the GetRootKey function.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') - winreg_file.Close() + registry_key = registry_file.GetRootKey() + self.assertIsNotNone(registry_key) + self.assertEqual(registry_key.path, u'\\') - def testOpenCloseNoRootKey(self): - """Test opening up a Registry file with no root key.""" - test_file = self._GetTestFilePath([u'ntuser.dat.LOG']) - file_entry = self._GetTestFileEntry(test_file) - winreg_file = regf.WinPyregfFile() - winreg_file.OpenFileEntry(file_entry) + registry_file.Close() - root_key = winreg_file.GetRootKey() + registry_file = self._OpenREGFRegistryFile(u'ntuser.dat.LOG') + + root_key = registry_file.GetRootKey() self.assertIsNone(root_key) - keys = list(winreg_file.RecurseKeys()) - self.assertEqual(keys, []) + def testGetKeyByPath(self): + """Tests the GetKeyByPath function.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + key_path = u'\\' + registry_key = registry_file.GetKeyByPath(key_path) + self.assertIsNotNone(registry_key) + self.assertEqual(registry_key.path, key_path) + + key_path = u'\\Software' + registry_key = registry_file.GetKeyByPath(key_path) + self.assertIsNotNone(registry_key) + self.assertEqual(registry_key.path, key_path) + + key_path = u'\\Bogus' + registry_key = registry_file.GetKeyByPath(key_path) + self.assertIsNone(registry_key) + + registry_file.Close() + + def testRecurseKeys(self): + """Tests the RecurseKeys function.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + registry_keys = list(registry_file.RecurseKeys()) + registry_file.Close() + + self.assertEqual(len(registry_keys), 1127) + + registry_file = self._OpenREGFRegistryFile(u'ntuser.dat.LOG') + + registry_keys = list(registry_file.RecurseKeys()) + registry_file.Close() + + self.assertEqual(len(registry_keys), 0) + + +class REGFWinRegistryKeyTest(REGFWinRegTestCase): + """Tests for the REGF Windows Registry key object.""" + + def testProperties(self): + """Tests the properties functions.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + key_path = u'\\Software' + registry_key = registry_file.GetKeyByPath(key_path) + self.assertIsNotNone(registry_key) + self.assertEqual(registry_key.last_written_time, 128938728930133750) + self.assertEqual(registry_key.name, u'Software') + self.assertEqual(registry_key.number_of_subkeys, 7) + self.assertEqual(registry_key.number_of_values, 0) + self.assertEqual(registry_key.offset, 82652) + self.assertEqual(registry_key.path, key_path) + + registry_file.Close() + + def testGetSubkeyByName(self): + """Tests the GetSubkeyByName function.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + registry_key = registry_file.GetRootKey() + + key_name = u'Software' + subkey = registry_key.GetSubkeyByName(key_name) + self.assertIsNotNone(subkey) + self.assertEqual(subkey.name, key_name) + + key_name = u'Bogus' + subkey = registry_key.GetSubkeyByName(key_name) + self.assertIsNone(subkey) + + registry_file.Close() + + def testGetSubkeys(self): + """Tests the GetSubkeys function.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + key_path = u'\\Software' + registry_key = registry_file.GetKeyByPath(key_path) + + subkeys = list(registry_key.GetSubkeys()) + self.assertEqual(len(subkeys), 7) + + registry_file.Close() + + def testGetValueByName(self): + """Tests the GetValueByName function.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + registry_key = registry_file.GetKeyByPath(u'\\Console') + + value_name = u'ColorTable14' + registry_value = registry_key.GetValueByName(value_name) + self.assertIsNotNone(registry_value) + self.assertEqual(registry_value.name, value_name) + + value_name = u'Bogus' + registry_value = registry_key.GetValueByName(value_name) + self.assertIsNone(registry_value) + + # Test retrieving the default (or nameless) value. + registry_key = registry_file.GetKeyByPath( + u'\\AppEvents\\EventLabels\\.Default') + + registry_value = registry_key.GetValueByName(u'') + self.assertIsNotNone(registry_value) + self.assertIsNone(registry_value.name) + + registry_file.Close() + + def testGetValues(self): + """Tests the GetValues function.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + key_path = u'\\Console' + registry_key = registry_file.GetKeyByPath(key_path) + + values = list(registry_key.GetValues()) + self.assertEqual(len(values), 31) + + registry_file.Close() + + def testRecurseKeys(self): + """Tests the RecurseKeys function.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + key_path = u'\\Software' + registry_key = registry_file.GetKeyByPath(key_path) + registry_keys = list(registry_key.RecurseKeys()) + registry_file.Close() + + self.assertEqual(len(registry_keys), 797) + + +class REGFWinRegistryValueTest(REGFWinRegTestCase): + """Tests for the REGF Windows Registry value object.""" + + def testProperties(self): + """Tests the properties functions.""" + registry_file = self._OpenREGFRegistryFile(u'NTUSER.DAT') + + registry_key = registry_file.GetKeyByPath(u'\\Console') + value_name = u'ColorTable14' + registry_value = registry_key.GetValueByName(value_name) + expected_raw_data = b'\xff\xff\x00\x00' + + self.assertIsNotNone(registry_value) + self.assertEqual(registry_value.data_type, 4) + self.assertEqual(registry_value.data_type_string, u'REG_DWORD_LE') + self.assertEqual(registry_value.data, 65535) + self.assertEqual(registry_value.name, value_name) + self.assertEqual(registry_value.offset, 29516) + self.assertEqual(registry_value.raw_data, expected_raw_data) + + registry_key = registry_file.GetKeyByPath( + u'\\AppEvents\\EventLabels\\CriticalBatteryAlarm') + value_name = u'DispFileName' + registry_value = registry_key.GetValueByName(value_name) + expected_raw_data = ( + b'@\x00m\x00m\x00s\x00y\x00s\x00.\x00c\x00p\x00l\x00,\x00-\x005\x008' + b'\x002\x007\x00\x00\x00') + + self.assertIsNotNone(registry_value) + self.assertEqual(registry_value.data_type, 1) + self.assertEqual(registry_value.data_type_string, u'REG_SZ') + self.assertEqual(registry_value.data, u'@mmsys.cpl,-5827') + self.assertEqual(registry_value.name, value_name) + self.assertEqual(registry_value.offset, 6012) + self.assertEqual(registry_value.raw_data, expected_raw_data) + + registry_key = registry_file.GetKeyByPath( + u'\\Software\\Microsoft\\Windows\\ShellNoRoam\\BagMRU') + value_name = u'0' + registry_value = registry_key.GetValueByName(value_name) + expected_raw_data = ( + b'\x14\x00\x1fP\xe0O\xd0 \xea:i\x10\xa2\xd8\x08\x00+00\x9d\x00\x00') + + self.assertIsNotNone(registry_value) + self.assertEqual(registry_value.data_type, 3) + self.assertEqual(registry_value.data_type_string, u'REG_BINARY') + self.assertEqual(registry_value.data, expected_raw_data) + self.assertEqual(registry_value.name, value_name) + self.assertEqual(registry_value.offset, 625588) + self.assertEqual(registry_value.raw_data, expected_raw_data) + + registry_file.Close() + + registry_file = self._OpenREGFRegistryFile(u'NTUSER-WIN7.DAT') + + registry_key = registry_file.GetKeyByPath( + u'\\Software\\Microsoft\\Cryptography\\CertificateTemplateCache\\User') + value_name = u'SupportedCSPs' + registry_value = registry_key.GetValueByName(value_name) + expected_data = [ + u'Microsoft Enhanced Cryptographic Provider v1.0', + u'Microsoft Base Cryptographic Provider v1.0'] + expected_raw_data = ( + b'M\x00i\x00c\x00r\x00o\x00s\x00o\x00f\x00t\x00 \x00E\x00n\x00h\x00a' + b'\x00n\x00c\x00e\x00d\x00 \x00C\x00r\x00y\x00p\x00t\x00o\x00g\x00r' + b'\x00a\x00p\x00h\x00i\x00c\x00 \x00P\x00r\x00o\x00v\x00i\x00d\x00e' + b'\x00r\x00 \x00v\x001\x00.\x000\x00\x00\x00M\x00i\x00c\x00r\x00o' + b'\x00s\x00o\x00f\x00t\x00 \x00B\x00a\x00s\x00e\x00 \x00C\x00r\x00y' + b'\x00p\x00t\x00o\x00g\x00r\x00a\x00p\x00h\x00i\x00c\x00 \x00P\x00r' + b'\x00o\x00v\x00i\x00d\x00e\x00r\x00 \x00v\x001\x00.\x000\x00\x00' + b'\x00\x00\x00') + + self.assertIsNotNone(registry_value) + self.assertEqual(registry_value.data_type, 7) + self.assertEqual(registry_value.data_type_string, u'REG_MULTI_SZ') + self.assertEqual(registry_value.data, expected_data) + self.assertEqual(registry_value.name, value_name) + self.assertEqual(registry_value.offset, 241452) + self.assertEqual(registry_value.raw_data, expected_raw_data) + + registry_file.Close() if __name__ == '__main__': diff --git a/tests/dfwinreg/registry.py b/tests/dfwinreg/registry.py index b70d8e2db5..17017fbede 100644 --- a/tests/dfwinreg/registry.py +++ b/tests/dfwinreg/registry.py @@ -5,23 +5,47 @@ import os import unittest -from dfvfs.lib import definitions as dfvfs_definitions -from dfvfs.path import factory as path_spec_factory -from dfvfs.resolver import resolver as path_spec_resolver - from plaso.dfwinreg import definitions +from plaso.dfwinreg import interface +from plaso.dfwinreg import regf from plaso.dfwinreg import registry from tests.dfwinreg import test_lib -class RegistryUnitTest(test_lib.WinRegTestCase): +class TestWinRegistryFileReader(interface.WinRegistryFileReader): + """A single file Windows Registry file reader.""" + + def Open(self, path, ascii_codepage=u'cp1252'): + """Opens the Windows Registry file specificed by the path. + + Args: + path: the path of the Windows Registry file. + ascii_codepage: optional ASCII string codepage. The default is cp1252 + (or windows-1252). + + Returns: + The Windows Registry file (instance of WinRegistryFile) or None. + """ + registry_file = regf.REGFWinRegistryFile(ascii_codepage=ascii_codepage) + file_object = open(path, 'rb') + try: + # If open is successful Registry file will manage the file object. + registry_file.Open(file_object) + except IOError: + file_object.close() + registry_file = None + + return registry_file + + +class RegistryTest(test_lib.WinRegTestCase): """Tests for the Windows Registry library.""" def setUp(self): """Sets up the needed objects used throughout the test.""" self._registry = registry.WinRegistry( - backend=registry.WinRegistry.BACKEND_PYREGF) + registry_file_reader=TestWinRegistryFileReader()) def _GetTestFilePath(self, path_segments): """Retrieves the path of a test file relative to the test data directory. @@ -36,50 +60,25 @@ def _GetTestFilePath(self, path_segments): # and not a list. return os.path.join(self._TEST_DATA_PATH, *path_segments) - def _GetTestFileEntryFromPath(self, path_segments): - """Creates a file entry that references a file in the test dir. - - Args: - path_segments: the path segments inside the test data directory. - - Returns: - A file entry object (instance of dfvfs.FileEntry). - """ - path = self._GetTestFilePath(path_segments) - path_spec = path_spec_factory.Factory.NewPathSpec( - dfvfs_definitions.TYPE_INDICATOR_OS, location=path) - return path_spec_resolver.Resolver.OpenFileEntry(path_spec) - - def _OpenWinRegFile(self, filename): - """Opens a Windows Registry file. - - Args: - filename: The filename of the Windows Registry file, relative to - the test data location. - - Returns: - A Windows Registry file object (instance of WinRegFile). - """ - file_entry = self._GetTestFileEntryFromPath([filename]) - return self._registry.OpenFileEntry(file_entry) - def testGetRegistryFileType(self): """Tests the GetRegistryFileType function.""" - winreg_file = self._OpenWinRegFile(u'NTUSER.DAT') + test_path = self._GetTestFilePath([u'NTUSER.DAT']) + registry_file = self._registry.OpenFile(test_path) - registry_file_type = self._registry.GetRegistryFileType(winreg_file) + registry_file_type = self._registry.GetRegistryFileType(registry_file) self.assertEqual( registry_file_type, definitions.REGISTRY_FILE_TYPE_NTUSER) - winreg_file.Close() + registry_file.Close() - winreg_file = self._OpenWinRegFile(u'SYSTEM') + test_path = self._GetTestFilePath([u'SYSTEM']) + registry_file = self._registry.OpenFile(test_path) - registry_file_type = self._registry.GetRegistryFileType(winreg_file) + registry_file_type = self._registry.GetRegistryFileType(registry_file) self.assertEqual( registry_file_type, definitions.REGISTRY_FILE_TYPE_SYSTEM) - winreg_file.Close() + registry_file.Close() if __name__ == '__main__': diff --git a/tests/dfwinreg/test_lib.py b/tests/dfwinreg/test_lib.py index 706944f7be..43aa88937e 100644 --- a/tests/dfwinreg/test_lib.py +++ b/tests/dfwinreg/test_lib.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Windows Registry related functions and classes for testing.""" -import construct import os import unittest @@ -9,169 +8,11 @@ from dfvfs.path import factory as path_spec_factory from dfvfs.resolver import resolver as path_spec_resolver -from plaso.dfwinreg import interface - - -class TestRegKey(interface.WinRegKey): - """Implementation of the Registry key interface for testing.""" - - def __init__(self, path, last_written_timestamp, values, offset=0, - subkeys=None): - """An abstract object for a Windows Registry key. - - This implementation is more a manual one, so it can be used for - testing the Registry plugins without requiring a full blown - Windows Registry file to extract key values. - - Args: - path: The full key name and path. - last_written_timestamp: An integer containing the the last written - timestamp of the Registry key. - values: A list of TestRegValue values this key holds. - offset: A byte offset into the Windows Registry file where the entry lies. - subkeys: A list of subkeys this key has. - """ - super(TestRegKey, self).__init__() - self._name = None - self._path = path - self._last_written_timestamp = last_written_timestamp - self._values = values - self._offset = offset - if subkeys is None: - self._subkeys = [] - else: - self._subkeys = subkeys - - @property - def path(self): - """The path of the key.""" - return self._path - - @property - def name(self): - """The name of the key.""" - if not self._name and self._path: - self._name = self._path.split(self.PATH_SEPARATOR)[-1] - return self._name - - @property - def offset(self): - """The offset of the key within the Windows Registry file.""" - return self._offset - - @property - def last_written_timestamp(self): - """The last written time of the key represented as a timestamp.""" - return self._last_written_timestamp - - def number_of_values(self): - """The number of values within the key.""" - return len(self._values) - - def GetValue(self, name): - """Return a WinRegValue object for a specific Registry key path.""" - for value in self._values: - if value.name == name: - return value - - def GetValues(self): - """Return a list of all values from the Registry key.""" - return self._values - - def number_of_subkeys(self): - """The number of subkeys within the key.""" - return len(self._subkeys) - - def GetSubkey(self, name): - """Retrieve a subkey by name. - - Args: - name: The relative path of the current key to the desired one. - - Returns: - The subkey with the relative path of name or None if not found. - """ - for subkey in self._subkeys: - if subkey.name == name: - return subkey - return - - def GetSubkeys(self): - """Return a list of all subkeys.""" - return self._subkeys - - -class TestRegValue(interface.WinRegValue): - """Implementation of the Registry value interface for testing.""" - - _INT32_BIG_ENDIAN = construct.SBInt32('value') - _INT32_LITTLE_ENDIAN = construct.SLInt32('value') - _INT64_LITTLE_ENDIAN = construct.SLInt64('value') - - def __init__(self, name, data, data_type, offset=0): - """Set up the test reg value object.""" - super(TestRegValue, self).__init__() - self._name = name - self._data = data - self._data_type = data_type - self._offset = offset - self._type_str = '' - - @property - def name(self): - """The name of the value.""" - return self._name - - @property - def offset(self): - """The offset of the value within the Windows Registry file.""" - return self._offset - - @property - def data_type(self): - """Numeric value that contains the data type.""" - return self._data_type - - @property - def raw_data(self): - """The value data as a byte string.""" - return self._data - - @property - def data(self): - """The value data as a native Python object.""" - if not self._data: - return None - - if self._data_type in [self.REG_SZ, self.REG_EXPAND_SZ, self.REG_LINK]: - try: - return unicode(self._data.decode('utf-16-le')) - except UnicodeError: - pass - - elif self._data_type == self.REG_DWORD and len(self._data) == 4: - return self._INT32_LITTLE_ENDIAN.parse(self._data) - - elif self._data_type == self.REG_DWORD_BIG_ENDIAN and len(self._data) == 4: - return self._INT32_BIG_ENDIAN.parse(self._data) - - elif self._data_type == self.REG_QWORD and len(self._data) == 8: - return self._INT64_LITTLE_ENDIAN.parse(self._data) - - elif self._data_type == self.REG_MULTI_SZ: - try: - utf16_string = unicode(self._data.decode('utf-16-le')) - return filter(None, utf16_string.split('\x00')) - except UnicodeError: - pass - - return self._data - class WinRegTestCase(unittest.TestCase): - """The unit test case for winreg.""" + """The unit test case for Windows Registry related object.""" - _TEST_DATA_PATH = os.path.join(os.getcwd(), 'test_data') + _TEST_DATA_PATH = os.path.join(os.getcwd(), u'test_data') # Show full diff results, part of TestCase so does not follow our naming # conventions. diff --git a/tests/lib/event.py b/tests/lib/event.py index 21a7e1a906..26b93148cf 100644 --- a/tests/lib/event.py +++ b/tests/lib/event.py @@ -13,6 +13,7 @@ import unittest +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.events import text_events from plaso.events import windows_events from plaso.lib import event @@ -42,61 +43,67 @@ def GetEventObjects(): hostname = u'MYHOSTNAME' data_type = 'test:event' - event_a = event.EventObject() - event_a.username = u'joesmith' - event_a.filename = u'c:/Users/joesmith/NTUSER.DAT' - event_a.hostname = hostname - event_a.timestamp = 0 - event_a.data_type = data_type - event_a.text = u'' + event_object = event.EventObject() + event_object.username = u'joesmith' + event_object.filename = u'c:/Users/joesmith/NTUSER.DAT' + event_object.hostname = hostname + event_object.timestamp = 0 + event_object.data_type = data_type + event_object.text = u'' + event_objects.append(event_object) + + filetime = dfwinreg_fake.Filetime() # TODO: move this to a WindowsRegistryEvent unit test. - timestamp = timelib.Timestamp.CopyFromString(u'2012-04-20 22:38:46.929596') - event_b = windows_events.WindowsRegistryEvent( - timestamp, u'MY AutoRun key', {u'Run': u'c:/Temp/evil.exe'}) - event_b.hostname = hostname - event_objects.append(event_b) - - timestamp = timelib.Timestamp.CopyFromString(u'2012-04-20 23:56:46.929596') - event_c = windows_events.WindowsRegistryEvent( - timestamp, u'//HKCU/Secret/EvilEmpire/Malicious_key', - {u'Value': u'send all the exes to the other world'}) - event_c.hostname = hostname - event_objects.append(event_c) - - timestamp = timelib.Timestamp.CopyFromString(u'2012-04-20 16:44:46.000000') - event_d = windows_events.WindowsRegistryEvent( - timestamp, u'//HKCU/Windows/Normal', - {u'Value': u'run all the benign stuff'}) - event_d.hostname = hostname - event_objects.append(event_d) - - event_objects.append(event_a) + filetime.CopyFromString(u'2012-04-20 22:38:46.929596') + values_dict = {u'Run': u'c:/Temp/evil.exe'} + event_object = windows_events.WindowsRegistryEvent( + filetime.timestamp, u'MY AutoRun key', values_dict) + event_object.hostname = hostname + event_objects.append(event_object) + + filetime.CopyFromString(u'2012-04-20 23:56:46.929596') + values_dict = {u'Value': u'send all the exes to the other world'} + event_object = windows_events.WindowsRegistryEvent( + filetime.timestamp, u'//HKCU/Secret/EvilEmpire/Malicious_key', + values_dict) + event_object.hostname = hostname + event_objects.append(event_object) + + filetime.CopyFromString(u'2012-04-20 16:44:46.000000') + values_dict = {u'Value': u'run all the benign stuff'} + event_object = windows_events.WindowsRegistryEvent( + filetime.timestamp, u'//HKCU/Windows/Normal', values_dict) + event_object.hostname = hostname + event_objects.append(event_object) timestamp = timelib.Timestamp.CopyFromString(u'2012-04-30 10:29:47.929596') filename = u'c:/Temp/evil.exe' - event_e = TestEvent(timestamp, { - u'text': u'This log line reads ohh so much.'}) - event_e.filename = filename - event_e.hostname = hostname + attributes = { + u'text': u'This log line reads ohh so much.'} + event_object = TestEvent(timestamp, attributes) + event_object.filename = filename + event_object.hostname = hostname - event_objects.append(event_e) + event_objects.append(event_object) timestamp = timelib.Timestamp.CopyFromString(u'2012-04-30 10:29:47.929596') - event_f = TestEvent(timestamp, { - u'text': u'Nothing of interest here, move on.'}) - event_f.filename = filename - event_f.hostname = hostname + attributes = { + u'text': u'Nothing of interest here, move on.'} + event_object = TestEvent(timestamp, attributes) + event_object.filename = filename + event_object.hostname = hostname - event_objects.append(event_f) + event_objects.append(event_object) timestamp = timelib.Timestamp.CopyFromString(u'2012-04-30 13:06:47.939596') - event_g = TestEvent(timestamp, { - u'text': u'Mr. Evil just logged into the machine and got root.'}) - event_g.filename = filename - event_g.hostname = hostname + attributes = { + u'text': u'Mr. Evil just logged into the machine and got root.'} + event_object = TestEvent(timestamp, attributes) + event_object.filename = filename + event_object.hostname = hostname - event_objects.append(event_g) + event_objects.append(event_object) text_dict = {u'body': ( u'This is a line by someone not reading the log line properly. And ' @@ -105,12 +112,12 @@ def GetEventObjects(): # TODO: move this to a TextEvent unit test. timestamp = timelib.Timestamp.CopyFromString(u'2012-06-05 22:14:19.000000') - event_h = text_events.TextEvent(timestamp, 12, text_dict) - event_h.text = event_h.body - event_h.hostname = hostname - event_h.filename = filename + event_object = text_events.TextEvent(timestamp, 12, text_dict) + event_object.text = event_object.body + event_object.hostname = hostname + event_object.filename = filename - event_objects.append(event_h) + event_objects.append(event_object) return event_objects diff --git a/tests/lib/storage.py b/tests/lib/storage.py index a158daed85..03b2deb63e 100644 --- a/tests/lib/storage.py +++ b/tests/lib/storage.py @@ -7,6 +7,7 @@ import unittest import zipfile +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.engine import queue from plaso.events import text_events from plaso.events import windows_events @@ -30,11 +31,13 @@ class DummyObject(object): class GroupMock(object): """Mock a class for grouping events together.""" + def __init__(self): + """Initializes the mock group object.""" self.groups = [] - def AddGroup(self, name, events, desc=None, first=0, last=0, color=None, - cat=None): + def AddGroup( + self, name, events, desc=None, first=0, last=0, color=None, cat=None): """Add a new group of events.""" self.groups.append((name, events, desc, first, last, color, cat)) @@ -63,41 +66,54 @@ class StorageFileTest(unittest.TestCase): def setUp(self): """Sets up the needed objects used throughout the test.""" - self._event_objects = [] - - event_1 = windows_events.WindowsRegistryEvent( - timelib.Timestamp.CopyFromString(u'2012-04-20 22:38:46.929596'), - u'MY AutoRun key', {u'Value': u'c:/Temp/evil.exe'}) - event_1.parser = 'UNKNOWN' - - event_2 = windows_events.WindowsRegistryEvent( - timelib.Timestamp.CopyFromString(u'2012-05-02 13:43:26.929596'), - u'\\HKCU\\Secret\\EvilEmpire\\Malicious_key', - {u'Value': u'send all the exes to the other world'}) - event_2.parser = 'UNKNOWN' - - event_3 = windows_events.WindowsRegistryEvent( - timelib.Timestamp.CopyFromString(u'2012-04-20 16:44:46.000000'), - u'\\HKCU\\Windows\\Normal', - {u'Value': u'run all the benign stuff'}) - event_3.parser = 'UNKNOWN' - - text_dict = {'text': ( - 'This is a line by someone not reading the log line properly. And ' - 'since this log line exceeds the accepted 80 chars it will be ' - 'shortened.'), 'hostname': 'nomachine', 'username': 'johndoe'} - event_4 = text_events.TextEvent( - timelib.Timestamp.CopyFromString(u'2009-04-05 12:27:39.000000'), - 12, text_dict) - event_4.parser = 'UNKNOWN' - - self._event_objects.append(event_1) - self._event_objects.append(event_2) - self._event_objects.append(event_3) - self._event_objects.append(event_4) - + self._event_objects = self._CreateTestEventObjects() self._formatter_mediator = formatters_mediator.FormatterMediator() + def _CreateTestEventObjects(self): + """Creates the event objects for testing. + + Returns: + A list of event objects (instances of EventObject). + """ + event_objects = [] + filetime = dfwinreg_fake.Filetime() + + filetime.CopyFromString(u'2012-04-20 22:38:46.929596') + values_dict = {u'Value': u'c:/Temp/evil.exe'} + event_object = windows_events.WindowsRegistryEvent( + filetime.timestamp, u'MY AutoRun key', values_dict) + event_object.parser = 'UNKNOWN' + event_objects.append(event_object) + + filetime.CopyFromString(u'2012-05-02 13:43:26.929596') + values_dict = {u'Value': u'send all the exes to the other world'} + event_object = windows_events.WindowsRegistryEvent( + filetime.timestamp, u'\\HKCU\\Secret\\EvilEmpire\\Malicious_key', + values_dict) + event_object.parser = 'UNKNOWN' + event_objects.append(event_object) + + filetime.CopyFromString(u'2012-04-20 16:44:46') + values_dict = {u'Value': u'run all the benign stuff'} + event_object = windows_events.WindowsRegistryEvent( + filetime.timestamp, u'\\HKCU\\Windows\\Normal', values_dict) + event_object.parser = 'UNKNOWN' + event_objects.append(event_object) + + timemstamp = timelib.Timestamp.CopyFromString(u'2009-04-05 12:27:39') + text_dict = { + u'hostname': u'nomachine', + u'text': ( + u'This is a line by someone not reading the log line properly. And ' + u'since this log line exceeds the accepted 80 chars it will be ' + u'shortened.'), + u'username': u'johndoe'} + event_object = text_events.TextEvent(timemstamp, 12, text_dict) + event_object.parser = 'UNKNOWN' + event_objects.append(event_object) + + return event_objects + def testStorageWriter(self): """Test the storage writer.""" self.assertEqual(len(self._event_objects), 4) @@ -224,7 +240,9 @@ def testStorage(self): self.assertEqual(len(event_objects), 4) self.assertEqual(len(tags), 4) - self.assertEqual(tags[0].timestamp, 1238934459000000) + expected_timestamp = timelib.Timestamp.CopyFromString( + u'2009-04-05 12:27:39') + self.assertEqual(tags[0].timestamp, expected_timestamp) self.assertEqual(tags[0].store_number, 1) self.assertEqual(tags[0].store_index, 0) self.assertEqual(tags[0].tag.comment, u'My comment') diff --git a/tests/parsers/winreg_plugins/appcompatcache.py b/tests/parsers/winreg_plugins/appcompatcache.py index 65a8df600e..79691a8b5b 100644 --- a/tests/parsers/winreg_plugins/appcompatcache.py +++ b/tests/parsers/winreg_plugins/appcompatcache.py @@ -7,11 +7,11 @@ from dfvfs.path import fake_path_spec from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import appcompatcache -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -34,7 +34,7 @@ def __init__(self, name): self.path_spec = fake_path_spec.FakePathSpec(location=name) def GetStat(self): - """Retrieves the stat object (instance of vfs.VFSStat).""" + """Retrieves the stat object (instance of dfvfs.VFSStat).""" return @@ -45,37 +45,44 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = appcompatcache.AppCompatCachePlugin() - def _CreateTestAppCompatCache(self, time_string, binary_data): - """Creates a AppCompatCache Registry key and value for testing. + def _CreateTestKey(self, time_string, binary_data): + """Creates Registry keys and values for testing. Args: time_string: string containing the key last written date and time. binary_data: the binary data of the AppCompatCache Registry value. Returns: - A Windows Registry key object (instance of TestRegKey). + A Windows Registry key (instance of dfwinreg.WinRegistryKey). """ key_path = u'\\ControlSet001\\Control\\Session Manager\\AppCompatCache' - timestamp = timelib.Timestamp.CopyFromString(time_string) - values = [dfwinreg_test_lib.TestRegValue( - u'AppCompatCache', binary_data, dfwinreg_definitions.REG_BINARY)] + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'AppCompatCache', key_path=key_path, + last_written_time=filetime.timestamp, offset=1456) - return dfwinreg_test_lib.TestRegKey( - key_path, timestamp, values, offset=1456) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'AppCompatCache', data=binary_data, + data_type=dfwinreg_definitions.REG_BINARY) + registry_key.AddValue(registry_value) - def _ParseAppCompatCacheKey(self, file_entry, winreg_key): + return registry_key + + def _ParseAppCompatCacheKey(self, file_entry, registry_key): """Parses the AppCompatCacheKey. Args: file_entry: the file entry object (instance of dfvfs.FileEntry). - winreg_key: the Windows Registry key object (instance of WinRegKey). + registry_key: the Windows Registry key object (instance of + dfwinreg.WinRegistryKey). Returns: A list of event objects (instances of EventObjects). """ knowledge_base_values = {u'current_control_set': u'ControlSet001'} event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, knowledge_base_values=knowledge_base_values, + self._plugin, registry_key, knowledge_base_values=knowledge_base_values, file_entry=file_entry, parser_chain=self._plugin.plugin_name) return self._GetEventObjectsFromQueue(event_queue_consumer) @@ -165,9 +172,9 @@ def testProcessWindowsXP(self): ])) file_entry = TestFileEntry(u'SYSTEM-XP') - winreg_key = self._CreateTestAppCompatCache( + registry_key = self._CreateTestKey( u'2015-06-15 11:53:37.043061', binary_data) - event_objects = self._ParseAppCompatCacheKey(file_entry, winreg_key) + event_objects = self._ParseAppCompatCacheKey(file_entry, registry_key) self.assertEqual(len(event_objects), 2) @@ -175,11 +182,12 @@ def testProcessWindowsXP(self): event_object = event_objects[event_object_index] expected_path = u'\\??\\C:\\WINDOWS\\system32\\hticons.dll' - expected_msg = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( + expected_message = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( event_object.keyname, event_object_index + 1, expected_path) - expected_msg_short = u'Path: {0:s}'.format(expected_path) + expected_short_message = u'Path: {0:s}'.format(expected_path) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) def testProcessWindows2003(self): """Tests the Process function for Windows 2003 AppCompatCache data.""" @@ -200,9 +208,9 @@ def testProcessWindows2003(self): ])) file_entry = TestFileEntry(u'SYSTEM-Windows2003') - winreg_key = self._CreateTestAppCompatCache( + registry_key = self._CreateTestKey( u'2015-06-15 11:53:37.043061', binary_data) - event_objects = self._ParseAppCompatCacheKey(file_entry, winreg_key) + event_objects = self._ParseAppCompatCacheKey(file_entry, registry_key) self.assertEqual(len(event_objects), 1) @@ -211,11 +219,12 @@ def testProcessWindows2003(self): expected_path = ( u'\\??\\C:\\WINDOWS\\Microsoft.NET\\Framework\\v1.1.4322\\ngen.exe') - expected_msg = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( + expected_message = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( event_object.keyname, event_object_index + 1, expected_path) - expected_msg_short = u'Path: {0:s}'.format(expected_path) + expected_short_message = u'Path: {0:s}'.format(expected_path) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) # TODO: implement 64 bit @@ -234,9 +243,9 @@ def testProcessWindowsVista(self): ])) file_entry = TestFileEntry(u'SYSTEM-Vista') - winreg_key = self._CreateTestAppCompatCache( + registry_key = self._CreateTestKey( u'2015-06-15 11:53:37.043061', binary_data) - event_objects = self._ParseAppCompatCacheKey(file_entry, winreg_key) + event_objects = self._ParseAppCompatCacheKey(file_entry, registry_key) self.assertEqual(len(event_objects), 1) @@ -244,11 +253,12 @@ def testProcessWindowsVista(self): event_object = event_objects[event_object_index] expected_path = u'\\??\\C:\\Windows\\SYSTEM32\\WISPTIS.EXE' - expected_msg = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( + expected_message = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( event_object.keyname, event_object_index + 1, expected_path) - expected_msg_short = u'Path: {0:s}'.format(expected_path) + expected_short_message = u'Path: {0:s}'.format(expected_path) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) # TODO: implement 64 bit @@ -256,8 +266,8 @@ def testProcessWindows7(self): """Tests the Process function for Windows 7 AppCompatCache data.""" file_entry = self._GetTestFileEntryFromPath([u'SYSTEM']) key_path = u'\\ControlSet001\\Control\\Session Manager\\AppCompatCache' - winreg_key = self._GetKeyFromFileEntry(file_entry, key_path) - event_objects = self._ParseAppCompatCacheKey(file_entry, winreg_key) + registry_key = self._GetKeyFromFileEntry(file_entry, key_path) + event_objects = self._ParseAppCompatCacheKey(file_entry, registry_key) self.assertEqual(len(event_objects), 330) @@ -274,11 +284,12 @@ def testProcessWindows7(self): self.assertEqual(event_object.parser, self._plugin.plugin_name) expected_path = u'\\??\\C:\\Windows\\PSEXESVC.EXE' - expected_msg = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( + expected_message = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( event_object.keyname, event_object_index + 1, expected_path) - expected_msg_short = u'Path: {0:s}'.format(expected_path) + expected_short_message = u'Path: {0:s}'.format(expected_path) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) # TODO: implement 64 bit @@ -309,9 +320,9 @@ def testProcessWindows8_0(self): ])) file_entry = TestFileEntry(u'SYSTEM-Windows8.0') - winreg_key = self._CreateTestAppCompatCache( + registry_key = self._CreateTestKey( u'2015-06-15 11:53:37.043061', binary_data) - event_objects = self._ParseAppCompatCacheKey(file_entry, winreg_key) + event_objects = self._ParseAppCompatCacheKey(file_entry, registry_key) self.assertEqual(len(event_objects), 1) @@ -319,11 +330,12 @@ def testProcessWindows8_0(self): event_object = event_objects[event_object_index] expected_path = u'SYSVOL\\Windows\\System32\\wbem\\WmiPrvSE.exe' - expected_msg = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( + expected_message = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( event_object.keyname, event_object_index + 1, expected_path) - expected_msg_short = u'Path: {0:s}'.format(expected_path) + expected_short_message = u'Path: {0:s}'.format(expected_path) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) def testProcessWindows8_1(self): """Tests the Process function for Windows 8.1 AppCompatCache data.""" @@ -351,9 +363,9 @@ def testProcessWindows8_1(self): ])) file_entry = TestFileEntry(u'SYSTEM-Windows8.1') - winreg_key = self._CreateTestAppCompatCache( + registry_key = self._CreateTestKey( u'2015-06-15 11:53:37.043061', binary_data) - event_objects = self._ParseAppCompatCacheKey(file_entry, winreg_key) + event_objects = self._ParseAppCompatCacheKey(file_entry, registry_key) self.assertEqual(len(event_objects), 1) @@ -361,11 +373,12 @@ def testProcessWindows8_1(self): event_object = event_objects[event_object_index] expected_path = u'SYSVOL\\Windows\\System32\\dllhost.exe' - expected_msg = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( + expected_message = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( event_object.keyname, event_object_index + 1, expected_path) - expected_msg_short = u'Path: {0:s}'.format(expected_path) + expected_short_message = u'Path: {0:s}'.format(expected_path) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) def testProcessWindows10(self): """Tests the Process function for Windows 10 AppCompatCache data.""" @@ -395,9 +408,9 @@ def testProcessWindows10(self): ])) file_entry = TestFileEntry(u'SYSTEM-Windows10') - winreg_key = self._CreateTestAppCompatCache( + registry_key = self._CreateTestKey( u'2015-06-15 11:53:37.043061', binary_data) - event_objects = self._ParseAppCompatCacheKey(file_entry, winreg_key) + event_objects = self._ParseAppCompatCacheKey(file_entry, registry_key) self.assertEqual(len(event_objects), 1) @@ -405,11 +418,12 @@ def testProcessWindows10(self): event_object = event_objects[event_object_index] expected_path = u'C:\\Windows\\system32\\MpSigStub.exe' - expected_msg = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( + expected_message = u'[{0:s}] Cached entry: {1:d} Path: {2:s}'.format( event_object.keyname, event_object_index + 1, expected_path) - expected_msg_short = u'Path: {0:s}'.format(expected_path) + expected_short_message = u'Path: {0:s}'.format(expected_path) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/bagmru.py b/tests/parsers/winreg_plugins/bagmru.py index 6f3603d548..98ce18b255 100644 --- a/tests/parsers/winreg_plugins/bagmru.py +++ b/tests/parsers/winreg_plugins/bagmru.py @@ -23,9 +23,9 @@ def testProcess(self): test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER.DAT']) key_path = ( u'\\Software\\Microsoft\\Windows\\ShellNoRoam\\BagMRU') - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 15) @@ -41,15 +41,14 @@ def testProcess(self): u'2009-08-04 15:19:16.997750') self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'Index: 1 [MRU Value 0]: ' u'Shell item path: ').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}] Index: 1 [MRU Value 0]: Shel...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) event_object = event_objects[1] @@ -57,15 +56,14 @@ def testProcess(self): u'2009-08-04 15:19:10.669625') self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}\\0] ' u'Index: 1 [MRU Value 0]: ' u'Shell item path: C:\\').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}\\0] Index: 1 [MRU Value 0]: Sh...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) event_object = event_objects[14] @@ -75,9 +73,10 @@ def testProcess(self): # The winreg_formatter will add a space after the key path even when there # is not text. - expected_msg = u'[{0:s}\\0\\0\\0\\0\\0] '.format(key_path) + expected_message = u'[{0:s}\\0\\0\\0\\0\\0] '.format(key_path) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg) + self._TestGetMessageStrings( + event_object, expected_message, expected_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/ccleaner.py b/tests/parsers/winreg_plugins/ccleaner.py index e92fbc701c..009ce5beda 100644 --- a/tests/parsers/winreg_plugins/ccleaner.py +++ b/tests/parsers/winreg_plugins/ccleaner.py @@ -25,12 +25,12 @@ def testProcess(self): """Tests the Process function.""" test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER-CCLEANER.DAT']) key_path = u'\\Software\\Piriform\\CCleaner' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) - self.assertEqual(len(event_objects), 17) + self.assertEqual(len(event_objects), 2) event_object = event_objects[0] @@ -43,25 +43,42 @@ def testProcess(self): u'2013-07-13 10:03:14') self.assertEqual(event_object.timestamp, expected_timestamp) - regvalue_identifier = u'UpdateKey' - expected_value = u'07/13/2013 10:03:14 AM' - self._TestRegvalue(event_object, regvalue_identifier, expected_value) - - expected_string = u'[{0:s}] {1:s}: {2:s}'.format( - key_path, regvalue_identifier, expected_value) - self._TestGetMessageStrings(event_object, expected_string, expected_string) + expected_message = u'Origin: {0:s}'.format(key_path) + self._TestGetMessageStrings( + event_object, expected_message, expected_message) - event_object = event_objects[2] + event_object = event_objects[1] - self.assertEqual(event_object.timestamp, 0) + expected_timestamp = timelib.Timestamp.CopyFromString( + u'2013-07-13 14:03:26.861688') + self.assertEqual(event_object.timestamp, expected_timestamp) regvalue_identifier = u'(App)Delete Index.dat files' expected_value = u'True' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_string = u'[{0:s}] {1:s}: {2:s}'.format( - key_path, regvalue_identifier, expected_value) - self._TestGetMessageStrings(event_object, expected_string, expected_string) + expected_message = ( + u'[{0:s}] ' + u'(App)Cookies: True ' + u'(App)Delete Index.dat files: True ' + u'(App)History: True ' + u'(App)Last Download Location: True ' + u'(App)Other Explorer MRUs: True ' + u'(App)Recent Documents: True ' + u'(App)Recently Typed URLs: True ' + u'(App)Run (in Start Menu): True ' + u'(App)Temporary Internet Files: True ' + u'(App)Thumbnail Cache: True ' + u'CookiesToSave: *.piriform.com ' + u'WINDOW_HEIGHT: 524 ' + u'WINDOW_LEFT: 146 ' + u'WINDOW_MAX: 0 ' + u'WINDOW_TOP: 102 ' + u'WINDOW_WIDTH: 733').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) + + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/default.py b/tests/parsers/winreg_plugins/default.py index b0638efab6..d2be57e24b 100644 --- a/tests/parsers/winreg_plugins/default.py +++ b/tests/parsers/winreg_plugins/default.py @@ -5,11 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import default -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,27 +20,55 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = default.DefaultPlugin() + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'TimeZoneInformation', key_path=key_path, + last_written_time=filetime.timestamp, offset=1456) + + value_data = u'acb'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'MRUList', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=123) + registry_key.AddValue(registry_value) + + value_data = u'Some random text here'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'a', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1892) + registry_key.AddValue(registry_value) + + value_data = u'c:/evil.exe'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'b', data=value_data, data_type=dfwinreg_definitions.REG_BINARY, + offset=612) + registry_key.AddValue(registry_value) + + value_data = u'C:/looks_legit.exe'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'c', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1001) + registry_key.AddValue(registry_value) + + return registry_key + def testProcess(self): """Tests the Process function.""" key_path = u'\\Microsoft\\Some Windows\\InterestingApp\\MRU' - values = [] - values.append(dfwinreg_test_lib.TestRegValue( - u'MRUList', u'acb'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=123)) - values.append(dfwinreg_test_lib.TestRegValue( - u'a', u'Some random text here'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=1892)) - values.append(dfwinreg_test_lib.TestRegValue( - u'b', u'c:/evil.exe'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_BINARY, offset=612)) - values.append(dfwinreg_test_lib.TestRegValue( - u'c', u'C:/looks_legit.exe'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=1001)) - - timestamp = timelib.Timestamp.CopyFromString(u'2012-08-28 09:23:49.002031') - winreg_key = dfwinreg_test_lib.TestRegKey(key_path, timestamp, values, 1456) - - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) + + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -51,21 +79,19 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'MRUList: [REG_SZ] acb ' u'a: [REG_SZ] Some random text here ' u'b: [REG_BINARY] ' u'c: [REG_SZ] C:/looks_legit.exe').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}] MRUList: [REG_SZ] acb a: [REG_SZ...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/lfu.py b/tests/parsers/winreg_plugins/lfu.py index 1ef0239aa2..4d55a8fef2 100644 --- a/tests/parsers/winreg_plugins/lfu.py +++ b/tests/parsers/winreg_plugins/lfu.py @@ -5,11 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import lfu -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,61 +20,87 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = lfu.BootExecutePlugin() - def testProcess(self): - """Tests the Process function.""" - key_path = u'\\ControlSet001\\Control\\Session Manager' - values = [] + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'Session Manager', key_path=key_path, + last_written_time=filetime.timestamp, offset=153) value_data = u'autocheck autochk *\x00'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'BootExecute', value_data, dfwinreg_definitions.REG_MULTI_SZ, - offset=123)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'BootExecute', data=value_data, + data_type=dfwinreg_definitions.REG_MULTI_SZ, offset=123) + registry_key.AddValue(registry_value) value_data = u'2592000'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'CriticalSectionTimeout', value_data, dfwinreg_definitions.REG_SZ, - offset=153)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'CriticalSectionTimeout', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=153) + registry_key.AddValue(registry_value) value_data = u'\x00'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'ExcludeFromKnownDlls', value_data, dfwinreg_definitions.REG_MULTI_SZ, - offset=163)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'ExcludeFromKnownDlls', data=value_data, + data_type=dfwinreg_definitions.REG_MULTI_SZ, offset=163) + registry_key.AddValue(registry_value) value_data = u'0'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'GlobalFlag', value_data, dfwinreg_definitions.REG_SZ, offset=173)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'GlobalFlag', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=173) + registry_key.AddValue(registry_value) value_data = u'0'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'HeapDeCommitFreeBlockThreshold', value_data, - dfwinreg_definitions.REG_SZ, offset=183)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'HeapDeCommitFreeBlockThreshold', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=183) + registry_key.AddValue(registry_value) value_data = u'0'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'HeapDeCommitTotalFreeThreshold', value_data, - dfwinreg_definitions.REG_SZ, offset=203)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'HeapDeCommitTotalFreeThreshold', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=203) + registry_key.AddValue(registry_value) value_data = u'0'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'HeapSegmentCommit', value_data, dfwinreg_definitions.REG_SZ, - offset=213)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'HeapSegmentCommit', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=213) + registry_key.AddValue(registry_value) value_data = u'0'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'HeapSegmentReserve', value_data, dfwinreg_definitions.REG_SZ, - offset=223)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'HeapSegmentReserve', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=223) + registry_key.AddValue(registry_value) value_data = u'2'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'NumberOfInitialSessions', value_data, dfwinreg_definitions.REG_SZ, - offset=243)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'NumberOfInitialSessions', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=243) + registry_key.AddValue(registry_value) - timestamp = timelib.Timestamp.CopyFromString(u'2012-08-31 20:45:29') - winreg_key = dfwinreg_test_lib.TestRegKey(key_path, timestamp, values, 153) + return registry_key + + def testProcess(self): + """Tests the Process function.""" + key_path = u'\\ControlSet001\\Control\\Session Manager' + time_string = u'2012-08-31 20:45:29' + registry_key = self._CreateTestKey(key_path, time_string) knowledge_base_values = {u'current_control_set': u'ControlSet001'} event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, knowledge_base_values=knowledge_base_values) + self._plugin, registry_key, knowledge_base_values=knowledge_base_values) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 2) @@ -85,18 +111,18 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-31 20:45:29') + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_string = ( + expected_message = ( u'[{0:s}] BootExecute: autocheck autochk *').format(key_path) - self._TestGetMessageStrings(event_object, expected_string, expected_string) + self._TestGetMessageStrings( + event_object, expected_message, expected_message) event_object = event_objects[1] - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'CriticalSectionTimeout: 2592000 ' u'ExcludeFromKnownDlls: [] ' @@ -106,11 +132,10 @@ def testProcess(self): u'HeapSegmentCommit: 0 ' u'HeapSegmentReserve: 0 ' u'NumberOfInitialSessions: 2').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}] CriticalSectionTimeout: 2592000 Excl...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class TestBootVerificationRegistry(test_lib.RegistryPluginTestCase): @@ -120,22 +145,40 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = lfu.BootVerificationPlugin() - def testProcess(self): - """Tests the Process function.""" - key_path = u'\\ControlSet001\\Control\\BootVerificationProgram' - values = [] + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'BootVerificationProgram', key_path=key_path, + last_written_time=filetime.timestamp, offset=153) value_data = u'C:\\WINDOWS\\system32\\googleupdater.exe'.encode( u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'ImagePath', value_data, dfwinreg_definitions.REG_SZ, offset=123)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'ImagePath', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=123) + registry_key.AddValue(registry_value) - timestamp = timelib.Timestamp.CopyFromString(u'2012-08-31 20:45:29') - winreg_key = dfwinreg_test_lib.TestRegKey(key_path, timestamp, values, 153) + return registry_key + + def testProcess(self): + """Tests the Process function.""" + key_path = u'\\ControlSet001\\Control\\BootVerificationProgram' + time_string = u'2012-08-31 20:45:29' + registry_key = self._CreateTestKey(key_path, time_string) knowledge_base_values = {u'current_control_set': u'ControlSet001'} event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, knowledge_base_values=knowledge_base_values) + self._plugin, registry_key, knowledge_base_values=knowledge_base_values) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -146,19 +189,17 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-31 20:45:29') + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'ImagePath: C:\\WINDOWS\\system32\\googleupdater.exe').format( key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}] ImagePath: C:\\WINDOWS\\system...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/mountpoints.py b/tests/parsers/winreg_plugins/mountpoints.py index 88ab6361c9..f684025ba2 100644 --- a/tests/parsers/winreg_plugins/mountpoints.py +++ b/tests/parsers/winreg_plugins/mountpoints.py @@ -22,9 +22,9 @@ def testProcess(self): """Tests the Process function.""" test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER-WIN7.DAT']) key_path = self._plugin.REG_KEYS[0] - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 5) @@ -43,14 +43,14 @@ def testProcess(self): regvalue = event_object.regvalue self.assertEqual(regvalue.get(u'Share_Name'), u'\\home\\nfury') - expected_string = ( + expected_message = ( u'[{0:s}] Label: Home Drive Remote_Server: controller Share_Name: ' u'\\home\\nfury Type: Remote Drive Volume: ' u'##controller#home#nfury').format(key_path) - expected_string_short = u'{0:s}...'.format(expected_string[0:77]) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) self._TestGetMessageStrings( - event_object, expected_string, expected_string_short) + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/mrulist.py b/tests/parsers/winreg_plugins/mrulist.py index 510dbf00f9..5b4a89ff09 100644 --- a/tests/parsers/winreg_plugins/mrulist.py +++ b/tests/parsers/winreg_plugins/mrulist.py @@ -5,11 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import mrulist -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,30 +20,55 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = mrulist.MRUListStringPlugin() + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'MRU', key_path=key_path, last_written_time=filetime.timestamp, + offset=1456) + + value_data = u'acb'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'MRUList', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=123) + registry_key.AddValue(registry_value) + + value_data = u'Some random text here'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'a', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1892) + registry_key.AddValue(registry_value) + + value_data = u'c:/evil.exe'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'b', data=value_data, data_type=dfwinreg_definitions.REG_BINARY, + offset=612) + registry_key.AddValue(registry_value) + + value_data = u'C:/looks_legit.exe'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'c', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1001) + registry_key.AddValue(registry_value) + + return registry_key + def testProcess(self): """Tests the Process function.""" key_path = u'\\Microsoft\\Some Windows\\InterestingApp\\MRU' - values = [] - - values.append(dfwinreg_test_lib.TestRegValue( - u'MRUList', u'acb'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=123)) - values.append(dfwinreg_test_lib.TestRegValue( - u'a', u'Some random text here'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=1892)) - values.append(dfwinreg_test_lib.TestRegValue( - u'b', u'c:/evil.exe'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_BINARY, offset=612)) - values.append(dfwinreg_test_lib.TestRegValue( - u'c', u'C:/looks_legit.exe'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=1001)) - - timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') - winreg_key = dfwinreg_test_lib.TestRegKey( - key_path, timestamp, values, 1456) - - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) + + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -54,20 +79,18 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'Index: 1 [MRU Value a]: Some random text here ' u'Index: 2 [MRU Value c]: C:/looks_legit.exe ' u'Index: 3 [MRU Value b]: c:/evil.exe').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}] Index: 1 [MRU Value a]: Some ran...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class TestMRUListShellItemListPlugin(test_lib.RegistryPluginTestCase): @@ -77,14 +100,29 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = mrulist.MRUListShellItemListPlugin() - def testProcess(self): - """Tests the Process function.""" - key_path = ( - u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\' - u'DesktopStreamMRU') - values = [] - - data = b''.join(map(chr, [ + def _CreateTestKey(self, key_path, time_string): + """Creates MRUList Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'DesktopStreamMRU', key_path=key_path, + last_written_time=filetime.timestamp, offset=1456) + + value_data = u'a'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'MRUList', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=123) + registry_key.AddValue(registry_value) + + value_data = b''.join(map(chr, [ 0x14, 0x00, 0x1f, 0x00, 0xe0, 0x4f, 0xd0, 0x20, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xd8, 0x08, 0x00, 0x2b, 0x30, 0x30, 0x9d, 0x19, 0x00, 0x23, 0x43, 0x3a, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -99,18 +137,22 @@ def testProcess(self): 0x00, 0x00, 0x00, 0x2e, 0x3e, 0xe4, 0x62, 0x10, 0x00, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x00, 0x00, 0x00, 0x00])) - values.append(dfwinreg_test_lib.TestRegValue( - u'MRUList', u'a'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=123)) - values.append(dfwinreg_test_lib.TestRegValue( - u'a', data, dfwinreg_definitions.REG_BINARY, offset=612)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'a', data=value_data, data_type=dfwinreg_definitions.REG_BINARY, + offset=612) + registry_key.AddValue(registry_value) - timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') - winreg_key = dfwinreg_test_lib.TestRegKey( - key_path, timestamp, values, 1456) + return registry_key - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + def testProcess(self): + """Tests the Process function.""" + key_path = ( + u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\' + u'DesktopStreamMRU') + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) + + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 5) @@ -122,19 +164,18 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'Index: 1 [MRU Value a]: Shell item path: ' u' C:\\Winnt\\Profiles\\Administrator\\Desktop').format( key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = u'[{0:s}] Index:...'.format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) # A shell item event object. event_object = event_objects[0] @@ -143,17 +184,17 @@ def testProcess(self): u'2011-01-14 12:03:52') self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'Name: Winnt ' u'Shell item path: C:\\Winnt ' u'Origin: {0:s}').format(key_path) - - expected_msg_short = ( + expected_short_message = ( u'Name: Winnt ' - u'Origin: \\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\' - u'Deskt...') + u'Origin: \\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer' + u'\\Deskt...') - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/mrulistex.py b/tests/parsers/winreg_plugins/mrulistex.py index 597d3b0d2f..246c7b5bf0 100644 --- a/tests/parsers/winreg_plugins/mrulistex.py +++ b/tests/parsers/winreg_plugins/mrulistex.py @@ -5,11 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import mrulistex -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,33 +20,56 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = mrulistex.MRUListExStringPlugin() - def testProcess(self): - """Tests the Process function.""" - key_path = u'\\Microsoft\\Some Windows\\InterestingApp\\MRUlist' - values = [] + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'MRUlist', key_path=key_path, + last_written_time=filetime.timestamp, offset=1456) # The order is: 201 value_data = b'\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00' - values.append(dfwinreg_test_lib.TestRegValue( - u'MRUListEx', value_data, dfwinreg_definitions.REG_BINARY, - offset=123)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'MRUListEx', data=value_data, + data_type=dfwinreg_definitions.REG_BINARY, offset=123) + registry_key.AddValue(registry_value) value_data = u'Some random text here'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'0', value_data, dfwinreg_definitions.REG_SZ, offset=1892)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'0', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1892) + registry_key.AddValue(registry_value) value_data = u'c:\\evil.exe'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'1', value_data, dfwinreg_definitions.REG_BINARY, offset=612)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'1', data=value_data, data_type=dfwinreg_definitions.REG_BINARY, + offset=612) + registry_key.AddValue(registry_value) value_data = u'C:\\looks_legit.exe'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'2', value_data, dfwinreg_definitions.REG_SZ, offset=1001)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'2', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1001) + registry_key.AddValue(registry_value) - timestamp = timelib.Timestamp.CopyFromString(u'2012-08-28 09:23:49.002031') - winreg_key = dfwinreg_test_lib.TestRegKey(key_path, timestamp, values, 1456) + return registry_key - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + def testProcess(self): + """Tests the Process function.""" + key_path = u'\\Microsoft\\Some Windows\\InterestingApp\\MRUlist' + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) + + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -58,20 +81,18 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'Index: 1 [MRU Value 2]: C:\\looks_legit.exe ' u'Index: 2 [MRU Value 0]: Some random text here ' u'Index: 3 [MRU Value 1]: c:\\evil.exe').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}] Index: 1 [MRU Value 2]: C:\\l...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class TestMRUListExShellItemListPlugin(test_lib.RegistryPluginTestCase): @@ -87,9 +108,9 @@ def testProcess(self): key_path = ( u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\' u'OpenSavePidlMRU') - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 65) @@ -106,19 +127,17 @@ def testProcess(self): u'2011-08-28 22:48:28.159308') self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}\\exe] ' u'Index: 1 [MRU Value 1]: Shell item path: ' u'P:\\Application Tools\\Firefox 6.0\\Firefox Setup 6.0.exe ' u'Index: 2 [MRU Value 0]: Shell item path: ' u'\\\\controller\\WebDavShare\\Firefox Setup 3.6.12.exe' u'').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\' - u'OpenSavePidlMRU...') - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) # A shell item event object. event_object = event_objects[0] @@ -127,20 +146,20 @@ def testProcess(self): u'2012-03-08 22:16:02') self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'Name: ALLOYR~1 ' u'Long name: Alloy Research ' u'NTFS file reference: 44518-33 ' u'Shell item path: ' u'\\Alloy Research ' u'Origin: {0:s}\\*').format(key_path) - - expected_msg_short = ( + expected_short_message = ( u'Name: Alloy Research ' u'NTFS file reference: 44518-33 ' u'Origin: \\Software\\Microsof...') - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class TestMRUListExStringAndShellItemPlugin(test_lib.RegistryPluginTestCase): @@ -155,9 +174,9 @@ def testProcess(self): test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER-WIN7.DAT']) key_path = ( u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs') - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 6) @@ -174,7 +193,7 @@ def testProcess(self): u'2012-04-01 13:52:39.113741') self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'Index: 1 [MRU Value 17]: Path: The SHIELD, ' u'Shell item: [The SHIELD.lnk] ' @@ -216,11 +235,10 @@ def testProcess(self): u'Shell item: [StarFury (2).lnk] ' u'Index: 9 [MRU Value 7]: Path: Earth_SA-26_Thunderbolt.jpg, ' u'Shell item: [Earth_SA-26_Thunderbolt.lnk]').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}] Index: 1 [MR...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class TestMRUListExStringAndShellItemListPlugin( @@ -237,9 +255,9 @@ def testProcess(self): key_path = ( u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\' u'LastVisitedPidlMRU') - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 31) @@ -256,7 +274,7 @@ def testProcess(self): u'2012-04-01 13:52:38.966290') self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'Index: 1 [MRU Value 1]: Path: chrome.exe, ' u'Shell item path: ' @@ -282,12 +300,10 @@ def testProcess(self): u'Shell item path: P:\\Application Tools\\Firefox 6.0 ' u'Index: 8 [MRU Value 2]: Path: Skype.exe, ' u'Shell item path: ').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\' - u'LastVisitedPidl...') - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/msie_zones.py b/tests/parsers/winreg_plugins/msie_zones.py index ceffe94653..05b2ad584c 100644 --- a/tests/parsers/winreg_plugins/msie_zones.py +++ b/tests/parsers/winreg_plugins/msie_zones.py @@ -24,9 +24,9 @@ def setUp(self): def testProcessForZone(self): """Tests the Process function.""" key_path = u'\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones' - winreg_key = self._GetKeyFromFile(self._test_file, key_path) + registry_key = self._GetKeyFromFile(self._test_file, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=self._file_entry) + self._plugin, registry_key, file_entry=self._file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 6) @@ -45,7 +45,7 @@ def testProcessForZone(self): expected_value = u'0 (Allow)' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = ( + expected_message = ( u'[{0:s}\\0 (My Computer)] ' u'[1001] Download signed ActiveX controls: 0 (Allow) ' u'[1004] Download unsigned ActiveX controls: 0 (Allow) ' @@ -142,19 +142,19 @@ def testProcessForZone(self): u'[LowIcon]: inetcpl.cpl#005422 ' u'[PMDisplayName]: Computer ' u'[Protected Mode]').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = u'[{0:s}\\0 (My Computer)] [...'.format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) def testProcessForLockDown(self): """Tests the Process function for the lockdown zone key.""" key_path = ( u'\\Microsoft\\Windows\\CurrentVersion\\Internet Settings' u'\\Lockdown_Zones') - winreg_key = self._GetKeyFromFile(self._test_file, key_path) + registry_key = self._GetKeyFromFile(self._test_file, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=self._file_entry) + self._plugin, registry_key, file_entry=self._file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 6) @@ -173,7 +173,7 @@ def testProcessForLockDown(self): expected_value = u'3 (Not Allowed)' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = ( + expected_message = ( u'[{0:s}\\0 (My Computer)] ' u'[1001] Download signed ActiveX controls: 1 (Prompt User) ' u'[1004] Download unsigned ActiveX controls: 3 (Not Allowed) ' @@ -266,10 +266,10 @@ def testProcessForLockDown(self): u'[LowIcon]: inetcpl.cpl#005422 ' u'[PMDisplayName]: Computer ' u'[Protected Mode]').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = u'[{0:s}\\0 (My Com...'.format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class MsieZoneSettingsUserZonesPluginTest(test_lib.RegistryPluginTestCase): @@ -287,9 +287,9 @@ def testProcessForZone(self): key_path = ( u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings' u'\\Zones') - winreg_key = self._GetKeyFromFile(self._test_file, key_path) + registry_key = self._GetKeyFromFile(self._test_file, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=self._file_entry) + self._plugin, registry_key, file_entry=self._file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 6) @@ -308,7 +308,7 @@ def testProcessForZone(self): expected_value = u'0 (Allow)' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = ( + expected_message = ( u'[{0:s}\\0 (My Computer)] ' u'[1200] Run ActiveX controls and plug-ins: 0 (Allow) ' u'[1400] Active scripting: 0 (Allow) ' @@ -324,19 +324,19 @@ def testProcessForZone(self): u'[LowIcon]: inetcpl.cpl#005422 ' u'[PMDisplayName]: Computer ' u'[Protected Mode]').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = u'[{0:s}\\0 (My Com...'.format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) def testProcessForLockDown(self): """Tests the Process function.""" key_path = ( u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings' u'\\Lockdown_Zones') - winreg_key = self._GetKeyFromFile(self._test_file, key_path) + registry_key = self._GetKeyFromFile(self._test_file, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=self._file_entry) + self._plugin, registry_key, file_entry=self._file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 6) @@ -355,7 +355,7 @@ def testProcessForLockDown(self): expected_value = u'3 (Not Allowed)' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = ( + expected_message = ( u'[{0:s}\\0 (My Computer)] ' u'[1200] Run ActiveX controls and plug-ins: 3 (Not Allowed) ' u'[1400] Active scripting: 1 (Prompt User) ' @@ -367,10 +367,10 @@ def testProcessForLockDown(self): u'[LowIcon]: inetcpl.cpl#005422 ' u'[PMDisplayName]: Computer ' u'[Protected Mode]').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = u'[{0:s}\\...'.format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/officemru.py b/tests/parsers/winreg_plugins/officemru.py index 89f0feaf48..69c3a35081 100644 --- a/tests/parsers/winreg_plugins/officemru.py +++ b/tests/parsers/winreg_plugins/officemru.py @@ -25,12 +25,12 @@ def testProcess(self): """Tests the Process function.""" test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER-WIN7.DAT']) key_path = u'\\Software\\Microsoft\\Office\\14.0\\Word\\File MRU' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) - self.assertEqual(len(event_objects), 5) + self.assertEqual(len(event_objects), 6) event_object = event_objects[0] @@ -50,11 +50,12 @@ def testProcess(self): u'SA-23E Mitchell-Hyundyne Starfury.docx') self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = u'[{0:s}] {1:s}: {2:s}'.format( + expected_message = u'[{0:s}] {1:s}: {2:s}'.format( key_path, regvalue_identifier, expected_value) - expected_msg_short = u'[{0:s}] {1:s}: [F00000000][T01CD0146...'.format( - key_path, regvalue_identifier) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) + + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/outlook.py b/tests/parsers/winreg_plugins/outlook.py index 9d079985c9..a00d87f9da 100644 --- a/tests/parsers/winreg_plugins/outlook.py +++ b/tests/parsers/winreg_plugins/outlook.py @@ -5,10 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import +from plaso.lib import timelib from plaso.parsers.winreg_plugins import outlook -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -19,29 +20,41 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = outlook.OutlookSearchMRUPlugin() - def testProcess(self): - """Tests the Process function.""" - key_path = u'\\Software\\Microsoft\\Office\\15.0\\Outlook\\Search' - values = [] + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. - values.append(dfwinreg_test_lib.TestRegValue( - (u'C:\\Users\\username\\AppData\\Local\\Microsoft\\Outlook\\' - u'username@example.com.ost'), b'\xcf\x2b\x37\x00', - dfwinreg_definitions.REG_DWORD, offset=1892)) + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. - winreg_key = dfwinreg_test_lib.TestRegKey( - key_path, 1346145829002031, values, 1456) - - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) - event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'Search', key_path=key_path, last_written_time=filetime.timestamp, + offset=1456) - expected_msg = ( - u'[{0:s}] ' + value_name = ( u'C:\\Users\\username\\AppData\\Local\\Microsoft\\Outlook\\' - u'username@example.com.ost: 0x00372bcf').format(key_path) + u'username@example.com.ost') + value_data = b'\xcf\x2b\x37\x00' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + value_name, data=value_data, data_type=dfwinreg_definitions.REG_DWORD, + offset=1892) + registry_key.AddValue(registry_value) - expected_msg_short = u'[{0:s}] C:\\Users\\username\\AppData\\Lo...'.format( - key_path) + return registry_key + + def testProcess(self): + """Tests the Process function.""" + key_path = u'\\Software\\Microsoft\\Office\\15.0\\Outlook\\Search' + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) + + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) + event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -51,9 +64,17 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - self.assertEqual(event_object.timestamp, 1346145829002031) + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) + self.assertEqual(event_object.timestamp, expected_timestamp) + + expected_message = ( + u'[{0:s}] ' + u'C:\\Users\\username\\AppData\\Local\\Microsoft\\Outlook\\' + u'username@example.com.ost: 0x00372bcf').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) # TODO: The catalog for Office 2013 (15.0) contains binary values not @@ -72,15 +93,22 @@ def testProcess(self): # """Tests the Process function.""" # key_path = ( # u'\\Software\\Microsoft\\Office\\15.0\\Outlook\\Search\\Catalog') -# values = [] +# time_string = u'2012-08-28 09:23:49.002031' # -# values.append(dfwinreg_test_lib.TestRegValue( -# (u'C:\\Users\\username\\AppData\\Local\\Microsoft\\Outlook\\' -# u'username@example.com.ost'), b'\x94\x01\x00\x00\x00\x00', -# dfwinreg_definitions.REG_BINARY, offset=827)) +# filetime = dfwinreg_fake.Filetime() +# filetime.CopyFromString(time_string) +# registry_key = dfwinreg_fake.FakeWinRegistryKey( +# u'Catalog', key_path=key_path, last_written_time=filetime.timestamp, +# offset=3421) # -# winreg_key = dfwinreg_test_lib.TestRegKey( -# key_path, 1346145829002031, values, 3421) +# value_name = ( +# u'C:\\Users\\username\\AppData\\Local\\Microsoft\\Outlook\\' +# u'username@example.com.ost') +# value_data = b'\x94\x01\x00\x00\x00\x00' +# registry_value = dfwinreg_fake.FakeWinRegistryValue( +# value_name, data=value_data, +# data_type=dfwinreg_definitions.REG_BINARY, offset=827) +# registry_key.AddValue(registry_value) # # # TODO: add test for Catalog key. diff --git a/tests/parsers/winreg_plugins/run.py b/tests/parsers/winreg_plugins/run.py index 849a34ea7a..3785124865 100644 --- a/tests/parsers/winreg_plugins/run.py +++ b/tests/parsers/winreg_plugins/run.py @@ -5,6 +5,7 @@ import unittest from plaso.formatters import winreg as _ # pylint: disable=unused-import +from plaso.lib import timelib from plaso.parsers.winreg_plugins import run from tests.parsers.winreg_plugins import test_lib @@ -21,9 +22,9 @@ def testProcess(self): """Tests the Process function.""" test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER-RunTests.DAT']) key_path = u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -38,13 +39,13 @@ def testProcess(self): # Timestamp is: 2012-04-05T17:03:53.992061+00:00 self.assertEqual(event_object.timestamp, 1333645433992061) - expected_msg = ( + expected_message = ( u'[{0:s}] Sidebar: %ProgramFiles%\\Windows Sidebar\\Sidebar.exe ' u'/autoRun').format(key_path) - expected_msg_short = ( - u'[{0:s}] Sidebar: %ProgramFiles%\\Wind...').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class RunOnceNtuserPlugintest(test_lib.RegistryPluginTestCase): @@ -58,9 +59,9 @@ def testProcess(self): """Tests the Process function.""" test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER-RunTests.DAT']) key_path = u'\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -72,16 +73,17 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - # Timestamp is: 2012-04-05T17:03:53.992061+00:00 - self.assertEqual(event_object.timestamp, 1333645433992061) + expected_timestamp = timelib.Timestamp.CopyFromString( + u'2012-04-05 17:03:53.992061') + self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] mctadmin: C:\\Windows\\System32\\mctadmin.exe').format( key_path) - expected_msg_short = ( - u'[{0:s}] mctadmin: C:\\Windows\\Sys...').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class RunSoftwarePluginTest(test_lib.RegistryPluginTestCase): @@ -95,9 +97,9 @@ def testProcess(self): """Tests the Process function.""" test_file_entry = self._GetTestFileEntryFromPath([u'SOFTWARE-RunTests']) key_path = u'\\Microsoft\\Windows\\CurrentVersion\\Run' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 3) @@ -109,18 +111,21 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - # Timestamp is: 2011-09-16T20:57:09.067575+00:00 - self.assertEqual(event_object.timestamp, 1316206629067575) + expected_timestamp = timelib.Timestamp.CopyFromString( + u'2011-09-16 20:57:09.067575') + self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] VMware Tools: \"C:\\Program Files\\VMware\\VMware Tools' u'\\VMwareTray.exe\"').format(key_path) - expected_msg_short = ( - u'[{0:s}] VMware Tools: \"C:\\Program Files\\VMwar...').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) - self.assertEqual(event_objects[1].timestamp, 1316206629067575) + expected_timestamp = timelib.Timestamp.CopyFromString( + u'2011-09-16 20:57:09.067575') + self.assertEqual(event_objects[1].timestamp, expected_timestamp) class RunOnceSoftwarePluginTest(test_lib.RegistryPluginTestCase): @@ -134,9 +139,9 @@ def testProcess(self): """Tests the Process function.""" test_file_entry = self._GetTestFileEntryFromPath([u'SOFTWARE-RunTests']) key_path = u'\\Microsoft\\Windows\\CurrentVersion\\RunOnce' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -148,16 +153,17 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - # Timestamp is: 2012-04-06T14:07:27.750000+00:00 - self.assertEqual(event_object.timestamp, 1333721247750000) + expected_timestamp = timelib.Timestamp.CopyFromString( + u'2012-04-06 14:07:27.750000') + self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] *WerKernelReporting: %SYSTEMROOT%\\SYSTEM32\\WerFault.exe ' u'-k -rq').format(key_path) - expected_msg_short = ( - u'[{0:s}] *WerKernelReporting: %SYSTEMROOT%...').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/sam_users.py b/tests/parsers/winreg_plugins/sam_users.py index 17d1636143..0b6d06c2ed 100644 --- a/tests/parsers/winreg_plugins/sam_users.py +++ b/tests/parsers/winreg_plugins/sam_users.py @@ -25,9 +25,9 @@ def testProcess(self): """Tests the Process function.""" test_file = self._GetTestFilePath([u'SAM']) key_path = u'\\SAM\\Domains\\Account\\Users' - winreg_key = self._GetKeyFromFile(test_file, key_path) + registry_key = self._GetKeyFromFile(test_file, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key) + self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 7) @@ -39,25 +39,22 @@ def testProcess(self): self._TestRegvalue(event_object, u'user_guid', u'000001F4') self._TestRegvalue(event_object, u'username', u'Administrator') - expected_msg = ( - u'[\\SAM\\Domains\\Account\\Users] ' - u'account_rid: 500 ' - u'comments: Built-in account for administering the computer/domain ' - u'login_count: 6 ' - u'user_guid: 000001F4 ' - u'username: Administrator') - # Match UTC timestamp. time = long(timelib.Timestamp.CopyFromString( u'2014-09-24 03:36:06.358837')) self.assertEqual(event_object.timestamp, time) - expected_msg_short = ( + expected_message = ( u'[\\SAM\\Domains\\Account\\Users] ' u'account_rid: 500 ' - u'comments: Built-in account for ...') + u'comments: Built-in account for administering the computer/domain ' + u'login_count: 6 ' + u'user_guid: 000001F4 ' + u'username: Administrator') + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/services.py b/tests/parsers/winreg_plugins/services.py index b5534e23db..f7bcfee76e 100644 --- a/tests/parsers/winreg_plugins/services.py +++ b/tests/parsers/winreg_plugins/services.py @@ -5,11 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import services -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,40 +20,74 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = services.ServicesPlugin() + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'TestDriver', key_path=key_path, last_written_time=filetime.timestamp, + offset=1456) + + value_data = b'\x02\x00\x00\x00' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'Type', data=value_data, data_type=dfwinreg_definitions.REG_DWORD, + offset=123) + registry_key.AddValue(registry_value) + + value_data = b'\x02\x00\x00\x00' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'Start', data=value_data, data_type=dfwinreg_definitions.REG_DWORD, + offset=127) + registry_key.AddValue(registry_value) + + value_data = b'\x01\x00\x00\x00' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'ErrorControl', data=value_data, + data_type=dfwinreg_definitions.REG_DWORD, offset=131) + registry_key.AddValue(registry_value) + + value_data = u'Pnp Filter'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'Group', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=140) + registry_key.AddValue(registry_value) + + value_data = u'Test Driver'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'DisplayName', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=160) + registry_key.AddValue(registry_value) + + value_data = u'testdriver.inf_x86_neutral_dd39b6b0a45226c4'.encode( + u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'DriverPackageId', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=180) + registry_key.AddValue(registry_value) + + value_data = u'C:\\Dell\\testdriver.sys'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'ImagePath', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=200) + registry_key.AddValue(registry_value) + + return registry_key + def testProcess(self): """Tests the Process function on a virtual key.""" key_path = u'\\ControlSet001\\services\\TestDriver' + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) - values = [] - values.append(dfwinreg_test_lib.TestRegValue( - u'Type', b'\x02\x00\x00\x00', dfwinreg_definitions.REG_DWORD, - offset=123)) - values.append(dfwinreg_test_lib.TestRegValue( - u'Start', b'\x02\x00\x00\x00', dfwinreg_definitions.REG_DWORD, - offset=127)) - values.append(dfwinreg_test_lib.TestRegValue( - u'ErrorControl', b'\x01\x00\x00\x00', dfwinreg_definitions.REG_DWORD, - offset=131)) - values.append(dfwinreg_test_lib.TestRegValue( - u'Group', u'Pnp Filter'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=140)) - values.append(dfwinreg_test_lib.TestRegValue( - u'DisplayName', u'Test Driver'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=160)) - values.append(dfwinreg_test_lib.TestRegValue( - u'DriverPackageId', - u'testdriver.inf_x86_neutral_dd39b6b0a45226c4'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=180)) - values.append(dfwinreg_test_lib.TestRegValue( - u'ImagePath', u'C:\\Dell\\testdriver.sys'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=200)) - - timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') - winreg_key = dfwinreg_test_lib.TestRegKey( - key_path, timestamp, values, 1456) - - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -64,11 +98,10 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'DisplayName: Test Driver ' u'DriverPackageId: testdriver.inf_x86_neutral_dd39b6b0a45226c4 ' @@ -77,18 +110,16 @@ def testProcess(self): u'ImagePath: C:\\Dell\\testdriver.sys ' u'Start: Auto Start (2) ' u'Type: File System Driver (0x2)').format(key_path) - expected_msg_short = ( - u'[{0:s}] ' - u'DisplayName: Test Driver ' - u'DriverPackageId...').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) def testProcessFile(self): """Tests the Process function on a key in a file.""" test_file_entry = self._GetTestFileEntryFromPath([u'SYSTEM']) key_path = u'\\ControlSet001\\services' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_objects = [] @@ -97,7 +128,7 @@ def testProcessFile(self): mc_task_manager_event_objects = None rdp_video_miniport_event_objects = None - for winreg_subkey in winreg_key.GetSubkeys(): + for winreg_subkey in registry_key.GetSubkeys(): event_queue_consumer = self._ParseKeyWithPlugin( self._plugin, winreg_subkey, file_entry=test_file_entry) sub_event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) diff --git a/tests/parsers/winreg_plugins/shutdown.py b/tests/parsers/winreg_plugins/shutdown.py index e4f7184c58..bfee4aa00c 100644 --- a/tests/parsers/winreg_plugins/shutdown.py +++ b/tests/parsers/winreg_plugins/shutdown.py @@ -26,9 +26,9 @@ def testProcess(self): knowledge_base_values = {u'current_control_set': u'ControlSet001'} test_file_entry = self._GetTestFileEntryFromPath([u'SYSTEM']) key_path = u'\\ControlSet001\\Control\\Windows' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, knowledge_base_values=knowledge_base_values, + self._plugin, registry_key, knowledge_base_values=knowledge_base_values, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) @@ -44,20 +44,17 @@ def testProcess(self): expected_value = u'ShutdownTime' self._TestRegvalue(event_object, u'Description', expected_value) - expected_msg = ( - u'[\\ControlSet001\\Control\\Windows] ' - u'Description: ShutdownTime') - # Match UTC timestamp. time = long(timelib.Timestamp.CopyFromString( u'2012-04-04 01:58:40.839249')) self.assertEqual(event_object.timestamp, time) - expected_msg_short = ( + expected_message = ( u'[\\ControlSet001\\Control\\Windows] ' u'Description: ShutdownTime') - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/task_scheduler.py b/tests/parsers/winreg_plugins/task_scheduler.py index a855f04919..7bcda1349d 100644 --- a/tests/parsers/winreg_plugins/task_scheduler.py +++ b/tests/parsers/winreg_plugins/task_scheduler.py @@ -23,8 +23,8 @@ def testProcess(self): test_file = self._GetTestFilePath([u'SOFTWARE-RunTests']) key_path = ( u'\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache') - winreg_key = self._GetKeyFromFile(test_file, key_path) - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + registry_key = self._GetKeyFromFile(test_file, key_path) + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 174) @@ -43,12 +43,12 @@ def testProcess(self): expected_value = u'[ID: {044A6734-E90E-4F8F-B357-B2DC8AB3B5EC}]' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = u'[{0:s}] {1:s}: {2:s}'.format( + expected_message = u'[{0:s}] {1:s}: {2:s}'.format( key_path, regvalue_identifier, expected_value) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = u'[{0:s}] Task: SynchronizeTi...'.format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) event_object = event_objects[1] @@ -58,14 +58,14 @@ def testProcess(self): regvalue_identifier = u'Task: SynchronizeTime' - expected_msg = ( + expected_message = ( u'Task: SynchronizeTime ' u'[Identifier: {044A6734-E90E-4F8F-B357-B2DC8AB3B5EC}]') - - expected_msg_short = ( + expected_short_message = ( u'Task: SynchronizeTime') - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/terminal_server.py b/tests/parsers/winreg_plugins/terminal_server.py index f987b701fe..5555c0bcf9 100644 --- a/tests/parsers/winreg_plugins/terminal_server.py +++ b/tests/parsers/winreg_plugins/terminal_server.py @@ -5,11 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import terminal_server -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,30 +20,45 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = terminal_server.TerminalServerClientPlugin() - def testProcess(self): - """Tests the Process function.""" - key_path = u'\\Software\\Microsoft\\Terminal Server Client\\Servers' - values = [] + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. - values.append(dfwinreg_test_lib.TestRegValue( - u'UsernameHint', u'DOMAIN\\username'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=1892)) + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'Servers', key_path=key_path, last_written_time=filetime.timestamp, + offset=865) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') + server_subkey = dfwinreg_fake.FakeWinRegistryKey( + u'myserver.com', last_written_time=filetime.timestamp, offset=1456) - server_key_path = ( - u'\\Software\\Microsoft\\Terminal Server Client\\Servers\\myserver.com') - server_key = dfwinreg_test_lib.TestRegKey( - server_key_path, expected_timestamp, values, offset=1456) + value_data = u'DOMAIN\\username'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'UsernameHint', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1892) + server_subkey.AddValue(registry_value) - winreg_key = dfwinreg_test_lib.TestRegKey( - key_path, expected_timestamp, None, offset=865, subkeys=[server_key]) + registry_key.AddSubkey(server_subkey) - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + return registry_key + + def testProcess(self): + """Tests the Process function.""" + key_path = u'\\Software\\Microsoft\\Terminal Server Client\\Servers' + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) + + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) - self.assertEqual(len(event_objects), 1) + self.assertEqual(len(event_objects), 2) event_object = event_objects[0] @@ -51,13 +66,26 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = u'[{0:s}] UsernameHint: DOMAIN\\username'.format(key_path) - expected_msg_short = ( - u'[{0:s}] UsernameHint: DOMAIN\\use...').format(key_path) + expected_message = ( + u'[{0:s}\\myserver.com] ' + u'Username hint: DOMAIN\\username').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) + + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) + + event_object = event_objects[1] + + expected_message = ( + u'[{0:s}] ' + u'myserver.com: DOMAIN\\username').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class DefaultTerminalServerClientMRUPluginTest(test_lib.RegistryPluginTestCase): @@ -67,27 +95,46 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = terminal_server.TerminalServerClientMRUPlugin() + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'Default', key_path=key_path, last_written_time=filetime.timestamp, + offset=1456) + + value_data = u'192.168.16.60'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'MRU0', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1892) + registry_key.AddValue(registry_value) + + value_data = u'computer.domain.com'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'MRU1', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=612) + registry_key.AddValue(registry_value) + + return registry_key + def testProcess(self): """Tests the Process function.""" key_path = u'\\Software\\Microsoft\\Terminal Server Client\\Default' - values = [] - - values.append(dfwinreg_test_lib.TestRegValue( - u'MRU0', u'192.168.16.60'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, offset=1892)) - values.append(dfwinreg_test_lib.TestRegValue( - u'MRU1', u'computer.domain.com'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ, 612)) - - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') - winreg_key = dfwinreg_test_lib.TestRegKey( - key_path, expected_timestamp, values, 1456) + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) - self.assertEqual(len(event_objects), 2) + self.assertEqual(len(event_objects), 1) event_object = event_objects[0] @@ -95,21 +142,17 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_msg = u'[{0:s}] MRU0: 192.168.16.60'.format(key_path) - expected_msg_short = u'[{0:s}] MRU0: 192.168.16.60'.format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) - - event_object = event_objects[1] - - self.assertEqual(event_object.timestamp, 0) - - expected_msg = u'[{0:s}] MRU1: computer.domain.com'.format(key_path) - expected_msg_short = u'[{0:s}] MRU1: computer.domain.com'.format(key_path) + expected_message = ( + u'[{0:s}] ' + u'MRU0: 192.168.16.60 ' + u'MRU1: computer.domain.com').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/test_lib.py b/tests/parsers/winreg_plugins/test_lib.py index 08b33f4705..eccd8ee34b 100644 --- a/tests/parsers/winreg_plugins/test_lib.py +++ b/tests/parsers/winreg_plugins/test_lib.py @@ -6,6 +6,7 @@ from dfvfs.resolver import resolver as path_spec_resolver from plaso.dfwinreg import registry as dfwinreg_registry +from plaso.dfwinreg import regf from plaso.engine import single_process from tests.parsers import test_lib @@ -22,7 +23,7 @@ def _GetKeyFromFile(self, path, key_path): key_path: The path of the key to parse. Returns: - A Windows Registry key (instance of WinRegKey). + A Windows Registry key (instance of dfwinreg.WinRegistryKey). """ path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_OS, location=path) @@ -37,21 +38,41 @@ def _GetKeyFromFileEntry(self, file_entry, key_path): key_path: The path of the key to parse. Returns: - A Windows Registry key (instance of WinRegKey). + A Windows Registry key (instance of dfwinreg.WinRegistryKey). """ + # TODO: refactor. registry = dfwinreg_registry.WinRegistry( backend=dfwinreg_registry.WinRegistry.BACKEND_PYREGF) - winreg_file = registry.OpenFileEntry(file_entry, codepage=u'cp1252') + winreg_file = registry.OpenFileEntry(file_entry) return winreg_file.GetKeyByPath(key_path) + def _OpenREGFRegistryFile(self, filename): + """Opens a REGF Windows Registry file. + + Args: + filename: the name of the file relative to the test file path. + + Returns: + The Windows Registry file object (instance of REGFWinRegistryFileTest) or + None. + """ + test_file = self._GetTestFilePath([filename]) + file_entry = self._GetTestFileEntry(test_file) + file_object = file_entry.GetFileObject() + + registry_file = regf.REGFWinRegistryFile() + registry_file.Open(file_object) + + return registry_file + def _ParseKeyWithPlugin( - self, plugin_object, winreg_key, knowledge_base_values=None, + self, plugin_object, registry_key, knowledge_base_values=None, file_entry=None, parser_chain=None): """Parses a key within a Windows Registry file using the plugin object. Args: plugin_object: The plugin object. - winreg_key: The Windows Registry Key. + registry_key: The Windows Registry Key. knowledge_base_values: Optional dict containing the knowledge base values. The default is None. file_entry: Optional file entry object (instance of dfvfs.FileEntry). @@ -63,7 +84,7 @@ def _ParseKeyWithPlugin( An event object queue consumer object (instance of TestItemQueueConsumer). """ - self.assertNotEqual(winreg_key, None) + self.assertNotEqual(registry_key, None) event_queue = single_process.SingleProcessQueue() event_queue_consumer = test_lib.TestItemQueueConsumer(event_queue) @@ -89,7 +110,7 @@ def _ParseKeyWithPlugin( # as access to the parser chain should be very infrequent. parser_mediator._parser_chain_components = parser_chain.split(u'/') - plugin_object.Process(parser_mediator, key=winreg_key) + plugin_object.Process(parser_mediator, key=registry_key) return event_queue_consumer diff --git a/tests/parsers/winreg_plugins/timezone.py b/tests/parsers/winreg_plugins/timezone.py index 6b3a063a0d..d3262f2083 100644 --- a/tests/parsers/winreg_plugins/timezone.py +++ b/tests/parsers/winreg_plugins/timezone.py @@ -5,11 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import timezone as winreg_timezone -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,68 +20,109 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = winreg_timezone.WinRegTimezonePlugin() - def testProcessMock(self): - """Tests the Process function on created key.""" - knowledge_base_values = {u'current_control_set': u'ControlSet001'} - key_path = u'\\ControlSet001\\Control\\TimeZoneInformation' - values = [] - - values.append(dfwinreg_test_lib.TestRegValue( - u'ActiveTimeBias', b'\xff\xff\xff\xc4', - dfwinreg_definitions.REG_DWORD_BIG_ENDIAN)) - - values.append(dfwinreg_test_lib.TestRegValue( - u'Bias', b'\xff\xff\xff\xc4', - dfwinreg_definitions.REG_DWORD_BIG_ENDIAN)) - - values.append(dfwinreg_test_lib.TestRegValue( - u'DaylightBias', b'\xff\xff\xff\xc4', - dfwinreg_definitions.REG_DWORD_BIG_ENDIAN)) - - values.append(dfwinreg_test_lib.TestRegValue( - u'DaylightName', u'@tzres.dll,-321'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ)) + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'TimeZoneInformation', key_path=key_path, + last_written_time=filetime.timestamp, offset=153) + + value_data = u'C:\\Downloads\\plaso-static.rar'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'1', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=612) + registry_key.AddValue(registry_value) + + value_data = b'\xff\xff\xff\xc4' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'ActiveTimeBias', data=value_data, + data_type=dfwinreg_definitions.REG_DWORD_BIG_ENDIAN) + registry_key.AddValue(registry_value) + + value_data = b'\xff\xff\xff\xc4' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'Bias', data=value_data, + data_type=dfwinreg_definitions.REG_DWORD_BIG_ENDIAN) + registry_key.AddValue(registry_value) + + value_data = b'\xff\xff\xff\xc4' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'DaylightBias', data=value_data, + data_type=dfwinreg_definitions.REG_DWORD_BIG_ENDIAN) + registry_key.AddValue(registry_value) + + value_data = u'@tzres.dll,-321'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'DaylightName', data=value_data, + data_type=dfwinreg_definitions.REG_SZ) + registry_key.AddValue(registry_value) value_data = ( b'\x00\x00\x03\x00\x05\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00') - values.append(dfwinreg_test_lib.TestRegValue( - u'DaylightStart', value_data, dfwinreg_definitions.REG_BINARY)) - - values.append(dfwinreg_test_lib.TestRegValue( - u'DynamicDaylightTimeDisabled', b'\x00\x00\x00\x00', - dfwinreg_definitions.REG_DWORD_BIG_ENDIAN)) - - values.append(dfwinreg_test_lib.TestRegValue( - u'StandardBias', b'\x00\x00\x00\x00', - dfwinreg_definitions.REG_DWORD_BIG_ENDIAN)) - - values.append(dfwinreg_test_lib.TestRegValue( - u'StandardName', u'@tzres.dll,-322'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'DaylightStart', data=value_data, + data_type=dfwinreg_definitions.REG_BINARY) + registry_key.AddValue(registry_value) + + value_data = b'\x00\x00\x00\x00' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'DynamicDaylightTimeDisabled', data=value_data, + data_type=dfwinreg_definitions.REG_DWORD_BIG_ENDIAN) + registry_key.AddValue(registry_value) + + value_data = b'\x00\x00\x00\x00' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'StandardBias', data=value_data, + data_type=dfwinreg_definitions.REG_DWORD_BIG_ENDIAN) + registry_key.AddValue(registry_value) + + value_data = u'@tzres.dll,-322'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'StandardName', data=value_data, + data_type=dfwinreg_definitions.REG_SZ) + registry_key.AddValue(registry_value) value_data = ( b'\x00\x00\x0A\x00\x05\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00') - values.append(dfwinreg_test_lib.TestRegValue( - u'StandardStart', value_data, dfwinreg_definitions.REG_BINARY)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'StandardStart', data=value_data, + data_type=dfwinreg_definitions.REG_BINARY) + registry_key.AddValue(registry_value) - values.append(dfwinreg_test_lib.TestRegValue( - u'TimeZoneKeyName', u'W. Europe Standard Time'.encode(u'utf_16_le'), - dfwinreg_definitions.REG_SZ)) + value_data = u'W. Europe Standard Time'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'TimeZoneKeyName', data=value_data, + data_type=dfwinreg_definitions.REG_SZ) + registry_key.AddValue(registry_value) - timestamp = timelib.Timestamp.CopyFromString(u'2013-01-30 10:47:57') - winreg_key = dfwinreg_test_lib.TestRegKey(key_path, timestamp, values, 153) + return registry_key + def testProcessMock(self): + """Tests the Process function on created key.""" + key_path = u'\\ControlSet001\\Control\\TimeZoneInformation' + time_string = u'2013-01-30 10:47:57' + registry_key = self._CreateTestKey(key_path, time_string) + + knowledge_base_values = {u'current_control_set': u'ControlSet001'} event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, knowledge_base_values=knowledge_base_values) + self._plugin, registry_key, knowledge_base_values=knowledge_base_values) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2013-01-30 10:47:57') + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_objects[0].timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'ActiveTimeBias: -60 ' u'Bias: -60 ' @@ -91,25 +132,20 @@ def testProcessMock(self): u'StandardBias: 0 ' u'StandardName: @tzres.dll,-322 ' u'TimeZoneKeyName: W. Europe Standard Time').format(key_path) - - expected_msg_short = ( - u'[{0:s}] ' - u'ActiveTimeBias: -60 ' - u'Bias: -60 ' - u'Da...').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) self._TestGetMessageStrings( - event_objects[0], expected_msg, expected_msg_short) + event_objects[0], expected_message, expected_short_message) def testProcessFile(self): """Tests the Process function on registry file.""" knowledge_base_values = {u'current_control_set': u'ControlSet001'} test_file = self._GetTestFilePath([u'SYSTEM']) key_path = u'\\ControlSet001\\Control\\TimeZoneInformation' - winreg_key = self._GetKeyFromFile(test_file, key_path) + registry_key = self._GetKeyFromFile(test_file, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, knowledge_base_values=knowledge_base_values) + self._plugin, registry_key, knowledge_base_values=knowledge_base_values) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -118,7 +154,7 @@ def testProcessFile(self): u'2012-03-11 07:00:00.000642') self.assertEqual(event_objects[0].timestamp, expected_timestamp) - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'ActiveTimeBias: 240 ' u'Bias: 300 ' @@ -128,15 +164,10 @@ def testProcessFile(self): u'StandardBias: 0 ' u'StandardName: @tzres.dll,-112 ' u'TimeZoneKeyName: Eastern Standard Time').format(key_path) - - expected_msg_short = ( - u'[{0:s}] ' - u'ActiveTimeBias: 240 ' - u'Bias: 300 ' - u'Da...').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) self._TestGetMessageStrings( - event_objects[0], expected_msg, expected_msg_short) + event_objects[0], expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/typedurls.py b/tests/parsers/winreg_plugins/typedurls.py index 0779d7c1a6..ed22d577b0 100644 --- a/tests/parsers/winreg_plugins/typedurls.py +++ b/tests/parsers/winreg_plugins/typedurls.py @@ -25,12 +25,12 @@ def testProcess(self): """Tests the Process function.""" test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER-WIN7.DAT']) key_path = u'\\Software\\Microsoft\\Internet Explorer\\TypedURLs' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) - self.assertEqual(len(event_objects), 13) + self.assertEqual(len(event_objects), 1) event_object = event_objects[0] @@ -47,9 +47,25 @@ def testProcess(self): expected_value = u'http://cnn.com/' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_string = u'[{0:s}] {1:s}: {2:s}'.format( - key_path, regvalue_identifier, expected_value) - self._TestGetMessageStrings(event_object, expected_string, expected_string) + expected_message = ( + u'[{0:s}] ' + u'url1: http://cnn.com/ ' + u'url10: http://www.adobe.com/ ' + u'url11: http://www.google.com/ ' + u'url12: http://www.firefox.com/ ' + u'url13: http://go.microsoft.com/fwlink/?LinkId=69157 ' + u'url2: http://twitter.com/ ' + u'url3: http://linkedin.com/ ' + u'url4: http://tweetdeck.com/ ' + u'url5: mozilla ' + u'url6: http://google.com/ ' + u'url7: http://controller.shieldbase.local/certsrv/ ' + u'url8: http://controller.shieldbase.local/ ' + u'url9: http://www.stark-research-labs.com/').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) + + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) class TypedPathsPluginTest(test_lib.RegistryPluginTestCase): @@ -64,9 +80,9 @@ def testProcess(self): test_file_entry = self._GetTestFileEntryFromPath([u'NTUSER-WIN7.DAT']) key_path = ( u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\TypedPaths') - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 1) @@ -86,11 +102,11 @@ def testProcess(self): expected_value = u'\\\\controller' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = u'[{0:s}] {1:s}: {2:s}'.format( + expected_message = u'[{0:s}] {1:s}: {2:s}'.format( key_path, regvalue_identifier, expected_value) - expected_msg_short = u'[{0:s}] {1:s}: \\\\cont...'.format( - key_path, regvalue_identifier) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/usb.py b/tests/parsers/winreg_plugins/usb.py index c2b4164a40..8bc18a4c6a 100644 --- a/tests/parsers/winreg_plugins/usb.py +++ b/tests/parsers/winreg_plugins/usb.py @@ -26,9 +26,9 @@ def testProcess(self): knowledge_base_values = {u'current_control_set': u'ControlSet001'} test_file_entry = self._GetTestFileEntryFromPath([u'SYSTEM']) key_path = u'\\ControlSet001\\Enum\\USB' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, knowledge_base_values=knowledge_base_values, + self._plugin, registry_key, knowledge_base_values=knowledge_base_values, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) @@ -46,21 +46,21 @@ def testProcess(self): self._TestRegvalue(event_object, u'vendor', u'VID_0E0F') self._TestRegvalue(event_object, u'product', u'PID_0002') - expected_msg = ( - u'[\\ControlSet001\\Enum\\USB] ' - u'product: PID_0002 ' - u'serial: 6&2ab01149&0&2 ' - u'subkey_name: VID_0E0F&PID_0002 ' - u'vendor: VID_0E0F') - # Match UTC timestamp. time = long(timelib.Timestamp.CopyFromString( u'2012-04-07 10:31:37.625246')) self.assertEqual(event_object.timestamp, time) - expected_msg_short = u'{0:s}...'.format(expected_msg[0:77]) + expected_message = ( + u'[{0:s}] ' + u'product: PID_0002 ' + u'serial: 6&2ab01149&0&2 ' + u'subkey_name: VID_0E0F&PID_0002 ' + u'vendor: VID_0E0F').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/usbstor.py b/tests/parsers/winreg_plugins/usbstor.py index 35559112fa..64b3865f21 100644 --- a/tests/parsers/winreg_plugins/usbstor.py +++ b/tests/parsers/winreg_plugins/usbstor.py @@ -23,9 +23,9 @@ def testProcess(self): knowledge_base_values = {u'current_control_set': u'ControlSet001'} test_file_entry = self._GetTestFileEntryFromPath([u'SYSTEM']) key_path = u'\\ControlSet001\\Enum\\USBSTOR' - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, knowledge_base_values=knowledge_base_values, + self._plugin, registry_key, knowledge_base_values=knowledge_base_values, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) @@ -50,7 +50,7 @@ def testProcess(self): self._TestRegvalue(event_object, u'product', u'Prod_v100w') self._TestRegvalue(event_object, u'revision', u'Rev_1024') - expected_msg = ( + expected_message = ( u'[{0:s}] ' u'device_type: Disk ' u'friendly_name: HP v100w USB Device ' @@ -59,13 +59,10 @@ def testProcess(self): u'serial: AA951D0000007252&0 ' u'subkey_name: Disk&Ven_HP&Prod_v100w&Rev_1024 ' u'vendor: Ven_HP').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - expected_msg_short = ( - u'[{0:s}] ' - u'device_type: Disk ' - u'friendly_name: HP v100w USB D...').format(key_path) - - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/userassist.py b/tests/parsers/winreg_plugins/userassist.py index d4b1b33245..d6ffc9ee59 100644 --- a/tests/parsers/winreg_plugins/userassist.py +++ b/tests/parsers/winreg_plugins/userassist.py @@ -24,9 +24,9 @@ def testProcessOnWinXP(self): key_path = ( u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist' u'\\{75048700-EF1F-11D0-9888-006097DEACF9}') - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 14) @@ -46,12 +46,12 @@ def testProcessOnWinXP(self): expected_value = u'[Count: 14]' self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = u'[{0:s}\\Count] {1:s}: {2:s}'.format( + expected_message = u'[{0:s}\\Count] {1:s}: {2:s}'.format( key_path, regvalue_identifier, expected_value) - # The short message contains the first 76 characters of the key path. - expected_msg_short = u'[{0:s}...'.format(key_path[:76]) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) def testProcessOnWin7(self): """Tests the Process function on a Windows 7 Registry file.""" @@ -60,9 +60,9 @@ def testProcessOnWin7(self): key_path = ( u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist' u'\\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}') - winreg_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) event_queue_consumer = self._ParseKeyWithPlugin( - self._plugin, winreg_key, file_entry=test_file_entry) + self._plugin, registry_key, file_entry=test_file_entry) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) self.assertEqual(len(event_objects), 61) @@ -74,7 +74,6 @@ def testProcessOnWin7(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) - expected_timestamp = timelib.Timestamp.CopyFromString( u'2010-11-10 07:49:37.078067') self.assertEqual(event_object.timestamp, expected_timestamp) @@ -85,12 +84,12 @@ def testProcessOnWin7(self): u'Focus duration: 420000]') self._TestRegvalue(event_object, regvalue_identifier, expected_value) - expected_msg = u'[{0:s}\\Count] {1:s}: {2:s}'.format( + expected_message = u'[{0:s}\\Count] {1:s}: {2:s}'.format( key_path, regvalue_identifier, expected_value) - # The short message contains the first 76 characters of the key path. - expected_msg_short = u'[{0:s}...'.format(key_path[:76]) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/winrar.py b/tests/parsers/winreg_plugins/winrar.py index c2e4e179fa..edcfccf08e 100644 --- a/tests/parsers/winreg_plugins/winrar.py +++ b/tests/parsers/winreg_plugins/winrar.py @@ -5,11 +5,11 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import from plaso.lib import timelib from plaso.parsers.winreg_plugins import winrar -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,31 +20,47 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = winrar.WinRarHistoryPlugin() - def testProcess(self): - """Tests the Process function.""" - key_path = u'\\Software\\WinRAR\\ArcHistory' + def _CreateTestKey(self, key_path, time_string): + """Creates WinRAR ArcHistory Registry keys and values for testing. - values = [] + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'ArcHistory', key_path=key_path, last_written_time=filetime.timestamp, + offset=1456) value_data = u'C:\\Downloads\\The Sleeping Dragon CD1.iso'.encode( u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'0', value_data, dfwinreg_definitions.REG_SZ, offset=1892)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'0', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=1892) + registry_key.AddValue(registry_value) value_data = u'C:\\Downloads\\plaso-static.rar'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'1', value_data, dfwinreg_definitions.REG_SZ, offset=612)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'1', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=612) + registry_key.AddValue(registry_value) - expected_timestamp = timelib.Timestamp.CopyFromString( - u'2012-08-28 09:23:49.002031') + return registry_key - winreg_key = dfwinreg_test_lib.TestRegKey( - key_path, expected_timestamp, values, offset=1456) + def testProcess(self): + """Tests the Process function.""" + key_path = u'\\Software\\WinRAR\\ArcHistory' + time_string = u'2012-08-28 09:23:49.002031' + registry_key = self._CreateTestKey(key_path, time_string) - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) - self.assertEqual(len(event_objects), 2) + self.assertEqual(len(event_objects), 1) event_object = event_objects[0] @@ -52,20 +68,19 @@ def testProcess(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) self.assertEqual(event_object.timestamp, expected_timestamp) - expected_string = ( - u'[{0:s}] 0: C:\\Downloads\\The Sleeping Dragon CD1.iso').format( - key_path) - self._TestGetMessageStrings(event_object, expected_string, expected_string) - - event_object = event_objects[1] - - self.assertEqual(event_object.timestamp, 0) - - expected_string = u'[{0:s}] 1: C:\\Downloads\\plaso-static.rar'.format( - key_path) - self._TestGetMessageStrings(event_object, expected_string, expected_string) + expected_message = ( + u'[{0:s}] ' + u'0: C:\\Downloads\\The Sleeping Dragon CD1.iso ' + u'1: C:\\Downloads\\plaso-static.rar').format(key_path) + expected_message_short = ( + u'[{0:s}] ' + u'0: C:\\Downloads\\The Sleeping Dragon CD1.iso ' + u'1: ...').format(key_path) + self._TestGetMessageStrings( + event_object, expected_message, expected_message_short) if __name__ == '__main__': diff --git a/tests/parsers/winreg_plugins/winver.py b/tests/parsers/winreg_plugins/winver.py index b041c1bac0..af2fe5a192 100644 --- a/tests/parsers/winreg_plugins/winver.py +++ b/tests/parsers/winreg_plugins/winver.py @@ -5,11 +5,12 @@ import unittest from plaso.dfwinreg import definitions as dfwinreg_definitions +from plaso.dfwinreg import fake as dfwinreg_fake from plaso.formatters import winreg as _ # pylint: disable=unused-import +from plaso.lib import eventdata from plaso.lib import timelib from plaso.parsers.winreg_plugins import winver -from tests.dfwinreg import test_lib as dfwinreg_test_lib from tests.parsers.winreg_plugins import test_lib @@ -20,37 +21,64 @@ def setUp(self): """Sets up the needed objects used throughout the test.""" self._plugin = winver.WinVerPlugin() - def testWinVer(self): - """Test the WinVer plugin.""" - key_path = u'\\Microsoft\\Windows NT\\CurrentVersion' - values = [] + def _CreateTestKey(self, key_path, time_string): + """Creates Registry keys and values for testing. + + Args: + key_path: the Windows Registry key path. + time_string: string containing the key last written date and time. + + Returns: + A Windows Registry key (instance of dfwinreg.WinRegistryKey). + """ + filetime = dfwinreg_fake.Filetime() + filetime.CopyFromString(time_string) + registry_key = dfwinreg_fake.FakeWinRegistryKey( + u'CurrentVersion', key_path=key_path, + last_written_time=filetime.timestamp, offset=153) + + value_data = u'Service Pack 1'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'CSDVersion', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=1892) + registry_key.AddValue(registry_value) + + value_data = u'5.1'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'CurrentVersion', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=1121) + registry_key.AddValue(registry_value) - value_data = u'MyTestOS'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'ProductName', value_data, dfwinreg_definitions.REG_SZ, offset=123)) + value_data = b'\x13\x1aAP' + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'InstallDate', data=value_data, + data_type=dfwinreg_definitions.REG_DWORD_LITTLE_ENDIAN, offset=1001) + registry_key.AddValue(registry_value) - value_data = u'5'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'CSDBuildNumber', value_data, dfwinreg_definitions.REG_SZ, - offset=1892)) + value_data = u'MyTestOS'.encode(u'utf_16_le') + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'ProductName', data=value_data, data_type=dfwinreg_definitions.REG_SZ, + offset=123) + registry_key.AddValue(registry_value) value_data = u'A Concerned Citizen'.encode(u'utf_16_le') - values.append(dfwinreg_test_lib.TestRegValue( - u'RegisteredOwner', value_data, dfwinreg_definitions.REG_SZ, - offset=612)) + registry_value = dfwinreg_fake.FakeWinRegistryValue( + u'RegisteredOwner', data=value_data, + data_type=dfwinreg_definitions.REG_SZ, offset=612) + registry_key.AddValue(registry_value) - value_data = b'\x13\x1aAP' - values.append(dfwinreg_test_lib.TestRegValue( - u'InstallDate', value_data, dfwinreg_definitions.REG_BINARY, - offset=1001)) + return registry_key - timestamp = timelib.Timestamp.CopyFromString(u'2012-08-31 20:09:55') - winreg_key = dfwinreg_test_lib.TestRegKey(key_path, timestamp, values, 153) + def testProcess(self): + """Tests the Process function.""" + key_path = u'\\Microsoft\\Windows NT\\CurrentVersion' + time_string = u'2012-08-31 20:09:55.123521' + registry_key = self._CreateTestKey(key_path, time_string) - event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, winreg_key) + event_queue_consumer = self._ParseKeyWithPlugin(self._plugin, registry_key) event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) - self.assertEqual(len(event_objects), 1) + self.assertEqual(len(event_objects), 2) event_object = event_objects[0] @@ -58,24 +86,72 @@ def testWinVer(self): # and not through the parser. self.assertEqual(event_object.parser, self._plugin.plugin_name) + expected_timestamp = timelib.Timestamp.CopyFromString(time_string) + self.assertEqual(event_object.timestamp, expected_timestamp) + self.assertEqual(event_object.data_type, 'windows:registry:key_value') + + expected_message = ( + u'[{0:s}] ' + u'Owner: A Concerned Citizen ' + u'Product name: MyTestOS ' + u'Service pack: Service Pack 1 ' + u'Windows Version Information: 5.1').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) + + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) + + event_object = event_objects[1] + self.assertEqual( + event_object.timestamp_desc, eventdata.EventTimestamp.INSTALLATION_TIME) expected_timestamp = timelib.Timestamp.CopyFromString( u'2012-08-31 20:09:55') self.assertEqual(event_object.timestamp, expected_timestamp) + self.assertEqual(event_object.data_type, 'windows:registry:installation') - # Note that the double spaces here are intentional. - expected_msg = ( - u'[{0:s}] ' - u'Windows Version Information: ' - u'Owner: A Concerned Citizen ' - u'Product name: MyTestOS sp: 5').format(key_path) + expected_message = ( + u'MyTestOS 5.1 Service Pack 1 ' + u'Owner: owner ' + u'Origin: \\Microsoft\\Windows NT\\CurrentVersion') + expected_short_message = ( + u'MyTestOS 5.1 Service Pack 1 ' + u'Origin: \\Microsoft\\Windows NT\\CurrentVersion') - expected_msg_short = ( - u'[{0:s}] ' - u'Windows Version Information: ' - u'Owner: ...').format(key_path) + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) - self._TestGetMessageStrings(event_object, expected_msg, expected_msg_short) - # TODO: Write a test for a non-synthetic key + def testProcessFile(self): + """Tests the Process function on a Windows Registry file.""" + key_path = u'\\Microsoft\\Windows NT\\CurrentVersion' + test_file_entry = self._GetTestFileEntryFromPath([u'SOFTWARE-RunTests']) + registry_key = self._GetKeyFromFileEntry(test_file_entry, key_path) + event_queue_consumer = self._ParseKeyWithPlugin( + self._plugin, registry_key, file_entry=test_file_entry) + event_objects = self._GetEventObjectsFromQueue(event_queue_consumer) + + self.assertEqual(len(event_objects), 2) + + event_object = event_objects[0] + + # This should just be the plugin name, as we're invoking it directly, + # and not through the parser. + self.assertEqual(event_object.parser, self._plugin.plugin_name) + + expected_timestamp = timelib.Timestamp.CopyFromString( + u'2012-03-15 07:09:20.671875') + self.assertEqual(event_object.timestamp, expected_timestamp) + self.assertEqual(event_object.data_type, 'windows:registry:key_value') + + expected_message = ( + u'[{0:s}] ' + u'Owner: Windows User ' + u'Product name: Windows 7 Ultimate ' + u'Service pack: Service Pack 1 ' + u'Windows Version Information: 6.1').format(key_path) + expected_short_message = u'{0:s}...'.format(expected_message[0:77]) + + self._TestGetMessageStrings( + event_object, expected_message, expected_short_message) if __name__ == '__main__': diff --git a/tests/preprocessors/windows.py b/tests/preprocessors/windows.py index dc84438ae3..ce61c73925 100644 --- a/tests/preprocessors/windows.py +++ b/tests/preprocessors/windows.py @@ -31,7 +31,7 @@ def setUp(self): self._searcher = file_system_searcher.FileSystemSearcher( self._fake_file_system, mount_point) - registry_file_reader = dfwinreg_registry.WinRegistryFileReader( + registry_file_reader = dfwinreg_registry.SearcherWinRegistryFileReader( self._searcher, pre_obj=pre_obj) self._win_registry = dfwinreg_registry.WinRegistry( backend=dfwinreg_registry.WinRegistry.BACKEND_PYREGF, @@ -54,7 +54,7 @@ def setUp(self): self._searcher = file_system_searcher.FileSystemSearcher( self._fake_file_system, mount_point) - registry_file_reader = dfwinreg_registry.WinRegistryFileReader( + registry_file_reader = dfwinreg_registry.SearcherWinRegistryFileReader( self._searcher, pre_obj=pre_obj) self._win_registry = dfwinreg_registry.WinRegistry( backend=dfwinreg_registry.WinRegistry.BACKEND_PYREGF, diff --git a/tools/preg.py b/tools/preg.py index 62ffd7db94..f9d64a69b6 100755 --- a/tools/preg.py +++ b/tools/preg.py @@ -1284,8 +1284,8 @@ def _CommandGetCurrentKey(self): """Command function to retrieve the currently loaded Registry key. Returns: - The currently loaded Registry key (instance of WinPyregfKey) or None - if there is no loaded key. + The currently loaded Registry key (instance of dfwinreg.WinRegistryKey) + or None if there is no loaded key. """ registry_helper = self._currently_loaded_helper return registry_helper.GetCurrentRegistryKey() @@ -1297,9 +1297,9 @@ def _CommandGetValue(self, value_name): value_name: string containing the name of the value to be retrieved. Returns: - The Registry value (instance of WinPyregfValue) if it exists, None if - either there is no currently loaded Registry key or if the value does - not exist. + The Registry value (instance of dfwinreg.WinRegistryValue) if it exists, + None if either there is no currently loaded Registry key or if the value + does not exist. """ registry_helper = self._currently_loaded_helper @@ -1307,7 +1307,7 @@ def _CommandGetValue(self, value_name): if not current_key: return - return current_key.GetValue(value_name) + return current_key.GetValueByName(value_name) def _CommandGetValueData(self, value_name): """Return the value data from a value in the currently loaded Registry key.