Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions volatility3/framework/plugins/linux/check_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,23 @@
from typing import List, Dict, Generator

import volatility3.framework.symbols.linux.utilities.modules as linux_utilities_modules
from volatility3.framework import interfaces, deprecation
from volatility3.framework import constants, interfaces, deprecation, renderers
from volatility3.framework.configuration import requirements
from volatility3.framework.objects import utility
from volatility3.framework.symbols.linux import extensions
from volatility3.framework.interfaces import plugins

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)
_required_framework_version = (2, 0, 0)

@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
Expand All @@ -39,13 +38,16 @@ def compare_kset_and_lsmod(
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,
Expand All @@ -54,9 +56,15 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
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(
Expand All @@ -68,3 +76,18 @@ 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,
)
46 changes: 38 additions & 8 deletions volatility3/framework/plugins/linux/hidden_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
from typing import List, Set, Tuple, Iterable
from typing import List, Set, Tuple, Iterable, Generator
from volatility3.framework.symbols.linux.utilities import (
modules as linux_utilities_modules,
)
from volatility3.framework import interfaces, exceptions, deprecation
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
Expand All @@ -18,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)
):
Expand Down Expand Up @@ -81,24 +87,33 @@ def get_hidden_modules(
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(
Expand Down Expand Up @@ -195,3 +210,18 @@ def get_lsmod_module_addresses(
)
}
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,
)
41 changes: 35 additions & 6 deletions volatility3/framework/plugins/linux/lsmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import List, Iterable

import volatility3.framework.symbols.linux.utilities.modules as linux_utilities_modules
from volatility3.framework import interfaces, deprecation
from volatility3.framework import constants, interfaces, deprecation, renderers
from volatility3.framework.configuration import requirements
from volatility3.framework.interfaces import plugins

Expand All @@ -18,21 +18,35 @@ 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),
),
requirements.BooleanRequirement(
name="dump",
description="Extract listed modules",
default=False,
optional=True,
),
] + linux_utilities_modules.ModuleDisplayPlugin.get_requirements()
]

@classmethod
@deprecation.deprecated_method(
Expand All @@ -46,3 +60,18 @@ def list_modules(
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,
)
68 changes: 30 additions & 38 deletions volatility3/framework/symbols/linux/utilities/modules.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import warnings
from typing import (
Callable,
Iterable,
Iterator,
List,
Expand All @@ -23,7 +24,6 @@
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
Expand Down Expand Up @@ -383,7 +383,7 @@ def get_hidden_modules(
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
Expand Down Expand Up @@ -920,19 +920,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,
Expand All @@ -941,25 +933,29 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
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

Expand All @@ -969,33 +965,33 @@ def generator(self):

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(
f"Unable to reconstruct the ELF for module struct at {module.vol.offset:#x}"
)
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 0, (
Expand All @@ -1007,15 +1003,11 @@ def generator(self):
file_name,
)

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),
]
Loading