mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-25 23:52:23 +02:00
Merge pull request #1100 from adiego8/windows-psscan-offset
Windows: Add filtering by offset to psscan
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,25 @@ 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,
|
||||
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 +259,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,25 @@ 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,
|
||||
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 +453,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),
|
||||
)
|
||||
|
||||
@@ -59,6 +59,75 @@ class PsScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
|
||||
),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def physical_offset_from_virtual(cls, context, layer_name, proc):
|
||||
"""Calculate the physical offset from the virtual offset of a process.
|
||||
|
||||
Args:
|
||||
context: The context containing layers and modules information.
|
||||
layer_name: The name of the layer containing the process memory.
|
||||
proc: The process object for which to calculate the physical offset.
|
||||
|
||||
Returns:
|
||||
int: The physical offset of the process.
|
||||
Raises:
|
||||
TypeError: If the primary layer is not an Intel layer.
|
||||
"""
|
||||
memory = context.layers[layer_name]
|
||||
|
||||
if not isinstance(memory, layers.intel.Intel):
|
||||
raise TypeError("Primary layer is not an intel layer")
|
||||
|
||||
(_, _, ph_offset, _, _) = list(
|
||||
memory.mapping(offset=proc.vol.offset, length=0)
|
||||
)[0]
|
||||
|
||||
return ph_offset
|
||||
|
||||
@classmethod
|
||||
def create_offset_filter(
|
||||
cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
layer_name: str,
|
||||
offset: int = None,
|
||||
physical: bool = True,
|
||||
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
|
||||
exclude: Accept only tasks that are not the offset argument
|
||||
|
||||
Returns:
|
||||
Filter function to be passed to the list of processes.
|
||||
"""
|
||||
filter_func = lambda _: False
|
||||
|
||||
if offset:
|
||||
if physical:
|
||||
if exclude:
|
||||
filter_func = (
|
||||
lambda proc: cls.physical_offset_from_virtual(
|
||||
context, layer_name, proc
|
||||
)
|
||||
== offset
|
||||
)
|
||||
else:
|
||||
filter_func = (
|
||||
lambda proc: cls.physical_offset_from_virtual(
|
||||
context, layer_name, proc
|
||||
)
|
||||
!= offset
|
||||
)
|
||||
else:
|
||||
if exclude:
|
||||
filter_func = lambda proc: proc.vol.offset == offset
|
||||
else:
|
||||
filter_func = lambda proc: proc.vol.offset != offset
|
||||
|
||||
return filter_func
|
||||
|
||||
@classmethod
|
||||
def scan_processes(
|
||||
cls,
|
||||
|
||||
Reference in New Issue
Block a user