Windows: Convert malfind to LayerData renderer

This commit is contained in:
Mike Auty
2025-03-23 00:41:43 +00:00
parent ba82067dac
commit 1d5d981be1
@@ -2,7 +2,7 @@
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import logging
from typing import Iterable, Tuple
from typing import Iterable, Generator, Tuple
from volatility3.framework import interfaces, symbols, exceptions
from volatility3.framework import renderers
@@ -88,6 +88,25 @@ class Malfind(interfaces.plugins.PluginInterface):
symbol_table: str,
proc: interfaces.objects.ObjectInterface,
) -> Iterable[Tuple[interfaces.objects.ObjectInterface, bytes]]:
for vad, data_object in cls.list_injection_sites(
context, kernel_layer_name, symbol_table, proc
):
yield vad, data_object.context.layers[data_object.layer_name].read(
data_object.offset, data_object.length
)
@classmethod
def list_injection_sites(
cls,
context: interfaces.context.ContextInterface,
kernel_layer_name: str,
symbol_table: str,
proc: interfaces.objects.ObjectInterface,
) -> Generator[
Tuple[interfaces.objects.ObjectInterface, interfaces.renderers.LayerData],
None,
None,
]:
"""Generate memory regions for a process that may contain injected
code.
@@ -156,8 +175,15 @@ class Malfind(interfaces.plugins.PluginInterface):
vollog.warning(
f"[proc_id {proc_id}] Found suspicious DIRTY + {protection_string} page at {hex(dirty_page)}",
)
data = proc_layer.read(vad.get_start(), 64, pad=True)
yield vad, data
start = vad.get_start()
length = 64
data = interfaces.renderers.LayerData(
context=context,
layer_name=proc_layer_name,
offset=start,
length=length,
)
yield (vad, data)
def _generator(self, procs):
# determine if we're on a 32 or 64 bit kernel
@@ -166,7 +192,7 @@ class Malfind(interfaces.plugins.PluginInterface):
# set refined criteria to know when to add to "Notes" column
refined_criteria = {
b"MZ": "MZ header",
b"\x55\x8B": "PE header",
b"\x55\x8b": "PE header",
b"\x55\x48": "Function prologue",
b"\x55\x89": "Function prologue",
}
@@ -179,11 +205,14 @@ class Malfind(interfaces.plugins.PluginInterface):
# by default, "Notes" column will be set to N/A
process_name = utility.array_to_string(proc.ImageFileName)
for vad, data in self.list_injections(
for vad, data_object in self.list_injection_sites(
self.context, kernel.layer_name, kernel.symbol_table_name, proc
):
notes = renderers.NotApplicableValue()
# Check for unique headers and update "Notes" column if criteria is met
data = data_object.context.layers[data_object.layer_name].read(
data_object.offset, data_object.length, True
)
if data[0:2] in refined_criteria:
notes = refined_criteria[data[0:2]]
@@ -231,7 +260,7 @@ class Malfind(interfaces.plugins.PluginInterface):
vad.get_private_memory(),
file_output,
notes,
format_hints.HexBytes(data),
data_object,
disasm,
),
)
@@ -251,7 +280,7 @@ class Malfind(interfaces.plugins.PluginInterface):
("PrivateMemory", int),
("File output", str),
("Notes", str),
("Hexdump", format_hints.HexBytes),
("Hexdump", interfaces.renderers.LayerData),
("Disasm", interfaces.renderers.Disassembly),
],
self._generator(