Add PID filtering to windows.pstree

This commit is contained in:
Maxime THIEBAUT
2023-02-25 20:52:13 +01:00
parent 1770edf6fa
commit 588b096254
+36 -10
View File
@@ -3,7 +3,7 @@
#
import datetime
import logging
from typing import Dict, Set, Tuple
from typing import Callable, Dict, Set, Tuple
from volatility3.framework import objects, interfaces, renderers
from volatility3.framework.configuration import requirements
@@ -24,6 +24,7 @@ class PsTree(interfaces.plugins.PluginInterface):
self._processes: Dict[int, Tuple[interfaces.objects.ObjectInterface, int]] = {}
self._levels: Dict[int, int] = {}
self._children: Dict[int, Set[int]] = {}
self._ancestors: Set[int] = set([])
@classmethod
def get_requirements(cls):
@@ -45,18 +46,26 @@ class PsTree(interfaces.plugins.PluginInterface):
requirements.ListRequirement(
name="pid",
element_type=int,
description="Process ID to include (all other processes are excluded)",
description="Process ID to include (with ancestors and descendants, all other processes are excluded)",
optional=True,
),
]
def find_level(self, pid: objects.Pointer) -> None:
def find_level(
self,
pid: objects.Pointer,
filter_func: Callable[
[interfaces.objects.ObjectInterface], bool
] = lambda _: False,
) -> None:
"""Finds how deep the pid is in the processes list."""
seen = set([])
seen.add(pid)
seen = {pid}
level = 0
proc, _ = self._processes.get(pid, None)
filtered = not filter_func(proc)
while proc is not None and proc.InheritedFromUniqueProcessId not in seen:
if filtered:
self._ancestors.add(proc.UniqueProcessId)
child_list = self._children.get(proc.InheritedFromUniqueProcessId, set([]))
child_list.add(proc.UniqueProcessId)
self._children[proc.InheritedFromUniqueProcessId] = child_list
@@ -67,7 +76,12 @@ class PsTree(interfaces.plugins.PluginInterface):
level += 1
self._levels[pid] = level
def _generator(self):
def _generator(
self,
filter_func: Callable[
[interfaces.objects.ObjectInterface], bool
] = lambda _: False,
):
"""Generates the Tree of processes."""
kernel = self.context.modules[self.config["kernel"]]
@@ -87,15 +101,21 @@ class PsTree(interfaces.plugins.PluginInterface):
# Build the child/level maps
for pid in self._processes:
self.find_level(pid)
self.find_level(pid, filter_func)
process_pids = set([])
def yield_processes(pid):
def yield_processes(pid, descendant: bool = False):
if pid in process_pids:
vollog.debug(f"Pid cycle: already processed pid {pid}")
return
process_pids.add(pid)
if pid not in self._ancestors and not descendant:
vollog.debug(f"Pid cycle: pid {pid} not in filtered tree")
return
proc, offset = self._processes[pid]
row = (
proc.UniqueProcessId,
@@ -114,7 +134,9 @@ class PsTree(interfaces.plugins.PluginInterface):
yield (self._levels[pid] - 1, row)
for child_pid in self._children.get(pid, []):
yield from yield_processes(child_pid)
yield from yield_processes(
child_pid, descendant or not filter_func(proc)
)
for pid in self._levels:
if self._levels[pid] == 1:
@@ -140,5 +162,9 @@ class PsTree(interfaces.plugins.PluginInterface):
("CreateTime", datetime.datetime),
("ExitTime", datetime.datetime),
],
self._generator(),
self._generator(
filter_func=pslist.PsList.create_pid_filter(
self.config.get("pid", None)
),
),
)