diff --git a/config/dpkg/changelog b/config/dpkg/changelog index c410a97ef6..f81a9525ca 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, 03 Nov 2015 22:20:37 +0100 + -- Log2Timeline Thu, 12 Nov 2015 08:45:22 -0500 diff --git a/docs/plaso.dfwinreg.rst b/docs/plaso.dfwinreg.rst index d1688520ce..18f0f5db0e 100644 --- a/docs/plaso.dfwinreg.rst +++ b/docs/plaso.dfwinreg.rst @@ -36,14 +36,6 @@ plaso.dfwinreg.interface module :undoc-members: :show-inheritance: -plaso.dfwinreg.path_expander module ------------------------------------ - -.. automodule:: plaso.dfwinreg.path_expander - :members: - :undoc-members: - :show-inheritance: - plaso.dfwinreg.regf module -------------------------- diff --git a/plaso/__init__.py b/plaso/__init__.py index 4b5bdaeb7a..7260b5b1f5 100644 --- a/plaso/__init__.py +++ b/plaso/__init__.py @@ -3,7 +3,7 @@ __version__ = '1.3.1' VERSION_DEV = True -VERSION_DATE = '20151103' +VERSION_DATE = '20151112' def GetVersion(): diff --git a/plaso/dfwinreg/path_expander.py b/plaso/dfwinreg/path_expander.py deleted file mode 100644 index f027d62bec..0000000000 --- a/plaso/dfwinreg/path_expander.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -"""The Windows Registry key path expander.""" - - -class WinRegistryKeyPathExpander(object): - """Class that implements the Windows Registry key path expander object.""" - - def ExpandPath(self, key_path, path_attributes=None): - """Expand a Registry key path based on attributes in pre calculated values. - - A Registry key path may contain paths that are attributes, based on - calculations from either preprocessing or based on each individual - Windows Registry file. - - An attribute is defined as anything within a curly bracket, eg. - "\\System\\{my_attribute}\\Path\\Keyname". If the attribute my_attribute - is defined in the preprocessing object its 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, eg - "\\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 Windows Registry key path before being expanded. - path_attributes: optional dictionary of path attributes. - - Returns: - A Registry key path that's expanded based on attribute values. - - Raises: - KeyError: If an attribute name is in the key path not set in - the preprocessing object a KeyError will be raised. - """ - if not path_attributes: - return key_path - - try: - expanded_key_path = key_path.format(**path_attributes) - except KeyError as exception: - raise KeyError( - u'Unable to expand path with error: {0:s}'.format(exception)) - - return expanded_key_path diff --git a/plaso/dfwinreg/registry.py b/plaso/dfwinreg/registry.py index 262b454dd8..9e05838649 100644 --- a/plaso/dfwinreg/registry.py +++ b/plaso/dfwinreg/registry.py @@ -1,13 +1,6 @@ # -*- coding: utf-8 -*- """Classes for Windows Registry access.""" -import logging - -from dfvfs.helpers import file_system_searcher -from dfvfs.resolver import resolver - -from plaso.dfwinreg import interface -from plaso.dfwinreg import path_expander from plaso.dfwinreg import regf @@ -41,49 +34,46 @@ class WinRegistry(object): _PATH_SEPARATOR = u'\\' - # TODO: refactor to use %SystemRoot% and %UserProfile% instead. - # TODO: refactor to use Windows paths. - _REGISTRY_FILE_MAPPINGS_9X = [ WinRegistryFileMapping( u'HKEY_LOCAL_MACHINE', - u'{systemroot}/SYSTEM.DAT', + u'%SystemRoot%\\SYSTEM.DAT', []), WinRegistryFileMapping( u'HKEY_USERS', - u'{systemroot}/USER.DAT', + u'%SystemRoot%\\USER.DAT', []), ] _REGISTRY_FILE_MAPPINGS_NT = [ WinRegistryFileMapping( u'HKEY_CURRENT_USER', - u'{userprofile}/NTUSER.DAT', + u'%UserProfile%\\NTUSER.DAT', [u'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer']), WinRegistryFileMapping( u'HKEY_CURRENT_USER\\Software\\Classes', - u'{userprofile}/AppData/Local/Microsoft/Windows/UsrClass.dat', + u'%UserProfile%\\AppData\\Local\\Microsoft\\Windows\\UsrClass.dat', [u'\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion']), WinRegistryFileMapping( u'HKEY_CURRENT_USER\\Software\\Classes', - (u'{userprofile}/Local Settings/Application Data/Microsoft/' - u'Windows/UsrClass.dat'), + (u'%UserProfile%\\Local Settings\\Application Data\\Microsoft\\' + u'Windows\\UsrClass.dat'), []), WinRegistryFileMapping( u'HKEY_LOCAL_MACHINE\\SAM', - u'{systemroot}/System32/config/SAM', + u'%SystemRoot%\\System32\\config\\SAM', [u'\\SAM\\Domains\\Account\\Users']), WinRegistryFileMapping( u'HKEY_LOCAL_MACHINE\\Security', - u'{systemroot}/System32/config/SECURITY', + u'%SystemRoot%\\System32\\config\\SECURITY', [u'\\Policy\\PolAdtEv']), WinRegistryFileMapping( u'HKEY_LOCAL_MACHINE\\Software', - u'{systemroot}/System32/config/SOFTWARE', + u'%SystemRoot%\\System32\\config\\SOFTWARE', [u'\\Microsoft\\Windows\\CurrentVersion\\App Paths']), WinRegistryFileMapping( u'HKEY_LOCAL_MACHINE\\System', - u'{systemroot}/System32/config/SYSTEM', + u'%SystemRoot%\\System32\\config\\SYSTEM', [u'\\Select']) ] @@ -436,220 +426,3 @@ def OpenFileEntry(self, file_entry): registry_file = None return registry_file - - -class PathSpecWinRegistryFileReader(interface.WinRegistryFileReader): - """A single path specification Windows Registry file reader.""" - - def __init__(self, path_spec): - """Initializes a Windows Registry file reader object. - - Args: - path_spec: a path specification (instance of dfvfs.PathSpec). - """ - super(PathSpecWinRegistryFileReader, self).__init__() - self._path_spec = path_spec - - def _OpenPathSpec(self, path_spec, ascii_codepage=u'cp1252'): - """Opens the Windows Registry file specified by the path specification. - - Args: - path_spec: a path specification (instance of dfvfs.PathSpec). - ascii_codepage: optional ASCII string codepage. The default is cp1252 - (or windows-1252). - - Returns: - The Windows Registry file (instance of WinRegistryFile) or None. - """ - if not path_spec: - return - - file_entry = resolver.Resolver.OpenFileEntry(path_spec) - if file_entry is None: - return - - file_object = file_entry.GetFileObject() - if file_object is None: - return - - registry_file = regf.REGFWinRegistryFile(ascii_codepage=ascii_codepage) - try: - registry_file.Open(file_object) - except IOError as exception: - logging.warning( - u'Unable to open Windows Registry file with error: {0:s}'.format( - exception)) - file_object.close() - return - - return registry_file - - def Open(self, path, ascii_codepage=u'cp1252'): - """Opens the Windows Registry file specified 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. - """ - return self._OpenPathSpec(self._path_spec) - - -class SearcherWinRegistryFileReader(interface.WinRegistryFileReader): - """A file system searcher-based Windows Registry file reader.""" - - def __init__(self, searcher, path_attributes=None): - """Initializes a Windows Registry file reader object. - - Args: - searcher: the file system searcher object (instance of - dfvfs.FileSystemSearcher). - path_attributes: optional dictionary of path attributes. - """ - super(SearcherWinRegistryFileReader, self).__init__() - self._file_path_expander = path_expander.WinRegistryKeyPathExpander() - self._path_attributes = path_attributes or {} - self._searcher = searcher - - def _FindPathSpec(self, path): - """Searches for a path specification. - - Args: - path: the path of the Windows Registry file. - - Returns: - A path specification (instance of dfvfs.PathSpec) of - the Windows Registry file. - - Raises: - 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. - find_spec = file_system_searcher.FindSpec( - location=path, case_sensitive=False) - path_specs = list(self._searcher.Find(find_specs=[find_spec])) - - if not path_specs or len(path_specs) != 1: - raise IOError( - u'Unable to find directory: {0:s}'.format(path)) - - relative_path = self._searcher.GetRelativePath(path_specs[0]) - if not relative_path: - raise IOError(u'Unable to determine relative path of: {0:s}'.format(path)) - - # The path is split in segments to make it path segement separator - # independent (and thus platform independent). - path_segments = self._searcher.SplitPath(relative_path) - path_segments.append(filename) - - find_spec = file_system_searcher.FindSpec( - location=path_segments, case_sensitive=False) - path_specs = list(self._searcher.Find(find_specs=[find_spec])) - - if not path_specs: - raise IOError( - u'Unable to find file: {0:s} in directory: {1:s}'.format( - filename, relative_path)) - - if len(path_specs) != 1: - raise IOError(( - u'Find for file: {0:s} in directory: {1:s} returned {2:d} ' - u'results.').format(filename, relative_path, len(path_specs))) - - if not relative_path: - raise IOError( - u'Missing file: {0:s} in directory: {1:s}'.format( - filename, relative_path)) - - return path_specs[0] - - def _OpenPathSpec(self, path_spec, ascii_codepage=u'cp1252'): - """Opens the Windows Registry file specified by the path specification. - - Args: - path_spec: a path specification (instance of dfvfs.PathSpec). - ascii_codepage: optional ASCII string codepage. The default is cp1252 - (or windows-1252). - - Returns: - The Windows Registry file (instance of WinRegistryFile) or None. - """ - if not path_spec: - return - - file_entry = self._searcher.GetFileEntryByPathSpec(path_spec) - if file_entry is None: - return - - file_object = file_entry.GetFileObject() - if file_object is None: - return - - registry_file = regf.REGFWinRegistryFile(ascii_codepage=ascii_codepage) - try: - registry_file.Open(file_object) - except IOError as exception: - logging.warning( - u'Unable to open Windows Registry file with error: {0:s}'.format( - exception)) - file_object.close() - return - - return registry_file - - def Open(self, path, ascii_codepage=u'cp1252'): - """Opens the Windows Registry file specified 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. - """ - try: - expanded_path = self._file_path_expander.ExpandPath( - path, path_attributes=self._path_attributes) - - except KeyError as exception: - logging.warning( - u'Unable to expand path: {0:s} with error: {1:s}'.format( - path, exception)) - expanded_path = path - - path_spec = self._FindPathSpec(expanded_path) - return self._OpenPathSpec(path_spec) - - -class FileObjectWinRegistryFileReader(interface.WinRegistryFileReader): - """A single file-like object Windows Registry file reader.""" - - def Open(self, file_object, ascii_codepage=u'cp1252'): - """Opens a Windows Registry file-like object. - - Args: - file_object: the Windows Registry file-like object. - 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(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/engine/utils.py b/plaso/engine/utils.py index b1a32dd41e..d1e2de499f 100644 --- a/plaso/engine/utils.py +++ b/plaso/engine/utils.py @@ -5,7 +5,47 @@ from dfvfs.helpers import file_system_searcher -from plaso.dfwinreg import path_expander as dfwinreg_path_expander + +class _PathExpander(object): + """Class that implements the path expander.""" + + def ExpandPath(self, path, path_attributes=None): + """Expands a path based on attributes in pre calculated values. + + A path may contain paths that are attributes, based on calculations + from preprocessing. + + 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 its value will be replaced with the attribute + name, e.g. "\\System\\MyValue\\Path\\Keyname". + + If the 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: + path: the path before being expanded. + path_attributes: optional dictionary of path attributes. + + Returns: + A Registry key path that's expanded based on attribute values. + + Raises: + KeyError: If an attribute name is in the key path not set in + the preprocessing object a KeyError will be raised. + """ + if not path_attributes: + return path + + try: + expanded_path = path.format(**path_attributes) + except KeyError as exception: + raise KeyError( + u'Unable to expand path with error: {0:s}'.format(exception)) + + return expanded_path def BuildFindSpecsFromFile(filter_file_path, pre_obj=None): @@ -19,7 +59,7 @@ def BuildFindSpecsFromFile(filter_file_path, pre_obj=None): find_specs = [] if pre_obj: - expander = dfwinreg_path_expander.WinRegistryKeyPathExpander() + expander = _PathExpander() with open(filter_file_path, 'rb') as file_object: for line in file_object: diff --git a/plaso/parsers/winreg.py b/plaso/parsers/winreg.py index f308720365..74b6d70e80 100644 --- a/plaso/parsers/winreg.py +++ b/plaso/parsers/winreg.py @@ -1,12 +1,44 @@ # -*- coding: utf-8 -*- """Parser for Windows NT Registry (REGF) files.""" +import logging + +from plaso.dfwinreg import interface as dfwinreg_interface +from plaso.dfwinreg import regf as dfwinreg_regf from plaso.dfwinreg import registry as dfwinreg_registry from plaso.lib import specification from plaso.parsers import interface from plaso.parsers import manager +class FileObjectWinRegistryFileReader(dfwinreg_interface.WinRegistryFileReader): + """A single file-like object Windows Registry file reader.""" + + def Open(self, file_object, ascii_codepage=u'cp1252'): + """Opens a Windows Registry file-like object. + + Args: + file_object: the Windows Registry file-like object. + 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 = dfwinreg_regf.REGFWinRegistryFile( + ascii_codepage=ascii_codepage) + + try: + registry_file.Open(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 + + # TODO: rename to REGFParser. class WinRegistryParser(interface.FileObjectParser): """Parses Windows NT Registry (REGF) files.""" @@ -60,7 +92,7 @@ def ParseFileObject(self, parser_mediator, file_object, **kwargs): parser_mediator: a parser mediator object (instance of ParserMediator). file_object: a file-like object. """ - win_registry_reader = dfwinreg_registry.FileObjectWinRegistryFileReader() + win_registry_reader = FileObjectWinRegistryFileReader() registry_file = win_registry_reader.Open(file_object) win_registry = dfwinreg_registry.WinRegistry() diff --git a/plaso/preprocessors/manager.py b/plaso/preprocessors/manager.py index 6ac8633028..61febb57c5 100644 --- a/plaso/preprocessors/manager.py +++ b/plaso/preprocessors/manager.py @@ -4,11 +4,103 @@ import logging from dfvfs.helpers import file_system_searcher +from dfvfs.helpers import windows_path_resolver +from plaso.dfwinreg import interface as dfwinreg_interface +from plaso.dfwinreg import regf as dfwinreg_regf from plaso.dfwinreg import registry as dfwinreg_registry from plaso.lib import errors +class FileSystemWinRegistryFileReader(dfwinreg_interface.WinRegistryFileReader): + """A file system-based Windows Registry file reader.""" + + def __init__(self, file_system, mount_point, path_attributes=None): + """Initializes a Windows Registry file reader object. + + Args: + file_system: the file system object (instance of vfs.FileSystem). + mount_point: the mount point path specification (instance of + path.PathSpec). + path_attributes: optional dictionary of path attributes. The path + attributes correspond to environment variable names + that can be used in the Windows paths. E.g. the + systemroot path attribute corresponds to the + %SystemRoot% environment variable. At moment only + the systemroot and userprofile path attributes are + supported. + """ + super(FileSystemWinRegistryFileReader, self).__init__() + self._file_system = file_system + self._path_resolver = windows_path_resolver.WindowsPathResolver( + file_system, mount_point) + + if path_attributes: + for attribute_name, attribute_value in iter(path_attributes.items()): + # TODO: fix the call to this class and make sure only relevant + # values are passed. + if attribute_name == u'systemroot': + self._path_resolver.SetEnvironmentVariable( + u'SystemRoot', attribute_value) + + elif attribute_name == u'userprofile': + self._path_resolver.SetEnvironmentVariable( + u'UserProfile', attribute_value) + + def _OpenPathSpec(self, path_spec, ascii_codepage=u'cp1252'): + """Opens the Windows Registry file specified by the path specification. + + Args: + path_spec: a path specfication (instance of dfvfs.PathSpec). + ascii_codepage: optional ASCII string codepage. The default is cp1252 + (or windows-1252). + + Returns: + The Windows Registry file (instance of WinRegistryFile) or None. + """ + if not path_spec: + return + + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + if file_entry is None: + return + + file_object = file_entry.GetFileObject() + if file_object is None: + return + + registry_file = dfwinreg_regf.REGFWinRegistryFile( + ascii_codepage=ascii_codepage) + + try: + registry_file.Open(file_object) + except IOError as exception: + logging.warning( + u'Unable to open Windows Registry file with error: {0:s}'.format( + exception)) + file_object.close() + return + + return registry_file + + def Open(self, path, ascii_codepage=u'cp1252'): + """Opens the Windows Registry file specified by the path. + + Args: + path: string containing 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. + """ + path_spec = self._path_resolver.ResolvePath(path) + if path_spec is None: + return + + return self._OpenPathSpec(path_spec) + + class PreprocessPluginsManager(object): """Class that implements the preprocess plugins manager.""" @@ -158,10 +250,8 @@ def RunPlugins(cls, platform, file_system, mount_point, knowledge_base): pre_obj = None path_attributes = None - # TODO: do not pass the full pre_obj here but just - # the necessary values. - registry_file_reader = dfwinreg_registry.SearcherWinRegistryFileReader( - searcher, path_attributes=path_attributes) + registry_file_reader = FileSystemWinRegistryFileReader( + file_system, mount_point, path_attributes=path_attributes) win_registry = dfwinreg_registry.WinRegistry( registry_file_reader=registry_file_reader) diff --git a/plaso/preprocessors/windows.py b/plaso/preprocessors/windows.py index b78bbe0372..d9b9c639ce 100644 --- a/plaso/preprocessors/windows.py +++ b/plaso/preprocessors/windows.py @@ -107,8 +107,12 @@ def Run(self, win_registry, knowledge_base): registry_key = self._GetKeyByPath( win_registry, self.KEY_PATH, path_attributes) + if not registry_key: + return attribute_value = self._ParseKey(registry_key) + if not attribute_value: + return knowledge_base.SetValue(self.ATTRIBUTE, attribute_value) diff --git a/tests/preprocessors/windows.py b/tests/preprocessors/windows.py index f5dd0a3bd4..e6b4945d98 100644 --- a/tests/preprocessors/windows.py +++ b/tests/preprocessors/windows.py @@ -9,6 +9,7 @@ from plaso.dfwinreg import registry as dfwinreg_registry from plaso.engine import knowledge_base +from plaso.preprocessors import manager from plaso.preprocessors import windows from tests.preprocessors import test_lib @@ -19,18 +20,15 @@ class WindowsSoftwareRegistryTest(test_lib.PreprocessPluginTest): def setUp(self): """Sets up the needed objects used throughout the test.""" - path_attributes = {u'systemroot': u'/Windows'} + path_attributes = {u'systemroot': u'\\Windows'} file_data = self._ReadTestFile([u'SOFTWARE']) self._fake_file_system = self._BuildSingleFileFakeFileSystem( u'/Windows/System32/config/SOFTWARE', file_data) mount_point = fake_path_spec.FakePathSpec(location=u'/') - self._searcher = file_system_searcher.FileSystemSearcher( - self._fake_file_system, mount_point) - - registry_file_reader = dfwinreg_registry.SearcherWinRegistryFileReader( - self._searcher, path_attributes=path_attributes) + registry_file_reader = manager.FileSystemWinRegistryFileReader( + self._fake_file_system, mount_point, path_attributes=path_attributes) self._win_registry = dfwinreg_registry.WinRegistry( registry_file_reader=registry_file_reader) @@ -40,18 +38,15 @@ class WindowsSystemRegistryTest(test_lib.PreprocessPluginTest): def setUp(self): """Sets up the needed objects used throughout the test.""" - path_attributes = {u'systemroot': u'/Windows'} + path_attributes = {u'systemroot': u'\\Windows'} file_data = self._ReadTestFile([u'SYSTEM']) self._fake_file_system = self._BuildSingleFileFakeFileSystem( u'/Windows/System32/config/SYSTEM', file_data) mount_point = fake_path_spec.FakePathSpec(location=u'/') - self._searcher = file_system_searcher.FileSystemSearcher( - self._fake_file_system, mount_point) - - registry_file_reader = dfwinreg_registry.SearcherWinRegistryFileReader( - self._searcher, path_attributes=path_attributes) + registry_file_reader = manager.FileSystemWinRegistryFileReader( + self._fake_file_system, mount_point, path_attributes=path_attributes) self._win_registry = dfwinreg_registry.WinRegistry( registry_file_reader=registry_file_reader) @@ -109,7 +104,7 @@ def testGetValue(self): path = knowledge_base_object.GetValue(u'programfilesx86') # The test SOFTWARE Registry file does not contain a value for # the Program Files X86 path. - self.assertEqual(path, None) + self.assertIsNone(path) class WindowsSystemRegistryPathTest(test_lib.PreprocessPluginTest): @@ -187,6 +182,7 @@ def testGetValue(self): plugin.Run(self._win_registry, knowledge_base_object) users = knowledge_base_object.GetValue(u'users') + self.assertIsNotNone(users) self.assertEqual(len(users), 11) expected_sid = u'S-1-5-21-2036804247-3058324640-2116585241-1114'