|
@@ -33,6 +33,10 @@ class VtableDisambiguator(angr.Analysis):
|
|
|
subclass_map: dict[Symbol, set[Symbol]]
|
|
|
superclass_map: dict[Symbol, set[Symbol]]
|
|
|
|
|
|
+ # we use this to test if a function belongs to a class with a vtable
|
|
|
+ # this way we can prune static functions from the candidate pool
|
|
|
+ vtable_instances: set[demangler.Node]
|
|
|
+
|
|
|
def __init__(self):
|
|
|
self.loader = self.project.loader
|
|
|
self.memory = self.loader.memory
|
|
@@ -41,10 +45,14 @@ class VtableDisambiguator(angr.Analysis):
|
|
|
def analyze(self) -> None:
|
|
|
self.syms_by_addr = collections.defaultdict(set)
|
|
|
vtable_syms = set()
|
|
|
+ self.vtable_instances = set()
|
|
|
for symbol in self.loader.symbols:
|
|
|
self.syms_by_addr[symbol.rebased_addr].add(symbol)
|
|
|
- if symbol.name.startswith("_ZTV"):
|
|
|
+ if symbol.name.startswith("_ZTV") and not symbol.name.startswith("_ZTVZ"):
|
|
|
vtable_syms.add(symbol)
|
|
|
+ self.vtable_instances.add(
|
|
|
+ dh.extract_vtable_typename(demangler.parse(symbol.name))
|
|
|
+ )
|
|
|
|
|
|
# we associate a type with their subclasses so we can check them to disambiguate duplicates on the base
|
|
|
self.subclass_map = collections.defaultdict(set)
|
|
@@ -109,13 +117,23 @@ class VtableDisambiguator(angr.Analysis):
|
|
|
for fnsym in ambig_fnsyms:
|
|
|
funcsig_set.add(dh.extract_method_signature(demangler.parse(fnsym.name)))
|
|
|
|
|
|
+ non_class_syms = set()
|
|
|
+ for sym in ambig_fnsyms:
|
|
|
+ fnname = dh.extract_function_name(demangler.parse(sym.name))
|
|
|
+ if not any(vtname == fnname[: len(vtname)] for vtname in self.vtable_instances):
|
|
|
+ non_class_syms.add(sym)
|
|
|
+
|
|
|
+ if len(ambig_fnsyms - non_class_syms) == 1:
|
|
|
+ # all but one of the ambiguous symbols are not potential virtual class methods
|
|
|
+ return (ambig_fnsyms - non_class_syms).pop()
|
|
|
+
|
|
|
if len(funcsig_set) == 1:
|
|
|
# we only have one name-signature combination here
|
|
|
return set(ambig_fnsyms).pop()
|
|
|
|
|
|
rebased_fnsym_addrs = set(fnsym.rebased_addr for fnsym in ambig_fnsyms)
|
|
|
|
|
|
- for fnsym in ambig_fnsyms:
|
|
|
+ for fnsym in ambig_fnsyms - non_class_syms:
|
|
|
funcsig = dh.extract_method_signature(demangler.parse(fnsym.name))
|
|
|
for svt in related_vtsyms:
|
|
|
# only check functions at the same index
|