Skip to content

Commit f5feee8

Browse files
authored
Merge pull request #1841 from SolitudePy/check_creds_malware
Malware categorization: linux.check_creds
2 parents 63019c0 + 470c53c commit f5feee8

File tree

4 files changed

+85
-65
lines changed

4 files changed

+85
-65
lines changed

doc/source/getting-started-linux-tutorial.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ For plugin requests, please create an issue with a description of the requested
3737
banners.Banners Attempts to identify potential linux banners in an
3838
linux.bash.Bash Recovers bash command history from memory.
3939
linux.malware.check_afinfo.Check_afinfo
40-
linux.check_creds.Check_creds
40+
linux.malware.check_creds.Check_creds
4141
linux.malware.check_idt.Check_idt
4242
4343
.. note:: Here the command is piped to grep and head to provide the start of the list of linux plugins.

test/plugins/linux/linux.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def test_linux_generic_capabilities(self, image, volatility, python):
200200
class TestLinuxCheckCreds:
201201
def test_linux_generic_check_creds(self, image, volatility, python):
202202
rc, out, _err = test_volatility.runvol_plugin(
203-
"linux.check_creds.Check_creds", image, volatility, python
203+
"linux.malware.check_creds.Check_creds", image, volatility, python
204204
)
205205

206206
# linux-sample-1.bin has no processes sharing credentials.
Lines changed: 12 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,20 @@
1-
# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0
1+
# This file is Copyright 2025 Volatility Foundation and licensed under the Volatility Software License 1.0
22
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
33
#
4+
import logging
5+
from volatility3.framework import interfaces, deprecation
6+
from volatility3.plugins.linux.malware import check_creds
47

5-
from volatility3.framework import interfaces, renderers
6-
from volatility3.framework.renderers import format_hints
7-
from volatility3.framework.configuration import requirements
8-
from volatility3.plugins.linux import pslist
8+
vollog = logging.getLogger(__name__)
99

1010

11-
class Check_creds(interfaces.plugins.PluginInterface):
12-
"""Checks if any processes are sharing credential structures"""
11+
class Check_creds(
12+
interfaces.plugins.PluginInterface,
13+
deprecation.PluginRenameClass,
14+
replacement_class=check_creds.Check_creds,
15+
removal_date="2026-06-07",
16+
):
17+
"""Checks if any processes are sharing credential structures (deprecated)."""
1318

1419
_required_framework_version = (2, 0, 0)
1520
_version = (2, 0, 2)
16-
17-
@classmethod
18-
def get_requirements(cls):
19-
return [
20-
requirements.ModuleRequirement(
21-
name="kernel",
22-
description="Linux kernel",
23-
architectures=["Intel32", "Intel64"],
24-
),
25-
requirements.VersionRequirement(
26-
name="pslist", component=pslist.PsList, version=(4, 0, 0)
27-
),
28-
]
29-
30-
def _generator(self):
31-
vmlinux = self.context.modules[self.config["kernel"]]
32-
33-
type_task = vmlinux.get_type("task_struct")
34-
35-
if not type_task.has_member("cred"):
36-
raise TypeError(
37-
"This plugin requires the task_struct structure to have a cred member. "
38-
"This member is not present in the supplied symbol table. "
39-
"This means you are either analyzing an unsupported kernel version or that your symbol table is corrupt."
40-
)
41-
42-
creds = {}
43-
44-
tasks = pslist.PsList.list_tasks(self.context, vmlinux.name)
45-
46-
for task in tasks:
47-
task_cred_ptr = task.cred
48-
if not (task_cred_ptr and task_cred_ptr.is_readable()):
49-
continue
50-
51-
cred_addr = task_cred_ptr.dereference().vol.offset
52-
53-
creds.setdefault(cred_addr, [])
54-
creds[cred_addr].append(task.pid)
55-
56-
for cred_addr, pids in creds.items():
57-
if len(pids) > 1:
58-
pid_str = ", ".join(str(pid) for pid in pids)
59-
60-
fields = [
61-
format_hints.Hex(cred_addr),
62-
pid_str,
63-
]
64-
yield (0, fields)
65-
66-
def run(self):
67-
headers = [
68-
("CredVAddr", format_hints.Hex),
69-
("PIDs", str),
70-
]
71-
return renderers.TreeGrid(headers, self._generator())
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# This file is Copyright 2019 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+
from volatility3.framework import interfaces, renderers
6+
from volatility3.framework.renderers import format_hints
7+
from volatility3.framework.configuration import requirements
8+
from volatility3.plugins.linux import pslist
9+
10+
11+
class Check_creds(interfaces.plugins.PluginInterface):
12+
"""Checks if any processes are sharing credential structures"""
13+
14+
_required_framework_version = (2, 0, 0)
15+
_version = (2, 0, 2)
16+
17+
@classmethod
18+
def get_requirements(cls):
19+
return [
20+
requirements.ModuleRequirement(
21+
name="kernel",
22+
description="Linux kernel",
23+
architectures=["Intel32", "Intel64"],
24+
),
25+
requirements.VersionRequirement(
26+
name="pslist", component=pslist.PsList, version=(4, 0, 0)
27+
),
28+
]
29+
30+
def _generator(self):
31+
vmlinux = self.context.modules[self.config["kernel"]]
32+
33+
type_task = vmlinux.get_type("task_struct")
34+
35+
if not type_task.has_member("cred"):
36+
raise TypeError(
37+
"This plugin requires the task_struct structure to have a cred member. "
38+
"This member is not present in the supplied symbol table. "
39+
"This means you are either analyzing an unsupported kernel version or that your symbol table is corrupt."
40+
)
41+
42+
creds = {}
43+
44+
tasks = pslist.PsList.list_tasks(self.context, vmlinux.name)
45+
46+
for task in tasks:
47+
task_cred_ptr = task.cred
48+
if not (task_cred_ptr and task_cred_ptr.is_readable()):
49+
continue
50+
51+
cred_addr = task_cred_ptr.dereference().vol.offset
52+
53+
creds.setdefault(cred_addr, [])
54+
creds[cred_addr].append(task.pid)
55+
56+
for cred_addr, pids in creds.items():
57+
if len(pids) > 1:
58+
pid_str = ", ".join(str(pid) for pid in pids)
59+
60+
fields = [
61+
format_hints.Hex(cred_addr),
62+
pid_str,
63+
]
64+
yield (0, fields)
65+
66+
def run(self):
67+
headers = [
68+
("CredVAddr", format_hints.Hex),
69+
("PIDs", str),
70+
]
71+
return renderers.TreeGrid(headers, self._generator())

0 commit comments

Comments
 (0)