def extract_artifact(self, artifact_name): # pylint: disable=invalid-name """ Extract a particular artifact from all possible locations within this dfvfs-image """ real_partitions: List[PartitionInfo] = [] print("all", list(self.dfvfs_list[0].all_files())) # forensic images can have more than one partition, but we always only process one image at a time real_partitions = [ PartitionInfo(helper=self.dfvfs_list[0], path_spec=partition, name=chr(ord('c') + i)) for i, partition in enumerate(self.dfvfs_list[0].partitions()) if not dfvfs_utils.is_on_filesystem( partition, dfvfs_defs.TYPE_INDICATOR_VSHADOW) ] LOGGER.info("Found %d partitions", len(real_partitions)) for partinfo in real_partitions: current_os = self._guess_os(partinfo.helper, partinfo.path_spec) try: if current_os == definitions.OPERATING_SYSTEM_WINDOWS: system = WindowsSystem(partinfo.helper, partinfo.path_spec) elif current_os == definitions.OPERATING_SYSTEM_UNKNOWN: system = UnknownOS() LOGGER.warning( "Operating system not detected on partition %s. Only basic extraction possible.", dfvfs_utils.reconstruct_full_path(partinfo.path_spec)) else: LOGGER.warning( "Operating system %s is not yet supported on %s. Using basic extraction.", dfvfs_utils.reconstruct_full_path(partinfo.path_spec), current_os) system = UnknownOS() LOGGER.info("=== Starting processing of partition") resolver = ArtifactResolver(partinfo, self.artifact_registry, system) resolver.process_artifact(artifact_name, self.store) if current_os == definitions.OPERATING_SYSTEM_WINDOWS: system._reg_reader._cleanup_open_files("") # TODO except RuntimeError as err: LOGGER.exception( "Encountered exception during processing of %s: %s", dfvfs_utils.reconstruct_full_path(partinfo.path_spec), err) if 'pytest' in sys.modules: raise # we want to see what exactly is failing when tests are running self.store.close()
def _extract_files(self, artifact: ResolvedArtifact, artifact_output: ForensicStore) -> bool: """ Extract an artifact's files and folders to the forensic store :param artifact: artifact to extract :param artifact_output: Output forensic store :type artifact_output: ForensicStore :type artifact: ResolvedArtifact :return: True on success, False if nothing was written """ artifact_name = artifact.artifact.name success = False for export_file in artifact.files: success = True file_infos = get_file_infos(export_file) if not file_infos: LOGGER.warning("Could not get file infos for \"%s\". Skipping", dfvfs_utils.reconstruct_full_path(export_file)) continue if file_infos['type'] != dfvfs_defs.FILE_ENTRY_TYPE_FILE: LOGGER.debug("Not exporting entry of wrong type: %s", dfvfs_utils.reconstruct_full_path(export_file)) continue store_obj_id = artifact_output.add_file_element( artifact_name, file_infos['name'], created=file_infos.get('created', None), modified=file_infos.get('modified', None), accessed=file_infos.get('accessed', None), origin={ 'path': file_infos['path'], 'partition': self.partition_name }, errors=None) output_name = f"{self.partition_name}_" \ f"{dfvfs_utils.get_relative_path(export_file).replace('/', '_').strip('_')}" file_contents = dfvfs_helper.get_file_handle(export_file) with artifact_output.add_file_element_export( store_obj_id, export_name=output_name) as file_export: chunk_size = 65536 data = file_contents.read(chunk_size) while data: file_export.write(data) data = file_contents.read(chunk_size) file_contents.close() return success
def _read_system_infos(self): """ Determine some basic system information. We need this to bootstrap registry access. The rest of interesting system data can then be resolved with artifacts """ # find %SystemRoot% systemroot = list( self.dfvfs.find_paths(['/Windows', '/WINNT'], partitions=[self.partition])) if not systemroot: raise RuntimeError("No windows directory found on %s" % ( dfvfs_utils.reconstruct_full_path(self.partition))) if len(systemroot) > 1: LOGGER.warning("More than one installation of Windows detected? Using %s", dfvfs_utils.reconstruct_full_path(systemroot[0])) path_str = dfvfs_utils.get_relative_path(systemroot[0]) self.set_var("%SystemRoot%", path_str) # %SystemDrive% is always '/' self.set_var('%SystemDrive%', '/')
def Open(self, path, ascii_codepage='cp1252'): LOGGER.info("open registry %s", path) """ Opens a path within the dfVFS volume """ realpath = path.replace('\\', '/') if path in self.not_present: return None # check for variables and if we know them for match in re.finditer('%[a-zA-Z0-9_]+%', path): key = match.group(0) val = self.windows_system.get_var(key) if val: realpath = realpath.replace(key, val) else: LOGGER.warning("Could not resolve variable %s", key) return None if realpath.lower().startswith('c:/'): # catch absolute paths realpath = '/' + realpath[3:] if not realpath[0] == '/': realpath = '/' + realpath if realpath in self.not_present: return None path_specs = list( self.dfvfs.find_paths([realpath], partitions=[self.partition])) if not path_specs: LOGGER.warning("Could not find requested registry hive %s [%s]", path, realpath) self.not_present.add(path) self.not_present.add(realpath) return None if len(path_specs) > 1: LOGGER.warning( "Found multiple registry hives for query %s, using %s", path, dfvfs_utils.reconstruct_full_path(path_specs[0])) # extract the file locally filename = realpath.replace('/', '_') dfvfs_utils.export_file(path_specs[0], self.tmpfs, filename) try: file_object = self.tmpfs.open(filename, 'rb') except ResourceNotFound: files = self.tmpfs.listdir("/") LOGGER.warning("Could not open registry hive %s [%s] (%s)", path, realpath, files) return None self.open_handles.append((filename, file_object)) reg_file = regfile_impl.REGFWinRegistryFile( ascii_codepage=ascii_codepage) reg_file.Open(file_object) return reg_file
def __init__(self, dfvfs, partition): """ Creates a new WindowsSystem instance and extracts basic information :param dfvfs[DFVFSHelper]: DFVFSHelper-object to access data :param partition[PathSpec]: A DFVFS-PathSpec object identifying the root of the system partition """ super(WindowsSystem, self).__init__() self.dfvfs = dfvfs self.partition = partition LOGGER.info("Creating new WindowsSystem for %s", dfvfs_utils.reconstruct_full_path(partition)) self.users = {} self.vars = {} self._read_system_infos() # MUST be done first, since registry access needs %SystemRoot% to be set self._reg_reader = RegistryFileOpener(self.dfvfs, self.partition, self) self._registry = dfwinreg_reg.WinRegistry(registry_file_reader=self._reg_reader) self._read_users() # get user accounts from registry self._patch_dfwinreg() # patch user SIDs into registry library TODO: Use dfwinreg native when bugs are fixed