mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-13 05:07:38 +02:00
Windows PoolScan: Adds method
This updates the poolscanner plugin with an additional method, `generate_pool_scan_extended`, and does the corresponding minor version bump. Co-authored-by: Andrew Case <andrew@dfir.org>
This commit is contained in:
co-authored by
Andrew Case
parent
be8b7580dd
commit
5ed31d3133
@@ -79,6 +79,7 @@ class PoolHeaderScanner(interfaces.layers.ScannerInterface):
|
||||
offset=offset - self._header_offset,
|
||||
absolute=True,
|
||||
)
|
||||
|
||||
constraint = self._constraint_lookup[pattern]
|
||||
try:
|
||||
# Size check
|
||||
@@ -128,7 +129,7 @@ class PoolScanner(plugins.PluginInterface):
|
||||
"""A generic pool scanner plugin."""
|
||||
|
||||
_required_framework_version = (2, 0, 0)
|
||||
_version = (1, 0, 1)
|
||||
_version = (1, 1, 1)
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
||||
@@ -331,11 +332,12 @@ class PoolScanner(plugins.PluginInterface):
|
||||
return [constraint for constraint in builtins if constraint.tag in tags_filter]
|
||||
|
||||
@classmethod
|
||||
def generate_pool_scan(
|
||||
def generate_pool_scan_extended(
|
||||
cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
layer_name: str,
|
||||
symbol_table: str,
|
||||
kernel_layer_name: str,
|
||||
kernel_symbol_table: str,
|
||||
object_symbol_table: str,
|
||||
constraints: List[PoolConstraint],
|
||||
) -> Generator[
|
||||
Tuple[
|
||||
@@ -347,49 +349,60 @@ class PoolScanner(plugins.PluginInterface):
|
||||
None,
|
||||
]:
|
||||
"""
|
||||
The extended version of `generate_pool_scan` to support pool scanning for objects outside of the kernel (ntoskrnl).
|
||||
This requires the symbol table of the object being scanned for.
|
||||
|
||||
Args:
|
||||
context: The context to retrieve required elements (layers, symbol tables) from
|
||||
layer_name: The name of the layer on which to operate
|
||||
symbol_table: The name of the table containing the kernel symbols
|
||||
kernel_layer_name: The name of the base kernel layer
|
||||
kernel_symbol_table_name: The name of the table containing the kernel symbols
|
||||
object_symbol_table_name: The name of the symbol table for the object being scanned for
|
||||
constraints: List of pool constraints used to limit the scan results
|
||||
|
||||
Returns:
|
||||
Iterable of tuples, containing the constraint that matched, the object from memory, the object header used to determine the object
|
||||
"""
|
||||
|
||||
# get the object type map
|
||||
type_map = handles.Handles.get_type_map(
|
||||
context=context, layer_name=layer_name, symbol_table=symbol_table
|
||||
context=context,
|
||||
layer_name=kernel_layer_name,
|
||||
symbol_table=kernel_symbol_table,
|
||||
)
|
||||
|
||||
cookie = handles.Handles.find_cookie(
|
||||
context=context, layer_name=layer_name, symbol_table=symbol_table
|
||||
context=context,
|
||||
layer_name=kernel_layer_name,
|
||||
symbol_table=kernel_symbol_table,
|
||||
)
|
||||
|
||||
is_windows_10 = versions.is_windows_10(context, symbol_table)
|
||||
is_windows_8_or_later = versions.is_windows_8_or_later(context, symbol_table)
|
||||
is_windows_10 = versions.is_windows_10(context, kernel_symbol_table)
|
||||
is_windows_8_or_later = versions.is_windows_8_or_later(
|
||||
context, kernel_symbol_table
|
||||
)
|
||||
|
||||
# start off with the primary virtual layer
|
||||
scan_layer = layer_name
|
||||
scan_layer = kernel_layer_name
|
||||
|
||||
# switch to a non-virtual layer if necessary
|
||||
if not is_windows_10:
|
||||
scan_layer = context.layers[scan_layer].config["memory_layer"]
|
||||
|
||||
if symbols.symbol_table_is_64bit(context, symbol_table):
|
||||
if symbols.symbol_table_is_64bit(context, kernel_symbol_table):
|
||||
alignment = 0x10
|
||||
else:
|
||||
alignment = 8
|
||||
|
||||
# scan in the main kernel layer for the object(s)
|
||||
for constraint, header in cls.pool_scan(
|
||||
context, scan_layer, symbol_table, constraints, alignment=alignment
|
||||
context, scan_layer, object_symbol_table, constraints, alignment=alignment
|
||||
):
|
||||
|
||||
# construct the object in its own layer, using its own types
|
||||
mem_objects = header.get_object(
|
||||
constraint=constraint,
|
||||
use_top_down=is_windows_8_or_later,
|
||||
native_layer_name=layer_name,
|
||||
kernel_symbol_table=symbol_table,
|
||||
native_layer_name=kernel_layer_name,
|
||||
kernel_symbol_table=kernel_symbol_table,
|
||||
)
|
||||
|
||||
for mem_object in mem_objects:
|
||||
@@ -398,6 +411,7 @@ class PoolScanner(plugins.PluginInterface):
|
||||
constants.LOGLEVEL_VVV,
|
||||
f"Cannot create an instance of {constraint.type_name}",
|
||||
)
|
||||
|
||||
continue
|
||||
|
||||
if constraint.object_type is not None and not constraint.skip_type_test:
|
||||
@@ -418,6 +432,40 @@ class PoolScanner(plugins.PluginInterface):
|
||||
|
||||
yield constraint, mem_object, header
|
||||
|
||||
@classmethod
|
||||
def generate_pool_scan(
|
||||
cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
layer_name: str,
|
||||
symbol_table: str,
|
||||
constraints: List[PoolConstraint],
|
||||
) -> Generator[
|
||||
Tuple[
|
||||
PoolConstraint,
|
||||
interfaces.objects.ObjectInterface,
|
||||
interfaces.objects.ObjectInterface,
|
||||
],
|
||||
None,
|
||||
None,
|
||||
]:
|
||||
"""
|
||||
The original version of `generate_pool_scan` which is sufficient for objects in the kernel (ntoskrnl),
|
||||
|
||||
Args:
|
||||
context: The context to retrieve required elements (layers, symbol tables) from
|
||||
layer_name: The name of the layer on which to operate
|
||||
symbol_table: The name of the table containing the kernel symbols
|
||||
constraints: List of pool constraints used to limit the scan results
|
||||
|
||||
Returns:
|
||||
Iterable of tuples, containing the constraint that matched, the object from memory, the object header used to determine the object
|
||||
"""
|
||||
|
||||
# repeat the symbol table to match the original `generate_pool_scan` behaviour
|
||||
yield from cls.generate_pool_scan_extended(
|
||||
context, layer_name, symbol_table, symbol_table, constraints
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def pool_scan(
|
||||
cls,
|
||||
|
||||
Reference in New Issue
Block a user