Skip to content

Commit

Permalink
Merge pull request #1607 from volatilityfoundation/issue_1475_ldrmodules
Browse files Browse the repository at this point in the history
Make a generic DLL enumeration function that ensures the base address…
  • Loading branch information
ikelos authored Feb 8, 2025
2 parents 7719d29 + 67c001a commit ca420d9
Showing 1 changed file with 49 additions and 54 deletions.
103 changes: 49 additions & 54 deletions volatility3/framework/symbols/windows/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -848,69 +848,64 @@ def set_types(self, peb) -> str:
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."""
def _walk_ldr_list(
self, list_member: str, link_member: str
) -> Iterable[interfaces.objects.ObjectInterface]:
"""
Walks LDR_DATA_TABLEs and enforces the entries at least have a valid base address
This function also breaks up exception handling as much as possible to ensure the
most data is returned as possible
"""
pebs = []

try:
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",
)
peb = self.get_peb()
if peb:
pebs.append(peb)
except exceptions.InvalidAddressException:
return None
vollog.debug(f"Process at {self.vol.offset:#x} has invalid PEB")

try:
peb32 = self.get_peb32()
if peb32:
pebs.append(peb32)
except exceptions.InvalidAddressException:
vollog.debug(f"Process at {self.vol.offset:#x} has invalid 32 bit PEB")

for peb in pebs:
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)

for ldr in peb.Ldr.member(list_member).to_list(
f"{sym_table}{constants.BANG}" + "_LDR_DATA_TABLE_ENTRY", link_member
):
try:
# Several samples in testing crashed from DLLs being returned
# where DllBase was on the next page and that page was not in memory
# Not being able to retrieve the base makes the entry pretty useless
# So we enforce here its presence
ldr.DllBase
yield ldr
except exceptions.InvalidAddressException:
continue

def load_order_modules(self) -> Iterable[interfaces.objects.ObjectInterface]:
"""Generator for DLLs in the order that they were loaded."""

yield from self._walk_ldr_list("InLoadOrderModuleList", "InLoadOrderLinks")

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

try:
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
yield from self._walk_ldr_list(
"InInitializationOrderModuleList", "InInitializationOrderLinks"
)

def mem_order_modules(self) -> Iterable[interfaces.objects.ObjectInterface]:
"""Generator for DLLs in the order that they appear in memory"""
try:
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

yield from self._walk_ldr_list("InMemoryOrderModuleList", "InMemoryOrderLinks")

def get_handle_count(self):
try:
Expand Down

0 comments on commit ca420d9

Please sign in to comment.