예제 #1
0
def _process_offset(offset, ea, next_offset):
    """Process an offset in a __got section."""
    # Convert the address containing the offset into an offset in IDA, but continue if it fails.
    if not idc.OpOff(ea, 0, 0):
        _log(1, 'Could not convert {:#x} into an offset', ea)
    # Get the name to which the offset refers.
    name = idau.get_ea_name(offset, user=True)
    if not name:
        _log(3, 'Offset at address {:#x} has target {:#x} without a name', ea,
             offset)
        return False
    # Make sure this isn't an offset to another stub or to a jump function to another stub. See the
    # comment in _symbolicate_stub.
    if stub.symbol_references_stub(name):
        _log(
            1,
            'Offset at address {:#x} has target {:#x} (name {}) that references a stub',
            ea, offset, name)
        return False
    # Set the new name for the offset.
    symbol = next_offset(name)
    if symbol is None:
        _log(0, 'Could not generate offset symbol for {}: names exhausted',
             name)
        return False
    if not idau.set_ea_name(ea, symbol, auto=True):
        _log(2, 'Could not set name {} for offset at {:#x}', symbol, ea)
        return False
    return True
예제 #2
0
def _symbolicate_overrides_for_classinfo(classinfo, processed):
    """A recursive function to symbolicate vtable overrides for a class and its superclasses."""
    # If we've already been processed, stop.
    if classinfo in processed:
        return
    # First propagate symbol information to our superclass.
    if classinfo.superclass:
        _symbolicate_overrides_for_classinfo(classinfo.superclass, processed)
    # Now symbolicate the superclass.
    for _, override, original in class_vtable_overrides(classinfo, methods=True):
        # Skip this method if the override already has a name and we can't rename it.
        override_name = idau.get_ea_name(override, user=True)
        if override_name and not _ok_to_rename_method(override, override_name):
            continue
        # Skip this method if the original does not have a name or if it's a bad name.
        original_name = idau.get_ea_name(original, user=True)
        if not original_name or _bad_name_dont_use_as_override(original_name):
            continue
        # Get the new override name if we substitute for the override class's name.
        new_name = _vtable_method_symbol_substitute_class(original_name, classinfo.classname)
        if not new_name:
            _log(0, 'Could not substitute class {} into method symbol {} for override {:#x}',
                    classinfo.classname, original_name, override)
            continue
        # Now that we have the new name, set it.
        if override_name:
            _log(2, 'Renaming {} -> {}', override_name, new_name)
        if not idau.set_ea_name(override, new_name, rename=True):
            _log(0, 'Could not set name {} for method {:#x}', new_name, override)
    # We're done.
    processed.add(classinfo)
예제 #3
0
def _symbolicate_stub(stub, target, next_stub):
    """Set a symbol for a stub function."""
    name = idau.get_ea_name(target, username=True)
    if not name:
        _log(3, 'Stub {:#x} has target {:#x} without a name', stub, target)
        return False
    # Sometimes the target of the stub is a thunk in another kext. This is sometimes OK, but makes
    # a right mess of things when that thunk is itself a jump function for another stub, and
    # especially when there are multiple such jump functions to that stub in that kext.
    # Autorenaming of thunks interacts poorly with autonaming of stubs (you get things like
    # 'j_TARGET___stub_2_0', which stub_name_target() no longer thinks of as a stub). Thus, if the
    # current thing has '__stub_' in it, don't rename. The reason we don't just extract the inner
    # stub reference is that these jump functions are really wrappers with different names and
    # semantics in the original code, so it's not appropriate for us to cover that up with a stub.
    if symbol_references_stub(name):
        _log(
            1,
            'Stub {:#x} has target {:#x} (name {}) that references another stub',
            stub, target, name)
        return False
    symbol = next_stub(name)
    if symbol is None:
        _log(0, 'Could not generate stub symbol for {}: names exhausted', name)
        return False
    if not idau.set_ea_name(stub, symbol, auto=True):
        _log(2, 'Could not set name {} for stub at {:#x}', symbol, stub)
        return False
    return True
예제 #4
0
def add_vtable_symbol(vtable, classname):
    """Add a symbol for the virtual method table at the specified address.

    Arguments:
        vtable: The address of the virtual method table.
        classname: The name of the C++ class with this virtual method table.

    Returns:
        True if the data was successfully converted into a vtable and the symbol was added.
    """
    vtable_symbol = vtable_symbol_for_class(classname)
    if not idau.set_ea_name(vtable, vtable_symbol):
        _log(0, 'Address {:#x} already has name {} instead of vtable symbol {}'
                .format(vtable, idau.get_ea_name(vtable), vtable_symbol))
        return False
    return True
예제 #5
0
def add_metaclass_symbol(metaclass, classname):
    """Add a symbol for the OSMetaClass instance at the specified address.

    Arguments:
        metaclass: The address of the OSMetaClass instance.
        classname: The name of the C++ class with this OSMetaClass instance.

    Returns:
        True if the OSMetaClass instance's symbol was created successfully.
    """
    metaclass_symbol = metaclass_symbol_for_class(classname)
    if not idau.set_ea_name(metaclass, metaclass_symbol):
        _log(0, 'Address {:#x} already has name {} instead of OSMetaClass instance symbol {}'
                .format(metaclass, idau.get_ea_name(metaclass), metaclass_symbol))
        return False
    return True