mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-06 17:57:38 +02:00
Linux: Rework module calls to parameterize rather than pull in methods
This commit is contained in:
@@ -4,10 +4,10 @@
|
||||
"""A module containing a plugin that lists loaded kernel modules."""
|
||||
|
||||
import logging
|
||||
from typing import Iterable, List
|
||||
from typing import List, Iterable
|
||||
|
||||
import volatility3.framework.symbols.linux.utilities.modules as linux_utilities_modules
|
||||
from volatility3.framework import deprecation, interfaces
|
||||
from volatility3.framework import constants, interfaces, deprecation, renderers
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.interfaces import plugins
|
||||
|
||||
@@ -18,27 +18,41 @@ class Lsmod(plugins.PluginInterface):
|
||||
"""Lists loaded kernel modules."""
|
||||
|
||||
_required_framework_version = (2, 0, 0)
|
||||
_version = (3, 0, 1)
|
||||
_version = (3, 0, 3)
|
||||
|
||||
run = linux_utilities_modules.ModuleDisplayPlugin.run
|
||||
_generator = linux_utilities_modules.ModuleDisplayPlugin.generator
|
||||
implementation = linux_utilities_modules.Modules.list_modules
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
||||
return [
|
||||
requirements.ModuleRequirement(
|
||||
name="kernel",
|
||||
description="Linux kernel",
|
||||
architectures=constants.architectures.LINUX_ARCHS,
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="linux_utilities_modules",
|
||||
component=linux_utilities_modules.Modules,
|
||||
version=(3, 0, 0),
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="linux_utilities_modules_module_display_plugin",
|
||||
component=linux_utilities_modules.ModuleDisplayPlugin,
|
||||
version=(1, 0, 0),
|
||||
version=(2, 0, 0),
|
||||
),
|
||||
] + linux_utilities_modules.ModuleDisplayPlugin.get_requirements()
|
||||
requirements.BooleanRequirement(
|
||||
name="dump",
|
||||
description="Extract listed modules",
|
||||
default=False,
|
||||
optional=True,
|
||||
),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
@deprecation.deprecated_method(
|
||||
replacement=linux_utilities_modules.Modules.list_modules,
|
||||
replacement_version=(3, 0, 0),
|
||||
removal_date="2026-03-25",
|
||||
removal_date="2025-09-25",
|
||||
)
|
||||
def list_modules(
|
||||
cls, context: interfaces.context.ContextInterface, vmlinux_module_name: str
|
||||
@@ -46,3 +60,18 @@ class Lsmod(plugins.PluginInterface):
|
||||
return linux_utilities_modules.Modules.list_modules(
|
||||
context, vmlinux_module_name
|
||||
)
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid(
|
||||
linux_utilities_modules.ModuleDisplayPlugin.columns_results,
|
||||
self._generator(),
|
||||
)
|
||||
|
||||
def _generator(self):
|
||||
yield from linux_utilities_modules.ModuleDisplayPlugin.generate_results(
|
||||
self.context,
|
||||
self.implementation,
|
||||
self.config["kernel"],
|
||||
self.config["dump"],
|
||||
self.open,
|
||||
)
|
||||
|
||||
@@ -3,19 +3,18 @@
|
||||
#
|
||||
|
||||
import logging
|
||||
from typing import Dict, Generator, List
|
||||
from typing import List, Dict, Generator
|
||||
|
||||
import volatility3.framework.symbols.linux.utilities.modules as linux_utilities_modules
|
||||
from volatility3.framework import deprecation, interfaces
|
||||
from volatility3.framework import constants, interfaces, deprecation, renderers
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.interfaces import plugins
|
||||
from volatility3.framework.objects import utility
|
||||
from volatility3.framework.symbols.linux import extensions
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Check_modules(plugins.PluginInterface):
|
||||
class Check_modules(interfaces.plugins.PluginInterface):
|
||||
"""Compares module list to sysfs info, if available"""
|
||||
|
||||
_version = (3, 0, 1)
|
||||
@@ -23,7 +22,7 @@ class Check_modules(plugins.PluginInterface):
|
||||
|
||||
@classmethod
|
||||
def compare_kset_and_lsmod(
|
||||
cls, context: str, vmlinux_name: str
|
||||
cls, context: interfaces.context.ContextInterface, vmlinux_name: str
|
||||
) -> Generator[extensions.module, None, None]:
|
||||
kset_modules = linux_utilities_modules.Modules.get_kset_modules(
|
||||
context=context, vmlinux_name=vmlinux_name
|
||||
@@ -39,13 +38,16 @@ class Check_modules(plugins.PluginInterface):
|
||||
for mod_name in set(kset_modules.keys()).difference(lsmod_modules):
|
||||
yield kset_modules[mod_name]
|
||||
|
||||
run = linux_utilities_modules.ModuleDisplayPlugin.run
|
||||
_generator = linux_utilities_modules.ModuleDisplayPlugin.generator
|
||||
implementation = compare_kset_and_lsmod
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
||||
return [
|
||||
requirements.ModuleRequirement(
|
||||
name="kernel",
|
||||
description="Linux kernel",
|
||||
architectures=constants.architectures.LINUX_ARCHS,
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="modules",
|
||||
component=linux_utilities_modules.Modules,
|
||||
@@ -54,17 +56,38 @@ class Check_modules(plugins.PluginInterface):
|
||||
requirements.VersionRequirement(
|
||||
name="linux_utilities_modules_module_display_plugin",
|
||||
component=linux_utilities_modules.ModuleDisplayPlugin,
|
||||
version=(1, 0, 0),
|
||||
version=(2, 0, 0),
|
||||
),
|
||||
] + linux_utilities_modules.ModuleDisplayPlugin.get_requirements()
|
||||
requirements.BooleanRequirement(
|
||||
name="dump",
|
||||
description="Extract listed modules",
|
||||
default=False,
|
||||
optional=True,
|
||||
),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
@deprecation.deprecated_method(
|
||||
replacement=linux_utilities_modules.Modules.get_kset_modules,
|
||||
removal_date="2026-03-25",
|
||||
removal_date="2025-09-25",
|
||||
replacement_version=(3, 0, 0),
|
||||
)
|
||||
def get_kset_modules(
|
||||
cls, context: interfaces.context.ContextInterface, vmlinux_name: str
|
||||
) -> Dict[str, extensions.module]:
|
||||
return linux_utilities_modules.Modules.get_kset_modules(context, vmlinux_name)
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid(
|
||||
linux_utilities_modules.ModuleDisplayPlugin.columns_results,
|
||||
self._generator(),
|
||||
)
|
||||
|
||||
def _generator(self):
|
||||
yield from linux_utilities_modules.ModuleDisplayPlugin.generate_results(
|
||||
self.context,
|
||||
self.implementation,
|
||||
self.config["kernel"],
|
||||
self.config["dump"],
|
||||
self.open,
|
||||
)
|
||||
|
||||
@@ -2,15 +2,20 @@
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
import logging
|
||||
from typing import Iterable, List, Set, Tuple
|
||||
|
||||
from volatility3.framework import deprecation, exceptions, interfaces
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.interfaces import plugins
|
||||
from volatility3.framework.symbols.linux import extensions
|
||||
from typing import List, Set, Tuple, Iterable, Generator
|
||||
from volatility3.framework.symbols.linux.utilities import (
|
||||
modules as linux_utilities_modules,
|
||||
)
|
||||
from volatility3.framework import (
|
||||
constants,
|
||||
interfaces,
|
||||
exceptions,
|
||||
deprecation,
|
||||
renderers,
|
||||
)
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.symbols.linux import extensions
|
||||
from volatility3.framework.interfaces import plugins
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
@@ -19,12 +24,12 @@ class Hidden_modules(plugins.PluginInterface):
|
||||
"""Carves memory to find hidden kernel modules"""
|
||||
|
||||
_required_framework_version = (2, 25, 0)
|
||||
_version = (3, 0, 2)
|
||||
_version = (3, 0, 3)
|
||||
|
||||
@classmethod
|
||||
def find_hidden_modules(
|
||||
cls, context, vmlinux_module_name: str
|
||||
) -> extensions.module:
|
||||
) -> Generator[extensions.module, None, None]:
|
||||
if context.symbol_space.verify_table_versions(
|
||||
"dwarf2json", lambda version, _: (not version) or version < (0, 8, 0)
|
||||
):
|
||||
@@ -82,29 +87,38 @@ class Hidden_modules(plugins.PluginInterface):
|
||||
vmlinux_module_name, known_module_addresses, modules_memory_boundaries
|
||||
)
|
||||
|
||||
run = linux_utilities_modules.ModuleDisplayPlugin.run
|
||||
_generator = linux_utilities_modules.ModuleDisplayPlugin.generator
|
||||
implementation = find_hidden_modules
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
||||
return [
|
||||
requirements.ModuleRequirement(
|
||||
name="kernel",
|
||||
description="Linux kernel",
|
||||
architectures=constants.architectures.LINUX_ARCHS,
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="linux_utilities_modules_module_display_plugin",
|
||||
component=linux_utilities_modules.ModuleDisplayPlugin,
|
||||
version=(1, 0, 0),
|
||||
version=(2, 0, 0),
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="linux_utilities_modules",
|
||||
component=linux_utilities_modules.Modules,
|
||||
version=(3, 0, 1),
|
||||
),
|
||||
] + linux_utilities_modules.ModuleDisplayPlugin.get_requirements()
|
||||
requirements.BooleanRequirement(
|
||||
name="dump",
|
||||
description="Extract listed modules",
|
||||
default=False,
|
||||
optional=True,
|
||||
),
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
@deprecation.deprecated_method(
|
||||
replacement=linux_utilities_modules.Modules.get_modules_memory_boundaries,
|
||||
removal_date="2026-03-25",
|
||||
removal_date="2025-09-25",
|
||||
replacement_version=(3, 0, 0),
|
||||
)
|
||||
def get_modules_memory_boundaries(
|
||||
@@ -117,7 +131,7 @@ class Hidden_modules(plugins.PluginInterface):
|
||||
|
||||
@deprecation.deprecated_method(
|
||||
replacement=linux_utilities_modules.Modules.get_module_address_alignment,
|
||||
removal_date="2026-03-25",
|
||||
removal_date="2025-09-25",
|
||||
replacement_version=(3, 0, 0),
|
||||
)
|
||||
@classmethod
|
||||
@@ -145,13 +159,13 @@ class Hidden_modules(plugins.PluginInterface):
|
||||
|
||||
@deprecation.deprecated_method(
|
||||
replacement=linux_utilities_modules.Modules.get_hidden_modules,
|
||||
removal_date="2026-03-25",
|
||||
removal_date="2025-09-25",
|
||||
replacement_version=(3, 0, 0),
|
||||
)
|
||||
@staticmethod
|
||||
@deprecation.deprecated_method(
|
||||
replacement=linux_utilities_modules.Modules.validate_alignment_patterns,
|
||||
removal_date="2026-03-25",
|
||||
removal_date="2025-09-25",
|
||||
replacement_version=(3, 0, 0),
|
||||
)
|
||||
def _validate_alignment_patterns(
|
||||
@@ -196,3 +210,18 @@ class Hidden_modules(plugins.PluginInterface):
|
||||
)
|
||||
}
|
||||
return known_module_addresses
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid(
|
||||
linux_utilities_modules.ModuleDisplayPlugin.columns_results,
|
||||
self._generator(),
|
||||
)
|
||||
|
||||
def _generator(self):
|
||||
yield from linux_utilities_modules.ModuleDisplayPlugin.generate_results(
|
||||
self.context,
|
||||
self.implementation,
|
||||
self.config["kernel"],
|
||||
self.config["dump"],
|
||||
self.open,
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
import warnings
|
||||
from typing import (
|
||||
Callable,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
@@ -23,7 +24,6 @@ from volatility3.framework import (
|
||||
objects,
|
||||
renderers,
|
||||
)
|
||||
from volatility3.framework.constants import architectures
|
||||
from volatility3.framework.renderers import format_hints
|
||||
from volatility3.framework.configuration import requirements
|
||||
from volatility3.framework.objects import utility
|
||||
@@ -382,7 +382,7 @@ class Modules(interfaces.configuration.VersionableInterface):
|
||||
vmlinux_module_name: str,
|
||||
known_module_addresses: Set[int],
|
||||
modules_memory_boundaries: Tuple,
|
||||
) -> Iterable[interfaces.objects.ObjectInterface]:
|
||||
) -> Iterable[extensions.module]:
|
||||
"""Enumerate hidden modules by taking advantage of memory address alignment patterns
|
||||
|
||||
This technique is much faster and uses less memory than the traditional scan method
|
||||
@@ -919,19 +919,11 @@ class ModuleDisplayPlugin(interfaces.configuration.VersionableInterface):
|
||||
The constructor of the plugin must call super() with the `implementation` set
|
||||
"""
|
||||
|
||||
_version = (1, 0, 1)
|
||||
_required_framework_version = (2, 0, 0)
|
||||
|
||||
framework.require_interface_version(*_required_framework_version)
|
||||
_version = (2, 0, 0)
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
|
||||
return [
|
||||
requirements.ModuleRequirement(
|
||||
name="kernel",
|
||||
description="Linux kernel",
|
||||
architectures=architectures.LINUX_ARCHS,
|
||||
),
|
||||
requirements.VersionRequirement(
|
||||
name="linux_utilities_modules",
|
||||
component=Modules,
|
||||
@@ -940,25 +932,29 @@ class ModuleDisplayPlugin(interfaces.configuration.VersionableInterface):
|
||||
requirements.VersionRequirement(
|
||||
name="linux-tainting", component=tainting.Tainting, version=(1, 0, 0)
|
||||
),
|
||||
requirements.BooleanRequirement(
|
||||
name="dump",
|
||||
description="Extract listed modules",
|
||||
default=False,
|
||||
optional=True,
|
||||
),
|
||||
]
|
||||
|
||||
def generator(self):
|
||||
@classmethod
|
||||
def generate_results(
|
||||
cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
implementation: Callable[
|
||||
[interfaces.context.ContextInterface, str], Iterable[extensions.module]
|
||||
],
|
||||
kernel_module_name: str,
|
||||
dump: bool,
|
||||
open_implementation: Optional[interfaces.plugins.FileHandlerInterface],
|
||||
):
|
||||
"""
|
||||
Uses the implementation set in the constructor call to produce consistent output fields
|
||||
across module gathering plugins
|
||||
"""
|
||||
for module in self.implementation(self.context, self.config["kernel"]):
|
||||
for module in implementation(context, kernel_module_name):
|
||||
try:
|
||||
name = utility.array_to_string(module.name)
|
||||
except exceptions.InvalidAddressException:
|
||||
vollog.debug(
|
||||
f"Unable to recover name for module {module.vol.offset:#x} from implementation {self.implementation}"
|
||||
f"Unable to recover name for module {module.vol.offset:#x} from implementation {implementation}"
|
||||
)
|
||||
continue
|
||||
|
||||
@@ -968,21 +964,21 @@ class ModuleDisplayPlugin(interfaces.configuration.VersionableInterface):
|
||||
|
||||
taints = ",".join(
|
||||
tainting.Tainting.get_taints_parsed(
|
||||
self.context, self.config["kernel"], module.taints, True
|
||||
context, kernel_module_name, module.taints, True
|
||||
)
|
||||
)
|
||||
|
||||
parameters_iter = Modules.get_load_parameters(
|
||||
self.context, self.config["kernel"], module
|
||||
context, kernel_module_name, module
|
||||
)
|
||||
|
||||
parameters = ", ".join([f"{key}={value}" for key, value in parameters_iter])
|
||||
|
||||
file_name = renderers.NotApplicableValue()
|
||||
|
||||
if self.config["dump"]:
|
||||
if open_implementation:
|
||||
elf_data = linux_utilities_module_extract.ModuleExtract.extract_module(
|
||||
self.context, self.config["kernel"], module
|
||||
context, kernel_module_name, module
|
||||
)
|
||||
if not elf_data:
|
||||
vollog.warning(
|
||||
@@ -990,11 +986,11 @@ class ModuleDisplayPlugin(interfaces.configuration.VersionableInterface):
|
||||
)
|
||||
file_name = renderers.NotAvailableValue()
|
||||
else:
|
||||
file_name = self.open.sanitize_filename(
|
||||
file_name = open_implementation.sanitize_filename(
|
||||
f"kernel_module.{name}.{module.vol.offset:#x}.elf"
|
||||
)
|
||||
|
||||
with self.open(file_name) as file_handle:
|
||||
with open_implementation(file_name) as file_handle:
|
||||
file_handle.write(elf_data)
|
||||
|
||||
yield (
|
||||
@@ -1009,15 +1005,11 @@ class ModuleDisplayPlugin(interfaces.configuration.VersionableInterface):
|
||||
),
|
||||
)
|
||||
|
||||
def run(self):
|
||||
return renderers.TreeGrid(
|
||||
[
|
||||
("Offset", format_hints.Hex),
|
||||
("Module Name", str),
|
||||
("Code Size", format_hints.Hex),
|
||||
("Taints", str),
|
||||
("Load Arguments", str),
|
||||
("File Output", str),
|
||||
],
|
||||
self._generator(),
|
||||
)
|
||||
columns_results = [
|
||||
("Offset", format_hints.Hex),
|
||||
("Module Name", str),
|
||||
("Code Size", format_hints.Hex),
|
||||
("Taints", str),
|
||||
("Load Arguments", str),
|
||||
("File Output", str),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user