Skip to content

Commit bb6dc9a

Browse files
committed
Merge branch 'develop' into linux_boottime_support
2 parents 57ffd5b + a196140 commit bb6dc9a

File tree

8 files changed

+336
-17
lines changed

8 files changed

+336
-17
lines changed

volatility3/cli/volshell/generic.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
5858
]
5959

6060
def run(
61-
self, additional_locals: Dict[str, Any] = None
61+
self, additional_locals: Dict[str, Any] = {}
6262
) -> interfaces.renderers.TreeGrid:
6363
"""Runs the interactive volshell plugin.
6464
@@ -94,7 +94,10 @@ def run(
9494
"""
9595

9696
sys.ps1 = f"({self.current_layer}) >>> "
97-
self.__console = code.InteractiveConsole(locals=self._construct_locals_dict())
97+
# Dict self._construct_locals_dict() will have priority on keys
98+
combined_locals = additional_locals.copy()
99+
combined_locals.update(self._construct_locals_dict())
100+
self.__console = code.InteractiveConsole(locals=combined_locals)
98101
# Since we have to do work to add the option only once for all different modes of volshell, we can't
99102
# rely on the default having been set
100103
if self.config.get("script", None) is not None:

volatility3/framework/constants/linux/__init__.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
Linux-specific values that aren't found in debug symbols
77
"""
8-
from enum import IntEnum
8+
from enum import IntEnum, Flag
99

1010
KERNEL_NAME = "__kernel__"
1111

@@ -304,4 +304,41 @@ class ELF_CLASS(IntEnum):
304304
ELFCLASS64 = 2
305305

306306

307+
PT_OPT_FLAG_SHIFT = 3
308+
309+
PTRACE_EVENT_FORK = 1
310+
PTRACE_EVENT_VFORK = 2
311+
PTRACE_EVENT_CLONE = 3
312+
PTRACE_EVENT_EXEC = 4
313+
PTRACE_EVENT_VFORK_DONE = 5
314+
PTRACE_EVENT_EXIT = 6
315+
PTRACE_EVENT_SECCOMP = 7
316+
317+
PTRACE_O_EXITKILL = 1 << 20
318+
PTRACE_O_SUSPEND_SECCOMP = 1 << 21
319+
320+
321+
class PT_FLAGS(Flag):
322+
"PTrace flags"
323+
PT_PTRACED = 0x00001
324+
PT_SEIZED = 0x10000
325+
326+
PT_TRACESYSGOOD = 1 << (PT_OPT_FLAG_SHIFT + 0)
327+
PT_TRACE_FORK = 1 << (PT_OPT_FLAG_SHIFT + PTRACE_EVENT_FORK)
328+
PT_TRACE_VFORK = 1 << (PT_OPT_FLAG_SHIFT + PTRACE_EVENT_VFORK)
329+
PT_TRACE_CLONE = 1 << (PT_OPT_FLAG_SHIFT + PTRACE_EVENT_CLONE)
330+
PT_TRACE_EXEC = 1 << (PT_OPT_FLAG_SHIFT + PTRACE_EVENT_EXEC)
331+
PT_TRACE_VFORK_DONE = 1 << (PT_OPT_FLAG_SHIFT + PTRACE_EVENT_VFORK_DONE)
332+
PT_TRACE_EXIT = 1 << (PT_OPT_FLAG_SHIFT + PTRACE_EVENT_EXIT)
333+
PT_TRACE_SECCOMP = 1 << (PT_OPT_FLAG_SHIFT + PTRACE_EVENT_SECCOMP)
334+
335+
PT_EXITKILL = PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT
336+
PT_SUSPEND_SECCOMP = PTRACE_O_SUSPEND_SECCOMP << PT_OPT_FLAG_SHIFT
337+
338+
@property
339+
def flags(self) -> str:
340+
"""Returns the ptrace flags string"""
341+
return str(self).replace(self.__class__.__name__ + ".", "")
342+
343+
307344
NSEC_PER_SEC = 1e9

volatility3/framework/contexts/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ def object(
245245
"""
246246
if constants.BANG not in object_type:
247247
object_type = self.symbol_table_name + constants.BANG + object_type
248-
else:
248+
elif not object_type.startswith(self.symbol_table_name + constants.BANG):
249249
raise ValueError(
250250
"Cannot reference another module when constructing an object"
251251
)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
2+
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
3+
#
4+
5+
import logging
6+
from typing import List, Iterator
7+
8+
from volatility3.framework import renderers, interfaces
9+
from volatility3.framework.constants import architectures
10+
from volatility3.framework.objects import utility
11+
from volatility3.framework.configuration import requirements
12+
from volatility3.framework.interfaces import plugins
13+
from volatility3.plugins.linux import pslist
14+
15+
vollog = logging.getLogger(__name__)
16+
17+
18+
class Ptrace(plugins.PluginInterface):
19+
"""Enumerates ptrace's tracer and tracee tasks"""
20+
21+
_required_framework_version = (2, 10, 0)
22+
_version = (1, 0, 0)
23+
24+
@classmethod
25+
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
26+
return [
27+
requirements.ModuleRequirement(
28+
name="kernel",
29+
description="Linux kernel",
30+
architectures=architectures.LINUX_ARCHS,
31+
),
32+
requirements.PluginRequirement(
33+
name="pslist", plugin=pslist.PsList, version=(2, 2, 0)
34+
),
35+
]
36+
37+
@classmethod
38+
def enumerate_ptrace_tasks(
39+
cls,
40+
context: interfaces.context.ContextInterface,
41+
vmlinux_module_name: str,
42+
) -> Iterator[interfaces.objects.ObjectInterface]:
43+
"""Enumerates ptrace's tracer and tracee tasks
44+
45+
Args:
46+
context: The context to retrieve required elements (layers, symbol tables) from
47+
vmlinux_module_name: The name of the kernel module on which to operate
48+
49+
Yields:
50+
A task_struct object
51+
"""
52+
53+
tasks = pslist.PsList.list_tasks(
54+
context,
55+
vmlinux_module_name,
56+
filter_func=pslist.PsList.create_pid_filter(),
57+
include_threads=True,
58+
)
59+
60+
for task in tasks:
61+
if task.is_being_ptraced or task.is_ptracing:
62+
yield task
63+
64+
def _generator(self, vmlinux_module_name):
65+
for task in self.enumerate_ptrace_tasks(self.context, vmlinux_module_name):
66+
task_comm = utility.array_to_string(task.comm)
67+
user_pid = task.tgid
68+
user_tid = task.pid
69+
tracer_tid = task.get_ptrace_tracer_tid() or renderers.NotAvailableValue()
70+
tracee_tids = task.get_ptrace_tracee_tids() or [
71+
renderers.NotAvailableValue()
72+
]
73+
flags = task.get_ptrace_tracee_flags() or renderers.NotAvailableValue()
74+
75+
for level, tracee_tid in enumerate(tracee_tids):
76+
fields = [
77+
task_comm,
78+
user_pid,
79+
user_tid,
80+
tracer_tid,
81+
tracee_tid,
82+
flags,
83+
]
84+
yield (level, fields)
85+
86+
def run(self):
87+
vmlinux_module_name = self.config["kernel"]
88+
89+
headers = [
90+
("Process", str),
91+
("PID", int),
92+
("TID", int),
93+
("Tracer TID", int),
94+
("Tracee TID", int),
95+
("Flags", str),
96+
]
97+
return renderers.TreeGrid(headers, self._generator(vmlinux_module_name))

volatility3/framework/plugins/windows/unloadedmodules.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing import List, Iterable
88

99
from volatility3.framework import constants
10-
from volatility3.framework import interfaces, symbols
10+
from volatility3.framework import interfaces, symbols, exceptions
1111
from volatility3.framework import renderers
1212
from volatility3.framework.configuration import requirements
1313
from volatility3.framework.interfaces import configuration
@@ -132,10 +132,15 @@ def _generator(self):
132132
kernel.symbol_table_name,
133133
unloadedmodule_table_name,
134134
):
135+
try:
136+
name = mod.Name.String
137+
except exceptions.InvalidAddressException:
138+
name = renderers.UnreadableValue()
139+
135140
yield (
136141
0,
137142
(
138-
mod.Name.String,
143+
name,
139144
format_hints.Hex(mod.StartAddress),
140145
format_hints.Hex(mod.EndAddress),
141146
conversion.wintime_to_datetime(mod.CurrentTime),

volatility3/framework/symbols/linux/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def __init__(self, *args, **kwargs) -> None:
2626
# Set-up Linux specific types
2727
self.set_type_class("file", extensions.struct_file)
2828
self.set_type_class("list_head", extensions.list_head)
29+
self.set_type_class("hlist_head", extensions.hlist_head)
2930
self.set_type_class("mm_struct", extensions.mm_struct)
3031
self.set_type_class("super_block", extensions.super_block)
3132
self.set_type_class("task_struct", extensions.task_struct)
@@ -57,6 +58,7 @@ def __init__(self, *args, **kwargs) -> None:
5758
# Might not exist in older kernels or the current symbols
5859
self.optional_set_type_class("mount", extensions.mount)
5960
self.optional_set_type_class("mnt_namespace", extensions.mnt_namespace)
61+
self.optional_set_type_class("rb_root", extensions.rb_root)
6062

6163
# Network
6264
self.set_type_class("net", extensions.net)

0 commit comments

Comments
 (0)