diff --git a/volatility3/framework/symbols/windows/extensions/__init__.py b/volatility3/framework/symbols/windows/extensions/__init__.py index 230d59f95..1d6040265 100755 --- a/volatility3/framework/symbols/windows/extensions/__init__.py +++ b/volatility3/framework/symbols/windows/extensions/__init__.py @@ -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: