示例#1
0
def find_item(ea, q, parents=False, flags=0):
    """find item within AST of decompiled function

    arguments:
    ea:         address belonging to a function
    q:          lambda/function: f(cfunc_t, citem_t) returning a bool
    parents:    False -> discard cexpr_t parent nodes
                True  -> maintain citem_t parent nodes

    returns list of query_result_t objects
    """

    f = ida_funcs.get_func(ea)
    if f:
        cfunc = None
        hf = hx.hexrays_failure_t()
        try:
            cfunc = hx.decompile(f, hf, flags)
        except Exception as e:
            print("%s %x: unable to decompile: '%s'" % (SCRIPT_NAME, ea, hf))
            print("\t (%s)" % e)
            return list()

        if cfunc:
            return find_child_item(cfunc, cfunc.body, q, parents)
    return list()
示例#2
0
def _decompile(offset: int) -> tuple:
    """
    Attempt to decompile the function at the provided offset using the Hex-Rays plugin. Returns a tuple containing the
    decompiled text (which will be None if an error occurred) and the populated hexrays_failure_t object.
    :param offset: an offset in the function to decompile
    :return: (decompiled text, failure object)
    """
    func = ida_funcs.get_func(offset)
    hf = ida_hexrays.hexrays_failure_t()
    decompiled = ida_hexrays.decompile_func(func, hf, 0)
    return decompiled, hf
示例#3
0
def get_microcode(func, maturity):
    """
    Return the mba_t of the given function at the specified maturity.
    """
    mbr = ida_hexrays.mba_ranges_t(func)
    hf = ida_hexrays.hexrays_failure_t()
    ml = ida_hexrays.mlist_t()
    ida_hexrays.mark_cfunc_dirty(func.start_ea)
    mba = ida_hexrays.gen_microcode(mbr, hf, ml, ida_hexrays.DECOMP_NO_WAIT, maturity)
    if not mba:
        print("0x%08X: %s" % (hf.errea, hf.desc()))
        return None
    return mba
示例#4
0
def decompiled_code(address: int, _visited=None) -> Optional[ida_hexrays.cfuncptr_t]:
    """
    Generates IDA object representing the decompiled code for the given address.

    :param address: Start address of the function.

    :returns: cfuncptr_t object or None on failure.
    """
    if _visited is None:
        _visited = set()

    attempted_before = address in _visited
    _visited.add(address)

    # This requires Hexrays decompiler, load it and make sure it's available before continuing.
    if not ida_hexrays.init_hexrays_plugin():
        idc.load_and_run_plugin("hexrays", 0) or idc.load_and_run_plugin("hexx64", 0)
    if not ida_hexrays.init_hexrays_plugin():
        logger.debug("Unable to load Hexrays decompiler.")
        return None
    fail_obj = ida_hexrays.hexrays_failure_t()
    code = ida_hexrays.decompile(address, fail_obj)
    if code and not fail_obj.code:
        return code

    if not fail_obj:
        logger.warning(f"Unable to decompile function at {hex(address)}")
        return None

    # Cannot possibly recover from call analysis failure.
    if fail_obj.code == -12:
        logger.warning(f"Unable to decompile function at {hex(address)}: call analysis failed")
        return None

    # We may be able to still recover from this by first trying to decompile
    # the called function that caused the failure.
    # If we've attempted this before, ensure we don't try a third time
    # and cause an infinite loop.
    if not attempted_before:
        failed_address = fail_obj.errea
        if ida_ua.ua_mnem(failed_address) == "call":
            call_address = idc.get_operand_value(failed_address, 0)
            if decompiled_code(_visited=_visited) is not None:
                return decompiled_code(address, visited=_visited)

    # TODO: Observed this message pops up with fail_obj.code == 0... unsure if that is actually an error.
    logger.debug(f"Unable to decompile function at {hex(address)}: {fail_obj.code}")
    return None
示例#5
0
def show_microcode():
    """Generates and displays microcode for an address range.
    An address range can be a selection of code or that of
    the current function."""
    sel, sea, eea = kw.read_range_selection(None)
    pfn = ida_funcs.get_func(kw.get_screen_ea())
    if not sel and not pfn:
        return (False, "Position cursor within a function or select range")

    if not sel and pfn:
        sea = pfn.start_ea
        eea = pfn.end_ea

    addr_fmt = "%016x" if ida_ida.inf_is_64bit() else "%08x"
    fn_name = (ida_funcs.get_func_name(pfn.start_ea) if pfn else "0x%s-0x%s" %
               (addr_fmt % sea, addr_fmt % eea))
    F = ida_bytes.get_flags(sea)
    if not ida_bytes.is_code(F):
        return (False, "The selected range must start with an instruction")

    text, mmat, mba_flags = ask_desired_maturity()
    if text is None and mmat is None:
        return (True, "Cancelled")

    if not sel and pfn:
        mbr = hr.mba_ranges_t(pfn)
    else:
        mbr = hr.mba_ranges_t()
        mbr.ranges.push_back(ida_range.range_t(sea, eea))

    hf = hr.hexrays_failure_t()
    ml = hr.mlist_t()
    mba = hr.gen_microcode(mbr, hf, ml, hr.DECOMP_WARNINGS, mmat)
    if not mba:
        return (False, "0x%s: %s" % (addr_fmt % hf.errea, hf.desc()))
    vp = printer_t()
    mba.set_mba_flags(mba_flags)
    mba._print(vp)
    mcv = microcode_viewer_t()
    if not mcv.Create(
            mba, "0x%s-0x%s (%s)" %
        (addr_fmt % sea, addr_fmt % eea, text), text, fn_name, vp.get_mc()):
        return (False, "Error creating viewer")

    mcv.Show()
    return (True, "Successfully generated microcode for 0x%s..0x%s" %
            (addr_fmt % sea, addr_fmt % eea))
示例#6
0
    def run(self, _):
        fn = ida_funcs.get_func(ida_kernwin.get_screen_ea())
        if fn is None:
            ida_kernwin.warning("Please position the cursor within a function")
            return True

        mmat = MCExplorer.ask_desired_maturity()
        if mmat == 0:
            return True

        hf = ida_hexrays.hexrays_failure_t()
        mba = Native.gen_microcode(fn, hf, None, 0, mmat)
        if not mba:
            return True

        fn_name = ida_funcs.get_func_name(fn.start_ea)
        mmat_name = LEVELS[mmat - 1]
        MCTextView(mba, fn_name, mmat_name).Show()
        return True
示例#7
0
def scrape_unsupported_instructions():
    """
    Scrape all 'external' (unsupported) decompiler instructions from this IDB.

    Returns a tuple of two maps:
        ext2func = { opcode: set([func_ea, func2_ea, ...]) }
        func2ext = { func_ea: set([opcode1, opcode2, opcode3]) }

    """
    miv = MinsnVisitor()
    ext2func = collections.defaultdict(set)
    func2ext = {}

    for address in idautils.Functions():

        #address = 0x1800017E0
        print("0x%08X: DECOMPILING" % address)
        func = ida_funcs.get_func(address)

        func_mbr = ida_hexrays.mba_ranges_t(func)
        hf = ida_hexrays.hexrays_failure_t()
        flags = ida_hexrays.DECOMP_NO_XREFS | ida_hexrays.DECOMP_NO_WAIT | ida_hexrays.DECOMP_WARNINGS
        mba = ida_hexrays.gen_microcode(func_mbr, hf, None, flags,
                                        ida_hexrays.MMAT_GENERATED)

        if not mba:
            print(" - 0x%08x: FAILED %s" % (hf.errea, hf.str))
            continue

        miv.found = set()
        mba.for_all_insns(miv)

        # opcode --> [func_ea, func2_ea, ..]
        for ins_op in miv.found:
            ext2func[ins_op].add(address)

        # func_ea --> [ins_op, ins_op2, ..]
        func2ext[address] = miv.found

    print("\nDone scraping...\n")
    return (ext2func, func2ext)
示例#8
0
    i = xc.Show(True)
    if i >= 0:
        ida_kernwin.jumpto(xrefs[i])


if ida_hexrays.init_hexrays_plugin():
    ea = ida_kernwin.get_screen_ea()
    pfn = ida_funcs.get_func(ea)
    w = ida_kernwin.warning
    if pfn:
        F = ida_bytes.get_flags(ea)
        if ida_bytes.is_code(F):
            gco = ida_hexrays.gco_info_t()
            if ida_hexrays.get_current_operand(gco):
                # generate microcode
                hf = ida_hexrays.hexrays_failure_t()
                mbr = ida_hexrays.mba_ranges_t(pfn)
                mba = ida_hexrays.gen_microcode(mbr, hf, None,
                                                ida_hexrays.DECOMP_WARNINGS,
                                                ida_hexrays.MMAT_PREOPTIMIZED)
                if mba:
                    merr = mba.build_graph()
                    if merr == ida_hexrays.MERR_OK:
                        ncalls = mba.analyze_calls(ida_hexrays.ACFL_GUESS)
                        if ncalls < 0:
                            print(
                                "%08x: failed to determine some calling conventions",
                                pfn.start_ea)
                        mlist = ida_hexrays.mlist_t()
                        if gco.append_to_list(mlist, mba):
                            ctx = ida_hexrays.op_parent_info_t()
		if table is not None:
			os.write(table, "# Function infomation in " + idaapi.get_root_filename() + "\n")
			os.write(table, "\n|Address|Name|Declaration|Comment|\n")
			os.write(table, "|----|----|----|----|\n")
			for func_ea in idautils.Functions():
				name = idaapi.get_func_name(func_ea)
				if idaapi.is_uname(name):
					func = idaapi.get_func(func_ea)
					comment = idaapi.get_func_cmt(func, 1)
					if comment is None:
						comment = ""
					# new line in comment
					comment = comment.replace("\n", "<br>")
					# pf = ida_hexrays._decompile(func, None)
					try:
						pf = ida_hexrays.decompile(func_ea, ida_hexrays.hexrays_failure_t(0, func_ea, name))
					except ida_hexrays.DecompilationFailure, e:
						print e, name
						decl = ""
					else:
						decl = pf.print_dcl()
					# delete SOH
					decl = decl.replace("\x01", "")
					# delete STX
					decl = decl.replace("\x02", "")
					# delete ETB
					decl = decl.replace("\x17", "")
					decl = decl.replace("!", "")
					# delete call standard
					decl = decl.replace("__fastcall ", "")
					decl = decl.replace("__stdcall ", "")