mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-06 09:47:38 +02:00
Added the --heuristic-mode option, which relaxes constraints to improve detection of more advanced threats
This commit is contained in:
@@ -38,6 +38,13 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
optional=True,
|
||||
default=False,
|
||||
),
|
||||
requirements.BooleanRequirement(
|
||||
name="heuristic-mode",
|
||||
description="Relaxed constraints. This may generate some false positives and"
|
||||
"take a bit longer. This feature is available only when using the --fast option",
|
||||
optional=True,
|
||||
default=False,
|
||||
),
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
@@ -117,6 +124,7 @@ 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.
|
||||
|
||||
@@ -127,6 +135,7 @@ 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
|
||||
@@ -227,8 +236,8 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
The struct module alignment
|
||||
"""
|
||||
# FIXME: When dwarf2json/ISF supports type alignments. Read it directly from the type metadata
|
||||
# Also, 'context' and 'vmlinux_module_name' are not used yet, but they will be needed to obtain
|
||||
# the type metadata
|
||||
# Additionally, while 'context' and 'vmlinux_module_name' are currently unused, they will be
|
||||
# essential for retrieving type metadata in the future.
|
||||
return 64
|
||||
|
||||
@classmethod
|
||||
@@ -238,6 +247,7 @@ 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
|
||||
|
||||
@@ -258,7 +268,7 @@ 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
|
||||
"""
|
||||
@@ -281,21 +291,22 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
if module_addr in known_module_addresses:
|
||||
continue
|
||||
|
||||
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:
|
||||
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,
|
||||
):
|
||||
continue
|
||||
except (
|
||||
exceptions.PagedInvalidAddressException,
|
||||
exceptions.InvalidAddressException,
|
||||
):
|
||||
continue
|
||||
|
||||
module = vmlinux.object("module", offset=module_addr, absolute=True)
|
||||
if module and module.is_valid():
|
||||
if module and module.is_valid(strict_states=not heuristic_mode):
|
||||
yield module
|
||||
|
||||
@staticmethod
|
||||
@@ -322,6 +333,7 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
known_module_addresses: Set[int],
|
||||
modules_memory_boundaries: Tuple,
|
||||
fast_method: bool = False,
|
||||
heuristic_mode: bool = False,
|
||||
) -> Iterable[interfaces.objects.ObjectInterface]:
|
||||
"""Enumerate hidden modules
|
||||
|
||||
@@ -331,7 +343,7 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
known_module_addresses: Set with known module addresses
|
||||
modules_memory_boundaries: Minimum and maximum address boundaries for module allocation.
|
||||
fast_method: If True, it uses the fast method. Otherwise, it uses the traditional one.
|
||||
|
||||
heuristic_mode: If True, it loosens constraints to enhance the detection of advanced threats.
|
||||
Yields:
|
||||
module objects
|
||||
"""
|
||||
@@ -357,6 +369,7 @@ class Hidden_modules(interfaces.plugins.PluginInterface):
|
||||
vmlinux_module_name,
|
||||
known_module_addresses,
|
||||
modules_memory_boundaries,
|
||||
heuristic_mode,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -397,6 +410,7 @@ 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,13 +35,13 @@ 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):
|
||||
def is_valid(self, strict_states=True):
|
||||
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 not self.state.is_valid_choice:
|
||||
if strict_states and not self.state.is_valid_choice:
|
||||
return False
|
||||
|
||||
core_size = self.get_core_size()
|
||||
|
||||
Reference in New Issue
Block a user