From 7289f7dc70b77004bbf0c48d14ead436cfa925ff Mon Sep 17 00:00:00 2001 From: Andrew Case Date: Mon, 10 Mar 2025 03:27:56 +0000 Subject: [PATCH] Ensure that new symbol tables are only created when needed. Avoid name collisions leading to inconsistent behaviour. Make API for symbol table acquisition sane. --- .../framework/plugins/windows/modscan.py | 2 +- .../framework/plugins/windows/netscan.py | 2 +- .../framework/plugins/windows/poolscanner.py | 76 ++++++++++--------- .../framework/plugins/windows/psscan.py | 2 +- .../framework/plugins/windows/symlinkscan.py | 2 +- .../plugins/windows/windowstations.py | 2 +- 6 files changed, 45 insertions(+), 41 deletions(-) diff --git a/volatility3/framework/plugins/windows/modscan.py b/volatility3/framework/plugins/windows/modscan.py index 7330b2cb4..667fadd11 100644 --- a/volatility3/framework/plugins/windows/modscan.py +++ b/volatility3/framework/plugins/windows/modscan.py @@ -32,7 +32,7 @@ class ModScan(modules.Modules): architectures=["Intel32", "Intel64"], ), requirements.VersionRequirement( - name="poolscanner", component=poolscanner.PoolScanner, version=(2, 0, 0) + name="poolscanner", component=poolscanner.PoolScanner, version=(3, 0, 0) ), requirements.VersionRequirement( name="modules", component=modules.Modules, version=(3, 0, 0) diff --git a/volatility3/framework/plugins/windows/netscan.py b/volatility3/framework/plugins/windows/netscan.py index 0c8523cce..1ab748864 100644 --- a/volatility3/framework/plugins/windows/netscan.py +++ b/volatility3/framework/plugins/windows/netscan.py @@ -34,7 +34,7 @@ class NetScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): architectures=["Intel32", "Intel64"], ), requirements.VersionRequirement( - name="poolscanner", component=poolscanner.PoolScanner, version=(2, 0, 0) + name="poolscanner", component=poolscanner.PoolScanner, version=(3, 0, 0) ), requirements.VersionRequirement( name="info", component=info.Info, version=(2, 0, 0) diff --git a/volatility3/framework/plugins/windows/poolscanner.py b/volatility3/framework/plugins/windows/poolscanner.py index 5e75d9bbb..7dd6821b8 100644 --- a/volatility3/framework/plugins/windows/poolscanner.py +++ b/volatility3/framework/plugins/windows/poolscanner.py @@ -129,7 +129,7 @@ class PoolScanner(plugins.PluginInterface): """A generic pool scanner plugin.""" _required_framework_version = (2, 0, 0) - _version = (2, 0, 0) + _version = (3, 0, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: @@ -423,6 +423,7 @@ class PoolScanner(plugins.PluginInterface): # scan in the main kernel layer for the object(s) for constraint, header in cls.pool_scan( context, + kernel_module_name, scan_layer, object_symbol_table_name, constraints, @@ -501,6 +502,7 @@ class PoolScanner(plugins.PluginInterface): def pool_scan( cls, context: interfaces.context.ContextInterface, + kernel_module_name: str, layer_name: str, symbol_table: str, pool_constraints: List[PoolConstraint], @@ -534,8 +536,16 @@ class PoolScanner(plugins.PluginInterface): ) constraint_lookup[constraint.tag] = constraint - pool_header_table_name = cls.get_pool_header_table(context, symbol_table) - module = context.module(pool_header_table_name, layer_name, offset=0) + kernel = context.modules[kernel_module_name] + + if kernel.has_type("_POOL_HEADER"): + pool_header_table_name = kernel.symbol_table_name + else: + pool_header_table_name = cls.get_pool_header_table(context, symbol_table) + + module = context.module( + pool_header_table_name, layer_name, offset=kernel.offset + ) # Run the scan locating the offsets of a particular tag layer = context.layers[layer_name] @@ -553,43 +563,37 @@ class PoolScanner(plugins.PluginInterface): context: The context that the symbol tables does (or will) reside in symbol_table: The expected symbol_table to contain the _POOL_HEADER type """ - # Setup the pool header and offset differential - try: - context.symbol_space.get_type( - symbol_table + constants.BANG + "_POOL_HEADER" - ) - table_name = symbol_table - except exceptions.SymbolError: - # We have to manually load a symbol table + # We have to manually load a symbol table - if symbols.symbol_table_is_64bit( - context=context, symbol_table_name=symbol_table - ): - is_win_7 = versions.is_windows_7(context, symbol_table) - if is_win_7: - pool_header_json_filename = "poolheader-x64-win7" - else: - pool_header_json_filename = "poolheader-x64" + if symbols.symbol_table_is_64bit( + context=context, symbol_table_name=symbol_table + ): + is_win_7 = versions.is_windows_7(context, symbol_table) + if is_win_7: + pool_header_json_filename = "poolheader-x64-win7" else: - pool_header_json_filename = "poolheader-x86" + pool_header_json_filename = "poolheader-x64" + else: + pool_header_json_filename = "poolheader-x86" - # set the class_type to match the normal WindowsKernelIntermedSymbols - is_vista_or_later = versions.is_vista_or_later(context, symbol_table) - if is_vista_or_later: - class_type = extensions.pool.POOL_HEADER_VISTA - else: - class_type = extensions.pool.POOL_HEADER + # set the class_type to match the normal WindowsKernelIntermedSymbols + is_vista_or_later = versions.is_vista_or_later(context, symbol_table) + if is_vista_or_later: + class_type = extensions.pool.POOL_HEADER_VISTA + else: + class_type = extensions.pool.POOL_HEADER + + table_name = intermed.IntermediateSymbolTable.create( + context=context, + config_path=configuration.path_join( + context.symbol_space[symbol_table].config_path, "poolheader" + ), + sub_path="windows", + filename=pool_header_json_filename, + table_mapping={"nt_symbols": symbol_table}, + class_types={"_POOL_HEADER": class_type}, + ) - table_name = intermed.IntermediateSymbolTable.create( - context=context, - config_path=configuration.path_join( - context.symbol_space[symbol_table].config_path, "poolheader" - ), - sub_path="windows", - filename=pool_header_json_filename, - table_mapping={"nt_symbols": symbol_table}, - class_types={"_POOL_HEADER": class_type}, - ) return table_name def run(self) -> renderers.TreeGrid: diff --git a/volatility3/framework/plugins/windows/psscan.py b/volatility3/framework/plugins/windows/psscan.py index 45f935ceb..99fa9640b 100644 --- a/volatility3/framework/plugins/windows/psscan.py +++ b/volatility3/framework/plugins/windows/psscan.py @@ -40,7 +40,7 @@ class PsScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): name="info", component=info.Info, version=(2, 0, 0) ), requirements.VersionRequirement( - name="poolscanner", component=poolscanner.PoolScanner, version=(2, 0, 0) + name="poolscanner", component=poolscanner.PoolScanner, version=(3, 0, 0) ), requirements.ListRequirement( name="pid", diff --git a/volatility3/framework/plugins/windows/symlinkscan.py b/volatility3/framework/plugins/windows/symlinkscan.py index 459129843..358ea130e 100644 --- a/volatility3/framework/plugins/windows/symlinkscan.py +++ b/volatility3/framework/plugins/windows/symlinkscan.py @@ -28,7 +28,7 @@ class SymlinkScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterfa architectures=["Intel32", "Intel64"], ), requirements.VersionRequirement( - name="poolscanner", component=poolscanner.PoolScanner, version=(2, 0, 0) + name="poolscanner", component=poolscanner.PoolScanner, version=(3, 0, 0) ), ] diff --git a/volatility3/framework/plugins/windows/windowstations.py b/volatility3/framework/plugins/windows/windowstations.py index 9d666e3dd..0ca92eb97 100644 --- a/volatility3/framework/plugins/windows/windowstations.py +++ b/volatility3/framework/plugins/windows/windowstations.py @@ -47,7 +47,7 @@ class WindowStations(interfaces.plugins.PluginInterface): architectures=["Intel32", "Intel64"], ), requirements.VersionRequirement( - name="poolscanner", component=poolscanner.PoolScanner, version=(2, 0, 0) + name="poolscanner", component=poolscanner.PoolScanner, version=(3, 0, 0) ), requirements.VersionRequirement( name="modules", component=modules.Modules, version=(3, 0, 0)