diff --git a/volatility/framework/plugins/windows/pstree.py b/volatility/framework/plugins/windows/pstree.py index 43a6b8d95..5acbd4ccd 100644 --- a/volatility/framework/plugins/windows/pstree.py +++ b/volatility/framework/plugins/windows/pstree.py @@ -1,15 +1,16 @@ # This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0 # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0 # - +import datetime from typing import Dict, Set -from volatility.framework import objects, interfaces +from volatility.framework import objects, interfaces, renderers +from volatility.framework.configuration import requirements from volatility.framework.renderers import format_hints from volatility.plugins.windows import pslist -class PsTree(pslist.PsList): +class PsTree(interfaces.plugins.PluginInterface): """Plugin for listing processes in a tree based on their parent process ID.""" @@ -19,6 +20,26 @@ class PsTree(pslist.PsList): self._levels = {} # type: Dict[int, int] self._children = {} # type: Dict[int, Set[int]] + @classmethod + def get_requirements(cls): + return [ + requirements.TranslationLayerRequirement(name = 'primary', + description = 'Memory layer for the kernel', + architectures = ["Intel32", "Intel64"]), + requirements.SymbolTableRequirement(name = "nt_symbols", description = "Windows kernel symbols"), + requirements.BooleanRequirement(name = 'physical', + description = 'Display physical offsets instead of virtual', + default = pslist.PsList.PHYSICAL_DEFAULT, + optional = True), + requirements.VersionRequirement(name = 'pslist', + component = pslist.PsList, + version = (1, 0, 0)), + requirements.ListRequirement(name = 'pid', + element_type = int, + description = "Process ID to include (all other processes are excluded)", + optional = True) + ] + def find_level(self, pid: objects.Pointer) -> None: """Finds how deep the pid is in the processes list.""" seen = set([]) @@ -35,9 +56,9 @@ class PsTree(pslist.PsList): def _generator(self): """Generates the Tree of processes.""" - for proc in self.list_processes(self.context, self.config['primary'], self.config['nt_symbols']): + for proc in pslist.PsList.list_processes(self.context, self.config['primary'], self.config['nt_symbols']): - if not self.config.get('physical', self.PHYSICAL_DEFAULT): + if not self.config.get('physical', pslist.PsList.PHYSICAL_DEFAULT): offset = proc.vol.offset else: layer_name = self.config['primary'] @@ -64,3 +85,12 @@ class PsTree(pslist.PsList): for pid in self._levels: if self._levels[pid] == 1: yield from yield_processes(pid) + + def run(self): + offsettype = "(V)" if not self.config.get('physical', pslist.PsList.PHYSICAL_DEFAULT) else "(P)" + + return renderers.TreeGrid([("PID", int), ("PPID", int), ("ImageFileName", str), + ("Offset{0}".format(offsettype), format_hints.Hex), ("Threads", int), + ("Handles", int), ("SessionId", int), ("Wow64", bool), + ("CreateTime", datetime.datetime), ("ExitTime", datetime.datetime)], + self._generator())