mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-26 08:02:23 +02:00
Windows: Add filtering by offset to psscan
Add capability to the psscan plugin to filter by specific offset. The filter would be used by other plugins to find specific offset using the psscan capabilities, like find hidden processes as a result of some dkom for example. The `--offset` flag argument should represent a physical address space. The flag is included in the following plugins: - dlllist - handles
This commit is contained in:
@@ -13,7 +13,7 @@ from volatility3.framework.renderers import conversion, format_hints
|
||||
from volatility3.framework.symbols import intermed
|
||||
from volatility3.framework.symbols.windows.extensions import pe
|
||||
from volatility3.plugins import timeliner
|
||||
from volatility3.plugins.windows import info, pslist
|
||||
from volatility3.plugins.windows import info, pslist, psscan
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
@@ -36,6 +36,9 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
requirements.VersionRequirement(
|
||||
name="pslist", component=pslist.PsList, version=(2, 0, 0)
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="psscan", component=psscan.PsScan, version=(1, 1, 0)
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="info", component=info.Info, version=(1, 0, 0)
|
||||
),
|
||||
@@ -45,6 +48,11 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
description="Process IDs to include (all other processes are excluded)",
|
||||
optional=True,
|
||||
),
|
||||
requirements.IntRequirement(
|
||||
name="offset",
|
||||
description="Process offset in the physical address space",
|
||||
optional=True,
|
||||
),
|
||||
requirements.BooleanRequirement(
|
||||
name="dump",
|
||||
description="Extract listed DLLs",
|
||||
@@ -221,6 +229,24 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
|
||||
kernel = self.context.modules[self.config["kernel"]]
|
||||
|
||||
if self.config["offset"]:
|
||||
procs = psscan.PsScan.scan_processes(
|
||||
self.context,
|
||||
kernel.layer_name,
|
||||
kernel.symbol_table_name,
|
||||
filter_func=psscan.PsScan.create_offset_filter(
|
||||
self.context.layers[kernel.layer_name],
|
||||
self.config["offset"],
|
||||
),
|
||||
)
|
||||
else:
|
||||
procs = pslist.PsList.list_processes(
|
||||
context=self.context,
|
||||
layer_name=kernel.layer_name,
|
||||
symbol_table=kernel.symbol_table_name,
|
||||
filter_func=filter_func,
|
||||
)
|
||||
|
||||
return renderers.TreeGrid(
|
||||
[
|
||||
("PID", int),
|
||||
@@ -232,12 +258,5 @@ class DllList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
("LoadTime", datetime.datetime),
|
||||
("File output", str),
|
||||
],
|
||||
self._generator(
|
||||
pslist.PsList.list_processes(
|
||||
context=self.context,
|
||||
layer_name=kernel.layer_name,
|
||||
symbol_table=kernel.symbol_table_name,
|
||||
filter_func=filter_func,
|
||||
)
|
||||
),
|
||||
self._generator(procs=procs),
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@ from volatility3.framework import constants, exceptions, renderers, interfaces,
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.objects import utility
|
||||
from volatility3.framework.renderers import format_hints
|
||||
from volatility3.plugins.windows import pslist
|
||||
from volatility3.plugins.windows import pslist, psscan
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
@@ -43,14 +43,22 @@ class Handles(interfaces.plugins.PluginInterface):
|
||||
description="Windows kernel",
|
||||
architectures=["Intel32", "Intel64"],
|
||||
),
|
||||
requirements.PluginRequirement(
|
||||
name="pslist", plugin=pslist.PsList, version=(2, 0, 0)
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="psscan", component=psscan.PsScan, version=(1, 1, 0)
|
||||
),
|
||||
requirements.ListRequirement(
|
||||
name="pid",
|
||||
element_type=int,
|
||||
description="Process IDs to include (all other processes are excluded)",
|
||||
optional=True,
|
||||
),
|
||||
requirements.PluginRequirement(
|
||||
name="pslist", plugin=pslist.PsList, version=(2, 0, 0)
|
||||
requirements.IntRequirement(
|
||||
name="offset",
|
||||
description="Process offset in the physical address space",
|
||||
optional=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -416,6 +424,24 @@ class Handles(interfaces.plugins.PluginInterface):
|
||||
filter_func = pslist.PsList.create_pid_filter(self.config.get("pid", None))
|
||||
kernel = self.context.modules[self.config["kernel"]]
|
||||
|
||||
if self.config["offset"]:
|
||||
procs = psscan.PsScan.scan_processes(
|
||||
self.context,
|
||||
kernel.layer_name,
|
||||
kernel.symbol_table_name,
|
||||
filter_func=psscan.PsScan.create_offset_filter(
|
||||
self.context.layers[kernel.layer_name],
|
||||
self.config["offset"],
|
||||
),
|
||||
)
|
||||
else:
|
||||
procs = pslist.PsList.list_processes(
|
||||
context=self.context,
|
||||
layer_name=kernel.layer_name,
|
||||
symbol_table=kernel.symbol_table_name,
|
||||
filter_func=filter_func,
|
||||
)
|
||||
|
||||
return renderers.TreeGrid(
|
||||
[
|
||||
("PID", int),
|
||||
@@ -426,12 +452,5 @@ class Handles(interfaces.plugins.PluginInterface):
|
||||
("GrantedAccess", format_hints.Hex),
|
||||
("Name", str),
|
||||
],
|
||||
self._generator(
|
||||
pslist.PsList.list_processes(
|
||||
self.context,
|
||||
kernel.layer_name,
|
||||
kernel.symbol_table_name,
|
||||
filter_func=filter_func,
|
||||
)
|
||||
),
|
||||
self._generator(procs=procs),
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
from typing import Iterable, Callable, Optional, Tuple
|
||||
from typing import Iterable, Callable, List, Optional, Tuple
|
||||
|
||||
from volatility3.framework import renderers, interfaces, layers, exceptions
|
||||
from volatility3.framework.configuration import requirements
|
||||
@@ -59,6 +59,44 @@ class PsScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def create_offset_filter(
|
||||
cls,
|
||||
memory: interfaces.layers.DataLayerInterface,
|
||||
offset: int = None,
|
||||
exclude: bool = False,
|
||||
) -> Callable[[interfaces.objects.ObjectInterface], bool]:
|
||||
"""A factory for producing filter functions that filter based on the physical offset of the process.
|
||||
|
||||
Args:
|
||||
offset: A number that is the physical offset to be filtered out
|
||||
memory: Memory object needed to do the offset mapping to physical.
|
||||
exclude: Accept only tasks that are not the offset argument
|
||||
Returns:
|
||||
Filter function to be passed to the list of processes.
|
||||
"""
|
||||
if not isinstance(memory, interfaces.layers.DataLayerInterface):
|
||||
raise TypeError("memory object requires an instance of DataLayerInterface")
|
||||
|
||||
filter_func = lambda _: False
|
||||
|
||||
# return physical offset in tuple -> (_, _, physical_offset, _, _)
|
||||
# from the first item in the memory mapping list
|
||||
virtual_to_physical_offset = lambda virtual_offset, memory: list(
|
||||
memory.mapping(offset=virtual_offset, length=0)
|
||||
)[0][2]
|
||||
|
||||
if offset:
|
||||
if exclude:
|
||||
filter_func = (
|
||||
lambda x: virtual_to_physical_offset(x.vol.offset, memory) == offset
|
||||
)
|
||||
else:
|
||||
filter_func = (
|
||||
lambda x: virtual_to_physical_offset(x.vol.offset, memory) != offset
|
||||
)
|
||||
return filter_func
|
||||
|
||||
@classmethod
|
||||
def scan_processes(
|
||||
cls,
|
||||
|
||||
Reference in New Issue
Block a user