From c7f29936dcfb81bb9ae3fe33e261db2bb7c3be85 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 6 May 2024 11:15:45 +1000 Subject: [PATCH 01/12] CommandLine: Fix issue when --output filename doesn't contain an extension. If the argument is i.e. "--output aaa" ... it returned ".aaa" (hidden filename in linux) then "-1.aaa", "-2.aaa", etc. --- volatility3/cli/__init__.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/volatility3/cli/__init__.py b/volatility3/cli/__init__.py index 457a49311..c0eed20ee 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): From 32a5f131fd22d5351eee264fd6e58420a1458e9c Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 6 May 2024 11:17:51 +1000 Subject: [PATCH 02/12] LayerWriter plugin: Fix log wrong (non-existent) variable --- volatility3/framework/plugins/layerwriter.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index 1bee5f20d..a8664b3f1 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -115,9 +115,7 @@ class LayerWriter(plugins.PluginInterface): ) file_handle.close() 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}",) From 1246b20b6521e11110038fe091af912e2b5f4439 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 6 May 2024 11:25:45 +1000 Subject: [PATCH 03/12] LayerWriter plugin: Code improvements --- volatility3/framework/plugins/layerwriter.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index a8664b3f1..021c44248 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -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, From 6d22347ce6dd0152746564a2d77022ca1b4d9045 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 6 May 2024 11:27:15 +1000 Subject: [PATCH 04/12] LayerWriter plugin: Fix --output argument. It's referenced in the code but never mentioned as a requirement --- volatility3/framework/plugins/layerwriter.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index 021c44248..d60ead682 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -38,6 +38,10 @@ class LayerWriter(plugins.PluginInterface): default=False, optional=True, ), + requirements.StringRequirement( + name="output", + description="Output filename", + ), requirements.ListRequirement( name="layers", element_type=str, From e5a5b895771b655d21c36689c33a534034c31e36 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 6 May 2024 13:06:02 +1000 Subject: [PATCH 05/12] Intel layer: Fix. This if statement will never be executed unless "minimum_address > maximum_address" which doesn't make sense to me. --- volatility3/framework/layers/intel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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, From f116c08a7ec60f62e3ef931de7639e402f421d65 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 6 May 2024 13:07:23 +1000 Subject: [PATCH 06/12] NonLinearlySegmentedLayer: Fix maximum addresses in segmented layers --- volatility3/framework/layers/segmented.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From a6c77c488436c7b05040b5bf475be79cb59457f3 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 6 May 2024 13:09:45 +1000 Subject: [PATCH 07/12] LayerWriter: Fix - Last chunk size is wrongly calculated --- volatility3/framework/plugins/layerwriter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index d60ead682..178d86ba9 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]: @@ -81,7 +81,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: From d7aae3a9828ba03bd5531aa385724a954e48501a Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 6 May 2024 13:11:52 +1000 Subject: [PATCH 08/12] Store the real/final output filename so that we can notify it correctly to the user --- volatility3/cli/__init__.py | 4 ++-- volatility3/framework/plugins/layerwriter.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/volatility3/cli/__init__.py b/volatility3/cli/__init__.py index c0eed20ee..9873791e3 100644 --- a/volatility3/cli/__init__.py +++ b/volatility3/cli/__init__.py @@ -790,8 +790,8 @@ class CommandLine: return None self._file.close() - output_filename = self._get_final_filename() - os.rename(self._name, output_filename) + self._output_filename = self._get_final_filename() + os.rename(self._name, self._output_filename) if direct: return CLIDirectFileHandler diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index 178d86ba9..20d10d636 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -119,6 +119,7 @@ class LayerWriter(plugins.PluginInterface): progress_callback=self._progress_callback, ) file_handle.close() + output_name = file_handle._output_filename except IOError as excp: yield 0, (f"Layer cannot be written to {output_name}: {excp}",) From 85052b6238414617cc87f6812894f14917e03393 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Tue, 7 May 2024 08:12:31 +1000 Subject: [PATCH 09/12] LayerWriter: Fix missing optional flag for the --output argument --- volatility3/framework/plugins/layerwriter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index 20d10d636..6a06cc607 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -41,6 +41,7 @@ class LayerWriter(plugins.PluginInterface): requirements.StringRequirement( name="output", description="Output filename", + optional=True, ), requirements.ListRequirement( name="layers", From a72062f2889fdfe5d03e3974e4bc314a35e85700 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 10 Jun 2024 17:20:47 +1000 Subject: [PATCH 10/12] Revert "LayerWriter plugin: Fix --output argument. It's referenced in the code but never mentioned as a requirement" This reverts commit 6d22347ce6dd0152746564a2d77022ca1b4d9045. --- volatility3/framework/plugins/layerwriter.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index 6a06cc607..319e4fd7a 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -38,11 +38,6 @@ class LayerWriter(plugins.PluginInterface): default=False, optional=True, ), - requirements.StringRequirement( - name="output", - description="Output filename", - optional=True, - ), requirements.ListRequirement( name="layers", element_type=str, From ab84070df30ddfaccc2e304e26fb7815a5555444 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 10 Jun 2024 17:25:05 +1000 Subject: [PATCH 11/12] Revert "Store the real/final output filename so that we can notify it correctly to the user" This reverts commit d7aae3a9828ba03bd5531aa385724a954e48501a. --- volatility3/cli/__init__.py | 4 ++-- volatility3/framework/plugins/layerwriter.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/volatility3/cli/__init__.py b/volatility3/cli/__init__.py index 9873791e3..c0eed20ee 100644 --- a/volatility3/cli/__init__.py +++ b/volatility3/cli/__init__.py @@ -790,8 +790,8 @@ class CommandLine: return None self._file.close() - self._output_filename = self._get_final_filename() - os.rename(self._name, self._output_filename) + output_filename = self._get_final_filename() + os.rename(self._name, output_filename) if direct: return CLIDirectFileHandler diff --git a/volatility3/framework/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index 319e4fd7a..61c3118b5 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -115,7 +115,6 @@ class LayerWriter(plugins.PluginInterface): progress_callback=self._progress_callback, ) file_handle.close() - output_name = file_handle._output_filename except IOError as excp: yield 0, (f"Layer cannot be written to {output_name}: {excp}",) From 77fb0b7b26c2c52140380a2ce9f1a896a84c258a Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 10 Jun 2024 18:37:38 +1000 Subject: [PATCH 12/12] Update the output filename (preferred_filename) so that we can notify it correctly to the user --- volatility3/cli/__init__.py | 10 +++++++++- volatility3/framework/plugins/layerwriter.py | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/volatility3/cli/__init__.py b/volatility3/cli/__init__.py index c0eed20ee..6b17edac0 100644 --- a/volatility3/cli/__init__.py +++ b/volatility3/cli/__init__.py @@ -789,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/plugins/layerwriter.py b/volatility3/framework/plugins/layerwriter.py index 61c3118b5..24149a390 100644 --- a/volatility3/framework/plugins/layerwriter.py +++ b/volatility3/framework/plugins/layerwriter.py @@ -115,6 +115,10 @@ 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 {output_name}: {excp}",)