Exemplo n.º 1
0
def _convert_address_to_function(func):
    """Convert an address that IDA has classified incorrectly into a proper function."""
    # If everything goes wrong, we'll try to restore this function.
    orig = idc.first_func_chunk(func)
    # If the address is not code, let's undefine whatever it is.
    if not ida_bytes.is_code(ida_bytes.get_full_flags(func)):
        if not is_mapped(func):
            # Well, that's awkward.
            return False
        item = ida_bytes.get_item_head(func)
        itemend = ida_bytes.get_item_end(func)
        if item != idc.BADADDR:
            _log(1, 'Undefining item {:#x} - {:#x}', item, itemend)
            ida_bytes.del_items(item, ida_bytes.DELIT_EXPAND)
            idc.create_insn(func)
            # Give IDA a chance to analyze the new code or else we won't be able to create a
            # function.
            #ida_auto.auto_wait()
            autoanalyze()
            idc.plan_and_wait(item, itemend)
    else:
        # Just try removing the chunk from its current function. IDA can add it to another function
        # automatically, so make sure it's removed from all functions by doing it in loop until it
        # fails.
        for i in range(1024):
            if not idc.remove_fchunk(func, func):
                break
    # Now try making a function.
    if ida_funcs.add_func(func) != 0:
        return True
    # This is a stubborn chunk. Try recording the list of chunks, deleting the original function,
    # creating the new function, then re-creating the original function.
    if orig != idc.BADADDR:
        chunks = list(idautils.Chunks(orig))
        if ida_funcs.del_func(orig) != 0:
            # Ok, now let's create the new function, and recreate the original.
            if ida_funcs.add_func(func) != 0:
                if ida_funcs.add_func(orig) != 0:
                    # Ok, so we created the functions! Now, if any of the original chunks are not
                    # contained in a function, we'll abort and undo.
                    if all(idaapi.get_func(start) for start, end in chunks):
                        return True
            # Try to undo the damage.
            for start, _ in chunks:
                ida_funcs.del_func(start)
    # Everything we've tried so far has failed. If there was originally a function, try to restore
    # it.
    if orig != idc.BADADDR:
        _log(0, 'Trying to restore original function {:#x}', orig)
        ida_funcs.add_func(orig)
    return False
Exemplo n.º 2
0
def import_functions(fncs, add_names=True, always_thumb=True):

    name_counter = defaultdict(int)
    imported_functions = defaultdict(set)
    cfg_conflicts = defaultdict(set)
    symbol_defects = list()
    failed_fncs = list()

    countername_Fail = 0
    counterfct_fail = 0

    def set_name(addr, name):
        # FIXME creates unnamed_178 etc. instead of proper function name in IDA 7.2 on CYW20735
        name = name.replace("sub_", "unnamed_")
        cmt = idc.get_cmt(addr, 0)
        name_cmt = "fcn.%s" % name
        if cmt:
            name_cmt = cmt + ", " + name_cmt
        idc.set_cmt(addr, name_cmt, 0)
        if not add_names:
            return
        if name.isupper():
            try:
                # hackish way to stop warning about hex import
                # FIXME leave 'sub_' intact if it already exists
                # FIXME do not set the name to the hex prologue because it has duplicates, set it to
                #       'pp_{position}' instead
                a = int(name, 16)
                """continue"""
            except ValueError:
                pass
        ok = idc.set_name(addr, name, idc.SN_CHECK)
        if not ok:
            data = (name, size, addr)
            failed_fncs.append((data, "name"))
            print("{0:#x}: cannot add name, {1}".format(addr, name))
            countername_Fail = countername_Fail + 1
        else:
            imported_functions[addr].add(name)

    for name, size, addr, thumb in fncs:
        name_counter[name] += 1

        if not always_thumb:
            idc.split_sreg_range(addr, "T", int(thumb), idc.SR_user)
        idc.create_insn(addr)

        code = is_code(addr)
        fnc = is_func(addr)
        fnc_chnk = is_func_chunk(addr)
        data = (name, size, addr)
        start = get_func_start(addr)
        generic = fnc and func_is_generic(addr)

        # BADADDR automatically finds end of fnc.
        if size >= 2 and size % 2 == 0:
            end = addr + size
        else:
            end = idaapi.BADADDR

        if not code and not (fnc or fnc_chnk):
            symbol_defects.append(data)
        elif (fnc or fnc_chnk) and not code:
            cfg_conflicts[idc.get_func_name(addr)] = (data, start)
        elif start == addr and not generic:
            set_name(addr, name)  # duplicate symbol
        elif start == addr and generic:
            set_name(addr, name)
        elif start != addr:
            if fnc_chnk:
                idc.remove_fchunk(addr, addr)
            elif fnc:
                idc.set_func_end(addr,
                                 addr)  # force previous function to end here.
            ok = idaapi.add_func(addr, end)
            if not ok:
                failed_fncs.append((data, "fnc"))
                print("{0:#x}: cannot add fnc, {1}, {2:#x}".format(
                    addr, size, end))
                counterfct_fail = counterfct_fail + 1
            else:
                set_name(addr, name)
        else:
            failed_fncs.append((data, "unknown"))
            print(
                "{0:#x}: unknown problem - code: {1}, fnc: {2}, start {3:#x}, size {4}, end {5}"
                .format(addr, code, fnc, start, size, end))

    ida_auto.auto_wait()
    print("not added functions: {1} , not added names: {0}".format(
        countername_Fail, counterfct_fail))
    return name_counter, imported_functions, failed_fncs, cfg_conflicts, symbol_defects
Exemplo n.º 3
0
    def create_function(
        fnc,
        overwrite_names,
        offset,
        add_names=True,
    ):
        def set_name(addr, name):
            if not add_names:
                return
            try:
                numericName = int(name, 16)
                return
            except ValueError:
                pass
            ok = False
            if not IDAtools.is_dummy_name(name):
                ok = idc.set_name(addr, name, idc.SN_CHECK)
            if not ok:
                data = (name, size, addr)

        name = fnc.get("name")
        addr = int(fnc.get("addr"))
        addr = addr + int(offset)
        size = int(fnc.get("size"))

        if type(addr) == int:
            idc.create_insn(addr)

            code = IDAtools.is_code(addr)
            fnc = IDAtools.is_func(addr)
            fnc_chnk = IDAtools.is_func_chunk(addr)
            start = IDAtools.get_func_start(addr)
            generic = fnc and IDAtools.func_is_generic(addr)

            if size >= 2 and size % 2 == 0:
                end = addr + size
            else:
                end = idaapi.BADADDR

            if (fnc or fnc_chnk):
                ok = idc.set_func_end(addr, addr)
                if not ok:
                    pass
                    #print("{0:#x}: cannot add fnc, there still exists code, {1}, {2:#x}".format(addr, size, end))
            if IDAtools.is_dummy_name_by_addr(addr) and (
                    not name.startswith("sub_") and overwrite_names):
                set_name(addr, name)
            elif start == addr and overwrite_names:
                set_name(addr, name)

            elif start != addr:
                if fnc_chnk:
                    idc.remove_fchunk(addr, addr)
                elif fnc:
                    idc.set_func_end(
                        addr, addr)  # force previous function to end here.
                ok = idaapi.add_func(addr, end)
                if ok and add_names and overwrite_names:
                    set_name(addr, name)
                if not ok:
                    print("{0:#x}: cannot add fnc, {1}, {2:#x}".format(
                        addr, size, end))
            else:
                print(
                    "{0:#x}: unknown problem - code: {1}, fnc: {2}, start {3:#x}, size {4}, end {5}"
                    .format(addr, code, fnc, start, size, end))

        IDAtools.ida_wait()