From 26cd73115b58cf5b1adfb430c9f1070e45dbe727 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 8 Sep 2024 13:31:09 +0100 Subject: [PATCH 1/3] CLI: Filter on rendered values --- volatility3/cli/text_renderer.py | 38 +++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/volatility3/cli/text_renderer.py b/volatility3/cli/text_renderer.py index ab9e44141..1f9cfa9d8 100644 --- a/volatility3/cli/text_renderer.py +++ b/volatility3/cli/text_renderer.py @@ -179,7 +179,15 @@ class QuickTextRenderer(CLIRenderer): outfd.write("\n{}\n".format("\t".join(line))) def visitor(node: interfaces.renderers.TreeNode, accumulator): - if self.filter and self.filter.filter(node.values): + line = [] + for column_index in range(len(grid.columns)): + column = grid.columns[column_index] + renderer = self._type_renderers.get( + column.type, self._type_renderers["default"] + ) + line.append(renderer(node.values[column_index])) + + if self.filter and self.filter.filter(line): return accumulator accumulator.write("\n") @@ -188,13 +196,6 @@ class QuickTextRenderer(CLIRenderer): "*" * max(0, node.path_depth - 1) + ("" if (node.path_depth <= 1) else " ") ) - line = [] - for column_index in range(len(grid.columns)): - column = grid.columns[column_index] - renderer = self._type_renderers.get( - column.type, self._type_renderers["default"] - ) - line.append(renderer(node.values[column_index])) accumulator.write("{}".format("\t".join(line))) accumulator.flush() return accumulator @@ -259,12 +260,18 @@ class CSVRenderer(CLIRenderer): def visitor(node: interfaces.renderers.TreeNode, accumulator): # Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case row = {"TreeDepth": str(max(0, node.path_depth - 1))} + line = [] for column_index in range(len(grid.columns)): column = grid.columns[column_index] renderer = self._type_renderers.get( column.type, self._type_renderers["default"] ) row[f"{column.name}"] = renderer(node.values[column_index]) + line.append(row[f"{column.name}"]) + + if self.filter and self.filter.filter(line): + return accumulator + accumulator.writerow(row) return accumulator @@ -317,10 +324,8 @@ class PrettyTextRenderer(CLIRenderer): max_column_widths.get(tree_indent_column, 0), node.path_depth ) - if self.filter and self.filter.filter(node.values): - return accumulator - line = {} + rendered_line = [] for column_index in range(len(grid.columns)): column = grid.columns[column_index] renderer = self._type_renderers.get( @@ -334,6 +339,11 @@ class PrettyTextRenderer(CLIRenderer): max_column_widths.get(column.name, len(column.name)), field_width ) line[column] = data.split("\n") + rendered_line.append(data) + + if self.filter and self.filter.filter(rendered_line): + return accumulator + accumulator.append((node.path_depth, line)) return accumulator @@ -437,6 +447,7 @@ class JsonRenderer(CLIRenderer): # Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case acc_map, final_tree = accumulator node_dict: Dict[str, Any] = {"__children": []} + line = [] for column_index in range(len(grid.columns)): column = grid.columns[column_index] renderer = self._type_renderers.get( @@ -446,6 +457,11 @@ class JsonRenderer(CLIRenderer): if isinstance(data, interfaces.renderers.BaseAbsentValue): data = None node_dict[column.name] = data + line.append(data) + + if self.filter and self.filter.filter(line): + return accumulator + if node.parent: acc_map[node.parent.path]["__children"].append(node_dict) else: From 8259ca90199f548e1592aa3ab05444c9353fe66a Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 8 Sep 2024 13:47:26 +0100 Subject: [PATCH 2/3] Core: Bump the framework number so we can differentiate CLI versions --- volatility3/framework/constants/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/volatility3/framework/constants/_version.py b/volatility3/framework/constants/_version.py index d30446d63..a131609c9 100644 --- a/volatility3/framework/constants/_version.py +++ b/volatility3/framework/constants/_version.py @@ -1,6 +1,6 @@ # We use the SemVer 2.0.0 versioning scheme VERSION_MAJOR = 2 # Number of releases of the library with a breaking change -VERSION_MINOR = 9 # Number of changes that only add to the interface +VERSION_MINOR = 10 # Number of changes that only add to the interface VERSION_PATCH = 0 # Number of changes that do not change the interface VERSION_SUFFIX = "" From fd2c97e1bafb5b30403a1788eae4c32723438746 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Mon, 9 Sep 2024 00:44:00 +0100 Subject: [PATCH 3/3] CLI: Use enumerate for renderers (thanks @gcmoreira) --- volatility3/cli/text_renderer.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/volatility3/cli/text_renderer.py b/volatility3/cli/text_renderer.py index 1f9cfa9d8..da0cdf62a 100644 --- a/volatility3/cli/text_renderer.py +++ b/volatility3/cli/text_renderer.py @@ -180,8 +180,7 @@ class QuickTextRenderer(CLIRenderer): def visitor(node: interfaces.renderers.TreeNode, accumulator): line = [] - for column_index in range(len(grid.columns)): - column = grid.columns[column_index] + for column_index, column in enumerate(grid.columns): renderer = self._type_renderers.get( column.type, self._type_renderers["default"] ) @@ -261,8 +260,7 @@ class CSVRenderer(CLIRenderer): # Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case row = {"TreeDepth": str(max(0, node.path_depth - 1))} line = [] - for column_index in range(len(grid.columns)): - column = grid.columns[column_index] + for column_index, column in enumerate(grid.columns): renderer = self._type_renderers.get( column.type, self._type_renderers["default"] ) @@ -326,8 +324,7 @@ class PrettyTextRenderer(CLIRenderer): line = {} rendered_line = [] - for column_index in range(len(grid.columns)): - column = grid.columns[column_index] + for column_index, column in enumerate(grid.columns): renderer = self._type_renderers.get( column.type, self._type_renderers["default"] ) @@ -357,8 +354,7 @@ class PrettyTextRenderer(CLIRenderer): format_string_list = [ "{0:<" + str(max_column_widths.get(tree_indent_column, 0)) + "s}" ] - for column_index in range(len(grid.columns)): - column = grid.columns[column_index] + for column_index, column in enumerate(grid.columns): format_string_list.append( "{" + str(column_index + 1) @@ -448,8 +444,7 @@ class JsonRenderer(CLIRenderer): acc_map, final_tree = accumulator node_dict: Dict[str, Any] = {"__children": []} line = [] - for column_index in range(len(grid.columns)): - column = grid.columns[column_index] + for column_index, column in enumerate(grid.columns): renderer = self._type_renderers.get( column.type, self._type_renderers["default"] )