Esempio n. 1
0
def import_objects(objs, add_names=True, always_thumb=True):
    """
    Create IDA function and data according to symbol definitions.
    Create name if add_name is True

    :param add_names: Create name for symbols?

    """

    failed_objs = []
    for name, size, addr, _ in objs:
        if not is_data_start(addr):
            if size:
                ok = idaapi.create_data(addr, idc.FF_BYTE, size, 0)
            else:
                ok = idc.create_byte(addr)
            if not ok:
                reason = "Could not create data at {addr:#x}".format(addr=addr)
                data = (name, size, addr)
                failed_objs.append((data, reason))
                """continue"""
        idc.set_cmt(addr, "obj.%s" % name, 0)
        if add_names:
            ok = idc.set_name(addr, name, idc.SN_CHECK)
            if not ok:
                reason = "Could not add name {name} at {addr:#x}".format(
                    name=name, addr=addr)
                data = (name, size, addr)
                failed_objs.append((data, reason))
    print("waiting for ida to finish analysis")
    ida_auto.auto_wait()
    print("ida finished import")
    return failed_objs
Esempio n. 2
0
    def __init__(self, arch, os):
        # Wait until IDA has finished analysis before we proceed, otherwise
        # we will end up missing code, data and cross references
        ida_auto.auto_wait()

        super(IDAProgram, self).__init__(arch, os)
        self._init_ctrl_flow_redirections()
Esempio n. 3
0
File: ESigs.py Progetto: newmsk/ESig
    def handle_dll_calls(self):
        dll_call_count = ida_bytes.get_dword(self.E_info_entry_ea +
                                             self.dll_call_count_offset)
        dll_call_lib_names_ea = ida_bytes.get_dword(
            self.E_info_entry_ea + self.dll_call_lib_names_offset)
        dll_call_func_names_ea = ida_bytes.get_dword(
            self.E_info_entry_ea + self.dll_call_func_names_offset)
        self.dll_calls = Dll_calls(dll_call_lib_names_ea,
                                   dll_call_func_names_ea, dll_call_count)

        ida_auto.auto_wait()

        ea = ida_name.get_name_ea(idaapi.BADADDR, "j__krnl_MCallDllCmd")
        code_fref_eas = []
        fref_ea = ida_xref.get_first_fcref_to(ea)

        while fref_ea != idaapi.BADADDR:
            code_fref_eas.append(fref_ea)
            fref_ea = ida_xref.get_next_cref_to(ea, fref_ea)

        for ref_ea in code_fref_eas:
            #get prev mov instruction
            prev_ins_ea = idaapi.get_item_head(ref_ea - 1)
            ins = ida_lines.generate_disasm_line(prev_ins_ea,
                                                 ida_lines.GENDSM_REMOVE_TAGS)
            if (ins.startswith("mov     eax,")):
                index = ida_bytes.get_dword(prev_ins_ea + 1)
                cmt = self.dll_calls[index]
                ida_bytes.set_cmt(ref_ea, cmt, False)
Esempio n. 4
0
def wait_auto_analysis():
    import ida_auto

    try:
        # >= IDA Pro 7.4
        ida_auto.auto_wait()
    except AttributeError:
        # < IDA Pro 7.4
        ida_auto.autoWait()
Esempio n. 5
0
def run_scatterload(debug=False):
    # Newly identified region may have additional scatter load procedure. Thus,
    # we continuously proceed until no changes left.
    is_changed = True
    while is_changed:
        is_changed = False
        tables = find_scatter_table()
        scatter_funcs = find_scatter_funcs()

        for start, end in tables.items():
            print("Processing table: 0x%x to 0x%x" % (start, end))
            while start < end:
                ida_bytes.create_dword(start, 16)
                ida_offset.op_offset(start, 0, idc.REF_OFF32)
                src = ida_bytes.get_dword(start)
                dst = ida_bytes.get_dword(start + 4)
                size = ida_bytes.get_dword(start + 8)
                how = ida_bytes.get_dword(start + 12)

                if how not in scatter_funcs:
                    print("%x: no addr 0x%x in scatter_funcs" % (start, how))
                    start += 16
                    continue

                func_name = scatter_funcs[how]
                start += 16
                print("%s: 0x%x -> 0x%x (0x%x bytes)" %
                      (func_name, src, dst, size))

                if func_name != "__scatterload_zeroinit":
                    if not idc.is_loaded(src) or size == 0:
                        print("0x%x is not loaded." % (src))
                        continue

                if debug:
                    # only show information above
                    continue

                if func_name == "__scatterload_copy":
                    if add_segment(dst, size, "CODE"):
                        memcpy(src, dst, size)
                        is_changed = True
                elif func_name == "__scatterload_decompress":
                    if add_segment(dst, size, "DATA"):
                        decomp(src, dst, size)
                        is_changed = True
                # some old firmware images have this.
                elif func_name == "__scatterload_decompress2":
                    if add_segment(dst, size, "DATA"):
                        decomp2(src, dst, size)
                        is_changed = True
                elif func_name == "__scatterload_zeroinit":
                    # No need to further proceed for zero init.
                    if add_segment(dst, size, "DATA"):
                        memclr(dst, size)

                ida_auto.auto_wait()
Esempio n. 6
0
def set_type_single(address, type_):
    if isinstance(type_, fa_types.FaStruct) or \
            isinstance(type_, fa_types.FaEnum):
        type_str = type_.get_name()
    else:
        type_str = type_

    idc.SetType(address, type_str)
    ida_auto.auto_wait()
Esempio n. 7
0
 def command_autoanalysis(action):
     if action == "wait":
         ida_auto.auto_wait()
         return (
             'autoanalysis',
             'done',
         )
     else:
         raise RuntimeError("Invalid action received for command: "
                            "{}".format(action))
Esempio n. 8
0
def clean():
    """Removes the background color of all the database.
    It can be used to remove the colors added by `apply()`, but it doesn't remove the prefixes."""
    ida_auto.auto_wait()
    ea = idc.next_head(0)
    while ea != idaapi.BADADDR:
        idc.set_color(ea, idc.CIC_ITEM, 0xFFFFFF)
        ea = idc.next_head(ea)

    print("ANA color: Enjoy your boring database")
Esempio n. 9
0
def clear_names():
    """for some reason deleting names seems to need several takes.
    This will loop until all names are deleted.
    """

    names = list(idautils.Names())
    while names:
        for name_ea, _ in names:
            idc.set_name(name_ea, "")  # deletes name
        ida_auto.auto_wait()
        names = list(idautils.Names())
Esempio n. 10
0
def main():
    print("Waiting for autoanalysis...")
    ida_auto.auto_wait()
    if init_hexrays():
        eqty = ida_entry.get_entry_qty()
        if eqty:
            idbpath = idc.get_idb_path()
            cpath = idbpath[:-4] + ".c"
            with open(cpath, "w") as outfile:
                print("writing results to '%s'..." % cpath)
                for i in range(eqty):
                    ea = ida_entry.get_entry(ida_entry.get_entry_ordinal(i))
                    decompile_func(ea, outfile)
        else:
            print("No known entrypoint. Cannot decompile.")
    if ida_kernwin.cvar.batch:
        print("All done, exiting.")
        ida_pro.qexit(0)
Esempio n. 11
0
    def update_idb(self):
        sid = ida_struct.get_struc_id(self._name)
        if sid != -1:
            sptr = ida_struct.get_struc(sid)
            ida_struct.del_struc(sptr)

        sid = ida_struct.add_struc(idc.BADADDR, self._name, 0)
        sptr = ida_struct.get_struc(sid)

        for f in self._fields:
            ida_struct.add_struc_member(sptr, f.name, idc.BADADDR,
                                        (idc.FF_BYTE | idc.FF_DATA)
                                        & 0xFFFFFFFF, None, 1)
            member_name = "{}.{}".format(self._name, f.name)
            idc.SetType(
                idaapi.get_member_by_fullname(member_name)[0].id, f.type)

        ida_auto.auto_wait()
Esempio n. 12
0
    def update_idb(self, delete_existing_members=True):
        sid = ida_struct.get_struc_id(self._name)
        sptr = ida_struct.get_struc(sid)

        if sid == idc.BADADDR:
            sid = ida_struct.add_struc(idc.BADADDR, self._name, 0)
            sptr = ida_struct.get_struc(sid)
        else:
            if delete_existing_members:
                ida_struct.del_struc_members(sptr, 0, 0xffffffff)

        for f in self._fields:
            ida_struct.add_struc_member(sptr, f.name, f.offset,
                                        (idc.FF_BYTE | idc.FF_DATA)
                                        & 0xFFFFFFFF, None, 1)
            member_name = "{}.{}".format(self._name, f.name)
            idc.SetType(
                idaapi.get_member_by_fullname(member_name)[0].id, f.type)

        ida_auto.auto_wait()
Esempio n. 13
0
 def run(self, args):
     print "[+] Welcome to Driver Buddy"
     auto_wait()  # Wait for IDA autoanalysis to complete
     driver_entry = data.is_driver()
     if driver_entry == "":
         print "[-] No DriverEntry stub found"
         print "[-] Exiting..."
         return
     print "[+] DriverEntry found"
     if data.populate_data_structures() == False:
         print "[-] Unable to load functions"
         print "[-] Exiting..."
         return
     driver_type = data.get_driver_id(driver_entry)
     if driver_type == "":
         print "[-] Unable to determine driver type assuming wdm"
     else:
         print "[+] Driver type detected: " + driver_type
     if ioctl.find_ioctls() == False:
         print "[-] Unable to automatically find any IOCTLs"
     return
Esempio n. 14
0
def fix_func_prolog(ea, end_ea=idc.BADADDR):
    global FUNC_BY_LS

    func_cnt = 0
    func = ida_funcs.get_fchunk(ea)
    if func is None:
        func = ida_funcs.get_next_func(ea)
    ea = func.start_ea

    while func is not None and ea < end_ea:
        # if current function is small enough and there exists a function right
        # next to current function
        if (func.size() <= 8 and idc.get_func_attr(
                func.end_ea, idc.FUNCATTR_START) != idc.BADADDR):
            # If the next function can be connected, there must be a basic block reference.
            # xref.type == 21 means 'fl_F', which is an ordinary flow.
            if all(
                (func.start_ea <= xref.frm < func.end_ea) and xref.type == 21
                    for xref in XrefsTo(func.end_ea)):
                if func_cnt > 0 and func_cnt % 1000 == 0:
                    print("%x <- %x: prolog merging (%d)." %
                          (func.start_ea, func.end_ea, func_cnt))
                ida_bytes.del_items(func.end_ea, ida_bytes.DELIT_EXPAND)
                ida_bytes.del_items(func.start_ea, ida_bytes.DELIT_EXPAND)
                ida_auto.auto_wait()

                status = idc.add_func(func.start_ea)
                if not status:
                    print("Error merging 0x%x <- 0x%x" %
                          (func.start_ea, func.end_ea))
                else:
                    func_cnt += 1
                    FUNC_BY_LS.discard(func.end_ea)
                ida_auto.auto_wait()

        func = ida_funcs.get_next_func(ea)
        if func:
            ea = func.start_ea

    print("Fixed %d functions" % func_cnt)
Esempio n. 15
0
def apply():
    """Provides an `apply()` method to color and mark your database and a `clean()` method to undo it.
    The `apply()` method colors `call`, `push` and `pop` instructions (sets background color).
    It also adds the prefix `>>` to`call` instructions and the number of argument to its parameters (only available if the function declaration is defined).
    This is useful to quickly identify function calls, their parameters and the calling convention."""
    ida_auto.auto_wait()
    ea = idc.next_head(0)
    while ea != idaapi.BADADDR:
        instruction = idc.print_insn_mnem(ea)
        if instruction == "call":
            idc.set_color(ea, idc.CIC_ITEM, COLOR_CALL)
            addresses = idaapi.get_arg_addrs(ea)
            if addresses:
                _PARAMETERS.update({e: i + 1 for i, e in enumerate(addresses)})
        elif instruction == "push":
            idc.set_color(ea, idc.CIC_ITEM, COLOR_PUSH)
        elif instruction == "pop":
            idc.set_color(ea, idc.CIC_ITEM, COLOR_POP)
        ea = idc.next_head(ea)

    ida_lines.set_user_defined_prefix(ALL_PREFIX_WIDTH, _prefix_callback)

    print("ANA color: Enjoy your colorful database!")
Esempio n. 16
0
    def __init__(self,
                 arch: Arch,
                 os: OS,
                 maybe_base_address: Optional[int] = None):
        if maybe_base_address is not None:
            delta = abs(ida_nalt.get_imagebase() - maybe_base_address)
            if maybe_base_address < ida_nalt.get_imagebase():
                delta = delta * -1

            if ida_segment.rebase_program(delta, ida_segment.MSF_FIXONCE) != 0:
                raise RuntimeError("Failed to rebase the program")

        # Wait until IDA has finished analysis before we proceed, otherwise
        # we will end up missing code, data and cross references
        ida_auto.auto_wait()

        super(IDASpecification, self).__init__(arch, os)

        try:
            self._init_func_thunk_ctrl_flow()
        except:
            DEBUG(
                "Failed to initialize the control flow information for functin thunks"
            )
Esempio n. 17
0
    funcs = get_funcs()

    text_segm = ida_segment.get_segm_by_name(".text")
    for func in funcs:
        # we only care about functions in .text segment
        if not in_range(text_segm, func.start_ea):
            continue

        name = ida_funcs.get_func_name(func.start_ea)
        code = ida_hexrays.decompile_func(func, None)
        results[name] = {   "name": name,
                            "start_ea": func.start_ea,
                            "end_ea": func.end_ea,
                            "code": code.__str__(),
                            "size": func.size()
                            }
    print("JSON:")
    print(json.dumps({"time": time.time() - start, "data": results}))


# wait for the analysis to complete
ida_auto.auto_wait()

# actually do stuff
print(BEGIN_BANNER)
main()
print(END_BANNER)

# quit to stop GUI from poping up
ida_pro.qexit(0)
Esempio n. 18
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
Esempio n. 19
0
def reset_db():
    idc.del_items(min_ea, size=max_ea - min_ea)
    idc.delete_all_segments()
    clear_names()
    ida_auto.auto_wait()
Esempio n. 20
0
 def ida_wait():
     ida_auto.auto_wait()
Esempio n. 21
0
def analyze_linear_sweep(start_ea, end_ea=idc.BADADDR):
    global FUNC_BY_LS, FUNC_BY_LS_TIME
    if "FUNC_BY_LS" not in globals() or len(FUNC_BY_LS) == 0:
        FUNC_BY_LS = set()

    cand_cnt = 0
    func_cnt = 0
    ea = start_ea
    start_time = time.time()
    while ea < end_ea and ea != idc.BADADDR:
        ea, mode = find_next_func_cand(ea, end_ea)
        if ea == idc.BADADDR:
            break

        cand_cnt += 1
        if cand_cnt % 10000 == 0:
            print("%x: %d/%d function has been found (%d secs)" %
                  (ea, func_cnt, cand_cnt, time.time() - start_time))

        # set IDA segment register to specify ARM mode
        old_flag = idc.get_sreg(ea, "T")
        if mode == THUMB:
            idc.split_sreg_range(ea, "T", 1, idc.SR_user)
        elif mode == ARM:
            idc.split_sreg_range(ea, "T", 0, idc.SR_user)
        else:
            print("Unknown mode")
            raise NotImplemented

        # add_func ignores the existing function, but existing function is
        # already filtered when finding the candidate
        status = idc.add_func(ea)
        if status:
            func_cnt += 1
            FUNC_BY_LS.add(ea)

            # Wait IDA's auto analysis
            ida_auto.auto_wait()

            # even though add_func succeed, it may not be correct.
            # TODO: how to check the correctness? we may check the function end?
            func_end = idc.get_func_attr(ea, idc.FUNCATTR_END)
            if func_end > ea:
                ea = func_end
            else:
                # sometimes, ida returns wrong addr
                ea = next_addr_aligned(ea)

        else:
            if idc.get_func_attr(ea, idc.FUNCATTR_START) == idc.BADADDR:
                # IDA automatically make code, and this remains even though
                # add_func fails.
                ida_bytes.del_items(ea, ida_bytes.DELIT_EXPAND)

                # reset IDA segment register to previous ARM mode
                idc.split_sreg_range(ea, "T", old_flag, idc.SR_user)

                # Wait IDA's auto analysis
                ida_auto.auto_wait()

            ea = next_addr_aligned(ea)

    # linear sweep may choose wrong prologs. We merge the prologs of two
    # adjacent functions.
    if func_cnt > 0:
        fix_func_prolog(start_ea, end_ea)

    FUNC_BY_LS_TIME = time.time() - start_time
    print("Found %d/%d functions. (%d sec)" %
          (len(FUNC_BY_LS), cand_cnt, FUNC_BY_LS_TIME))
Esempio n. 22
0
 def autoanalyze():
     ida_auto.auto_wait()
Esempio n. 23
0
  once that is done, produce a .c file containing the
  decompilation of all the functions in that file.

  Run like so:

        ida -A "-S...path/to/produce_c_file.py" <binary-file>

  where:

    * -A instructs IDA to run in non-interactive mode
    * -S holds a path to the script to run (note this is a single token;
         there is no space between '-S' and its path.)
"""

import ida_pro
import ida_auto
import ida_loader
import ida_hexrays

# derive output file name
idb_path = ida_loader.get_path(ida_loader.PATH_TYPE_IDB)
c_path = "%s.c" % idb_path

ida_auto.auto_wait()  # wait for end of auto-analysis
ida_hexrays.decompile_many(  # generate .c file
    c_path, None, ida_hexrays.VDRUN_NEWFILE
    | ida_hexrays.VDRUN_SILENT
    | ida_hexrays.VDRUN_MAYSTOP)

ida_pro.qexit(0)
Esempio n. 24
0
def load_file(fd, neflags, format):
    global prologues
    size = 0
    base_addr = 0
    ea = 0
    nfunc = 0
    idaapi.set_processor_type("arm", idaapi.SETPROC_LOADER)
    idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT
    if (neflags & idaapi.NEF_RELOAD) != 0:
        return 1
    fd.seek(0, idaapi.SEEK_END)
    size = fd.tell()
    segm = idaapi.segment_t()
    segm.bitness = 2  # 64-bit
    segm.start_ea = 0
    segm.end_ea = size
    idaapi.add_segm_ex(segm, "iBoot", "CODE", idaapi.ADDSEG_OR_DIE)
    fd.seek(0)
    fd.file2base(0, 0, size, False)
    idaapi.add_entry(0, 0, "start", 1)
    idaapi.add_func(ea, idaapi.BADADDR)
    print("[+] Marked as code")
    # heuristic
    while (True):
        mnemonic = idaapi.ua_mnem(ea)
        if mnemonic == None:
            mnemonic = ''
        if "LDR" in mnemonic:
            base_str = idc.print_operand(ea, 1)
            base_addr = int(base_str.split("=")[1], 16)
            break
        ea += 4
    print("[+] Rebasing to address 0x%x" % (base_addr))
    idaapi.rebase_program(base_addr, idc.MSF_NOFIX)
    ida_auto.auto_wait()

    segment_start = base_addr
    segment_end = idc.get_segm_attr(segment_start, idc.SEGATTR_END)
    ea = segment_start

    print("[+] Searching and defining functions")

    for prologue in prologues:
        while ea != idc.BADADDR:
            ea = ida_search.find_binary(ea, idc.ida_search.SEARCH_DOWN,
                                        prologue, 16, ida_search.SEARCH_DOWN)
            if ea != idc.BADADDR:
                ea = ea - 2
                if (ea % 4) == 0 and ida_bytes.get_flags(ea) < 0x200:
                    print("[+] Defining a function at 0x%x" % (ea))
                    idaapi.add_func(ea, idaapi.BADADDR)
                    nfunc = nfunc + 1
                ea = ea + 4

    ida_auto.plan_and_wait(segment_start, segment_end)
    print("[+] Identified %d new functions" % (nfunc))
    print("[+] Looking for interesting functions")
    find_interesting(segment_start)
    return 1


# EOF
Esempio n. 25
0
#
# This example tries to load a decompiler plugin corresponding to the current
# architecture (and address size) right after auto-analysis is performed,
# and then tries to decompile the function at the first entrypoint.
#
# It is particularly suited for use with the '-S' flag.
#

import ida_ida
import ida_auto
import ida_loader
import ida_hexrays
import ida_idp
import ida_entry

ida_auto.auto_wait()
ALL_DECOMPILERS = {
    ida_idp.PLFM_386 : ("hexrays", "hexx64"),
    ida_idp.PLFM_ARM : ("hexarm", "hexarm64"),
    ida_idp.PLFM_PPC : ("hexppc", "hexppc64"),
}
pair = ALL_DECOMPILERS.get(ida_idp.ph.id, None)
if pair:
    decompiler = pair[1 if ida_ida.cvar.inf.is_64bit() else 0]
    if ida_loader.load_plugin(decompiler) and ida_hexrays.init_hexrays_plugin():
        eqty = ida_entry.get_entry_qty()
        if eqty:
            ea = ida_entry.get_entry(ida_entry.get_entry_ordinal(0))
            print("Decompiling at: %X" % ea)
            cf = ida_hexrays.decompile(ea)
            if cf: