Skip to content

Commit eadd6d2

Browse files
authored
Merge pull request #1572 from hsarkey/hsarkey/wow64-dlllist
Windows: Allow windows.dlllist to report back DLLs from wow64 processes
2 parents a4987b3 + 29567a7 commit eadd6d2

File tree

2 files changed

+2538
-17
lines changed

2 files changed

+2538
-17
lines changed

volatility3/framework/symbols/windows/extensions/__init__.py

Lines changed: 112 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from volatility3.framework.renderers import conversion
2525
from volatility3.framework.symbols import generic
2626
from volatility3.framework.symbols.windows.extensions import pool
27+
from volatility3.framework.symbols import windows
2728

2829
vollog = logging.getLogger(__name__)
2930

@@ -781,39 +782,133 @@ def get_peb(self) -> interfaces.objects.ObjectInterface:
781782
)
782783
return peb
783784

785+
def get_peb32(self) -> Optional[interfaces.objects.ObjectInterface]:
786+
"""Constructs a PEB32 object"""
787+
if constants.BANG not in self.vol.type_name:
788+
raise ValueError(
789+
f"Invalid symbol table name syntax (no {constants.BANG} found)"
790+
)
791+
792+
# add_process_layer can raise InvalidAddressException.
793+
# if that happens, we let the exception propagate upwards
794+
proc_layer_name = self.add_process_layer()
795+
proc_layer = self._context.layers[proc_layer_name]
796+
797+
# Determine if process is running under WOW64.
798+
if self.get_is_wow64():
799+
proc = self.get_wow_64_process()
800+
else:
801+
return None
802+
# Confirm WoW64Process points to a valid process address
803+
if not proc_layer.is_valid(proc):
804+
raise exceptions.InvalidAddressException(
805+
proc_layer_name, proc, f"Invalid Wow64Process address at {self.Peb:0x}"
806+
)
807+
808+
# Leverage the context of existing symbol table to help configure
809+
# a new symbol table for 32-bit types
810+
sym_table = self.get_symbol_table_name()
811+
config_path = self._context.symbol_space[sym_table].config_path
812+
813+
# Load the 32-bit types into a new symbol space
814+
# We use the WindowsKernelIntermedSymbols class to make
815+
# sure we get all the object helpers. For example, traversing
816+
# linked-lists.
817+
self._32bit_table_name = windows.WindowsKernelIntermedSymbols.create(
818+
self._context, config_path, "windows", "wow64"
819+
)
820+
821+
# windows 10
822+
if self._context.symbol_space.has_type(
823+
sym_table + constants.BANG + "_EWOW64PROCESS"
824+
):
825+
offset = proc.Peb
826+
827+
# vista sp0-sp1 and 2003 sp1-sp2
828+
elif self._context.symbol_space.has_type(
829+
sym_table + constants.BANG + "_WOW64_PROCESS"
830+
):
831+
offset = proc.Wow64
832+
833+
else:
834+
offset = proc
835+
836+
peb32 = self._context.object(
837+
f"{self._32bit_table_name}{constants.BANG}_PEB32",
838+
layer_name=proc_layer_name,
839+
offset=offset,
840+
)
841+
return peb32
842+
843+
def set_types(self, peb) -> str:
844+
ldr_data = self._context.symbol_space.get_type(
845+
self._32bit_table_name + constants.BANG + "_PEB_LDR_DATA"
846+
)
847+
peb.Ldr = peb.Ldr.cast("pointer", subtype=ldr_data)
848+
sym_table = self._32bit_table_name
849+
return sym_table
850+
784851
def load_order_modules(self) -> Iterable[interfaces.objects.ObjectInterface]:
785852
"""Generator for DLLs in the order that they were loaded."""
786-
787853
try:
788-
peb = self.get_peb()
789-
yield from peb.Ldr.InLoadOrderModuleList.to_list(
790-
f"{self.get_symbol_table_name()}{constants.BANG}_LDR_DATA_TABLE_ENTRY",
791-
"InLoadOrderLinks",
792-
)
854+
pebs = [
855+
self.get_peb(),
856+
self.get_peb32(),
857+
]
858+
for peb in pebs:
859+
if peb:
860+
sym_table = self.get_symbol_table_name()
861+
if peb.Ldr.vol.type_name.split(constants.BANG)[-1] == (
862+
"unsigned long"
863+
):
864+
sym_table = self.set_types(peb)
865+
yield from peb.Ldr.InLoadOrderModuleList.to_list(
866+
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY",
867+
"InLoadOrderLinks",
868+
)
793869
except exceptions.InvalidAddressException:
794870
return None
795871

796872
def init_order_modules(self) -> Iterable[interfaces.objects.ObjectInterface]:
797873
"""Generator for DLLs in the order that they were initialized"""
798874

799875
try:
800-
peb = self.get_peb()
801-
yield from peb.Ldr.InInitializationOrderModuleList.to_list(
802-
f"{self.get_symbol_table_name()}{constants.BANG}_LDR_DATA_TABLE_ENTRY",
803-
"InInitializationOrderLinks",
804-
)
876+
pebs = [
877+
self.get_peb(),
878+
self.get_peb32(),
879+
]
880+
for peb in pebs:
881+
if peb:
882+
sym_table = self.get_symbol_table_name()
883+
if peb.Ldr.vol.type_name.split(constants.BANG)[-1] == (
884+
"unsigned long"
885+
):
886+
sym_table = self.set_types(peb)
887+
yield from peb.Ldr.InInitializationOrderModuleList.to_list(
888+
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY",
889+
"InInitializationOrderLinks",
890+
)
805891
except exceptions.InvalidAddressException:
806892
return None
807893

808894
def mem_order_modules(self) -> Iterable[interfaces.objects.ObjectInterface]:
809895
"""Generator for DLLs in the order that they appear in memory"""
810-
811896
try:
812-
peb = self.get_peb()
813-
yield from peb.Ldr.InMemoryOrderModuleList.to_list(
814-
f"{self.get_symbol_table_name()}{constants.BANG}_LDR_DATA_TABLE_ENTRY",
815-
"InMemoryOrderLinks",
816-
)
897+
pebs = [
898+
self.get_peb(),
899+
self.get_peb32(),
900+
]
901+
for peb in pebs:
902+
if peb:
903+
sym_table = self.get_symbol_table_name()
904+
if peb.Ldr.vol.type_name.split(constants.BANG)[-1] == (
905+
"unsigned long"
906+
):
907+
sym_table = self.set_types(peb)
908+
yield from peb.Ldr.InMemoryOrderModuleList.to_list(
909+
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY",
910+
"InMemoryOrderLinks",
911+
)
817912
except exceptions.InvalidAddressException:
818913
return None
819914

0 commit comments

Comments
 (0)