mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-06 09:47:38 +02:00
Linux: hidden_modules: Add @Abyss-W4tcher suggestion to optimize the fast scan method for even better performance, using the mkobj.mod self referential validation used in module.is_valid() as pre-filter
Removed the --heuristic-mode and the module.states validation, since the self referential check is enough by itself
This commit is contained in:
@@ -38,13 +38,6 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
optional=True,
|
||||
default=False,
|
||||
),
|
||||
requirements.BooleanRequirement(
|
||||
name="heuristic-mode",
|
||||
description="Relaxed constraints. This may generate false positives and "
|
||||
"take a bit longer. This feature is available only when using the --fast option",
|
||||
optional=True,
|
||||
default=False,
|
||||
),
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
@@ -124,7 +117,6 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
vmlinux_module_name: str,
|
||||
known_module_addresses: Set[int],
|
||||
modules_memory_boundaries: Tuple,
|
||||
heuristic_mode: bool = False,
|
||||
) -> Iterable[interfaces.objects.ObjectInterface]:
|
||||
"""Enumerate hidden modules using the traditional implementation.
|
||||
|
||||
@@ -135,7 +127,6 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
vmlinux_module_name: The name of the kernel module on which to operate
|
||||
known_module_addresses: Set with known module addresses
|
||||
modules_memory_boundaries: Minimum and maximum address boundaries for module allocation.
|
||||
heuristic_mode: ignored for this scan method.
|
||||
|
||||
Yields:
|
||||
module objects
|
||||
@@ -247,7 +238,6 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
vmlinux_module_name: str,
|
||||
known_module_addresses: Set[int],
|
||||
modules_memory_boundaries: Tuple,
|
||||
heuristic_mode: bool = False,
|
||||
) -> Iterable[interfaces.objects.ObjectInterface]:
|
||||
"""Enumerate hidden modules by taking advantage of memory address alignment patterns
|
||||
|
||||
@@ -268,7 +258,6 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
vmlinux_module_name: The name of the kernel module on which to operate
|
||||
known_module_addresses: Set with known module addresses
|
||||
modules_memory_boundaries: Minimum and maximum address boundaries for module allocation.
|
||||
heuristic_mode: If True, it loosens constraints to enhance the detection of advanced threats.
|
||||
Yields:
|
||||
module objects
|
||||
"""
|
||||
@@ -276,37 +265,41 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
vmlinux_layer = context.layers[vmlinux.layer_name]
|
||||
|
||||
module_addr_min, module_addr_max = modules_memory_boundaries
|
||||
|
||||
module_state_values_bytes = cls._get_module_state_values_bytes(
|
||||
context, vmlinux_module_name
|
||||
)
|
||||
|
||||
module_address_alignment = cls._get_module_address_alignment(
|
||||
context, vmlinux_module_name
|
||||
)
|
||||
|
||||
mkobj_offset = vmlinux.get_type("module").relative_child_offset("mkobj")
|
||||
mod_offset = vmlinux.get_type("module_kobject").relative_child_offset("mod")
|
||||
offset_to_mkobj_mod = mkobj_offset + mod_offset
|
||||
mod_member_template = vmlinux.get_type("module_kobject").vol.members["mod"][1]
|
||||
mod_size = mod_member_template.size
|
||||
mod_member_data_format = mod_member_template.data_format
|
||||
|
||||
for module_addr in range(
|
||||
module_addr_min, module_addr_max, module_address_alignment
|
||||
):
|
||||
if module_addr in known_module_addresses:
|
||||
continue
|
||||
|
||||
if not heuristic_mode:
|
||||
try:
|
||||
# This is just a pre-filter. Module readability and consistency are verified in module.is_valid()
|
||||
module_state_bytes = vmlinux_layer.read(
|
||||
module_addr, len(module_state_values_bytes[0])
|
||||
)
|
||||
if module_state_bytes not in module_state_values_bytes:
|
||||
continue
|
||||
except (
|
||||
exceptions.PagedInvalidAddressException,
|
||||
exceptions.InvalidAddressException,
|
||||
):
|
||||
try:
|
||||
# This is just a pre-filter. Module readability and consistency are verified in module.is_valid()
|
||||
self_referential_bytes = vmlinux_layer.read(
|
||||
module_addr + offset_to_mkobj_mod, mod_size
|
||||
)
|
||||
self_referential = objects.convert_data_to_value(
|
||||
self_referential_bytes, int, mod_member_data_format
|
||||
)
|
||||
if self_referential != module_addr:
|
||||
continue
|
||||
except (
|
||||
exceptions.PagedInvalidAddressException,
|
||||
exceptions.InvalidAddressException,
|
||||
):
|
||||
continue
|
||||
|
||||
module = vmlinux.object("module", offset=module_addr, absolute=True)
|
||||
if module and module.is_valid(strict_states=not heuristic_mode):
|
||||
if module and module.is_valid():
|
||||
yield module
|
||||
|
||||
@staticmethod
|
||||
@@ -369,7 +362,6 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
vmlinux_module_name,
|
||||
known_module_addresses,
|
||||
modules_memory_boundaries,
|
||||
heuristic_mode,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -410,7 +402,6 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
known_module_addresses,
|
||||
modules_memory_boundaries,
|
||||
fast_method=self.config.get("fast"),
|
||||
heuristic_mode=self.config.get("heuristic-mode"),
|
||||
):
|
||||
module_addr = module.vol.offset
|
||||
module_name = module.get_name() or renderers.NotAvailableValue()
|
||||
|
||||
@@ -35,15 +35,12 @@ class module(generic.GenericIntelProcess):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._mod_mem_type = None # Initialize _mod_mem_type to None for memoization
|
||||
|
||||
def is_valid(self, strict_states=True):
|
||||
def is_valid(self):
|
||||
layer = self._context.layers[self.vol.layer_name]
|
||||
# Make sure the entire module content is readable
|
||||
if not layer.is_valid(self.vol.offset, self.vol.size):
|
||||
return False
|
||||
|
||||
if strict_states and not self.state.is_valid_choice:
|
||||
return False
|
||||
|
||||
core_size = self.get_core_size()
|
||||
if not (
|
||||
1 <= core_size <= 20000000
|
||||
@@ -52,14 +49,13 @@ class module(generic.GenericIntelProcess):
|
||||
):
|
||||
return False
|
||||
|
||||
if self.has_member("mkobj") and self.mkobj.has_member("mod"):
|
||||
if not (
|
||||
self.mkobj
|
||||
and self.mkobj.mod
|
||||
and self.mkobj.mod.is_readable()
|
||||
and self.mkobj.mod == self.vol.offset
|
||||
):
|
||||
return False
|
||||
if not (
|
||||
self.mkobj
|
||||
and self.mkobj.mod
|
||||
and self.mkobj.mod.is_readable()
|
||||
and self.mkobj.mod == self.vol.offset
|
||||
):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user