def testExpandUsersHomeDirectoryPath(self): """Tests the ExpandUsersHomeDirectoryPath function.""" user_account_artifact1 = artifacts.UserAccountArtifact( user_directory='C:\\Users\\Test1', username='******') user_account_artifact2 = artifacts.UserAccountArtifact( user_directory='%SystemDrive%\\Users\\Test2', username='******') path = '%%users.homedir%%\\Profile' expanded_paths = path_helper.PathHelper.ExpandUsersHomeDirectoryPath( path, '\\', [user_account_artifact1, user_account_artifact2]) expected_expanded_paths = [ '\\Users\\Test1\\Profile', '\\Users\\Test2\\Profile' ] self.assertEqual(expanded_paths, expected_expanded_paths) path = 'C:\\Temp' expanded_paths = path_helper.PathHelper.ExpandUsersHomeDirectoryPath( path, '\\', [user_account_artifact1, user_account_artifact2]) expected_expanded_paths = ['\\Temp'] self.assertEqual(expanded_paths, expected_expanded_paths) path = 'C:\\Temp\\%%users.homedir%%' expanded_paths = path_helper.PathHelper.ExpandUsersHomeDirectoryPath( path, '\\', [user_account_artifact1, user_account_artifact2]) expected_expanded_paths = ['\\Temp\\%%users.homedir%%'] self.assertEqual(expanded_paths, expected_expanded_paths)
def testExpandUsersVariablePathSegments(self): """Tests the _ExpandUsersVariablePathSegments function.""" user_account_artifact1 = artifacts.UserAccountArtifact( identifier='1000', path_separator='\\', user_directory='C:\\Users\\Test1', username='******') user_account_artifact2 = artifacts.UserAccountArtifact( identifier='1001', path_separator='\\', user_directory='%SystemDrive%\\Users\\Test2', username='******') user_accounts = [user_account_artifact1, user_account_artifact2] path_segments = ['%%users.appdata%%', 'Microsoft', 'Windows', 'Recent'] expanded_paths = path_helper.PathHelper._ExpandUsersVariablePathSegments( path_segments, '\\', user_accounts) expected_expanded_paths = [ '\\Users\\Test1\\AppData\\Roaming\\Microsoft\\Windows\\Recent', '\\Users\\Test1\\Application Data\\Microsoft\\Windows\\Recent', '\\Users\\Test2\\AppData\\Roaming\\Microsoft\\Windows\\Recent', '\\Users\\Test2\\Application Data\\Microsoft\\Windows\\Recent'] self.assertEqual(sorted(expanded_paths), expected_expanded_paths) path_segments = ['C:', 'Windows'] expanded_paths = path_helper.PathHelper._ExpandUsersVariablePathSegments( path_segments, '\\', user_accounts) expected_expanded_paths = ['\\Windows'] self.assertEqual(sorted(expanded_paths), expected_expanded_paths)
def testExpandUsersHomeDirectoryPathSegments(self): """Tests the _ExpandUsersHomeDirectoryPathSegments function.""" user_account_artifact1 = artifacts.UserAccountArtifact( user_directory='/home/Test1', username='******') user_account_artifact2 = artifacts.UserAccountArtifact( user_directory='/Users/Test2', username='******') user_account_artifact3 = artifacts.UserAccountArtifact( username='******') user_accounts = [ user_account_artifact1, user_account_artifact2, user_account_artifact3 ] path_segments = ['%%users.homedir%%', '.bashrc'] expanded_paths = ( path_helper.PathHelper._ExpandUsersHomeDirectoryPathSegments( path_segments, '/', user_accounts)) expected_expanded_paths = [ '/home/Test1/.bashrc', '/Users/Test2/.bashrc' ] self.assertEqual(expanded_paths, expected_expanded_paths) user_account_artifact1 = artifacts.UserAccountArtifact( path_separator='\\', user_directory='C:\\Users\\Test1', username='******') user_account_artifact2 = artifacts.UserAccountArtifact( path_separator='\\', user_directory='%SystemDrive%\\Users\\Test2', username='******') user_accounts = [user_account_artifact1, user_account_artifact2] path_segments = ['%%users.userprofile%%', 'Profile'] expanded_paths = ( path_helper.PathHelper._ExpandUsersHomeDirectoryPathSegments( path_segments, '\\', user_accounts)) expected_expanded_paths = [ '\\Users\\Test1\\Profile', '\\Users\\Test2\\Profile' ] self.assertEqual(expanded_paths, expected_expanded_paths) path_segments = ['C:', 'Temp'] expanded_paths = ( path_helper.PathHelper._ExpandUsersHomeDirectoryPathSegments( path_segments, '\\', user_accounts)) expected_expanded_paths = ['\\Temp'] self.assertEqual(expanded_paths, expected_expanded_paths) path_segments = ['C:', 'Temp', '%%users.userprofile%%'] expanded_paths = ( path_helper.PathHelper._ExpandUsersHomeDirectoryPathSegments( path_segments, '\\', user_accounts)) expected_expanded_paths = ['\\Temp\\%%users.userprofile%%'] self.assertEqual(expanded_paths, expected_expanded_paths)
def _CreateTestKnowledgeBaseWindows(self): """Creates a knowlege base for testing Windows paths. Creates a knowledge base with 2 user accounts. Returns: KnowledgeBase: knowledge base. """ knowledge_base = knowledge_base_engine.KnowledgeBase() test_user1 = artifacts.UserAccountArtifact( identifier='1000', path_separator='\\', user_directory='C:\\Users\\testuser1', username='******') knowledge_base.AddUserAccount(test_user1) test_user2 = artifacts.UserAccountArtifact( identifier='1001', path_separator='\\', user_directory='%SystemDrive%\\Users\\testuser2', username='******') knowledge_base.AddUserAccount(test_user2) return knowledge_base
def testBuildFindSpecsWithFileSystem(self): """Tests the BuildFindSpecs function for file type artifacts.""" knowledge_base = knowledge_base_engine.KnowledgeBase() testuser1 = artifacts.UserAccountArtifact( identifier='1000', user_directory='C:\\\\Users\\\\testuser1', username='******') knowledge_base.AddUserAccount(testuser1) testuser2 = artifacts.UserAccountArtifact( identifier='1001', user_directory='C:\\\\Users\\\\testuser2', username='******') knowledge_base.AddUserAccount(testuser2) test_filter_file = self._CreateTestArtifactDefinitionsFilterHelper( ['TestFiles', 'TestFiles2'], knowledge_base) environment_variable = artifacts.EnvironmentVariableArtifact( case_sensitive=False, name='SystemDrive', value='C:') test_filter_file.BuildFindSpecs( environment_variables=[environment_variable]) find_specs_per_source_type = knowledge_base.GetValue( test_filter_file.KNOWLEDGE_BASE_VALUE) find_specs = find_specs_per_source_type.get( artifact_types.TYPE_INDICATOR_FILE, []) # Should build 15 FindSpec entries. self.assertEqual(len(find_specs), 15) # Last find_spec should contain the testuser2 profile path. location_segments = sorted( [find_spec._location_segments for find_spec in find_specs]) path_segments = [ 'Users', 'testuser2', 'Documents', 'WindowsPowerShell', 'profile\\.ps1' ] self.assertEqual(location_segments[2], path_segments) path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location='.') file_system = path_spec_resolver.Resolver.OpenFileSystem(path_spec) searcher = file_system_searcher.FileSystemSearcher( file_system, path_spec) path_spec_generator = searcher.Find(find_specs=find_specs) self.assertIsNotNone(path_spec_generator) path_specs = list(path_spec_generator) # Two evtx, one symbolic link to evtx, one AUTHORS, two filter_*.txt files, # total 6 path specifications. self.assertEqual(len(path_specs), 6) file_system.Close()
def _ParseKey(self, mediator, registry_key, value_name): """Parses a Windows Registry key for a preprocessing attribute. Args: mediator (PreprocessMediator): mediates interactions between preprocess plugins and other components, such as storage and knowledge base. registry_key (dfwinreg.WinRegistryKey): Windows Registry key. value_name (str): name of the Windows Registry value or None if not specified. Raises: errors.PreProcessFail: if the preprocessing fails. """ user_account = artifacts.UserAccountArtifact( identifier=registry_key.name, path_separator='\\') registry_value = registry_key.GetValueByName('ProfileImagePath') if registry_value: profile_path = registry_value.GetDataAsObject() username = self._GetUsernameFromProfilePath(profile_path) user_account.user_directory = profile_path or None user_account.username = username or None try: mediator.AddUserAccount(user_account) except KeyError: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, ('Unable to add user account: "{0!s}" to knowledge ' 'base').format(username))
def _ParseFileObject(self, knowledge_base, file_object): """Parses a passwd file-like object. A passwd file consist of colon seperated values in the format: "username:password:uid:gid:full name:home directory:shell". Args: knowledge_base (KnowledgeBase): to fill with preprocessing information. file_object (dfvfs.FileIO): file-like object. Raises: errors.PreProcessFail: if the preprocessing fails. """ text_file_object = text_file.TextFile(file_object) try: reader = csv.reader(text_file_object, delimiter=b':') except csv.Error: raise errors.PreProcessFail(u'Unable to read: {0:s}.'.format(self._PATH)) for row in reader: if len(row) < 7 or not row[0] or not row[2]: # TODO: add and store preprocessing errors. continue user_account = artifacts.UserAccountArtifact( identifier=row[2], username=row[0]) user_account.group_identifier = row[3] or None user_account.full_name = row[4] or None user_account.user_directory = row[5] or None user_account.shell = row[6] or None # TODO: refactor the use of store number. user_account.store_number = 0 knowledge_base.SetUserAccount(user_account)
def _ParseKey(self, knowledge_base, registry_key, value_name): """Parses a Windows Registry key for a preprocessing attribute. Args: knowledge_base (KnowledgeBase): to fill with preprocessing information. registry_key (dfwinreg.WinRegistryKey): Windows Registry key. value_name (str): name of the Windows Registry value. Raises: errors.PreProcessFail: if the preprocessing fails. """ user_account = artifacts.UserAccountArtifact( identifier=registry_key.name) registry_value = registry_key.GetValueByName('ProfileImagePath') if registry_value: profile_path = registry_value.GetDataAsObject() username = self._GetUsernameFromProfilePath(profile_path) user_account.user_directory = profile_path or None user_account.username = username or None try: knowledge_base.AddUserAccount(user_account) except KeyError: # TODO: add and store preprocessing errors. pass
def _ParseKey(self, knowledge_base, registry_key): """Parses a Windows Registry key for a preprocessing attribute. Args: knowledge_base (KnowledgeBase): to fill with preprocessing information. registry_key (WinRegistryKey): Windows Registry key. """ for subkey in registry_key.GetSubkeys(): if not subkey.name: # TODO: add and store preprocessing errors. continue user_account = artifacts.UserAccountArtifact( identifier=subkey.name) registry_value = subkey.GetValueByName(u'ProfileImagePath') if registry_value: profile_path = registry_value.GetDataAsObject() username = self._GetUsernameFromPath(profile_path) user_account.user_directory = profile_path or None user_account.username = username or None # TODO: refactor the use of store number. user_account.store_number = 0 knowledge_base.SetUserAccount(user_account)
def testGetAttributeNames(self): """Tests the GetAttributeNames function.""" attribute_container = artifacts.UserAccountArtifact() expected_attribute_names = [ 'full_name', 'group_identifier', 'identifier', 'user_directory', 'username'] attribute_names = sorted(attribute_container.GetAttributeNames()) self.assertEqual(attribute_names, expected_attribute_names)
def testAddUserAccount(self): """Tests the AddUserAccount function.""" knowledge_base_object = knowledge_base.KnowledgeBase() user_account = artifacts.UserAccountArtifact( identifier='1000', user_directory='/home/testuser', username='******') knowledge_base_object.AddUserAccount(user_account) with self.assertRaises(KeyError): knowledge_base_object.AddUserAccount(user_account)
def testExpandUsersVariablePath(self): """Tests the ExpandUsersVariablePath function.""" user_account_artifact1 = artifacts.UserAccountArtifact( user_directory='C:\\Users\\Test1', username='******') user_account_artifact2 = artifacts.UserAccountArtifact( user_directory='%SystemDrive%\\Users\\Test2', username='******') user_accounts = [user_account_artifact1, user_account_artifact2] path = '%%users.appdata%%\\Microsoft\\Windows\\Recent' expanded_paths = path_helper.PathHelper.ExpandUsersVariablePath( path, '\\', user_accounts) expected_expanded_paths = [ '\\Users\\Test1\\AppData\\Roaming\\Microsoft\\Windows\\Recent', '\\Users\\Test1\\Application Data\\Microsoft\\Windows\\Recent', '\\Users\\Test2\\AppData\\Roaming\\Microsoft\\Windows\\Recent', '\\Users\\Test2\\Application Data\\Microsoft\\Windows\\Recent' ] self.assertEqual(sorted(expanded_paths), expected_expanded_paths)
def testHasUserAccounts(self): """Tests the HasUserAccounts function.""" knowledge_base_object = knowledge_base.KnowledgeBase() self.assertFalse(knowledge_base_object.HasUserAccounts()) user_account = artifacts.UserAccountArtifact( identifier='1000', user_directory='/home/testuser', username='******') knowledge_base_object.AddUserAccount(user_account) self.assertTrue(knowledge_base_object.HasUserAccounts())
def testUserAccountsProperty(self): """Tests the user accounts property.""" knowledge_base_object = knowledge_base.KnowledgeBase() self.assertEqual(len(knowledge_base_object.user_accounts), 0) user_account = artifacts.UserAccountArtifact( identifier='1000', user_directory='/home/testuser', username='******') knowledge_base_object.AddUserAccount(user_account) self.assertEqual(len(knowledge_base_object.user_accounts), 1)
def _ParseFileEntry(self, knowledge_base, file_entry): """Parses artifact file system data for a preprocessing attribute. Args: knowledge_base (KnowledgeBase): to fill with preprocessing information. file_entry (dfvfs.FileEntry): file entry that contains the artifact value data. Returns: bool: True if all the preprocessing attributes were found and the preprocessor plugin is done. Raises: errors.PreProcessFail: if the preprocessing fails. """ root_key = self._GetPlistRootKey(file_entry) if not root_key: location = getattr(file_entry.path_spec, 'location', '') raise errors.PreProcessFail( ('Unable to read: {0:s} plist: {1:s} with error: missing root ' 'key.').format(self.ARTIFACT_DEFINITION_NAME, location)) try: match = self._GetKeysDefaultEmpty(root_key, self._KEYS) except KeyError as exception: location = getattr(file_entry.path_spec, 'location', '') raise errors.PreProcessFail( 'Unable to read: {0:s} plist: {1:s} with error: {2!s}'.format( self.ARTIFACT_DEFINITION_NAME, location, exception)) name = match.get('name', [None])[0] uid = match.get('uid', [None])[0] if not name or not uid: # TODO: add and store preprocessing errors. return False user_account = artifacts.UserAccountArtifact(identifier=uid, username=name) user_account.group_identifier = match.get('gid', [None])[0] user_account.full_name = match.get('realname', [None])[0] user_account.shell = match.get('shell', [None])[0] user_account.user_directory = match.get('home', [None])[0] try: knowledge_base.AddUserAccount(user_account) except KeyError: # TODO: add and store preprocessing errors. pass return False
def _ParseFileEntry(self, mediator, file_entry): """Parses artifact file system data for a preprocessing attribute. Args: mediator (PreprocessMediator): mediates interactions between preprocess plugins and other components, such as storage and knowledge base. file_entry (dfvfs.FileEntry): file entry that contains the artifact value data. Raises: errors.PreProcessFail: if the preprocessing fails. """ file_object = file_entry.GetFileObject() try: plist_file = plist.PlistFile() plist_file.Read(file_object) match = self._GetTopLevelKeys(plist_file.root_key, self._KEYS) except (IOError, plistlib.InvalidFileException) as exception: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to read plist with error: {0!s}.'.format(exception)) return name = match.get('name', [None])[0] uid = match.get('uid', [None])[0] if not name or not uid: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Missing name or user identifier') return user_account = artifacts.UserAccountArtifact(identifier=uid, username=name) user_account.group_identifier = match.get('gid', [None])[0] user_account.full_name = match.get('realname', [None])[0] user_account.shell = match.get('shell', [None])[0] user_account.user_directory = match.get('home', [None])[0] try: mediator.AddUserAccount(user_account) except KeyError: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to add user account: {0:s} to knowledge base.'.format( name))
def testGetSystemConfigurationArtifact(self): """Tests the GetSystemConfigurationArtifact function.""" knowledge_base_object = knowledge_base.KnowledgeBase() hostname_artifact = artifacts.HostnameArtifact(name='myhost.mydomain') knowledge_base_object.SetHostname(hostname_artifact) user_account = artifacts.UserAccountArtifact( identifier='1000', user_directory='/home/testuser', username='******') knowledge_base_object.AddUserAccount(user_account) system_configuration = ( knowledge_base_object.GetSystemConfigurationArtifact()) self.assertIsNotNone(system_configuration) self.assertIsNotNone(system_configuration.hostname) self.assertEqual(system_configuration.hostname.name, 'myhost.mydomain')
def testGetUsernameByIdentifier(self): """Tests the GetUsernameByIdentifier function.""" knowledge_base_object = knowledge_base.KnowledgeBase() user_account = artifacts.UserAccountArtifact( identifier='1000', user_directory='/home/testuser', username='******') knowledge_base_object.AddUserAccount(user_account) usename = knowledge_base_object.GetUsernameByIdentifier('1000') self.assertEqual(usename, 'testuser') usename = knowledge_base_object.GetUsernameByIdentifier(1000) self.assertEqual(usename, '') usename = knowledge_base_object.GetUsernameByIdentifier('1001') self.assertEqual(usename, '')
def testReadSystemConfigurationArtifact(self): """Tests the ReadSystemConfigurationArtifact function.""" knowledge_base_object = knowledge_base.KnowledgeBase() system_configuration = artifacts.SystemConfigurationArtifact() system_configuration.hostname = artifacts.HostnameArtifact( name='myhost.mydomain') user_account = artifacts.UserAccountArtifact( identifier='1000', user_directory='/home/testuser', username='******') system_configuration.user_accounts.append(user_account) knowledge_base_object.ReadSystemConfigurationArtifact(system_configuration) hostname = knowledge_base_object.GetHostname() self.assertEqual(hostname, 'myhost.mydomain')
def _SetUserAccounts(self, knowledge_base_object, users): """Sets the user accounts in the knowledge base. Args: knowledge_base_object (KnowledgeBase): knowledge base. users (list[dict[str,str])): users. """ for user in users: identifier = user.get('sid', user.get('uid', None)) if not identifier: continue user_account = artifacts.UserAccountArtifact( identifier=identifier, user_directory=user.get('path', None), username=user.get('name', None)) knowledge_base_object.AddUserAccount(user_account)
def _ParseFileData(self, knowledge_base, file_object): """Parses file content (data) for user account preprocessing attributes. Args: knowledge_base (KnowledgeBase): to fill with preprocessing information. file_object (dfvfs.FileIO): file-like object that contains the artifact value data. Returns: bool: True if all the preprocessing attributes were found and the preprocessor plugin is done. Raises: errors.PreProcessFail: if the preprocessing fails. """ result = False text_file_object = dfvfs_text_file.TextFile(file_object) try: reader = csv.reader(text_file_object, delimiter=b':') except csv.Error as exception: raise errors.PreProcessFail( 'Unable to read: {0:s} with error: {1!s}'.format( self.ARTIFACT_DEFINITION_NAME, exception)) for row in reader: if len(row) < 7 or not row[0] or not row[2]: # TODO: add and store preprocessing errors. continue user_account = artifacts.UserAccountArtifact( identifier=row[2], username=row[0]) user_account.group_identifier = row[3] or None user_account.full_name = row[4] or None user_account.user_directory = row[5] or None user_account.shell = row[6] or None try: knowledge_base.AddUserAccount(user_account) result = True except KeyError: # TODO: add and store preprocessing errors. pass return result
def testCopyToDict(self): """Tests the CopyToDict function.""" attribute_container = artifacts.UserAccountArtifact( full_name='Full Name', group_identifier=1001, identifier=1000, user_directory='/home/username', username='******') self.assertEqual(attribute_container.username, 'username') expected_dict = { 'full_name': 'Full Name', 'group_identifier': 1001, 'identifier': 1000, 'user_directory': '/home/username', 'username': '******'} test_dict = attribute_container.CopyToDict() self.assertEqual(test_dict, expected_dict)
def testCopyToDict(self): """Tests the CopyToDict function.""" user_account = artifacts.UserAccountArtifact( full_name=u'Full Name', group_identifier=1001, identifier=1000, user_directory=u'/home/username', username=u'username') self.assertEqual(user_account.username, u'username') expected_dict = { u'full_name': u'Full Name', u'group_identifier': 1001, u'identifier': 1000, u'user_directory': u'/home/username', u'username': u'username'} user_account_dict = user_account.CopyToDict() self.assertEqual(user_account_dict, expected_dict)
def _ParsePlistFileEntry(self, knowledge_base, file_entry): """Parses an user account plist file. Args: knowledge_base (KnowledgeBase): to fill with preprocessing information. file_entry (dfvfs.FileNetry): file entry of the user account plist file. Raises: errors.PreProcessFail: if the preprocessing fails. """ root_key = self._GetPlistRootKey(file_entry) if not root_key: location = getattr(file_entry.path_spec, u'location', u'') raise errors.PreProcessFail( u'Missing root key in plist: {0:s}'.format(location)) try: match = self._GetKeysDefaultEmpty(root_key, self._KEYS) except KeyError as exception: location = getattr(file_entry.path_spec, u'location', u'') raise errors.PreProcessFail( u'Unable to read user plist file: {0:s} with error: {1:s}'. format(location, exception)) name = match.get(u'name', [None])[0] uid = match.get(u'uid', [None])[0] if not name or not uid: # TODO: add and store preprocessing errors. return user_account = artifacts.UserAccountArtifact(identifier=uid, username=name) user_account.group_identifier = match.get(u'gid', [None])[0] user_account.full_name = match.get(u'realname', [None])[0] user_account.shell = match.get(u'shell', [None])[0] user_account.user_directory = match.get(u'home', [None])[0] try: knowledge_base.AddUserAccount(user_account) except KeyError: # TODO: add and store preprocessing errors. pass
def _SetUserAccounts(self, knowledge_base_object, users): """Sets the user accounts in the knowledge base. Args: knowledge_base_object (KnowledgeBase): used to store information about users. users (list[dict[str, str])): users, for example [{'name': 'me', 'sid': 'S-1', 'uid': '1'}] """ for user in users: identifier = user.get('sid', user.get('uid', None)) if not identifier: continue user_account_artifact = artifacts.UserAccountArtifact( identifier=identifier, user_directory=user.get('path', None), username=user.get('name', None)) knowledge_base_object.AddUserAccount(user_account_artifact)
def _ParseFileData(self, mediator, file_object): """Parses file content (data) for user account preprocessing attributes. Args: mediator (PreprocessMediator): mediates interactions between preprocess plugins and other components, such as storage and knowledge base. file_object (dfvfs.FileIO): file-like object that contains the artifact value data. Raises: errors.PreProcessFail: if the preprocessing fails. """ line_reader = line_reader_file.BinaryLineReader(file_object) try: reader = line_reader_file.BinaryDSVReader(line_reader, b':') except csv.Error as exception: raise errors.PreProcessFail( 'Unable to read: {0:s} with error: {1!s}'.format( self.ARTIFACT_DEFINITION_NAME, exception)) for line_number, row in enumerate(reader): if len(row) < 7 or not row[0] or not row[2]: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unsupported number of values in line: {0:d}.'.format( line_number)) continue try: username = row[0].decode('utf-8') except UnicodeDecodeError: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to decode username.') continue try: identifier = row[2].decode('utf-8') except UnicodeDecodeError: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to decode user identifier.') continue group_identifier = None if row[3]: try: group_identifier = row[3].decode('utf-8') except UnicodeDecodeError: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to decode group identifier.') full_name = None if row[4]: try: full_name = row[4].decode('utf-8') except UnicodeDecodeError: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to decode full name.') user_directory = None if row[5]: try: user_directory = row[5].decode('utf-8') except UnicodeDecodeError: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to decode user directory.') shell = None if row[6]: try: shell = row[6].decode('utf-8') except UnicodeDecodeError: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to decode shell.') user_account = artifacts.UserAccountArtifact(identifier=identifier, username=username) user_account.group_identifier = group_identifier user_account.full_name = full_name user_account.user_directory = user_directory user_account.shell = shell try: mediator.AddUserAccount(user_account) except KeyError as exception: mediator.ProducePreprocessingWarning( self.ARTIFACT_DEFINITION_NAME, 'Unable to add user account with error: {0!s}'.format( exception))
def _ParseFileData(self, knowledge_base, file_object): """Parses file content (data) for user account preprocessing attributes. Args: knowledge_base (KnowledgeBase): to fill with preprocessing information. file_object (dfvfs.FileIO): file-like object that contains the artifact value data. Raises: errors.PreProcessFail: if the preprocessing fails. """ line_reader = line_reader_file.BinaryLineReader(file_object) try: reader = line_reader_file.BinaryDSVReader(line_reader, b':') except csv.Error as exception: raise errors.PreProcessFail( 'Unable to read: {0:s} with error: {1!s}'.format( self.ARTIFACT_DEFINITION_NAME, exception)) for row in reader: if len(row) < 7 or not row[0] or not row[2]: # TODO: add and store preprocessing errors. continue try: username = row[0].decode('utf-8') except UnicodeDecodeError: # TODO: add and store preprocessing errors. logger.error('Unable to decode username.') continue try: identifier = row[2].decode('utf-8') except UnicodeDecodeError: # TODO: add and store preprocessing errors. logger.error('Unable to decode identifier.') continue group_identifier = None if row[3]: try: group_identifier = row[3].decode('utf-8') except UnicodeDecodeError: # TODO: add and store preprocessing errors. logger.error('Unable to decode group identifier.') full_name = None if row[4]: try: full_name = row[4].decode('utf-8') except UnicodeDecodeError: # TODO: add and store preprocessing errors. logger.error('Unable to decode full name.') user_directory = None if row[5]: try: user_directory = row[5].decode('utf-8') except UnicodeDecodeError: # TODO: add and store preprocessing errors. logger.error('Unable to decode user directory.') shell = None if row[6]: try: shell = row[6].decode('utf-8') except UnicodeDecodeError: # TODO: add and store preprocessing errors. logger.error('Unable to decode shell.') user_account = artifacts.UserAccountArtifact(identifier=identifier, username=username) user_account.group_identifier = group_identifier user_account.full_name = full_name user_account.user_directory = user_directory user_account.shell = shell try: knowledge_base.AddUserAccount(user_account) except KeyError: # TODO: add and store preprocessing errors. pass
def testBuildFindSpecsFromFileArtifact(self): """Tests the BuildFindSpecsFromFileArtifact function for file artifacts.""" knowledge_base = knowledge_base_engine.KnowledgeBase() test_filter_file = self._CreateTestArtifactDefinitionsFilterHelper( [], knowledge_base) separator = '\\' user_accounts = [] # Test expansion of environment variables. path_entry = '%%environ_systemroot%%\\test_data\\*.evtx' environment_variable = [ artifacts.EnvironmentVariableArtifact(case_sensitive=False, name='SystemRoot', value='C:\\Windows') ] find_specs = test_filter_file.BuildFindSpecsFromFileArtifact( path_entry, separator, environment_variable, user_accounts) # Should build 1 find_spec. self.assertEqual(len(find_specs), 1) # Location segments should be equivalent to \Windows\test_data\*.evtx. if py2to3.PY_3: # Underscores are not escaped in regular expressions in supported versions # of Python 3. See https://bugs.python.org/issue2650. path_segments = ['Windows', 'test_data', '.*\\.evtx'] else: path_segments = ['Windows', 'test\\_data', '.*\\.evtx'] self.assertEqual(find_specs[0]._location_segments, path_segments) # Test expansion of globs. path_entry = '\\test_data\\**' find_specs = test_filter_file.BuildFindSpecsFromFileArtifact( path_entry, separator, environment_variable, user_accounts) # Glob expansion should by default recurse ten levels. self.assertEqual(len(find_specs), 10) # Last entry in find_specs list should be 10 levels of depth. if py2to3.PY_3: # Underscores are not escaped in regular expressions in supported versions # of Python 3. See https://bugs.python.org/issue2650 path_segments = ['test_data'] else: path_segments = ['test\\_data'] path_segments.extend( ['.*', '.*', '.*', '.*', '.*', '.*', '.*', '.*', '.*', '.*']) self.assertEqual(find_specs[9]._location_segments, path_segments) # Test expansion of user home directories separator = '/' testuser1 = artifacts.UserAccountArtifact( user_directory='/homes/testuser1', username='******') testuser2 = artifacts.UserAccountArtifact( user_directory='/home/testuser2', username='******') user_accounts = [testuser1, testuser2] path_entry = '%%users.homedir%%/.thumbnails/**3' find_specs = test_filter_file.BuildFindSpecsFromFileArtifact( path_entry, separator, environment_variable, user_accounts) # Six total find specs should be created for testuser1 and testuser2. self.assertEqual(len(find_specs), 6) # Last entry in find_specs list should be testuser2 with a depth of 3 path_segments = [ 'home', 'testuser2', '\\.thumbnails', '.*', '.*', '.*' ] self.assertEqual(find_specs[5]._location_segments, path_segments) # Test Windows path with profile directories and globs with a depth of 4. separator = '\\' testuser1 = artifacts.UserAccountArtifact( user_directory='\\Users\\\\testuser1', username='******') testuser2 = artifacts.UserAccountArtifact( user_directory='\\Users\\\\testuser2', username='******') user_accounts = [testuser1, testuser2] path_entry = '%%users.homedir%%\\AppData\\**4' find_specs = test_filter_file.BuildFindSpecsFromFileArtifact( path_entry, separator, environment_variable, user_accounts) # Eight find specs should be created for testuser1 and testuser2. self.assertEqual(len(find_specs), 8) # Last entry in find_specs list should be testuser2, with a depth of 4. path_segments = [ 'Users', 'testuser2', 'AppData', '.*', '.*', '.*', '.*' ] self.assertEqual(find_specs[7]._location_segments, path_segments)