Skip to content

Commit d7d84b4

Browse files
committed
Merge branch 'develop' into linux_lsof_refactoring_fixes_and_improvements
2 parents 32eaeeb + 72abb41 commit d7d84b4

File tree

22 files changed

+2079
-130
lines changed

22 files changed

+2079
-130
lines changed

volatility3/framework/constants/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,5 @@ def __getattr__(name):
134134
]:
135135
warnings.warn(f"{name} is deprecated", FutureWarning)
136136
return globals()[f"{deprecated_tag}{name}"]
137-
return None
137+
138+
return getattr(__import__(__name__), name)

volatility3/framework/interfaces/configuration.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,7 @@ def unsatisfied(
494494
"""Validates the instance requirement based upon its
495495
`instance_type`."""
496496
config_path = path_join(config_path, self.name)
497-
498-
value = self.config_value(context, config_path, None)
497+
value = self.config_value(context, config_path, self.default)
499498
if not isinstance(value, self.instance_type):
500499
vollog.log(
501500
constants.LOGLEVEL_V,
@@ -536,7 +535,7 @@ def unsatisfied(
536535
"""Checks to see if a class can be recovered."""
537536
config_path = path_join(config_path, self.name)
538537

539-
value = self.config_value(context, config_path, None)
538+
value = self.config_value(context, config_path, self.default)
540539
self._cls = None
541540
if value is not None and isinstance(value, str):
542541
if "." in value:

volatility3/framework/plugins/linux/check_creds.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,19 @@
22
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
33
#
44

5-
import logging
6-
75
from volatility3.framework import interfaces, renderers
6+
from volatility3.framework.renderers import format_hints
87
from volatility3.framework.configuration import requirements
98
from volatility3.plugins.linux import pslist
109

11-
vollog = logging.getLogger(__name__)
12-
1310

1411
class Check_creds(interfaces.plugins.PluginInterface):
1512
"""Checks if any processes are sharing credential structures"""
1613

1714
_required_framework_version = (2, 0, 0)
1815

16+
_version = (2, 0, 0)
17+
1918
@classmethod
2019
def get_requirements(cls):
2120
return [
@@ -46,20 +45,28 @@ def _generator(self):
4645
tasks = pslist.PsList.list_tasks(self.context, vmlinux.name)
4746

4847
for task in tasks:
49-
cred_addr = task.cred.dereference().vol.offset
48+
task_cred_ptr = task.cred
49+
if not (task_cred_ptr and task_cred_ptr.is_readable()):
50+
continue
5051

51-
if cred_addr not in creds:
52-
creds[cred_addr] = []
52+
cred_addr = task_cred_ptr.dereference().vol.offset
5353

54+
creds.setdefault(cred_addr, [])
5455
creds[cred_addr].append(task.pid)
5556

56-
for _, pids in creds.items():
57+
for cred_addr, pids in creds.items():
5758
if len(pids) > 1:
58-
pid_str = ""
59-
for pid in pids:
60-
pid_str = pid_str + f"{pid:d}, "
61-
pid_str = pid_str[:-2]
62-
yield (0, [str(pid_str)])
59+
pid_str = ", ".join([str(pid) for pid in pids])
60+
61+
fields = [
62+
format_hints.Hex(cred_addr),
63+
pid_str,
64+
]
65+
yield (0, fields)
6366

6467
def run(self):
65-
return renderers.TreeGrid([("PIDs", str)], self._generator())
68+
headers = [
69+
("CredVAddr", format_hints.Hex),
70+
("PIDs", str),
71+
]
72+
return renderers.TreeGrid(headers, self._generator())

volatility3/framework/plugins/linux/malfind.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import List
66
import logging
77
from volatility3.framework import constants, interfaces
8-
from volatility3.framework import renderers
8+
from volatility3.framework import renderers, symbols
99
from volatility3.framework.configuration import requirements
1010
from volatility3.framework.objects import utility
1111
from volatility3.framework.renderers import format_hints
@@ -63,15 +63,9 @@ def _list_injections(self, task):
6363
def _generator(self, tasks):
6464
# determine if we're on a 32 or 64 bit kernel
6565
vmlinux = self.context.modules[self.config["kernel"]]
66-
if (
67-
self.context.symbol_space.get_type(
68-
vmlinux.symbol_table_name + constants.BANG + "pointer"
69-
).size
70-
== 4
71-
):
72-
is_32bit_arch = True
73-
else:
74-
is_32bit_arch = False
66+
is_32bit_arch = not symbols.symbol_table_is_64bit(
67+
self.context, vmlinux.symbol_table_name
68+
)
7569

7670
for task in tasks:
7771
process_name = utility.array_to_string(task.comm)

volatility3/framework/plugins/linux/pidhashtable.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class PIDHashTable(plugins.PluginInterface):
2020

2121
_required_framework_version = (2, 0, 0)
2222

23-
_version = (1, 0, 0)
23+
_version = (1, 0, 1)
2424

2525
@classmethod
2626
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -45,9 +45,7 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
4545
]
4646

4747
def _is_valid_task(self, task) -> bool:
48-
vmlinux = self.context.modules[self.config["kernel"]]
49-
vmlinux_layer = self.context.layers[vmlinux.layer_name]
50-
return bool(task and task.pid > 0 and vmlinux_layer.is_valid(task.parent))
48+
return bool(task and task.pid > 0 and task.parent.is_readable())
5149

5250
def _get_pidtype_pid(self):
5351
vmlinux = self.context.modules[self.config["kernel"]]
@@ -96,7 +94,7 @@ def _walk_upid(self, seen_upids, upid):
9694
seen_upids.add(upid.vol.offset)
9795

9896
pid_chain = upid.pid_chain
99-
if not (pid_chain and vmlinux_layer.is_valid(pid_chain.vol.offset)):
97+
if not (pid_chain.next and pid_chain.next.is_readable()):
10098
break
10199

102100
upid = linux.LinuxUtilities.container_of(
@@ -105,7 +103,6 @@ def _walk_upid(self, seen_upids, upid):
105103

106104
def _get_upids(self):
107105
vmlinux = self.context.modules[self.config["kernel"]]
108-
vmlinux_layer = self.context.layers[vmlinux.layer_name]
109106

110107
# 2.6.24 <= kernels < 4.15
111108
pidhash = self._get_pidhash_array()
@@ -115,7 +112,7 @@ def _get_upids(self):
115112
# each entry in the hlist is a upid which is wrapped in a pid
116113
ent = hlist.first
117114

118-
while ent and vmlinux_layer.is_valid(ent.vol.offset):
115+
while ent and ent.is_readable():
119116
# upid->pid_chain exists 2.6.24 <= kernel < 4.15
120117
upid = linux.LinuxUtilities.container_of(
121118
ent.vol.offset, "upid", "pid_chain", vmlinux
@@ -143,7 +140,7 @@ def _pid_hash_implementation(self):
143140
continue
144141

145142
pid_tasks_0 = pid.tasks[pidtype_pid].first
146-
if not pid_tasks_0:
143+
if not (pid_tasks_0 and pid_tasks_0.is_readable()):
147144
continue
148145

149146
task = vmlinux.object(
@@ -160,7 +157,7 @@ def _task_for_radix_pid_node(self, nodep):
160157
pidtype_pid = self._get_pidtype_pid()
161158

162159
pid_tasks_0 = pid.tasks[pidtype_pid].first
163-
if not pid_tasks_0:
160+
if not (pid_tasks_0 and pid_tasks_0.is_readable()):
164161
return None
165162

166163
task_struct_type = vmlinux.get_type("task_struct")

volatility3/framework/plugins/linux/sockstat.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class SockHandlers(interfaces.configuration.VersionableInterface):
2222

2323
_required_framework_version = (2, 0, 0)
2424

25-
_version = (1, 0, 1)
25+
_version = (2, 0, 0)
2626

2727
def __init__(self, vmlinux, task, *args, **kwargs):
2828
super().__init__(*args, **kwargs)
@@ -450,7 +450,7 @@ def get_requirements(cls):
450450
architectures=["Intel32", "Intel64"],
451451
),
452452
requirements.VersionRequirement(
453-
name="SockHandlers", component=SockHandlers, version=(1, 0, 0)
453+
name="SockHandlers", component=SockHandlers, version=(2, 0, 0)
454454
),
455455
requirements.PluginRequirement(
456456
name="lsof", plugin=lsof.Lsof, version=(2, 0, 0)
@@ -550,7 +550,7 @@ def list_sockets(
550550
except AttributeError:
551551
netns_id = NotAvailableValue()
552552

553-
yield task, netns_id, fd_num, family, sock_type, protocol, sock_fields
553+
yield task_comm, task, netns_id, fd_num, family, sock_type, protocol, sock_fields
554554

555555
def _format_fields(self, sock_stat, protocol):
556556
"""Prepare the socket fields to be rendered
@@ -597,6 +597,7 @@ def _generator(self, pids: List[int], netns_id_arg: int, symbol_table: str):
597597
)
598598

599599
for (
600+
task_comm,
600601
task,
601602
netns_id,
602603
fd_num,
@@ -619,6 +620,7 @@ def _generator(self, pids: List[int], netns_id_arg: int, symbol_table: str):
619620

620621
fields = (
621622
netns_id,
623+
task_comm,
622624
task.tgid,
623625
task.pid,
624626
fd_num,
@@ -639,6 +641,7 @@ def run(self):
639641

640642
tree_grid_args = [
641643
("NetNS", int),
644+
("Process Name", str),
642645
("PID", int),
643646
("TID", int),
644647
("FD", int),

volatility3/framework/plugins/timeliner.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class Timeliner(interfaces.plugins.PluginInterface):
4545
orders the results by time."""
4646

4747
_required_framework_version = (2, 0, 0)
48+
_version = (1, 1, 0)
4849

4950
def __init__(self, *args, **kwargs):
5051
super().__init__(*args, **kwargs)
@@ -198,9 +199,10 @@ def _generator(
198199
),
199200
)
200201
)
201-
except Exception:
202+
except Exception as e:
202203
vollog.log(
203-
logging.INFO, f"Exception occurred running plugin: {plugin_name}"
204+
logging.INFO,
205+
f"Exception occurred running plugin: {plugin_name}: {e}",
204206
)
205207
vollog.log(logging.DEBUG, traceback.format_exc())
206208

@@ -245,6 +247,18 @@ def run(self):
245247
filter_list = self.config["plugin-filter"]
246248
# Identify plugins that we can run which output datetimes
247249
for plugin_class in self.usable_plugins:
250+
if not issubclass(plugin_class, TimeLinerInterface):
251+
# get_usable_plugins() should filter this, but adding a safeguard just in case
252+
continue
253+
254+
if filter_list and not any(
255+
[
256+
filter in plugin_class.__module__ + "." + plugin_class.__name__
257+
for filter in filter_list
258+
]
259+
):
260+
continue
261+
248262
try:
249263
automagics = automagic.choose_automagic(self.automagics, plugin_class)
250264

@@ -276,15 +290,8 @@ def run(self):
276290
config_value,
277291
)
278292

279-
if isinstance(plugin, TimeLinerInterface):
280-
if not len(filter_list) or any(
281-
[
282-
filter
283-
in plugin.__module__ + "." + plugin.__class__.__name__
284-
for filter in filter_list
285-
]
286-
):
287-
plugins_to_run.append(plugin)
293+
plugins_to_run.append(plugin)
294+
288295
except exceptions.UnsatisfiedException as excp:
289296
# Remove the failed plugin from the list and continue
290297
vollog.debug(

volatility3/framework/plugins/windows/callbacks.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,12 @@ def scan(
248248
context, layer_name, nt_symbol_table, constraints
249249
):
250250
try:
251-
if hasattr(mem_object, "is_valid") and not mem_object.is_valid():
252-
continue
251+
if isinstance(mem_object, callbacks._SHUTDOWN_PACKET):
252+
if not mem_object.is_parseable(type_map):
253+
continue
254+
elif hasattr(mem_object, "is_valid"):
255+
if not mem_object.is_valid():
256+
continue
253257

254258
yield cls._process_scanned_callback(mem_object, type_map)
255259
except exceptions.InvalidAddressException:

0 commit comments

Comments
 (0)