Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
13 changes: 9 additions & 4 deletions ida_kernelcache/phases/create_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,18 @@ def _create_types_bfs(self):
# Might raise StringExtractionError or DemanglingError
func_name = symbols.extract_method_name(vtable_entry.vmethod_info.mangled_symbol)

# TODO: IDA has a bug that does will fail to parse vtable declaration if two vmethods have the same name,
# even if they have a different signature.
# IDA has a bug that does will fail to parse vtable declaration if two vmethods have the same name,
# even if they have a different signature. We will add a suffix to the function name in this case.
if func_name in func_names:
func_name_conflicts += 1

# TODO: maybe just add a running suffix
func_name = consts.VMETHOD_NAME_TEMPLATE.format(index=vtable_entry.index)
for i in range(20):
new_func_name = f'{func_name}{i}'
if new_func_name not in func_names:
func_name = new_func_name
break
else:
func_name = consts.VMETHOD_NAME_TEMPLATE.format(index=vtable_entry.index)

func_names.add(func_name)

Expand Down
43 changes: 22 additions & 21 deletions ida_kernelcache/phases/pac_symbolicate.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ def run(self):
f'pv:{int(vtable_entry.pure_virtual)} '
f'a:{int(vtable_entry.added)}')

if class_info.superclass is not None and class_info.superclass.vtable_info is None:
self.log.warning(f"{class_info.class_name}: Superclass vtable info is None, Could not handle overrides.")

num_not_symbolicated = len(self._kc.vmethod_info_map) - self._kc.vmethod_info_map.num_symbolicated

self.log.info(f'{self.num_total_vtable_entries} total vtable entries (multiple may point to the same vmethod)')
Expand Down Expand Up @@ -111,29 +114,27 @@ def _handle_added(self, origin_class_info: 'ClassInfo', vtable_entry: 'VtableEnt
If the vtable entry was added in this current class we search the symbols db. Unfortunately, in case we don't find a match, we don't have information about this vmethod
So we use some generic class_name::vmethod_{i} template. We may use the "guess type" functionality of IDA but it is far from accurate.

Searching the descendants adds ~100 symbols
"""

for class_info in origin_class_info.descendants(inclusive=True):
mangled_symbol = self._lookup_db(class_info.class_name, vtable_entry.pac_diversifier)
if mangled_symbol:
self.num_added += 1

# In case we were able to resolve through superclass pac dict then
# must adjust the classname of the symbol to fit the current class
if class_info != origin_class_info:
return symbols.sub_classname(mangled_symbol, origin_class_info.class_name)
return mangled_symbol
mangled_symbol = self._lookup_db(origin_class_info.class_name, vtable_entry.pac_diversifier)
if mangled_symbol:
self.num_added += 1
return mangled_symbol
return None

def _handle_overrides(self, origin_class_info: 'ClassInfo', vtable_entry: 'VtableEntry') -> str | None:
# Search the entire inheritance branch
for class_info in itertools.chain(origin_class_info.ancestors(True), origin_class_info.descendants(inclusive=False)):
mangled_symbol = self._lookup_db(class_info.class_name, vtable_entry.pac_diversifier)
if mangled_symbol:
self.num_overrides += 1

# In case we were able to resolve through superclass pac dict then
# must adjust the classname of the symbol to fit the current class
if class_info != origin_class_info:
return symbols.sub_classname(mangled_symbol, origin_class_info.class_name)
return mangled_symbol
parent_class_info = origin_class_info.superclass
if parent_class_info is None:
raise PhaseException(f'Unexpected Overrides for {origin_class_info.class_name} on {vtable_entry} - no parent class info!')
elif parent_class_info.vtable_info is None:
# This case is logged once in the parent method
self.num_invalid += 1
return None

parent_vtable_item = parent_class_info.vtable_info.entries[vtable_entry.index]
if parent_vtable_item.has_symbol:
mangled_symbol = parent_vtable_item.vmethod_info.mangled_symbol
self.num_overrides += 1
return symbols.sub_classname(mangled_symbol, origin_class_info.class_name)
return None
7 changes: 5 additions & 2 deletions ida_kernelcache/rtti.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,12 @@ def __hash__(self):
def __eq__(self, other):
return self.entry_ea == other.entry_ea

@property
def has_symbol(self) -> bool:
return bool(self.vmethod_info and self.vmethod_info.mangled_symbol)

def __repr__(self) -> str:
has_symbol = int(bool(self.vmethod_info and self.vmethod_info.mangled_symbol))
return f'VtableEntry(index={self.index}, entry_ea={self.entry_ea:#x}, pac_diversifier={self.pac_diversifier:#x}, o={int(self.overrides)}, i={int(self.inherited)}, pv={int(self.pure_virtual)}, a={int(self.added)}, symbolicated={has_symbol})'
return f'VtableEntry(index={self.index}, entry_ea={self.entry_ea:#x}, pac_diversifier={self.pac_diversifier:#x}, o={int(self.overrides)}, i={int(self.inherited)}, pv={int(self.pure_virtual)}, a={int(self.added)}, symbolicated={int(self.has_symbol)})'


class VtableInfo:
Expand Down
1 change: 1 addition & 0 deletions tasks.todo
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Symbolication:
✔ Implement getting the PAC diversifier of every vtable entry @done(25-01-27 11:47)
✔ Fix errors "does not seem to be a signed PAC pointer". UPDATE: seems like some objects are subject to multiple inheritance? In the past this was not supported by libkern++ @done(25-01-27 11:47)
according to Apple's documentation. There are these sentinels and non virtual thunks, weird. On a recent kernelcache there are 93 classes that contain a sentinel.
☐ Create PAC Signatures for pure virtual methods, including OSMetaClassBase methods that OSObject implements.

Get rid of old code!:
✔ Delete old and unused scripts! @done(25-01-27 11:47)
Expand Down