mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-23 14:42:25 +02:00
This also adds support for manually constructed configurables to populate the config tree in the current context. I'm still toying around with this though, I need to figure out what to do with optional values and think the whole thing through to make sure it's worthwhile.
51 lines
2.7 KiB
Python
51 lines
2.7 KiB
Python
import volatility.framework.interfaces.plugins as plugins
|
|
from volatility.framework.configuration import requirements
|
|
from volatility.framework.renderers import TreeGrid
|
|
|
|
|
|
class PsList(plugins.PluginInterface):
|
|
@classmethod
|
|
def get_requirements(cls):
|
|
return [requirements.TranslationLayerRequirement(name = 'primary',
|
|
description = 'Kernel Address Space'),
|
|
requirements.SymbolRequirement(name = "ntkrnlmp",
|
|
description = "Windows OS"),
|
|
requirements.IntRequirement(name = 'pid',
|
|
description = "Process ID",
|
|
optional = True),
|
|
requirements.IntRequirement(name = 'offset',
|
|
description = 'Virtual address of any process')]
|
|
|
|
def update_configuration(self):
|
|
"""No operation since all values provided by config/requirements initially"""
|
|
|
|
@staticmethod
|
|
def kernel_process_from_physical_process(ctx, physical_layer, kernel_layer, offset):
|
|
"""Return a kernel process object from physical process data."""
|
|
# Get the process in the physical space
|
|
flateproc = ctx.object("ntkrnlmp!_EPROCESS", physical_layer, offset = offset)
|
|
# Determine the relative offset from the Thread head to the ThreadListEntry
|
|
reloff = ctx.symbol_space.get_type("ntkrnlmp!_ETHREAD").relative_child_offset("ThreadListEntry")
|
|
# Get the thread object in kernel space from the
|
|
ethread = ctx.object("ntkrnlmp!_ETHREAD", kernel_layer, offset = flateproc.ThreadListHead.Flink - reloff)
|
|
# Get the process from the thread object in kernel space
|
|
return ethread.owning_process()
|
|
|
|
def _generator(self, eproc):
|
|
for proc in eproc.ActiveProcessLinks:
|
|
yield (0, (proc.UniqueProcessId, proc.InheritedFromUniqueProcessId,
|
|
proc.ImageFileName.cast("String", max_length = proc.ImageFileName.vol.count,
|
|
errors = 'replace')))
|
|
|
|
def run(self):
|
|
# Use the primary twice until we figure out how to specify base layers of a particular translation layer
|
|
eproc = self.kernel_process_from_physical_process(self.context,
|
|
self.config['primary.memory_layer'],
|
|
self.config['primary'],
|
|
self.config['offset'])
|
|
|
|
return TreeGrid([("PID", int),
|
|
("PPID", int),
|
|
("ImageFileName", str)],
|
|
self._generator(eproc))
|