Skip to content

Commit 4ac8599

Browse files
authored
Merge pull request #1730 from volatilityfoundation/threads_useful_columns
Add win32 start address listing. Add paths for both thread starting a…
2 parents 083dae7 + 1952079 commit 4ac8599

File tree

5 files changed

+85
-12
lines changed

5 files changed

+85
-12
lines changed

volatility3/framework/plugins/windows/orphan_kernel_threads.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
3434
architectures=["Intel32", "Intel64"],
3535
),
3636
requirements.VersionRequirement(
37-
name="thrdscan", component=thrdscan.ThrdScan, version=(1, 1, 0)
37+
name="thrdscan", component=thrdscan.ThrdScan, version=(2, 0, 0)
3838
),
3939
requirements.VersionRequirement(
4040
name="ssdt", component=ssdt.SSDT, version=(2, 0, 0)

volatility3/framework/plugins/windows/psxview.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def get_requirements(cls):
5555
name="psscan", component=psscan.PsScan, version=(2, 0, 0)
5656
),
5757
requirements.VersionRequirement(
58-
name="thrdscan", component=thrdscan.ThrdScan, version=(1, 0, 0)
58+
name="thrdscan", component=thrdscan.ThrdScan, version=(2, 0, 0)
5959
),
6060
requirements.VersionRequirement(
6161
name="handles", component=handles.Handles, version=(3, 0, 0)

volatility3/framework/plugins/windows/suspicious_threads.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
3535
optional=True,
3636
),
3737
requirements.VersionRequirement(
38-
name="thrdscan", component=thrdscan.ThrdScan, version=(1, 1, 0)
38+
name="thrdscan", component=thrdscan.ThrdScan, version=(2, 0, 0)
3939
),
4040
requirements.VersionRequirement(
4141
name="pslist", component=pslist.PsList, version=(3, 0, 0)
@@ -181,11 +181,11 @@ def _generator(self):
181181
if not info:
182182
continue
183183

184-
_, _, tid, start_address, _, _ = info
184+
_, _, tid, start_address, _, win32_start_address, _, _, _ = info
185185

186186
addresses = [
187187
(start_address, "Start"),
188-
(thread.Win32StartAddress, "Win32Start"),
188+
(win32_start_address, "Win32Start"),
189189
]
190190

191191
for address, context in addresses:

volatility3/framework/plugins/windows/thrdscan.py

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
##
44
import logging
55
import datetime
6-
from typing import Callable, Iterable
6+
from typing import Callable, Iterable, Tuple, Optional, Dict
77

88
from volatility3.framework import renderers, interfaces, exceptions
99
from volatility3.framework.configuration import requirements
1010
from volatility3.framework.renderers import format_hints
11-
from volatility3.plugins.windows import poolscanner
11+
from volatility3.plugins.windows import poolscanner, pe_symbols
1212
from volatility3.plugins import timeliner
1313

1414
vollog = logging.getLogger(__name__)
@@ -19,7 +19,7 @@ class ThrdScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface)
1919

2020
# version 2.6.0 adds support for scanning for 'Ethread' structures by pool tags
2121
_required_framework_version = (2, 6, 0)
22-
_version = (1, 1, 0)
22+
_version = (2, 0, 0)
2323

2424
def __init__(self, *args, **kwargs):
2525
super().__init__(*args, **kwargs)
@@ -67,39 +67,109 @@ def scan_threads(
6767
yield mem_object
6868

6969
@classmethod
70-
def gather_thread_info(cls, ethread):
70+
def gather_thread_info(
71+
cls,
72+
ethread: interfaces.objects.ObjectInterface,
73+
vads_cache: Dict[int, pe_symbols.ranges_type] = None,
74+
) -> Tuple[
75+
int,
76+
int,
77+
int,
78+
int,
79+
Optional[str],
80+
int,
81+
Optional[str],
82+
Optional[datetime.datetime],
83+
Optional[datetime.datetime],
84+
]:
7185
try:
7286
thread_offset = ethread.vol.offset
7387
owner_proc_pid = ethread.Cid.UniqueProcess
7488
thread_tid = ethread.Cid.UniqueThread
7589
thread_start_addr = ethread.StartAddress
90+
thread_win32start_addr = ethread.Win32StartAddress
7691
thread_create_time = (
7792
ethread.get_create_time()
7893
) # datetime.datetime object / volatility3.framework.renderers.UnparsableValue object
7994
thread_exit_time = (
8095
ethread.get_exit_time()
8196
) # datetime.datetime object / volatility3.framework.renderers.UnparsableValue object
97+
98+
owner_proc = None
99+
if vads_cache is not None:
100+
owner_proc = ethread.owning_process()
82101
except exceptions.InvalidAddressException:
83102
vollog.debug(f"Thread invalid address {ethread.vol.offset:#x}")
84103
return None
85104

105+
if vads_cache is not None:
106+
vads = pe_symbols.PESymbols.get_vads_for_process_cache(
107+
vads_cache, owner_proc
108+
)
109+
# no vads = terminated/smeared, pid 4 = kernel = don't check VADs
110+
if (
111+
owner_proc_pid != 4
112+
and owner_proc.InheritedFromUniqueProcessId != 4
113+
and (not vads or len(vads) < 5)
114+
):
115+
vollog.debug(
116+
f"No vads for process at {owner_proc.vol.offset:#x}. Skipping thread at {ethread.vol.offset:#x}"
117+
)
118+
return None
119+
120+
start_path = pe_symbols.PESymbols.filepath_for_address(
121+
vads, thread_start_addr
122+
)
123+
win32start_path = pe_symbols.PESymbols.filepath_for_address(
124+
vads, thread_win32start_addr
125+
)
126+
else:
127+
start_path = None
128+
win32start_path = None
129+
86130
return (
87131
format_hints.Hex(thread_offset),
88132
owner_proc_pid,
89133
thread_tid,
90134
format_hints.Hex(thread_start_addr),
135+
start_path,
136+
format_hints.Hex(thread_win32start_addr),
137+
win32start_path,
91138
thread_create_time,
92139
thread_exit_time,
93140
)
94141

95142
def _generator(self, filter_func: Callable):
96143
kernel_name = self.config["kernel"]
97144

145+
vads_cache: Dict[int, pe_symbols.ranges_type] = {}
146+
98147
for ethread in self.implementation(self.context, kernel_name):
99-
info = self.gather_thread_info(ethread)
148+
info = self.gather_thread_info(ethread, vads_cache)
100149

101150
if info:
102-
yield (0, info)
151+
(
152+
offset,
153+
pid,
154+
tid,
155+
start_addr,
156+
start_path,
157+
win32start_addr,
158+
win32start_path,
159+
create_time,
160+
exit_time,
161+
) = info
162+
yield 0, (
163+
offset,
164+
pid,
165+
tid,
166+
start_addr,
167+
start_path or renderers.NotAvailableValue(),
168+
win32start_addr,
169+
win32start_path or renderers.NotAvailableValue(),
170+
create_time,
171+
exit_time,
172+
)
103173

104174
def generate_timeline(self):
105175
filt_func = self.filter_func(self.config)
@@ -145,6 +215,9 @@ def run(self):
145215
("PID", int),
146216
("TID", int),
147217
("StartAddress", format_hints.Hex),
218+
("StartPath", str),
219+
("Win32StartAddress", format_hints.Hex),
220+
("Win32StartPath", str),
148221
("CreateTime", datetime.datetime),
149222
("ExitTime", datetime.datetime),
150223
],

volatility3/framework/plugins/windows/threads.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
3232
architectures=["Intel32", "Intel64"],
3333
),
3434
requirements.VersionRequirement(
35-
name="thrdscan", component=thrdscan.ThrdScan, version=(1, 1, 0)
35+
name="thrdscan", component=thrdscan.ThrdScan, version=(2, 0, 0)
3636
),
3737
]
3838

0 commit comments

Comments
 (0)