def _get_vss_store_identifiers(self, scan_node, interactive): """Determines the VSS store identifiers. Args: scan_node: the scan node (instance of dfvfs.ScanNode). Returns: A list of VSS store identifiers. Raises: RuntimeError: if the format of or within the source is not supported or the the scan node is invalid. """ if not scan_node or not scan_node.path_spec: raise RuntimeError(u'Invalid scan node.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] try: selected_store_identifiers = self._prompt_user_for_vss_store_identifiers( volume_system, volume_identifiers, interactive) except KeyboardInterrupt: raise errors.UserAbort(u'File system scan aborted.') return selected_store_identifiers
def _GetVSSStoreIdentifiers(self, scan_node, vss_stores=None): """Determines the VSS store identifiers. Args: scan_node: the scan node (instance of dfvfs.ScanNode). vss_stores: Optional list of preferred VSS store identifiers. The default is None. Returns: A list of VSS store identifiers. Raises: SourceScannerError: if the format of or within the source is not supported or the the scan node is invalid. """ if not scan_node or not scan_node.path_spec: raise errors.SourceScannerError(u'Invalid scan node.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] try: selected_store_identifiers = self._PromptUserForVSSStoreIdentifiers( volume_system, volume_identifiers, vss_stores=vss_stores) except KeyboardInterrupt: raise errors.UserAbort(u'File system scan aborted.') return selected_store_identifiers
def testGetNormalizedVShadowVolumeIdentifiers(self): """Tests the _GetNormalizedVShadowVolumeIdentifiers function.""" test_tool = storage_media_tool.StorageMediaTool() test_path = self._GetTestFilePath(['vsstest.qcow2']) os_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=test_path) qcow_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_QCOW, parent=os_path_spec) vss_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_VSHADOW, parent=qcow_path_spec) volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(vss_path_spec) volume_identifiers = test_tool._GetNormalizedVShadowVolumeIdentifiers( volume_system, ['vss1', 'vss2']) self.assertEqual(volume_identifiers, [1, 2]) with self.assertRaises(KeyError): test_tool._GetNormalizedTSKVolumeIdentifiers(volume_system, [1, 2]) with self.assertRaises(KeyError): test_tool._GetNormalizedTSKVolumeIdentifiers( volume_system, ['vss3'])
def _GetVolumeVssStoreIdentifiers(self, scan_context, vss_stores=None): """Determines the VSS store identifiers. Args: scan_context: the scan context (instance of dfvfs.ScanContext). vss_stores: Optional list of preferred VSS stored identifiers. The default is None. Raises: SourceScannerError: if the format of or within the source is not supported or the the scan context is invalid. """ if (not scan_context or not scan_context.last_scan_node or not scan_context.last_scan_node.path_spec): raise errors.SourceScannerError(u'Invalid scan context.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_context.last_scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return try: self.vss_stores = self._GetVssStoreIdentifiersFromUser( volume_system, volume_identifiers, vss_stores=vss_stores) except KeyboardInterrupt: raise errors.UserAbort(u'File system scan aborted.') return
def _GetVSSStoreIdentifiers(self, scan_node): """Determines the VSS store identifiers. Args: scan_node: the scan node (instance of dfvfs.ScanNode). Returns: A list of VSS store identifiers. Raises: ScannerError: if the format of or within the source is not supported, the the scan node is invalid or no mediator is provided and VSS store identifiers are found. """ if not scan_node or not scan_node.path_spec: raise errors.ScannerError(u'Invalid scan node.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not self._mediator and not volume_identifiers: return [] if not self._mediator: raise errors.ScannerError( u'Unable to proceed VSS. Identifiers found but no mediator to ' u'determine how they should be used.') try: return self._mediator.GetVSSStoreIdentifiers( volume_system, volume_identifiers) except KeyboardInterrupt: raise errors.UserAbort(u'File system scan aborted.')
def _GetVSSStoreIdentifiers(self, scan_node): if not scan_node or not scan_node.path_spec: raise errors.SourceScannerError('Invalid scan node.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] # TODO: refactor to use scan options. if self._vss_stores: if self._vss_stores == 'all': vss_stores = range(1, volume_system.number_of_volumes + 1) else: vss_stores = self._ParseVolumeIdentifiersString( self._vss_stores, prefix='vss') selected_volume_identifiers = self._NormalizedVolumeIdentifiers( volume_system, vss_stores, prefix='vss') if not set(selected_volume_identifiers).difference( volume_identifiers): return selected_volume_identifiers return self._NormalizedVolumeIdentifiers(volume_system, volume_identifiers, prefix='vss')
def testNormalizedVolumeIdentifiersVSS(self): """Tests the _NormalizedVolumeIdentifiers function on a VSS.""" test_mediator = TestVolumeScannerMediator() test_scanner = volume_scanner.VolumeScanner(mediator=test_mediator) test_path = self._GetTestFilePath(['vsstest.qcow2']) self._SkipIfPathNotExists(test_path) test_os_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_OS, location=test_path) test_qcow_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_QCOW, parent=test_os_path_spec) test_vss_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_VSHADOW, parent=test_qcow_path_spec) volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(test_vss_path_spec) volume_identifiers = test_scanner._NormalizedVolumeIdentifiers( volume_system, ['vss1', 'vss2'], prefix='vss') self.assertEqual(volume_identifiers, ['vss1', 'vss2']) volume_identifiers = test_scanner._NormalizedVolumeIdentifiers( volume_system, [1, 2], prefix='vss') self.assertEqual(volume_identifiers, ['vss1', 'vss2']) # Test error conditions. with self.assertRaises(errors.ScannerError): test_scanner._NormalizedVolumeIdentifiers(volume_system, ['vss3'], prefix='vss')
def _GetVSSStoreIdentifiers(self, scan_node, options): """Determines the VSS store identifiers. Args: scan_node (SourceScanNode): scan node. options (VolumeScannerOptions): volume scanner options. Returns: list[str]: VSS store identifiers. Raises: ScannerError: if the format the scan node is invalid or no mediator is provided and VSS store identifiers are found. UserAbort: if the user requested to abort. """ if not scan_node or not scan_node.path_spec: raise errors.ScannerError('Invalid scan node.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] if options.snapshots: if options.snapshots == ['all']: snapshots = range(1, volume_system.number_of_volumes + 1) elif options.snapshots == ['none']: snapshots = [] else: snapshots = options.snapshots try: selected_volumes = self._NormalizedVolumeIdentifiers( volume_system, snapshots, prefix='vss') if not set(selected_volumes).difference(volume_identifiers): return selected_volumes except errors.ScannerError as exception: if self._mediator: self._mediator.PrintWarning('{0!s}'.format(exception)) if not self._mediator: raise errors.ScannerError( 'Unable to proceed. VSS stores found but no mediator to determine ' 'how they should be used.') try: volume_identifiers = self._mediator.GetVSSStoreIdentifiers( volume_system, volume_identifiers) except KeyboardInterrupt: raise errors.UserAbort('File system scan aborted.') return self._NormalizedVolumeIdentifiers(volume_system, volume_identifiers, prefix='vss')
def _GetVSSStoreIdentifiers(self, scan_node): """Determines the VSS store identifiers. Args: scan_node (dfvfs.SourceScanNode): scan node. Returns: list[str]: VSS store identifiers. Raises: SourceScannerError: if the format of or within the source is not supported or the scan node is invalid. UserAbort: if the user requested to abort. """ if not scan_node or not scan_node.path_spec: raise errors.SourceScannerError('Invalid scan node.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] # TODO: refactor to use scan options. if self._vss_stores: if self._vss_stores == 'all': vss_stores = range(1, volume_system.number_of_volumes + 1) else: vss_stores = self._ParseVolumeIdentifiersString( self._vss_stores, prefix='vss') selected_volume_identifiers = self._NormalizedVolumeIdentifiers( volume_system, vss_stores, prefix='vss') if not set(selected_volume_identifiers).difference( volume_identifiers): return selected_volume_identifiers if self._unattended_mode: return [] try: volume_identifiers = self._PromptUserForVSSStoreIdentifiers( volume_system, volume_identifiers) except KeyboardInterrupt: raise errors.UserAbort('File system scan aborted.') return self._NormalizedVolumeIdentifiers(volume_system, volume_identifiers, prefix='vss')
def _GetVSSStoreIdentifiers(self, scan_node): if not scan_node or not scan_node.path_spec: raise RuntimeError(u'Invalid scan node.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] return list(range(1, volume_system.number_of_volumes + 1))
def __init__(self, node): if node.path_spec.store_index is None: # VSS Root vss = vshadow_volume_system.VShadowVolumeSystem() vss.Open(node.path_spec) for shadow_volume in vss.volumes: self.append( wx.propgrid.PropertyCategory(u'{}'.format( shadow_volume.identifier))) for attribute in shadow_volume.attributes: self.append( wx.propgrid.StringProperty( u'{} {}'.format(shadow_volume.identifier, attribute.identifier), value=u'{}'.format(attribute.value))) else: # VSS Index vss = vshadow_volume_system.VShadowVolumeSystem() vss.Open(node.path_spec) vss_index = node.path_spec.store_index vss_label = node.path_spec.location[1:] _vss_cnt = 0 for shadow_volume in vss.volumes: if vss_label == shadow_volume.identifier: self.append( wx.propgrid.PropertyCategory(u'{}'.format( shadow_volume.identifier))) for attribute in shadow_volume.attributes: self.append( wx.propgrid.StringProperty( u'{} {}'.format(shadow_volume.identifier, attribute.identifier), value=u'{}'.format(attribute.value))) _vss_cnt += 1
def testPrintVSSStoreIdentifiersOverview(self): """Tests the _PrintVSSStoreIdentifiersOverview function.""" test_file_path = self._GetTestFilePath(['vsstest.qcow2']) self._SkipIfPathNotExists(test_file_path) test_os_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=test_file_path) test_qcow_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_QCOW, parent=test_os_path_spec) test_vss_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_VSHADOW, parent=test_qcow_path_spec) volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(test_vss_path_spec) file_object = io.BytesIO() test_output_writer = tools.FileObjectOutputWriter(file_object) test_mediator = storage_media_tool.StorageMediaToolMediator( output_writer=test_output_writer) test_mediator._PrintVSSStoreIdentifiersOverview( volume_system, ['vss1', 'vss2']) file_object.seek(0, os.SEEK_SET) output_data = file_object.read() expected_output_data = [ b'The following Volume Shadow Snapshots (VSS) were found:', b'', b'Identifier Creation Time', b'vss1 2013-12-03 06:35:09.7363787', b'vss2 2013-12-03 06:37:48.9190583', b'', b''] if not win32console: # Using join here since Python 3 does not support format of bytes. expected_output_data[2] = b''.join([ b'\x1b[1m', expected_output_data[2], b'\x1b[0m']) self.assertEqual(output_data.split(b'\n'), expected_output_data)
def _GetVSSStoreIdentifiers(self, scan_node): """Determines the VSS store identifiers. Args: scan_node (SourceScanNode): scan node. Returns: list[str]: VSS store identifiers. Raises: ScannerError: if the format the scan node is invalid or no mediator is provided and VSS store identifiers are found. UserAbort: if the user requested to abort. """ if not scan_node or not scan_node.path_spec: raise errors.ScannerError('Invalid scan node.') volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] if not self._mediator: raise errors.ScannerError( 'Unable to proceed. VSS stores found but no mediator to determine ' 'how they should be used.') try: volume_identifiers = self._mediator.GetVSSStoreIdentifiers( volume_system, volume_identifiers) except KeyboardInterrupt: raise errors.UserAbort('File system scan aborted.') return self._NormalizedVolumeIdentifiers(volume_system, volume_identifiers, prefix='vss')
def testIterateVolumes(self): """Test the iterate volumes functionality.""" volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(self._vshadow_path_spec) self.assertEqual(volume_system.number_of_volumes, 2) volume = volume_system.GetVolumeByIndex(1) self.assertIsNotNone(volume) self.assertEqual(volume.number_of_extents, 1) self.assertEqual(volume.number_of_attributes, 4) self.assertEqual(volume.identifier, u'vss2') expected_value = u'600f0b6d-5bdf-11e3-9d6c-005056c00008' volume_attribute = volume.GetAttribute(u'identifier') self.assertIsNotNone(volume_attribute) self.assertEqual(volume_attribute.value, expected_value) expected_value = u'18f1ac6e-959d-436f-bdcc-e797a729e290' volume_attribute = volume.GetAttribute(u'copy_identifier') self.assertIsNotNone(volume_attribute) self.assertEqual(volume_attribute.value, expected_value) expected_value = u'8438a0ee-0f06-443b-ac0c-2905647ca5d6' volume_attribute = volume.GetAttribute(u'copy_set_identifier') self.assertIsNotNone(volume_attribute) self.assertEqual(volume_attribute.value, expected_value) expected_value = 130305262689190583 volume_attribute = volume.GetAttribute(u'creation_time') self.assertIsNotNone(volume_attribute) self.assertEqual(volume_attribute.value, expected_value) volume = volume_system.GetVolumeByIndex(7) self.assertIsNone(volume)
def testGetVSSStoreIdentifiers(self): """Tests the GetVSSStoreIdentifiers function.""" test_path = self._GetTestFilePath(['vsstest.qcow2']) test_os_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_OS, location=test_path) test_qcow_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_QCOW, parent=test_os_path_spec) test_vss_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_VSHADOW, parent=test_qcow_path_spec) volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(test_vss_path_spec) file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter(file_object) test_mediator = command_line.CLIVolumeScannerMediator( output_writer=test_output_writer) # Test selection of single store. input_file_object = io.BytesIO(b'2\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetVSSStoreIdentifiers( volume_system, ['vss1', 'vss2']) self.assertEqual(volume_identifiers, ['vss2']) # Test selection of single store. input_file_object = io.BytesIO(b'vss2\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetVSSStoreIdentifiers( volume_system, ['vss1', 'vss2']) self.assertEqual(volume_identifiers, ['vss2']) # Test selection of single store with invalid input on first attempt. input_file_object = io.BytesIO(b'bogus\nvss2\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetVSSStoreIdentifiers( volume_system, ['vss1', 'vss2']) self.assertEqual(volume_identifiers, ['vss2']) # Test selection of all stores. input_file_object = io.BytesIO(b'all\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetVSSStoreIdentifiers( volume_system, ['vss1', 'vss2']) self.assertEqual(volume_identifiers, ['vss1', 'vss2']) # Test selection of no stores. input_file_object = io.BytesIO(b'\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetVSSStoreIdentifiers( volume_system, ['vss1', 'vss2']) self.assertEqual(volume_identifiers, [])
def _ScanVolumeSystemRoot(self, scan_context, scan_node, options, base_path_specs): """Scans a volume system root scan node for volume and file systems. Args: scan_context (SourceScannerContext): source scanner context. scan_node (SourceScanNode): volume system root scan node. options (VolumeScannerOptions): volume scanner options. base_path_specs (list[PathSpec]): file system base path specifications. Raises: dfvfs.ScannerError: if the scan node is invalid, the scan node type is not supported or if a sub scan node cannot be retrieved. """ if not scan_node or not scan_node.path_spec: raise dfvfs_errors.ScannerError('Invalid scan node.') if scan_node.type_indicator == ( dfvfs_definitions.TYPE_INDICATOR_APFS_CONTAINER): volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._GetVolumeIdentifiers( volume_system, options) elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_GPT: volume_identifiers = self._GetPartitionIdentifiers( scan_node, options) elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_LVM: volume_system = lvm_volume_system.LVMVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._GetVolumeIdentifiers( volume_system, options) elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_VSHADOW: volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._GetVolumeSnapshotIdentifiers( volume_system, options) # Process VSS stores (snapshots) starting with the most recent one. volume_identifiers.reverse() # TODO: difference with dfVFS for current VSS volume support. if not options.snapshots_only and self._mediator and volume_identifiers: snapshots_only = not self._mediator.PromptUserForVSSCurrentVolume( ) options.snapshots_only = snapshots_only self._snapshots_only = snapshots_only else: raise dfvfs_errors.ScannerError( 'Unsupported volume system type: {0:s}.'.format( scan_node.type_indicator)) for volume_identifier in volume_identifiers: location = '/{0:s}'.format(volume_identifier) sub_scan_node = scan_node.GetSubNodeByLocation(location) if not sub_scan_node: raise dfvfs_errors.ScannerError( 'Scan node missing for volume identifier: {0:s}.'.format( volume_identifier)) self._ScanVolume(scan_context, sub_scan_node, options, base_path_specs)