def testProcessSourcesExtractWithFilter(self): """Tests the ProcessSources function with a filter file.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = self._GetTestFilePath( ['artifacts']) options.image = self._GetTestFilePath(['image.qcow2']) options.quiet = True with shared_test_lib.TempDirectory() as temp_directory: filter_file = os.path.join(temp_directory, 'filter.txt') with io.open(filter_file, 'wt', encoding='utf-8') as file_object: file_object.write('/a_directory/.+_file\n') options.file_filter = filter_file options.path = temp_directory test_tool.ParseOptions(options) test_tool.ProcessSources() expected_extracted_files = sorted([ os.path.join(temp_directory, 'filter.txt'), os.path.join(temp_directory, 'a_directory'), os.path.join(temp_directory, 'a_directory', 'another_file'), os.path.join(temp_directory, 'a_directory', 'a_file') ]) extracted_files = self._RecursiveList(temp_directory) self.assertEqual(sorted(extracted_files), expected_extracted_files)
def testCalculateDigestHash(self): """Tests the _CalculateDigestHash function.""" test_tool = image_export_tool.ImageExportTool() test_path = self._GetTestFilePath(['ímynd.dd']) os_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=test_path) tsk_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_TSK, inode=16, location='/a_directory/another_file', parent=os_path_spec) file_entry = path_spec_resolver.Resolver.OpenFileEntry(tsk_path_spec) digest_hash = test_tool._CalculateDigestHash(file_entry, '') expected_digest_hash = ( 'c7fbc0e821c0871805a99584c6a384533909f68a6bbe9a2a687d28d9f3b10c16') self.assertEqual(digest_hash, expected_digest_hash) test_path = self._GetTestFilePath(['ímynd.dd']) os_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=test_path) tsk_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_TSK, inode=12, location='/a_directory', parent=os_path_spec) file_entry = path_spec_resolver.Resolver.OpenFileEntry(tsk_path_spec) with self.assertRaises(IOError): test_tool._CalculateDigestHash(file_entry, '')
def testProcessSourcesWithImage(self): """Tests the ProcessSources function on a single partition image.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = self._GetTestFilePath( ['artifacts']) options.image = self._GetTestFilePath(['ímynd.dd']) options.quiet = True with shared_test_lib.TempDirectory() as temp_directory: options.path = temp_directory test_tool.ParseOptions(options) test_tool.ProcessSources() expected_output = '\n'.join([ 'Export started.', 'Extracting file entries.', 'Export completed.', '', '' ]) output = output_writer.ReadOutput() self.assertEqual(output, expected_output)
def testProcessSourcesExtractWithDateTimeFilter(self): """Tests the ProcessSources function with a date time filter.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = self._GetTestFilePath( ['artifacts']) options.date_filters = [ 'ctime,2012-05-25 15:59:00,2012-05-25 15:59:20' ] options.image = self._GetTestFilePath(['image.qcow2']) options.quiet = True with shared_test_lib.TempDirectory() as temp_directory: options.path = temp_directory test_tool.ParseOptions(options) test_tool.ProcessSources() expected_extracted_files = sorted([ os.path.join(temp_directory, 'a_directory'), os.path.join(temp_directory, 'a_directory', 'a_file') ]) extracted_files = self._RecursiveList(temp_directory) self.assertEqual(sorted(extracted_files), expected_extracted_files)
def testListSignatureIdentifiers(self): """Tests the ListSignatureIdentifiers function.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) test_tool._data_location = self._TEST_DATA_PATH test_tool.ListSignatureIdentifiers() expected_output = ( 'Available signature identifiers:\n' '7z, bzip2, esedb, evt, evtx, ewf_e01, ewf_l01, exe_mz, gzip, lnk, ' 'msiecf, nk2,\n' 'olecf, olecf_beta, pdf, pff, qcow, rar, regf, tar, tar_old, ' 'vhdi_footer,\n' 'vhdi_header, wtcdb_cache, wtcdb_index, zip\n' '\n') output = output_writer.ReadOutput() # Compare the output as list of lines which makes it easier to spot # differences. self.assertEqual(output.split('\n'), expected_output.split('\n')) test_tool._data_location = self._GetTestFilePath(['tmp']) with self.assertRaises(errors.BadConfigOption): test_tool.ListSignatureIdentifiers()
def testPrintFilterCollection(self): """Tests the PrintFilterCollection function.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = self._GetTestFilePath( ['artifacts']) options.date_filters = [ 'ctime,2012-05-25 15:59:00,2012-05-25 15:59:20' ] options.image = self._GetTestFilePath(['image.qcow2']) options.quiet = True test_tool.ParseOptions(options) test_tool.PrintFilterCollection() expected_output = '\n'.join([ 'Filters:', ('\tctime between 2012-05-25 15:59:00.000000 and ' '2012-05-25 15:59:20.000000'), '' ]) output = output_writer.ReadOutput() self.assertEqual(output, expected_output)
def testProcessSourcesExtractWithSignaturesFilter(self): """Tests the ProcessSources function with a signatures filter.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = self._GetTestFilePath( ['artifacts']) options.image = self._GetTestFilePath(['syslog_image.dd']) options.quiet = True options.signature_identifiers = 'gzip' with shared_test_lib.TempDirectory() as temp_directory: options.path = temp_directory test_tool.ParseOptions(options) test_tool.ProcessSources() expected_extracted_files = sorted([ os.path.join(temp_directory, 'logs'), os.path.join(temp_directory, 'logs', 'sys.tgz') ]) extracted_files = self._RecursiveList(temp_directory) self.assertEqual(sorted(extracted_files), expected_extracted_files)
def testProcessSourcesExtractWithArtifactsGroupFilter(self): """Tests the ProcessSources function with a group artifacts filter file.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = self._GetTestFilePath( ['artifacts']) options.image = self._GetTestFilePath(['image.qcow2']) options.quiet = True options.artifact_filters = 'TestGroupExport' with shared_test_lib.TempDirectory() as temp_directory: options.path = temp_directory test_tool.ParseOptions(options) test_tool.ProcessSources() expected_extracted_files = sorted([ os.path.join(temp_directory, 'a_directory'), os.path.join(temp_directory, 'a_directory', 'another_file'), os.path.join(temp_directory, 'a_directory', 'a_file'), os.path.join(temp_directory, 'passwords.txt') ]) extracted_files = self._RecursiveList(temp_directory) self.assertEqual(sorted(extracted_files), expected_extracted_files)
def testExtractFileEntry(self): """Tests the _ExtractFileEntry function.""" test_file_path = self._GetTestFilePath(['ímynd.dd']) self._SkipIfPathNotExists(test_file_path) output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool() os_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=test_file_path) tsk_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_TSK, inode=16, location='/a_directory/another_file', parent=os_path_spec) non_existent_test_path = self._GetTestFilePath(['does_not_exist']) non_existent_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=non_existent_test_path) with shared_test_lib.TempDirectory() as temp_directory: test_tool._ExtractFileEntry(tsk_path_spec, temp_directory, output_writer) test_tool._ExtractFileEntry(non_existent_path_spec, temp_directory, output_writer)
def testProcessSourcesExtractWithNamesFilter(self): """Tests the ProcessSources function with a names filter.""" test_artifacts_path = self._GetTestFilePath(['artifacts']) self._SkipIfPathNotExists(test_artifacts_path) test_file_path = self._GetTestFilePath(['image.qcow2']) self._SkipIfPathNotExists(test_file_path) output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = test_artifacts_path options.image = test_file_path options.names_string = 'another_file' options.quiet = False with shared_test_lib.TempDirectory() as temp_directory: options.path = temp_directory test_tool.ParseOptions(options) test_tool.ProcessSources() expected_extracted_files = sorted([ os.path.join(temp_directory, 'a_directory'), os.path.join(temp_directory, 'a_directory', 'another_file'), os.path.join(temp_directory, 'hashes.json') ]) extracted_files = self._RecursiveList(temp_directory) self.assertEqual(sorted(extracted_files), expected_extracted_files)
def testParseArguments(self): """Tests the ParseArguments function.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool(output_writer=output_writer) result = test_tool.ParseArguments() self.assertFalse(result)
def Main(): """The main function. Returns: bool: True if successful or False otherwise. """ tool = image_export_tool.ImageExportTool() if not tool.ParseArguments(sys.argv[1:]): return False if tool.show_troubleshooting: print('Using Python version {0!s}'.format(sys.version)) print() print('Path: {0:s}'.format(os.path.abspath(__file__))) print() print(tool.GetVersionInformation()) print() dependencies.CheckDependencies(verbose_output=True) print('Also see: https://plaso.readthedocs.io/en/latest/sources/user/' 'Troubleshooting.html') return True try: tool.CheckOutDated() except KeyboardInterrupt: return False if tool.list_signature_identifiers: tool.ListSignatureIdentifiers() return True if not tool.has_filters: logging.warning('No filter defined exporting all files.') # TODO: print more status information like PrintOptions. tool.PrintFilterCollection() try: tool.ProcessSources() except (KeyboardInterrupt, errors.UserAbort): logging.warning('Aborted by user.') return False except errors.BadConfigOption as exception: logging.warning(exception) return False except errors.SourceScannerError as exception: logging.warning(( 'Unable to scan for a supported filesystem with error: {0!s}\n' 'Most likely the image format is not supported by the ' 'tool.').format(exception)) return False return True
def testParseSignatureIdentifiers(self): """Tests the _ParseSignatureIdentifiers function.""" test_tool = image_export_tool.ImageExportTool() test_tool._ParseSignatureIdentifiers(self._DATA_PATH, 'gzip') with self.assertRaises(ValueError): test_tool._ParseSignatureIdentifiers(None, 'gzip') with self.assertRaises(IOError): test_path = os.path.join(os.sep, 'bogus') test_tool._ParseSignatureIdentifiers(test_path, 'gzip')
def testOutputJsonFile(self): """Tests the content of the output JSON file.""" test_artifacts_path = self._GetTestFilePath(['artifacts']) self._SkipIfPathNotExists(test_artifacts_path) test_file_path = self._GetTestFilePath(['ext4_with_binaries.dd']) self._SkipIfPathNotExists(test_file_path) output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool( output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = test_artifacts_path options.image = test_file_path options.signature_identifiers = 'elf' with shared_test_lib.TempDirectory() as temp_directory: options.path = temp_directory test_tool.ParseOptions(options) test_tool.ProcessSources() expected_json_data = [{ "sha256": "553c231c45eda751710eabb479d08668f70464c14e60064190a7ec206f26b5f5", "paths": ["bin" + os.path.sep + "bzcat"] }, { "sha256": "a106276270db8d3fe80a96dbb52f14f23f42a29bea12c68ac0f88d2e916471af", "paths": ["bin" + os.path.sep + "echo", "home" + os.path.sep + "echo"] }, { "sha256": "e21de6c5af94fa9d4e7f3295c8d25b93ab3d2d65982f5ef53c801669cc82dc47", "paths": ["sbin" + os.path.sep + "visudo"] }, { "sha256": "129f4d0e36b38742fdfa8f1ea9a014818e4ce5c41d4a889435aecee58a1c7c39", "paths": ["sbin" + os.path.sep + "tune2fs"] }] with open(os.path.join(temp_directory, 'hashes.json')) as json_file: json_data = json.load(json_file) json_data.sort(key=lambda d: d['sha256']) expected_json_data.sort(key=lambda d: d['sha256']) self.assertEqual(json_data, expected_json_data)
def testParseOptions(self): """Tests the ParseOptions function.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool(output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = self._GetTestFilePath(['artifacts']) options.image = self._GetTestFilePath(['image.qcow2']) test_tool.ParseOptions(options) options = test_lib.TestOptions() with self.assertRaises(errors.BadConfigOption): test_tool.ParseOptions(options)
def testWriteFileEntry(self): """Tests the _WriteFileEntry function.""" test_tool = image_export_tool.ImageExportTool() test_path = self._GetTestFilePath(['ímynd.dd']) os_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=test_path) tsk_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_TSK, inode=16, location='/a_directory/another_file', parent=os_path_spec) file_entry = path_spec_resolver.Resolver.OpenFileEntry(tsk_path_spec) with shared_test_lib.TempDirectory() as temp_directory: destination_path = os.path.join(temp_directory, 'another_file') test_tool._WriteFileEntry(file_entry, '', destination_path)
def testExtractDataStream(self): """Tests the _ExtractDataStream function.""" output_writer = test_lib.TestOutputWriter(encoding='utf-8') test_tool = image_export_tool.ImageExportTool() test_path = self._GetTestFilePath(['ímynd.dd']) os_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=test_path) tsk_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_TSK, inode=16, location='/a_directory/another_file', parent=os_path_spec) file_entry = path_spec_resolver.Resolver.OpenFileEntry(tsk_path_spec) with shared_test_lib.TempDirectory() as temp_directory: test_tool._ExtractDataStream( file_entry, '', temp_directory, output_writer)
def Main(): """The main function. Returns: bool: True if successful or False otherwise. """ tool = image_export_tool.ImageExportTool() if not tool.ParseArguments(): return False if tool.list_signature_identifiers: tool.ListSignatureIdentifiers() return True if not tool.has_filters: logging.warning('No filter defined exporting all files.') # TODO: print more status information like PrintOptions. tool.PrintFilterCollection() try: tool.ProcessSources() except (KeyboardInterrupt, errors.UserAbort): logging.warning('Aborted by user.') return False except errors.BadConfigOption as exception: logging.warning(exception) return False except errors.SourceScannerError as exception: logging.warning( ('Unable to scan for a supported filesystem with error: {0!s}\n' 'Most likely the image format is not supported by the ' 'tool.').format(exception)) return False return True
def testProcessSourcesExtractWithExtensionsFilter(self): """Tests the ProcessSources function with an extensions filter.""" output_writer = test_lib.TestOutputWriter(encoding=u'utf-8') test_tool = image_export_tool.ImageExportTool(output_writer=output_writer) options = test_lib.TestOptions() options.artifact_definitions_path = self._GetTestFilePath([u'artifacts']) options.extensions_string = u'txt' options.image = self._GetTestFilePath([u'image.qcow2']) options.quiet = True with shared_test_lib.TempDirectory() as temp_directory: options.path = temp_directory test_tool.ParseOptions(options) test_tool.ProcessSources() expected_extracted_files = sorted([ os.path.join(temp_directory, u'passwords.txt')]) extracted_files = self._RecursiveList(temp_directory) self.assertEqual(sorted(extracted_files), expected_extracted_files)
def testParseExtensionsString(self): """Tests the _ParseExtensionsString function.""" test_tool = image_export_tool.ImageExportTool() test_tool._ParseExtensionsString('txt')
def testParseNamesString(self): """Tests the _ParseNamesString function.""" test_tool = image_export_tool.ImageExportTool() test_tool._ParseNamesString('another_file')