diff --git a/volatility3/cli/__init__.py b/volatility3/cli/__init__.py index 457a49311..6b17edac0 100644 --- a/volatility3/cli/__init__.py +++ b/volatility3/cli/__init__.py @@ -716,19 +716,17 @@ class CommandLine: """Gets the final filename""" if output_dir is None: raise TypeError("Output directory is not a string") + os.makedirs(output_dir, exist_ok=True) - pref_name_array = self.preferred_filename.split(".") - filename, extension = ( - os.path.join(output_dir, ".".join(pref_name_array[:-1])), - pref_name_array[-1], - ) - output_filename = f"{filename}.{extension}" + output_filename = os.path.join(output_dir, self.preferred_filename) + filename, extension = os.path.splitext(output_filename) counter = 1 while os.path.exists(output_filename): - output_filename = f"{filename}-{counter}.{extension}" + output_filename = f"{filename}-{counter}{extension}" counter += 1 + return output_filename class CLIMemFileHandler(io.BytesIO, CLIFileHandler): @@ -791,8 +789,16 @@ class CommandLine: if self._file.closed: return None - self._file.close() output_filename = self._get_final_filename() + + # Update the filename, which may have changed if a file with + # the same name already existed. This needs to be done before + # closing the file, otherwise FileHandlerInterface will raise + # an exception. Also, the preferred_filename setter only allows + # a specific set of characters, where '/' is not in that list + self.preferred_filename = os.path.basename(output_filename) + + self._file.close() os.rename(self._name, output_filename) if direct: diff --git a/volatility3/framework/layers/intel.py b/volatility3/framework/layers/intel.py index 75e561b33..8589cdbb6 100644 --- a/volatility3/framework/layers/intel.py +++ b/volatility3/framework/layers/intel.py @@ -180,7 +180,7 @@ class Intel(linear.LinearlyMappedLayer): position = self._initial_position entry = self._initial_entry - if self.minimum_address > offset > self.maximum_address: + if not (self.minimum_address <= offset <= self.maximum_address): raise exceptions.PagedInvalidAddressException( self.name, offset, diff --git a/volatility3/framework/layers/segmented.py b/volatility3/framework/layers/segmented.py index 0d29d8bff..e8c067072 100644 --- a/volatility3/framework/layers/segmented.py +++ b/volatility3/framework/layers/segmented.py @@ -152,7 +152,7 @@ class NonLinearlySegmentedLayer( raise ValueError("SegmentedLayer must contain some segments") if self._maxaddr is None: mapped, _, length, _ = self._segments[-1] - self._maxaddr = mapped + length + self._maxaddr = mapped + length - 1 return self._maxaddr @property diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index 1bee5f20d..24149a390 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -18,7 +18,7 @@ class LayerWriter(plugins.PluginInterface): default_block_size = 0x500000 _required_framework_version = (2, 0, 0) - _version = (2, 0, 0) + _version = (2, 0, 1) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: @@ -77,7 +77,7 @@ class LayerWriter(plugins.PluginInterface): file_handle = open_method(preferred_name) for i in range(0, layer.maximum_address, chunk_size): - current_chunk_size = min(chunk_size, layer.maximum_address - i) + current_chunk_size = min(chunk_size, layer.maximum_address + 1 - i) data = layer.read(i, current_chunk_size, pad=True) file_handle.write(data) if progress_callback: @@ -95,7 +95,7 @@ class LayerWriter(plugins.PluginInterface): if not self.config["layers"]: self.config["layers"] = [] for name in self.context.layers: - if not self.context.layers[name].metadata.get("mapped", False): + if "mapped" not in self.context.layers[name].metadata: self.config["layers"] = [name] for name in self.config["layers"]: @@ -103,7 +103,8 @@ class LayerWriter(plugins.PluginInterface): if name not in self.context.layers: yield 0, (f"Layer Name {name} does not exist",) else: - output_name = self.config.get("output", ".".join([name, "raw"])) + default_output_name = f"{name}.raw" + output_name = self.config.get("output", default_output_name) try: file_handle = self.write_layer( self.context, @@ -114,10 +115,12 @@ class LayerWriter(plugins.PluginInterface): progress_callback=self._progress_callback, ) file_handle.close() + + # Update the filename, which may have changed if a file + # with the same name already existed. + output_name = file_handle.preferred_filename except IOError as excp: - yield 0, ( - f"Layer cannot be written to {self.config['output_name']}: {excp}", - ) + yield 0, (f"Layer cannot be written to {output_name}: {excp}",) yield 0, (f"Layer has been written to {output_name}",)