mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-17 20:35:40 +02:00
181 lines
7.0 KiB
Python
181 lines
7.0 KiB
Python
# This file is Copyright 2024 Volatility Foundation and licensed under the Volatility Software License 1.0
|
|
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
|
#
|
|
import logging
|
|
from typing import Dict, Iterator, List
|
|
|
|
import volatility3.framework.symbols.linux.utilities.modules as linux_utilities_modules
|
|
from volatility3.framework import deprecation, interfaces, renderers
|
|
from volatility3.framework.configuration import requirements
|
|
from volatility3.framework.constants import architectures
|
|
from volatility3.framework.renderers import format_hints
|
|
from volatility3.framework.symbols.linux import extensions
|
|
from volatility3.framework.symbols.linux.utilities import tainting
|
|
|
|
vollog = logging.getLogger(__name__)
|
|
|
|
|
|
class Modxview(interfaces.plugins.PluginInterface):
|
|
"""Centralize lsmod, check_modules and hidden_modules results to efficiently \
|
|
spot modules presence and taints."""
|
|
|
|
_version = (1, 0, 0)
|
|
_required_framework_version = (2, 17, 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=linux_utilities_modules.Modules,
|
|
version=(3, 0, 0),
|
|
),
|
|
requirements.VersionRequirement(
|
|
name="linux_utilities_module_gatherer_lsmod",
|
|
component=linux_utilities_modules.ModuleGathererLsmod,
|
|
version=(1, 0, 0),
|
|
),
|
|
requirements.VersionRequirement(
|
|
name="linux_utilities_module_gatherer_sysfs",
|
|
component=linux_utilities_modules.ModuleGathererSysFs,
|
|
version=(1, 0, 0),
|
|
),
|
|
requirements.VersionRequirement(
|
|
name="linux_utilities_module_gatherer_scanner",
|
|
component=linux_utilities_modules.ModuleGathererScanner,
|
|
version=(1, 0, 0),
|
|
),
|
|
requirements.VersionRequirement(
|
|
name="linux-tainting", component=tainting.Tainting, version=(1, 0, 0)
|
|
),
|
|
requirements.BooleanRequirement(
|
|
name="plain_taints",
|
|
description="Display the plain taints string for each module.",
|
|
optional=True,
|
|
default=False,
|
|
),
|
|
]
|
|
|
|
@classmethod
|
|
@deprecation.deprecated_method(
|
|
replacement=linux_utilities_modules.Modules.flatten_run_modules_results,
|
|
replacement_version=(3, 0, 0),
|
|
removal_date="2026-03-25",
|
|
)
|
|
def flatten_run_modules_results(
|
|
cls, run_results: Dict[str, List[extensions.module]], deduplicate: bool = True
|
|
) -> Iterator[extensions.module]:
|
|
"""Flatten a dictionary mapping plugin names and modules list, to a single merged list.
|
|
This is useful to get a generic lookup list of all the detected modules.
|
|
|
|
Args:
|
|
run_results: dictionary of plugin names mapping a list of detected modules
|
|
deduplicate: remove duplicate modules, based on their offsets
|
|
|
|
Returns:
|
|
Iterator of modules objects
|
|
"""
|
|
return linux_utilities_modules.Modules.flatten_run_modules_results(
|
|
run_results, deduplicate
|
|
)
|
|
|
|
@classmethod
|
|
@deprecation.deprecated_method(
|
|
replacement=linux_utilities_modules.Modules.run_modules_scanners,
|
|
replacement_version=(3, 0, 0),
|
|
removal_date="2026-03-25",
|
|
)
|
|
def run_modules_scanners(
|
|
cls,
|
|
context: interfaces.context.ContextInterface,
|
|
kernel_name: str,
|
|
run_hidden_modules: bool = True,
|
|
) -> Dict[str, List[extensions.module]]:
|
|
"""Run module scanning plugins and aggregate the results. It is designed
|
|
to not operate any inter-plugin results triage."""
|
|
return linux_utilities_modules.Modules.run_modules_scanners(
|
|
context, kernel_name, run_hidden_modules
|
|
)
|
|
|
|
def _generator(self):
|
|
kernel = self.context.modules[self.config["kernel"]]
|
|
|
|
wanted_gatherers = [
|
|
linux_utilities_modules.ModuleGathererLsmod,
|
|
linux_utilities_modules.ModuleGathererSysFs,
|
|
linux_utilities_modules.ModuleGathererScanner,
|
|
]
|
|
|
|
run_results = linux_utilities_modules.Modules.run_modules_scanners(
|
|
context=self.context,
|
|
kernel_module_name=self.config["kernel"],
|
|
caller_wanted_gatherers=wanted_gatherers,
|
|
flatten=False,
|
|
)
|
|
|
|
aggregated_modules = {}
|
|
# We want to be explicit on the plugins results we are interested in
|
|
for gatherer in wanted_gatherers:
|
|
# Iterate over each recovered module
|
|
for mod_info in run_results[gatherer.name]:
|
|
# Use offsets as unique keys, whether a module
|
|
# appears in many plugin runs or not
|
|
if aggregated_modules.get(mod_info.offset, None) is not None:
|
|
# Append the plugin to the list of originating plugins
|
|
aggregated_modules[mod_info.offset].append(gatherer.name)
|
|
else:
|
|
aggregated_modules[mod_info.offset] = [gatherer.name]
|
|
|
|
for module_offset, gatherers in aggregated_modules.items():
|
|
module = kernel.object("module", offset=module_offset, absolute=True)
|
|
|
|
# Tainting parsing capabilities applied to the module
|
|
if self.config.get("plain_taints"):
|
|
taints = tainting.Tainting.get_taints_as_plain_string(
|
|
self.context,
|
|
self.config["kernel"],
|
|
module.taints,
|
|
True,
|
|
)
|
|
else:
|
|
taints = ",".join(
|
|
tainting.Tainting.get_taints_parsed(
|
|
self.context,
|
|
self.config["kernel"],
|
|
module.taints,
|
|
True,
|
|
)
|
|
)
|
|
|
|
yield (
|
|
0,
|
|
(
|
|
module.get_name() or renderers.NotAvailableValue(),
|
|
format_hints.Hex(module_offset),
|
|
linux_utilities_modules.ModuleGathererLsmod.name in gatherers,
|
|
linux_utilities_modules.ModuleGathererSysFs.name in gatherers,
|
|
linux_utilities_modules.ModuleGathererScanner.name in gatherers,
|
|
taints or renderers.NotAvailableValue(),
|
|
),
|
|
)
|
|
|
|
def run(self):
|
|
columns = [
|
|
("Name", str),
|
|
("Address", format_hints.Hex),
|
|
("In procfs", bool),
|
|
("In sysfs", bool),
|
|
("In scan", bool),
|
|
("Taints", str),
|
|
]
|
|
|
|
return renderers.TreeGrid(
|
|
columns,
|
|
self._generator(),
|
|
)
|