def process_functions(functions, style=DEFAULT_STYLE): """Process additional functions. Arguments: functions: An iterator returning (function, classname, register) tuples. Depends on initialize_class_structs. """ classes.collect_class_info() _set_class_style(style) # First, for each class, collect all the (offset, size) pairs and their associated (address, # delta) pairs. all_accesses = _collect_all_class_accesses(functions) # Now, classify the accesses. class_accesses is a map from each class name to a counter of how # many times we've seen each (offset, size) access pair that falls within the class's own # fields. class_operands is a map from each class name to the set of (address, delta) pairs # that access that class. all_classes, class_accesses, class_operands = _classify_class_accesses( all_accesses, style) # Next, for each class, create dummy versions of the class's structs, but don't populate them. # We do this first so that we'll have all the types we need available when populating the # structs below. class_structs = {} for classinfo in all_classes: data = _create_class_structs(classinfo) if data is not None: class_structs[classinfo] = data # Populate the class's structs using the access tuples. for classinfo, data in class_structs.items(): _populate_class_structs(classinfo, class_accesses, *data) # Finally, convert each operand that generated an access into an appropriately typed struct # offset reference. _convert_operands_to_struct_offsets(class_operands)
def initialize_vtable_structs(): """Create IDA structs representing the C++ virtual method tables in the kernel.""" classes.collect_class_info() for classinfo in classes.class_info.values(): _create_vmethods_struct(classinfo) for classinfo in classes.class_info.values(): _create_vtable_struct(classinfo)
def initialize_vtables(): """Convert vtables into offsets and ensure that virtual methods are IDA functions.""" classes.collect_class_info() for vtable, length in classes.vtables.items(): if not convert_vtable_to_offsets(vtable, length): _log(0, 'Could not convert vtable at address {:x} into offsets', vtable) _convert_vtable_methods_to_functions(vtable, length)
def initialize_vtable_method_symbols(): """Symbolicate overridden methods in a virtual method table. Propagate symbol names from the virtual method tables of the base classes. """ processed = set() classes.collect_class_info() for classinfo in classes.class_info.values(): _symbolicate_overrides_for_classinfo(classinfo, processed)
def initialize_vtable_symbols(): """Populate IDA with virtual method table symbols for an iOS kernelcache.""" classes.collect_class_info() for classname, classinfo in classes.class_info.items(): if classinfo.vtable: _log(3, 'Class {} has vtable at {:#x}', classname, classinfo.vtable) if not add_vtable_symbol(classinfo.vtable, classname): _log(0, 'Could not add vtable symbol for class {} at address {:#x}', classname, classinfo.vtable) else: _log(0, 'Class {} has no known vtable', classname)
def initialize_metaclass_symbols(): """Populate IDA with OSMetaClass instance symbols for an iOS kernelcache. Search through the kernelcache for OSMetaClass instances and add a symbol for each known instance. """ classes.collect_class_info() for classname, classinfo in classes.class_info.items(): if classinfo.metaclass: _log(1, 'Class {} has OSMetaClass instance at {:#x}', classname, classinfo.metaclass) if not add_metaclass_symbol(classinfo.metaclass, classname): _log(0, 'Could not add metaclass symbol for class {} at address {:#x}', classname, classinfo.metaclass) else: _log(1, 'Class {} has no known OSMetaClass instance', classname)