Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
127 changes: 110 additions & 17 deletions volatility3/framework/symbols/windows/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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__)

Expand Down Expand Up @@ -775,39 +776,131 @@ def get_peb(self) -> interfaces.objects.ObjectInterface:
)
return peb

def get_peb32(self) -> 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)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't recall if this is strictly true. I suspect it's true but I think it's possible you could ask the symbol table directly for this type, and it wouldn't necessarily include the table name. Were you running into errors or is this just defensive coding?

)

# 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 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.endswith("unsigned long"):
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
yield from peb.Ldr.InLoadOrderModuleList.to_list(
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY",
"InLoadOrderLinks",
)
except exceptions.InvalidAddressException:
return None

def init_order_modules(self) -> Iterable[interfaces.objects.ObjectInterface]:
"""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.endswith("unsigned long"):
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
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.endswith("unsigned long"):
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
yield from peb.Ldr.InMemoryOrderModuleList.to_list(
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY",
"InMemoryOrderLinks",
)
except exceptions.InvalidAddressException:
return None

Expand Down
Loading
Loading