Framework: Fix remaining missing requirements

This adds all of the missing requirements discovered via the new code
analysis script.
This commit is contained in:
David McDonald
2025-03-28 13:22:01 -05:00
parent 2ad1536b4e
commit 0f73686364
28 changed files with 179 additions and 7 deletions
+7
View File
@@ -38,6 +38,8 @@ class Volshell(interfaces.plugins.PluginInterface):
_required_framework_version = (2, 0, 0)
_version = (1, 0, 0)
DEFAULT_NUM_DISPLAY_BYTES = 128
def __init__(self, *args, **kwargs):
@@ -61,6 +63,11 @@ class Volshell(interfaces.plugins.PluginInterface):
default=None,
optional=True,
),
requirements.VersionRequirement(
name="regex_scanner",
component=scanners.RegExScanner,
version=(1, 0, 0),
),
requirements.BooleanRequirement(
name="script-only",
description="Exit volshell after the script specified in --script completes",
+5
View File
@@ -36,6 +36,11 @@ class Volshell(generic.Volshell):
requirements.IntRequirement(
name="pid", description="Process ID", optional=True
),
requirements.VersionRequirement(
name="generic_volshell",
component=generic.Volshell,
version=(1, 0, 0),
),
]
def change_task(self, pid=None):
+5
View File
@@ -25,6 +25,11 @@ class Volshell(generic.Volshell):
requirements.IntRequirement(
name="pid", description="Process ID", optional=True
),
requirements.VersionRequirement(
name="generic_volshell",
component=generic.Volshell,
version=(1, 0, 0),
),
]
def change_task(self, pid=None):
+5
View File
@@ -23,6 +23,11 @@ class Volshell(generic.Volshell):
requirements.IntRequirement(
name="pid", description="Process ID", optional=True
),
requirements.VersionRequirement(
name="generic_volshell",
component=generic.Volshell,
version=(1, 0, 0),
),
]
def change_process(self, pid=None):
+19 -4
View File
@@ -17,7 +17,7 @@ from volatility3.framework import constants, exceptions, interfaces, layers
from volatility3.framework.configuration import requirements
from volatility3.framework.layers import intel, scanners
from volatility3.framework.symbols import native
from volatility3.framework.symbols.windows.pdbutil import PDBUtility
from volatility3.framework.symbols.windows import pdbutil
if __name__ == "__main__":
import sys
@@ -50,6 +50,21 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
max_pdb_size = 0x400000
exclusion_list = ["linux", "mac"]
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.VersionRequirement(
name="pdb_utility",
component=pdbutil.PDBUtility,
version=(1, 0, 1),
),
requirements.VersionRequirement(
name="bytes_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
]
def find_virtual_layers_from_req(
self,
context: interfaces.context.ContextInterface,
@@ -120,7 +135,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
):
raise TypeError("PDB name or GUID not a string value")
PDBUtility.load_windows_symbol_table(
pdbutil.PDBUtility.load_windows_symbol_table(
context=context,
guid=kernel["GUID"],
age=kernel["age"],
@@ -259,7 +274,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
bytes(name + ".pdb", "utf-8")
for name in constants.windows.KERNEL_MODULE_NAMES
]
kernels = PDBUtility.pdbname_scan(
kernels = pdbutil.PDBUtility.pdbname_scan(
ctx=context,
layer_name=layer_to_scan,
start=start_scan_address,
@@ -362,7 +377,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
with contextlib.suppress(exceptions.InvalidAddressException):
if vlayer.read(address, 0x2) == b"MZ":
res = list(
PDBUtility.pdbname_scan(
pdbutil.PDBUtility.pdbname_scan(
ctx=context,
layer_name=vlayer.name,
page_size=vlayer.page_size,
@@ -40,7 +40,12 @@ class SymbolFinder(interfaces.automagic.AutomagicInterface):
name="SQLiteCache",
component=symbol_cache.SqliteCache,
version=(1, 0, 0),
)
),
requirements.VersionRequirement(
name="multi_string_scanner",
component=scanners.MultiStringScanner,
version=(1, 0, 0),
),
]
@property
+11
View File
@@ -9,6 +9,7 @@ import struct
from typing import Any, Dict, List, Optional, Set, Tuple
from volatility3.framework import constants, exceptions, interfaces
from volatility3.framework.configuration import requirements
from volatility3.framework.layers import scanners, segmented
from volatility3.framework.symbols import intermed
@@ -99,6 +100,16 @@ class QemuSuspendLayer(segmented.NonLinearlySegmentedLayer):
context=context, config_path=config_path, name=name, metadata=metadata
)
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.VersionRequirement(
name="regex_scanner",
component=scanners.RegExScanner,
version=(1, 0, 0),
),
]
@classmethod
def _check_header(
cls, base_layer: interfaces.layers.DataLayerInterface, name: str = ""
@@ -11,6 +11,8 @@ from volatility3.framework.layers.scanners import multiregexp as multiregexp
class BytesScanner(layers.ScannerInterface):
thread_safe = True
_version = (1, 0, 0)
_required_framework_version = (2, 0, 0)
def __init__(self, needle: bytes) -> None:
@@ -38,6 +40,8 @@ class RegExScanner(layers.ScannerInterface):
thread_safe = True
_version = (1, 0, 0)
_required_framework_version = (2, 0, 0)
def __init__(self, pattern: bytes, flags: int = re.DOTALL) -> None:
@@ -57,6 +61,7 @@ class RegExScanner(layers.ScannerInterface):
class MultiStringScanner(layers.ScannerInterface):
thread_safe = True
_version = (1, 0, 0)
_required_framework_version = (2, 0, 0)
def __init__(self, patterns: List[bytes]) -> None:
+6 -1
View File
@@ -22,7 +22,12 @@ class Banners(interfaces.plugins.PluginInterface):
return [
requirements.TranslationLayerRequirement(
name="primary", description="Memory layer to scan"
)
),
requirements.VersionRequirement(
name="regex_scanner",
component=scanners.RegExScanner,
version=(1, 0, 0),
),
]
def _generator(self):
@@ -40,6 +40,16 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
component=timeliner.TimeLinerInterface,
version=(1, 0, 0),
),
requirements.VersionRequirement(
name="multi_string_scanner",
component=scanners.MultiStringScanner,
version=(1, 0, 0),
),
requirements.VersionRequirement(
name="bytes_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
requirements.ListRequirement(
name="pid",
element_type=int,
@@ -46,6 +46,11 @@ class Check_modules(plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
return [
requirements.VersionRequirement(
name="modules",
component=linux_utilities_modules.Modules,
version=(3, 0, 1),
),
requirements.VersionRequirement(
name="linux_utilities_modules_module_display_plugin",
component=linux_utilities_modules.ModuleDisplayPlugin,
@@ -93,6 +93,11 @@ class Hidden_modules(plugins.PluginInterface):
component=linux_utilities_modules.ModuleDisplayPlugin,
version=(1, 0, 0),
),
requirements.VersionRequirement(
name="linux_utilities_modules",
component=linux_utilities_modules.Modules,
version=(3, 0, 1),
),
] + linux_utilities_modules.ModuleDisplayPlugin.get_requirements()
@staticmethod
@@ -41,6 +41,11 @@ class PsScan(interfaces.plugins.PluginInterface):
requirements.VersionRequirement(
name="pslist", component=pslist.PsList, version=(4, 0, 0)
),
requirements.VersionRequirement(
name="multi_string_scanner",
component=scanners.MultiStringScanner,
version=(1, 0, 0),
),
]
def _generator(self):
@@ -46,6 +46,11 @@ class VmaRegExScan(plugins.PluginInterface):
requirements.StringRequirement(
name="pattern", description="RegEx pattern", optional=False
),
requirements.VersionRequirement(
name="regex_scanner",
component=scanners.RegExScanner,
version=(1, 0, 0),
),
requirements.IntRequirement(
name="maxsize",
description="Maximum size in bytes for displayed context",
+10
View File
@@ -38,6 +38,16 @@ class Bash(plugins.PluginInterface, timeliner.TimeLinerInterface):
component=timeliner.TimeLinerInterface,
version=(1, 0, 0),
),
requirements.VersionRequirement(
name="multi_string_scanner",
component=scanners.MultiStringScanner,
version=(1, 0, 0),
),
requirements.VersionRequirement(
name="bytes_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
requirements.ListRequirement(
name="pid",
description="Filter on specific process IDs",
@@ -31,6 +31,11 @@ class List_Files(plugins.PluginInterface):
requirements.VersionRequirement(
name="mount", component=mount.Mount, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="mac_utilities",
component=mac.MacUtilities,
version=(1, 3, 0),
),
]
@classmethod
@@ -39,6 +39,11 @@ class RegExScan(plugins.PluginInterface):
default=cls.MAXSIZE_DEFAULT,
optional=True,
),
requirements.VersionRequirement(
name="regex_scanner",
component=scanners.RegExScanner,
version=(1, 0, 0),
),
]
def _generator(self, regex_pattern):
+7
View File
@@ -26,6 +26,8 @@ class VMCSTest(enum.IntFlag):
class PageStartScanner(interfaces.layers.ScannerInterface):
_version = (1, 0, 0)
def __init__(self, signatures: List[bytes], page_size: int = 0x1000):
super().__init__()
if not len(signatures):
@@ -69,6 +71,11 @@ class Vmscan(plugins.PluginInterface):
requirements.TranslationLayerRequirement(
name="primary", description="Physical base memory layer"
),
requirements.VersionRequirement(
name="page_start_scanner",
component=PageStartScanner,
version=(1, 0, 0),
),
requirements.IntRequirement(
name="log-threshold",
description="Number of criteria failed to log to debug output",
@@ -41,6 +41,11 @@ class CmdScan(interfaces.plugins.PluginInterface):
requirements.VersionRequirement(
name="consoles", component=consoles.Consoles, version=(3, 0, 0)
),
requirements.VersionRequirement(
name="bytes_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
requirements.BooleanRequirement(
name="no_registry",
description="Don't search the registry for possible values of CommandHistorySize",
@@ -54,6 +54,11 @@ class Consoles(interfaces.plugins.PluginInterface):
requirements.VersionRequirement(
name="hivelist", component=hivelist.HiveList, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="bytes_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
requirements.BooleanRequirement(
name="no_registry",
description="Don't search the registry for possible values of CommandHistorySize and HistoryBufferMax",
@@ -37,6 +37,11 @@ class MBRScan(interfaces.plugins.PluginInterface):
default=False,
optional=True,
),
requirements.VersionRequirement(
name="multi_string_scanner",
component=scanners.MultiStringScanner,
version=(1, 0, 0),
),
]
@classmethod
@@ -55,6 +55,8 @@ class PoolConstraint:
class PoolHeaderScanner(interfaces.layers.ScannerInterface):
_version = (1, 0, 0)
def __init__(
self,
module: interfaces.context.ModuleInterface,
@@ -142,6 +144,11 @@ class PoolScanner(plugins.PluginInterface):
requirements.VersionRequirement(
name="handles", component=handles.Handles, version=(3, 0, 0)
),
requirements.VersionRequirement(
name="pool_header_scanner",
component=PoolHeaderScanner,
version=(1, 0, 0),
),
]
def _generator(self):
@@ -63,6 +63,11 @@ class Skeleton_Key_Check(interfaces.plugins.PluginInterface):
requirements.VersionRequirement(
name="pe_symbols", component=pe_symbols.PESymbols, version=(3, 0, 0)
),
requirements.VersionRequirement(
name="bytes_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
]
def _check_for_skeleton_key_vad(
@@ -42,6 +42,11 @@ class SvcList(svcscan.SvcScan):
description="Windows kernel",
architectures=["Intel32", "Intel64"],
),
requirements.VersionRequirement(
name="bytes_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
]
@classmethod
@@ -56,6 +56,11 @@ class SvcScan(interfaces.plugins.PluginInterface):
requirements.VersionRequirement(
name="hivelist", component=hivelist.HiveList, version=(2, 0, 0)
),
requirements.VersionRequirement(
name="bytes_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
]
@classmethod
@@ -41,6 +41,11 @@ class VadRegExScan(plugins.PluginInterface):
element_type=int,
optional=True,
),
requirements.VersionRequirement(
name="regex_scanner",
component=scanners.RegExScanner,
version=(1, 0, 0),
),
requirements.StringRequirement(
name="pattern", description="RegEx pattern", optional=False
),
@@ -48,6 +48,11 @@ class VerInfo(interfaces.plugins.PluginInterface):
requirements.VersionRequirement(
name="modules", component=modules.Modules, version=(3, 0, 0)
),
requirements.VersionRequirement(
name="page_start_scanner",
component=scanners.BytesScanner,
version=(1, 0, 0),
),
requirements.BooleanRequirement(
name="extensive",
description="Search physical layer for version information",
+6 -1
View File
@@ -118,7 +118,12 @@ class YaraScan(plugins.PluginInterface):
name="primary",
description="Memory layer for the kernel",
architectures=["Intel32", "Intel64"],
)
),
requirements.VersionRequirement(
name="yarascanner",
component=YaraScanner,
version=(2, 1, 1),
),
]
@classmethod