Merge pull request #1572 from hsarkey/hsarkey/wow64-dlllist

Windows: Allow windows.dlllist to report back DLLs from wow64 processes
This commit is contained in:
ikelos
2025-02-05 20:23:50 +00:00
committed by GitHub
2 changed files with 2538 additions and 17 deletions
@@ -24,6 +24,7 @@ from volatility3.framework.objects import utility
from volatility3.framework.renderers import conversion
from volatility3.framework.symbols import generic
from volatility3.framework.symbols.windows.extensions import pool
from volatility3.framework.symbols import windows
vollog = logging.getLogger(__name__)
@@ -781,15 +782,90 @@ class EPROCESS(generic.GenericIntelProcess, pool.ExecutiveObject):
)
return peb
def get_peb32(self) -> Optional[interfaces.objects.ObjectInterface]:
"""Constructs a PEB32 object"""
if constants.BANG not in self.vol.type_name:
raise ValueError(
f"Invalid symbol table name syntax (no {constants.BANG} found)"
)
# add_process_layer can raise InvalidAddressException.
# if that happens, we let the exception propagate upwards
proc_layer_name = self.add_process_layer()
proc_layer = self._context.layers[proc_layer_name]
# Determine if process is running under WOW64.
if self.get_is_wow64():
proc = self.get_wow_64_process()
else:
return None
# Confirm WoW64Process points to a valid process address
if not proc_layer.is_valid(proc):
raise exceptions.InvalidAddressException(
proc_layer_name, proc, f"Invalid Wow64Process address at {self.Peb:0x}"
)
# Leverage the context of existing symbol table to help configure
# a new symbol table for 32-bit types
sym_table = self.get_symbol_table_name()
config_path = self._context.symbol_space[sym_table].config_path
# Load the 32-bit types into a new symbol space
# We use the WindowsKernelIntermedSymbols class to make
# sure we get all the object helpers. For example, traversing
# linked-lists.
self._32bit_table_name = windows.WindowsKernelIntermedSymbols.create(
self._context, config_path, "windows", "wow64"
)
# windows 10
if self._context.symbol_space.has_type(
sym_table + constants.BANG + "_EWOW64PROCESS"
):
offset = proc.Peb
# vista sp0-sp1 and 2003 sp1-sp2
elif self._context.symbol_space.has_type(
sym_table + constants.BANG + "_WOW64_PROCESS"
):
offset = proc.Wow64
else:
offset = proc
peb32 = self._context.object(
f"{self._32bit_table_name}{constants.BANG}_PEB32",
layer_name=proc_layer_name,
offset=offset,
)
return peb32
def set_types(self, peb) -> str:
ldr_data = self._context.symbol_space.get_type(
self._32bit_table_name + constants.BANG + "_PEB_LDR_DATA"
)
peb.Ldr = peb.Ldr.cast("pointer", subtype=ldr_data)
sym_table = self._32bit_table_name
return sym_table
def load_order_modules(self) -> Iterable[interfaces.objects.ObjectInterface]:
"""Generator for DLLs in the order that they were loaded."""
try:
peb = self.get_peb()
yield from peb.Ldr.InLoadOrderModuleList.to_list(
f"{self.get_symbol_table_name()}{constants.BANG}_LDR_DATA_TABLE_ENTRY",
"InLoadOrderLinks",
)
pebs = [
self.get_peb(),
self.get_peb32(),
]
for peb in pebs:
if peb:
sym_table = self.get_symbol_table_name()
if peb.Ldr.vol.type_name.split(constants.BANG)[-1] == (
"unsigned long"
):
sym_table = self.set_types(peb)
yield from peb.Ldr.InLoadOrderModuleList.to_list(
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY",
"InLoadOrderLinks",
)
except exceptions.InvalidAddressException:
return None
@@ -797,23 +873,42 @@ class EPROCESS(generic.GenericIntelProcess, pool.ExecutiveObject):
"""Generator for DLLs in the order that they were initialized"""
try:
peb = self.get_peb()
yield from peb.Ldr.InInitializationOrderModuleList.to_list(
f"{self.get_symbol_table_name()}{constants.BANG}_LDR_DATA_TABLE_ENTRY",
"InInitializationOrderLinks",
)
pebs = [
self.get_peb(),
self.get_peb32(),
]
for peb in pebs:
if peb:
sym_table = self.get_symbol_table_name()
if peb.Ldr.vol.type_name.split(constants.BANG)[-1] == (
"unsigned long"
):
sym_table = self.set_types(peb)
yield from peb.Ldr.InInitializationOrderModuleList.to_list(
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY",
"InInitializationOrderLinks",
)
except exceptions.InvalidAddressException:
return None
def mem_order_modules(self) -> Iterable[interfaces.objects.ObjectInterface]:
"""Generator for DLLs in the order that they appear in memory"""
try:
peb = self.get_peb()
yield from peb.Ldr.InMemoryOrderModuleList.to_list(
f"{self.get_symbol_table_name()}{constants.BANG}_LDR_DATA_TABLE_ENTRY",
"InMemoryOrderLinks",
)
pebs = [
self.get_peb(),
self.get_peb32(),
]
for peb in pebs:
if peb:
sym_table = self.get_symbol_table_name()
if peb.Ldr.vol.type_name.split(constants.BANG)[-1] == (
"unsigned long"
):
sym_table = self.set_types(peb)
yield from peb.Ldr.InMemoryOrderModuleList.to_list(
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY",
"InMemoryOrderLinks",
)
except exceptions.InvalidAddressException:
return None
File diff suppressed because it is too large Load Diff