|
1 | | -# This file is Copyright 2024 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 |
2 | 2 | # which is available at https://www.volatilityfoundation.org/license/vsl-v1.0 |
3 | 3 | # |
4 | | -# This module compares services found through list walking versus scanning, |
5 | | -# with the aim of finding hidden services. |
6 | | -# |
7 | | -# For background of hidden services and a real-world example of the use of this plugin, |
8 | | -# please see our blogpost: |
9 | | -# |
10 | | -# https://volatilityfoundation.org/memory-forensics-rd-illustrated-detecting-hidden-windows-services/ |
11 | | - |
12 | 4 | import logging |
13 | | - |
14 | | -from volatility3.framework import symbols, interfaces |
15 | | -from volatility3.framework.configuration import requirements |
16 | | -from volatility3.plugins.windows import svclist, svcscan |
17 | | -from volatility3.framework.symbols.windows import versions |
| 5 | +from volatility3.framework import deprecation |
| 6 | +from volatility3.plugins.windows.malware import svcdiff |
| 7 | +from volatility3.plugins.windows import svcscan |
18 | 8 |
|
19 | 9 | vollog = logging.getLogger(__name__) |
20 | 10 |
|
21 | 11 |
|
22 | | -class SvcDiff(svcscan.SvcScan): |
23 | | - """Compares services found through list walking versus scanning to find rootkits""" |
24 | | - |
25 | | - _required_framework_version = (2, 4, 0) |
26 | | - |
27 | | - _version = (2, 0, 0) |
| 12 | +class SvcDiff( |
| 13 | + svcscan.SvcScan, |
| 14 | + deprecation.PluginRenameClass, |
| 15 | + replacement_class=svcdiff.SvcDiff, |
| 16 | + removal_date="2026-06-07", |
| 17 | +): |
| 18 | + """Compares services found through list walking versus scanning to find rootkits (deprecated).""" |
28 | 19 |
|
29 | 20 | def __init__(self, *args, **kwargs): |
30 | 21 | super().__init__(*args, **kwargs) |
31 | 22 | self._enumeration_method = self.service_diff |
32 | 23 |
|
33 | | - @classmethod |
34 | | - def get_requirements(cls): |
35 | | - # Since we're calling the plugin, make sure we have the plugin's requirements |
36 | | - return [ |
37 | | - requirements.ModuleRequirement( |
38 | | - name="kernel", |
39 | | - description="Windows kernel", |
40 | | - architectures=["Intel32", "Intel64"], |
41 | | - ), |
42 | | - requirements.VersionRequirement( |
43 | | - name="svclist", component=svclist.SvcList, version=(2, 0, 0) |
44 | | - ), |
45 | | - requirements.VersionRequirement( |
46 | | - name="svcscan", component=svcscan.SvcScan, version=(4, 0, 0) |
47 | | - ), |
48 | | - ] |
49 | | - |
50 | | - @classmethod |
51 | | - def service_diff( |
52 | | - cls, |
53 | | - context: interfaces.context.ContextInterface, |
54 | | - kernel_module_name: str, |
55 | | - service_table_name: str, |
56 | | - service_binary_dll_map, |
57 | | - filter_func, |
58 | | - ): |
59 | | - """ |
60 | | - On Windows 10 version 15063+ 64bit Windows memory samples, walk the services list |
61 | | - and scan for services then report differences |
62 | | - """ |
63 | | - kernel = context.modules[kernel_module_name] |
64 | | - |
65 | | - if not symbols.symbol_table_is_64bit( |
66 | | - context=context, symbol_table_name=kernel.symbol_table_name |
67 | | - ) or not versions.is_win10_15063_or_later( |
68 | | - context=context, symbol_table=kernel.symbol_table_name |
69 | | - ): |
70 | | - vollog.warning( |
71 | | - "This plugin only supports Windows 10 version 15063+ 64bit Windows memory samples" |
72 | | - ) |
73 | | - return |
74 | | - |
75 | | - from_scan = set() |
76 | | - from_list = set() |
77 | | - records = {} |
78 | | - |
79 | | - # collect unique service names from scanning |
80 | | - for service in svcscan.SvcScan.service_scan( |
81 | | - context, |
82 | | - kernel_module_name, |
83 | | - service_table_name, |
84 | | - service_binary_dll_map, |
85 | | - filter_func, |
86 | | - ): |
87 | | - from_scan.add(service[6]) |
88 | | - records[service[6]] = service |
89 | | - |
90 | | - # collect services from listing walking |
91 | | - for service in svclist.SvcList.service_list( |
92 | | - context, |
93 | | - kernel_module_name, |
94 | | - service_table_name, |
95 | | - service_binary_dll_map, |
96 | | - filter_func, |
97 | | - ): |
98 | | - from_list.add(service[6]) |
| 24 | + _required_framework_version = (2, 4, 0) |
99 | 25 |
|
100 | | - # report services found from scanning but not list walking |
101 | | - for hidden_service in from_scan - from_list: |
102 | | - yield records[hidden_service] |
| 26 | + _version = (2, 0, 0) |
0 commit comments