Example #1
0
    def paint_function(self, color, new_address):
        """
        Paint function with the given color

        :param color: the color
        :param new_address: address within the function where apply the color
        """
        #
        # paint all instructions within the function with default background
        # this has to be done because painting function paint all nodes in it
        #
        self.paint_function_instructions(new_address)
        new_func = ida_funcs.get_func(new_address)

        # get the previous user position
        user_position = self.users_positions.get(color)
        if user_position:
            address = user_position['address']
            func = ida_funcs.get_func(address)
            # paint it only if previous function and new function are different
            if not new_func or (func and new_func and func == new_func):
                return
        if new_func:
            # add the color to the new function color stack
            self._painted_functions[new_func.startEA].append(new_func.color)
            # finaly paint the function
            self.set_paint_function(new_func, color)
Example #2
0
    def __process_names(self):
        names = list()

        for i in range(0, ida_name.get_nlist_size()):
            ea = ida_name.get_nlist_ea(i)
            if ida_funcs.get_func(ea) is not None:
                continue

            name = {
                'rva': ea - self._base,
                'name': ida_name.get_nlist_name(i),
                'name_demangled':
                ida_name.get_demangled_name(ea, 0xFFFF, 0, 0),
                'is_public': ida_name.is_public_name(ea),
                'is_func': ida_funcs.get_func(ea) is not None
            }

            # PE32/PE32+ only support binaries up to 2GB
            if name['rva'] >= 2**32:
                print('RVA out of range for name: ' + name['name'],
                      file=sys.stderr)

            names.append(name)

        return names
Example #3
0
    def clear_function(self, name, new_address):
        """Clear paint from the specified user and function."""
        user_position = self._users_positions.get(name)
        new_func = ida_funcs.get_func(new_address)

        # If the stack is empty, this is the first time we meet this function,
        # so we must save the original color to restore it.
        if new_func and not self._painted_functions[new_func.start_ea]:
            func_color = self._get_paint_function(new_func)
            self._painted_functions[new_func.start_ea].append(func_color)

        if user_position:
            address = user_position["address"]
            self.clear_function_instructions(address)
            func = ida_funcs.get_func(address)

            # Clear it only if previous func and new func are different
            if (func and not new_func) or (func and new_func
                                           and func != new_func):
                color = self._painted_functions[func.start_ea].pop()
                # If the stack is not empty, repaint all the instructions with
                # the color popped from the stack.
                if self._painted_functions[func.start_ea]:
                    self.paint_function_instructions(address)
                self._set_paint_function(func, color)
Example #4
0
    def clear_function(self, color, new_address):
        """
        Clear paint from the given functions

        :param color: the color
        :param new_address: an address within the function where the color
                            needs to be cleared
        """
        user_position = self.users_positions.get(color)
        new_func = ida_funcs.get_func(new_address)

        #
        # if the deqeue is empty, this is the first time we meet this function
        # we must save the original color to restore it
        # TODO: broadcast the original color to others users
        #
        if new_func and not self._painted_functions[new_func.startEA]:
            self._painted_functions[new_func.startEA].append(new_func.color)

        if user_position:
            address = user_position['address']
            self.clear_function_instructions(address)
            func = ida_funcs.get_func(address)

            # clear it only if previous func and new func are different
            if (func and not new_func) or \
                    (func and new_func and func != new_func):
                color = self._painted_functions[func.startEA].pop()
                # if the queue is not empty, repaint all the instructions with
                # the background color
                if self._painted_functions[func.startEA]:
                    self.paint_function_instructions(address)
                self.set_paint_function(func, color)
Example #5
0
def main():
    is_selected, sel_start, sel_end = ida_kernwin.read_selection()
    if not is_selected:
        logger.error('range must be selected')
        return -1

    sel_end = ida_bytes.next_head(sel_end)

    buf = ida_bytes.get_bytes(sel_start, sel_end - sel_start)
    if buf is None:
        logger.error('failed to fetch instruction bytes')
        return -1

    f = ida_funcs.get_func(sel_start)
    if f != ida_funcs.get_func(sel_end):
        logger.error('range must be within a single function')
        return -1

    # find mappings from "$localN" to "custom_name"
    regvars = {}
    for i in range(0x1000):
        regvar = ida_frame.find_regvar(f, sel_start, '$local%d' % i)
        if regvar is None:
            continue
        regvars[regvar.canon] = regvar.user

        if len(regvars) >= f.regvarqty:
            break

    globals_ = {}
    for i, offset in netnode.Netnode('$ wasm.offsets').get('globals',
                                                           {}).items():
        globals_['$global' + i] = ida_name.get_name(offset)

    frame = {}
    if f.frame != ida_idaapi.BADADDR:
        names = set([])
        for i in range(ida_struct.get_struc_size(f.frame)):
            s = ida_struct.get_struc(f.frame)
            if not s:
                continue
            m = ida_struct.get_member(s, i)
            if not m:
                continue
            name = ida_struct.get_member_name(m.id)
            if name in names:
                continue
            frame[i] = name
            names.add(name)

    emu = Emulator(buf)
    emu.run()
    print(
        emu.render(ctx={
            'regvars': regvars,
            'frame': frame,
            'globals': globals_,
        }))
Example #6
0
 def ti_changed(self, ea, typeinf, fnames):
     res = ida_struct.get_member_by_id(ea)
     if res is not None:
         m, name, sptr = res
         if sptr.is_frame():
             func = ida_funcs.get_func(ida_frame.get_func_by_frame(sptr.id))
             if func is not None:
                 return self.func_updated(func)
     elif utils.is_func(ea):
         return self.func_updated(ida_funcs.get_func(ea))
     return 0
Example #7
0
def find_img4decodeinit(base_ea):
    ea_list = ida_search.find_imm(base_ea, ida_search.SEARCH_DOWN, 0x494D0000)

    if ea_list[0] != ida_idaapi.BADADDR:
        func_ea = ida_funcs.get_func(ea_list[0]).start_ea
        ea_func_list = list(idautils.XrefsTo(func_ea))

        if ea_func_list[0].frm != ida_idaapi.BADADDR:
            i4d_ea = ida_funcs.get_func(ea_func_list[0].frm).start_ea
            print "\t[+] _Img4DecodeInit = 0x%x" % (i4d_ea)
            idc.set_name(i4d_ea, "_Img4DecodeInit", idc.SN_CHECK)
            return i4d_ea

    return ida_idaapi.BADADDR
Example #8
0
    def _hxe_callback(self, event, *args):
        if not self._installed:
            return 0

        # this event gets triggered each time that a user changes the view to
        # a different decompilation view. It will also get triggered when staying on the
        # same view but having it refreshed
        if event == ida_hexrays.hxe_func_printed:
            ida_cfunc = args[0]
            func_addr = ida_cfunc.entry_ea
            func = ida_funcs.get_func(func_addr)

            # sanity check
            if func is None:
                return 0

            # run update tasks needed for this function since we are looking at it
            if not self.updating_states.locked():
                with self.updating_states:
                    self.controller.update_states[func_addr].do_updates()

            # create a new cache for unseen funcs
            if func.start_ea not in self._cached_funcs.keys():
                self._cached_funcs[func.start_ea] = {
                    "cmts": [],
                    "header": None
                }

            # push changes viewable only in decompilation
            self._push_new_comments(func.start_ea)
            self._push_new_func_header(ida_cfunc)

        return 0
    def activate(self, ctx):
        """
        :param ctx: idaapi.action_activation_ctx_t
        :return:    None
        """
        ea = get_screen_ea()

        if get_func(ea) is None:
            print("address = " + hex(ea))

            data = get_bytes(ea, 16)
            guid = str(UUID(bytes_le=data))
        else:
            name, data = extract_guid(ea)
            guid = str(UUID(bytes_le=data))

            print("Local variable EFI_GUID extraction for " + name)

        print("data = " + " ".join("%02x" % x for x in bytes(data)))
        print("guid = " + guid)

        try:
            import clipboard

            clipboard.copy(guid)
        except ImportError:
            print("clipboard module is not available.")
def propagate_function_type(ea: int, func_type: FUNCTION_TYPE):
    print(f"propagate func {hex(ea)}, type {func_type}")

    if visited.get(ea) is not None:
        return
    if func_type == FUNCTION_TYPE.NULLSUB:
        ida_name.set_name(ea, f"nullsub_{hex(ea)[2:]}")
    elif func_type == FUNCTION_TYPE.IDENTITY:
        ida_name.set_name(ea, f"identity_{hex(ea)[2:]}")
    elif func_type == FUNCTION_TYPE.GETVALUE:
        ida_name.set_name(ea, f"getvalue_{hex(ea)[2:]}")

    visited[ea] = True
    cref = ida_xref.get_first_cref_to(ea)
    while cref != idaapi.BADADDR:
        cref_func = ida_funcs.get_func(cref)
        #function is not defined or function has been visited
        if cref_func is None or visited.get(cref_func.start_ea) is not None:
            cref = ida_xref.get_next_cref_to(ea, cref)
            continue
        cref_func_type = infer_function_type(cref_func.start_ea, func_type)
        if cref_func_type == FUNCTION_TYPE.OTHER:
            cref = ida_xref.get_next_cref_to(ea, cref)
            visited[cref_func.start_ea] = True
            continue
        propagate_function_type(cref_func.start_ea, cref_func_type)
        cref = ida_xref.get_next_cref_to(ea, cref)
Example #11
0
def _erase_reg_in_range(s_ea, e_ea, reg):
    pfn = ida_funcs.get_func(s_ea)

    ea = s_ea
    prev_ranges = []

    #if there was a rename range with this reg containing the start of the range (s_ea) - remember it
    prev_range_s = ida_frame.find_regvar(pfn, s_ea, reg)
    if (prev_range_s is not None) and (prev_range_s.start_ea < s_ea):
        prev_ranges += [(prev_range_s.start_ea, s_ea, prev_range_s.user)]

    #if there was a rename range with this reg containing the end of the range (e_ea) - remember it
    prev_range_s = ida_frame.find_regvar(pfn, e_ea, reg)
    if (prev_range_s is not None) and (prev_range_s.start_ea <
                                       e_ea) and (prev_range_s.end_ea > e_ea):
        prev_ranges += [(e_ea, prev_range_s.end_ea, prev_range_s.user)]

    debug('Delete range %x : %x - %s' % (s_ea, e_ea, reg))
    #deletion seems to require actual existing range - so we'll change the name to orig, and then delete it
    idc.MakeLocal(s_ea, e_ea, reg, reg)
    idc.Refresh()
    ida_frame.del_regvar(pfn, s_ea, e_ea, reg)
    idc.Refresh()

    #restore ranges
    for s_ea, e_ea, reg_new_name in prev_ranges:
        debug('Restore range %x : %x - %s->%s' %
              (s_ea, e_ea, reg, reg_new_name))
        idc.MakeLocal(s_ea, e_ea, reg, reg_new_name)
        idc.Refresh()
def find_load_kernelcache_object(base, ea):
    if ea != ida_idaapi.BADADDR:
        ea_list = list(idautils.XrefsTo(ea))

        if ea_list[0].frm != ida_idaapi.BADADDR:
            func_ea = ida_funcs.get_func(ea_list[0].frm).start_ea
            print("\t[+] _load_kernelcache_object = 0x%x" % (func_ea))
            idc.set_name(func_ea, "_load_kernelcache_object", idc.SN_CHECK)
            return func_ea

        print("\t[-] _load_kernelcache_object = not found")
        return ida_idaapi.BADADDR
    else:
        str_ea = ida_search.find_text(base, 1, 1, "Kernelcache too large",
                                      ida_search.SEARCH_DOWN)

        if str_ea != ida_idaapi.BADADDR:
            for xref in idautils.XrefsTo(str_ea):
                func = idaapi.get_func(xref.frm)
                print("\t[+] _load_kernelcache_object = 0x%x" %
                      (func.start_ea))
                idc.set_name(func.start_ea, "_load_kernelcache_object",
                             idc.SN_CHECK)
                return func.start_ea

    print("\t[-] _load_kernelcache_object = not found")
    return ida_idaapi.BADADDR
Example #13
0
def function(addr):
    ida_func = ida_funcs.get_func(addr)
    if ida_func is None:
        l.warning(f"IDA function does not exist for {hex(addr)}.")
        return None

    func_addr = ida_func.start_ea

    try:
        ida_cfunc = idaapi.decompile(func_addr)
    except Exception:
        ida_cfunc = None

    if not ida_cfunc:
        l.warning(f"IDA function {hex(func_addr)} is not decompilable")
        return Function(func_addr,
                        get_func_size(func_addr),
                        last_change=int(time()))

    func = Function(func_addr,
                    get_func_size(func_addr),
                    last_change=int(time()))
    func_header: FunctionHeader = function_header(ida_cfunc)

    stack_vars = {
        offset: var
        for offset, var in get_func_stack_var_info(ida_func.start_ea).items()
    }
    func.header = func_header
    func.stack_vars = stack_vars

    return func
Example #14
0
def find_target_early_init(base_ea):
    ea_list = ida_search.find_imm(base_ea, ida_search.SEARCH_DOWN, 0x4A41)

    if ea_list[0] != ida_idaapi.BADADDR:
        func_ea = ida_funcs.get_func(ea_list[0]).start_ea
        print("\t[+] _target_early_init = 0x%x" % (func_ea))
        idc.set_name(func_ea, "_target_early_init", idc.SN_CHECK)
        tei_ea = func_ea

        str_ea = ida_search.find_text(tei_ea, 1, 1, "All pre",
                                      ida_search.SEARCH_DOWN)

        if str_ea != ida_idaapi.BADADDR:
            f_ea = idaapi.get_func(str_ea).start_ea

            if tei_ea != f_ea:
                print("\t[-] _platform_not_supported = not found")
                return tei_ea

            bl_ea = str_ea + 8
            dst = idc.print_operand(bl_ea, 0)
            pns_ea = idc.get_name_ea_simple(dst)
            print("\t[+] _platform_not_supported = 0x%x" % (pns_ea))
            idc.set_name(pns_ea, "_platform_not_supported", idc.SN_CHECK)
            return tei_ea

    print("\t[-] _target_early_init = not found")
    return ida_idaapi.BADADDR
Example #15
0
def set_repeated_comment(address, repeated_comment):
    assert type(repeated_comment) == str
    if is_function_start(address):
        pfn = ida_funcs.get_func(address)
        ida_funcs.set_func_cmt(pfn, repeated_comment, 1)
    else:
        ida_bytes.set_cmt(address, repeated_comment, 1)
Example #16
0
    def change_user_color(self, name, old_color, new_color):
        """Notifies the painter that an user has changed color."""
        # Replace the color for the given user
        self._users_positions[name]["color"] = new_color

        # Replace the color in painted instructions for the given user
        user_address = self._users_positions[name]["address"]
        for n, e in enumerate(self._painted_instructions[user_address]):
            if e == old_color:
                self._painted_instructions[user_address][n] = new_color
        # If the color is the current color instruction (not in the stack yet),
        # repaint the given instruction with the new color
        if new_color not in self._painted_instructions[user_address]:
            self._set_paint_instruction(user_address, new_color)

        # Replace the color in painted functions for the given user
        func = ida_funcs.get_func(user_address)
        if func:
            for n, e in enumerate(self._painted_functions[func.start_ea]):
                if e == old_color:
                    self._painted_functions[func.start_ea][n] = new_color

            # If the color is the current color function (not in the stack
            # yet, repaint the given function with the new color
            if new_color not in self._painted_functions[user_address]:
                self._set_paint_function(func, new_color)
        def init_contexts():
            logger.debug("Iterating contexts for call level: %d", depth)

            if not depth:
                yield init_context
                return

            func = utils.Function(ea)
            yielded = False
            for call_ea in func.calls_to:
                if call_ea in func:
                    logger.warning(
                        "Ignoring recursive function call at 0x%08X", call_ea)
                    continue
                if not ida_funcs.get_func(call_ea):
                    logger.warning(
                        "Ignoring call at 0x%08X. Not in a function", call_ea)
                    continue
                for context in self.iter_context_at(call_ea,
                                                    depth=depth - 1,
                                                    exhaustive=exhaustive,
                                                    follow_loops=follow_loops,
                                                    init_context=init_context,
                                                    _first_call=False):
                    if issubclass(self._context_class, x86_64ProcessorContext):
                        # increase the sp to account for the return address that gets pushed
                        # onto the stack so that we are aligned correctly.
                        context.sp -= context.byteness

                    # yield a context containing the caller executed first.
                    yield context
                    yielded = True
            # If we didn't yield, then we hit a function that has no callers or valid contexts.
            if not yielded:
                yield init_context
Example #18
0
 def __init__(self, callsite, call):
     self.callsite = callsite
     self.func_name = call
     self.ctx = ida_funcs.get_func(self.callsite).startEA
     self.target = None
     self.ret = None  # this is a NSObject
     self.success = False
Example #19
0
def is_func_ptr(offset: int) -> bool:
    """Returns true if the given offset is a function pointer."""
    # As a first check, simply see if the offset is the start of a function.
    func = ida_funcs.get_func(offset)
    if func and func.start_ea == offset:
        return True

    # Sometimes we will get a really strange issue where the IDA disassember has set a type for an
    # address that should not have been set during our course of emulation.
    # Therefore, before attempting to use get_function_data() to test if it's a function pointer,
    # first see if guess_type() will return None while is_loaded() is true.
    # If it doesn't, we know that it shouldn't be a function pointer.
    # (plus it saves on time)
    # TODO: Determine if we could have false negatives.
    #   - this caused a false negatives, so I added the check if offset is the start of a function.
    try:
        if idc.is_loaded(offset) and not idc.guess_type(offset):
            return False
    except TypeError:
        return False
    try:
        get_function_data(offset)
        return True
    except RuntimeError:
        return False
    except Exception as e:
        # If we get any other type of exception raise a more friendly error message.
        raise FunctionTracingError(
            "Failed to retrieve function data from {!r}: {}".format(offset, e))
    def __get_xref_sigs(self, addr: int, is_func: bool) -> Iterator[str]:
        """
        Create a signature from a function address
        XRef sigs are preferred, however if none are available the func itself will be used
        :param addr: Function address
        :param is_func: Indicates that this address is a func, and can be signatured directly
        :return: A series of Dalamud compatible signatures
        """
        xref_addrs = [xref.frm for xref in idautils.XrefsTo(addr)]

        if is_func and not ida_funcs.get_func(addr):
            Log.warn(
                f'Address at {addr:X} is identified as a func, but is not in IDA, attempting to make a subroutine'
            )
            ida_funcs.add_func(addr)

        # This should prune xrefs in places like .pdata by only keeping xrefs in a function
        xref_addrs = list(filter(ida_funcs.get_func_name, xref_addrs))

        # Grab the first N xrefs
        xref_addrs = xref_addrs[:self.XREFS_TO_SEARCH]

        if is_func:
            # Try to sig the func itself as well
            xref_addrs.insert(0, addr)

        for xref_addr in xref_addrs:
            yield from SigGen(xref_addr)
Example #21
0
    def render_img(self, buffers, addr, mouse_offs):
        colors = []
        head = ida_idaapi.BADADDR
        tail = ida_idaapi.BADADDR
        goffs = 0

        for mapped, buf in buffers:
            if mapped:
                if mouse_offs is not None:
                    if self.switch == 0:  # data
                        head = get_item_head(addr + mouse_offs)
                        tail = get_item_end(addr + mouse_offs)
                    else:  # code
                        f = get_func(addr + mouse_offs)
                        if f:
                            head = f.startEA
                            tail = f.endEA

                for pos in xrange(len(buf)):
                    c = ord(buf[pos]) & 0xFF

                    highlight = False
                    if mouse_offs is not None:

                        if addr + pos + goffs >= head and addr + pos + goffs < tail:
                            highlight = True
                    if highlight:
                        colors.append((True, qRgb(c, 0xFF, self.hl_color)))
                    else:
                        colors.append((True, qRgb(c, 0, 0)))
            else:
                for pos in xrange(len(buf)):
                    colors.append((False, 0))
            goffs += len(buf)
        return colors
def infer_function_type(ea: int, callee_type: FUNCTION_TYPE) -> FUNCTION_TYPE:

    func = ida_funcs.get_func(ea)
    if func == None:
        return FUNCTION_TYPE.OTHER
    func_size = func.end_ea - func.start_ea
    # function larger than 0x30 bytes is type other
    if func_size > 0x30:
        return FUNCTION_TYPE.OTHER
    try:
        code = str(idaapi.decompile(ea))
    except:
        print(f"decompile failed for func {hex(ea)}")
        return FUNCTION_TYPE.OTHER
    code_lines = code.split("\n")
    # function more than five lines is type other
    if len(code_lines) > 5:
        return FUNCTION_TYPE.OTHER
    # nullsub function only have a single ';'
    if code_lines[2] == "  ;":
        return FUNCTION_TYPE.NULLSUB
    # if there is only a return subXXX() statement, then it's type depends on its callee
    if code_lines[2].find("return") > 0 and callee_type != FUNCTION_TYPE.OTHER:
        return callee_type
    # if there is only a return a1 statement, then it's type is identity
    if code_lines[2].find("return a1;") > 0:
        return FUNCTION_TYPE.IDENTITY
    # if there is only a return *a1 statement, then it's type is getvalue
    # todo: dealing with more getvalue type rather than QWORD
    if code_lines[2].find("return *(_QWORD *)a1;") > 0:
        return FUNCTION_TYPE.GETVALUE

    return FUNCTION_TYPE.OTHER
Example #23
0
def acquire_pseudocode_vdui(addr):
    """
    Acquires a IDA HexRays vdui pointer, which is a pointer to a pseudocode view that contains
    the cfunc which describes the code on the screen. Using this function optimizes the switching of code views
    by using in-place switching if a view is already present.

    @param addr:
    @return:
    """
    func = ida_funcs.get_func(addr)
    if not func:
        return None

    names = ["Pseudocode-%c" % chr(ord("A") + i) for i in range(5)]
    for name in names:
        widget = ida_kernwin.find_widget(name)
        if not widget:
            continue

        vu = ida_hexrays.get_widget_vdui(widget)
        break
    else:
        vu = ida_hexrays.open_pseudocode(func.start_ea, False)

    if func.start_ea != vu.cfunc.entry_ea:
        target_cfunc = idaapi.decompile(func.start_ea)
        vu.switch_to(target_cfunc, False)

    return vu
Example #24
0
    def _read_taint_info(self):
        semantic_labels = self._read_semantic_labels()
        input_file = open(self._taint_file, "r")
        reader = csv.reader(input_file)
        self._ea_to_labels.clear()
        self._tainted_funcs.clear()
        self._skip_csv_header(reader, False)
        for row in reader:
            pid = int(row[1])
            pc = int(row[2], 16)
            label = int(row[3])

            try:
                label = semantic_labels[label]
            except KeyError:
                pass

            if pid != self._tainted_process['process_id']:
                continue
            fn = ida_funcs.get_func(pc)
            if not fn:
                continue
            fn_start = fn.start_ea
            self._tainted_funcs.add(fn_start)
            if pc not in self._ea_to_labels:
                self._ea_to_labels[pc] = set()
            self._ea_to_labels[pc].add(label)
        input_file.close()
Example #25
0
def main():
    # Get current ea
    ea = ida_kernwin.get_screen_ea()

    # Get segment class
    seg = ida_segment.getseg(ea)

    # Loop from segment start to end
    func_ea = seg.start_ea

    # Get a function at the start of the segment (if any)
    func = ida_funcs.get_func(func_ea)
    if func is None:
        # No function there, try to get the next one
        func = ida_funcs.get_next_func(func_ea)

    seg_end = seg.end_ea
    while func is not None and func.start_ea < seg_end:
        funcea = func.start_ea
        print("Function %s at 0x%x" %
              (ida_funcs.get_func_name(funcea), funcea))

        ref = ida_xref.get_first_cref_to(funcea)

        while ref != ida_idaapi.BADADDR:
            print("  called from %s(0x%x)" %
                  (ida_funcs.get_func_name(ref), ref))
            ref = ida_xref.get_next_cref_to(funcea, ref)

        func = ida_funcs.get_next_func(funcea)
Example #26
0
 def activate(self, ctx):
     cur_ea = ida_kernwin.get_screen_ea()
     pfn = ida_funcs.get_func(cur_ea)
     if pfn:
         v = ida_kernwin.get_current_viewer()
         result = ida_kernwin.get_highlight(v)
         if result:
             stkvar_name, _ = result
             frame = ida_frame.get_frame(cur_ea)
             sptr = ida_struct.get_struc(frame.id)
             mptr = ida_struct.get_member_by_name(sptr, stkvar_name)
             if mptr:
                 fii = ida_funcs.func_item_iterator_t()
                 ok = fii.set(pfn)
                 while ok:
                     ea = fii.current()
                     F = ida_bytes.get_flags(ea)
                     for n in range(ida_ida.UA_MAXOP):
                         if not ida_bytes.is_stkvar(F, n):
                             continue
                         insn = ida_ua.insn_t()
                         if not ida_ua.decode_insn(insn, ea):
                             continue
                         v = ida_frame.calc_stkvar_struc_offset(
                             pfn, insn, n)
                         if v >= mptr.soff and v < mptr.eoff:
                             print("Found xref at 0x%08x, operand #%d" %
                                   (ea, n))
                     ok = fii.next_code()
             else:
                 print("No stack variable named \"%s\"" % stkvar_name)
     else:
         print("Please position the cursor within a function")
Example #27
0
    def _hxe_callback(self, event, *_):
        if not self._installed:
            return 0

        if event == ida_hexrays.hxe_func_printed:
            ea = ida_kernwin.get_screen_ea()
            func = ida_funcs.get_func(ea)
            if func is None:
                return

            if self._func_ea != func.start_ea:
                self._func_ea = func.start_ea
                self._labels = HexRaysHooks._get_user_labels(self._func_ea)
                self._cmts = HexRaysHooks._get_user_cmts(self._func_ea)
                self._iflags = HexRaysHooks._get_user_iflags(self._func_ea)
                self._lvar_settings = HexRaysHooks._get_user_lvar_settings(
                    self._func_ea
                )
                self._numforms = HexRaysHooks._get_user_numforms(self._func_ea)
            self._send_user_labels(func.start_ea)
            self._send_user_cmts(func.start_ea)
            self._send_user_iflags(func.start_ea)
            self._send_user_lvar_settings(func.start_ea)
            self._send_user_numforms(func.start_ea)
        return 0
Example #28
0
                def _recurse(self, ea, path, depth):
                    if depth + 1 >= self.mr:
                        self.paths[path] = [("[...]", BADADDR)]
                        return

                    # for all callers of ea...
                    i = 0
                    for ref in idautils.CodeRefsTo(ea, False):
                        if i + 1 >= self.mf:
                            self.paths[path].append(("...", BADADDR))
                            break
                        cea = ref
                        func = ida_funcs.get_func(cea)
                        if func:
                            cea = func.start_ea
                        loc_name = ida_name.get_short_name(cea)
                        if not len(loc_name):
                            loc_name = "unkn_%x" % cea
                        elem = (loc_name, cea)
                        # if path doesn't exist yet
                        if path not in self.paths:
                            self.paths[path] = [elem]
                        # if caller doesn't exist yet
                        if elem not in self.paths[path]:
                            self.paths[path].append(elem)
                            i += 1

                        newpath = "%s/%s" % (path, loc_name)
                        self._recurse(cea, newpath, depth + 1)
                    return
Example #29
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()
def get_dispatcher(handler):
    """Retrieves the dispatcher of the TL/DR API calls

    :param handler: Handler of the TL/DR API calls
    :type handler: int
    :return: Dispatcher for the TL/DR API calls
    :rtype: int
    """

    func = ida_funcs.get_func(handler)
    insn = ida_ua.insn_t()
    ea = 0
    branch_addr = -1

    ea = func.start_ea

    while ea < func.end_ea:
        insn = ida_ua.insn_t()
        insn_len = max(1, ida_ua.decode_insn(insn, ea))
        if insn.itype == ida_allins.ARM_bl and \
                insn.ops[0].type == ida_ua.o_near:
            branch_addr = insn.ops[0].addr
            break
        ea += insn_len

    return branch_addr
Example #31
0
 def __init__(self, caller, sp):
     self.caller = caller
     self.sp     = sp
     f = ida_funcs.get_func(caller)
     self.displ = "%08x: " % caller
     if f:
         self.displ += ida_funcs.get_func_name(caller)
         t = caller - f.start_ea
         if t > 0: self.displ += "+" + hex(t)
     else:
         self.displ += hex(caller)
     self.displ += " [" + hex(sp) + "]"
Example #32
0
def Chunks(start):
    """
    Get a list of function chunks

    @param start: address of the function

    @return: list of funcion chunks (tuples of the form (start_ea, end_ea))
             belonging to the function
    """
    func_iter = ida_funcs.func_tail_iterator_t( ida_funcs.get_func( start ) )
    status = func_iter.main()
    while status:
        chunk = func_iter.chunk()
        yield (chunk.start_ea, chunk.end_ea)
        status = next(func_iter)
Example #33
0
def FuncItems(start):
    """
    Get a list of function items

    @param start: address of the function

    @return: ea of each item in the function
    """
    func = ida_funcs.get_func(start)
    if not func:
        return
    fii = ida_funcs.func_item_iterator_t()
    ok = fii.set(func)
    while ok:
        yield fii.current()
        ok = fii.next_code()
Example #34
0
def decompile(ea, hf=None):
    if isinstance(ea, (int, long)):
        func = ida_funcs.get_func(ea)
        if not func: return
    elif type(ea) == ida_funcs.func_t:
        func = ea
    else:
        raise RuntimeError('arg 1 of decompile expects either ea_t or cfunc_t argument')

    if hf is None:
        hf = hexrays_failure_t()

    ptr = _decompile(func, hf)

    if ptr.__deref__() is None:
        raise DecompilationFailure(hf)

    return ptr
Example #35
0
def function_graph_ir():
    # Get settings
    settings = GraphIRForm()
    ret = settings.Execute()
    if not ret:
        return

    func = ida_funcs.get_func(idc.ScreenEA())
    func_addr = func.startEA

    build_graph(
        func_addr,
        settings.cScope.value,
        simplify=settings.cOptions.value & OPTION_GRAPH_CODESIMPLIFY,
        dontmodstack=settings.cOptions.value & OPTION_GRAPH_DONTMODSTACK,
        loadint=settings.cOptions.value & OPTION_GRAPH_LOADMEMINT,
        verbose=False
    )
    return
Example #36
0
def find_import_ref(dllname):
    imports = find_imported_funcs(dllname)
    R = dict()
    for i, (ea, name,_) in enumerate(imports):
        #print "%x -> %s" % (ea, name)
        for xref in idautils.XrefsTo(ea):
            # check if referrer is a thunk
            ea = xref.frm
            f = ida_funcs.get_func(ea)
            if f and (f.flags & ida_funcs.FUNC_THUNK) != 0:
                imports.append([f.start_ea, ida_funcs.get_func_name(f.start_ea), 0])
                #print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.start_ea)
                continue

            # save results
            if i not in R:
                R[i] = []

            R[i].append(ea)

    return (imports, R)
Example #37
0
    def __init__(self, ira):

        self.ira = ira

        default_types_info = r"""ExprId("RDX", 64): char *"""
        archs = ["AMD64_unk", "X86_32_unk", "msp430_unk"]

        func = ida_funcs.get_func(idc.ScreenEA())
        func_addr = func.startEA

        start_addr = idc.SelStart()
        if start_addr == idc.BADADDR:
            start_addr = idc.ScreenEA()
        end_addr = idc.SelEnd()

        ida_kernwin.Form.__init__(self,
                      r"""BUTTON YES* Launch
BUTTON CANCEL NONE
Type Propagation Settings

{FormChangeCb}
Analysis scope:
<Whole function:{rFunction}>
<From an address to the end of function:{rAddr}>
<Between two addresses:{r2Addr}>{cScope}>

<Target function:{functionAddr}>
<Start address  :{startAddr}>
<End address    :{endAddr}>

<Architecture/compilator :{arch}>

<##Header file          :{headerFile}>
<Use a file for type informations:{rTypeFile}>{cTypeFile}>
<##Types informations   :{typeFile}>
<Types informations     :{strTypesInfo}>

<Unalias stack:{rUnaliasStack}>{cUnalias}>
""", {
                          'FormChangeCb': ida_kernwin.Form.FormChangeCb(self.OnFormChange),
                          'cScope': ida_kernwin.Form.RadGroupControl(
                              ("rFunction", "rAddr", "r2Addr")),
                          'functionAddr': ida_kernwin.Form.NumericInput(
                              tp=ida_kernwin.Form.FT_RAWHEX,
                              value=func_addr),
                          'startAddr': ida_kernwin.Form.NumericInput(
                              tp=ida_kernwin.Form.FT_RAWHEX,
                              value=start_addr),
                          'endAddr': ida_kernwin.Form.NumericInput(
                              tp=ida_kernwin.Form.FT_RAWHEX,
                              value=end_addr),
                          'arch': ida_kernwin.Form.DropdownListControl(
                              items=archs,
                              readonly=False,
                              selval=archs[0]),
                          'headerFile': ida_kernwin.Form.FileInput(swidth=20, open=True),
                          'cTypeFile': ida_kernwin.Form.ChkGroupControl(("rTypeFile",)),
                          'typeFile': ida_kernwin.Form.FileInput(swidth=20, open=True),
                          'strTypesInfo': ida_kernwin.Form.MultiLineTextControl(text=default_types_info,
                                                                    flags=ida_kernwin.Form.MultiLineTextControl.TXTF_FIXEDFONT),
                          'cUnalias': ida_kernwin.Form.ChkGroupControl(("rUnaliasStack",)),
                      })
        form, args = self.Compile()
        form.rUnaliasStack.checked = True
        form.rTypeFile.checked = True
Example #38
0
def CallStackWalk(nn):
    class Result:
        """
        Class holding the result of one call stack item
        Each call stack item instance has the following attributes:
            caller = ea of caller
            displ  = display string
            sp     = stack pointer
        """
        def __init__(self, caller, sp):
            self.caller = caller
            self.sp     = sp
            f = ida_funcs.get_func(caller)
            self.displ = "%08x: " % caller
            if f:
                self.displ += ida_funcs.get_func_name(caller)
                t = caller - f.start_ea
                if t > 0: self.displ += "+" + hex(t)
            else:
                self.displ += hex(caller)
            self.displ += " [" + hex(sp) + "]"

        def __str__(self):
            return self.displ

    # get stack pointer
    sp = idautils.cpu.Esp
    seg = ida_segment.getseg(sp)
    if not seg:
        return (False, "Could not locate stack segment!")

    stack_seg = Seg(seg)
    word_size = 2 ** (seg.bitness + 1)
    callers = []
    sp = idautils.cpu.Esp - word_size
    while sp < stack_seg.end_ea:
        sp += word_size
        ptr = next(idautils.GetDataList(sp, 1, word_size))
        seg = ida_segment.getseg(ptr)
        # only accept executable segments
        if (not seg) or ((seg.perm & ida_segment.SEGPERM_EXEC) == 0):
            continue
        # try to find caller
        caller = IsPrevInsnCall(ptr)
        # we have no recognized caller, skip!
        if caller is None:
            continue

        # do we have a debug name that is near?
        if nn:
            ret = nn.find(caller)
            if ret:
                ea = ret[0]
                # function exists?
                f = ida_funcs.get_func(ea)
                if not f:
                    # create function
                    ida_funcs.add_func(ea)

        # get the flags
        f = ida_bytes.get_flags(caller)
        # no code there?
        if not ida_bytes.is_code(f):
            ida_ua.create_insn(caller)

        callers.append(Result(caller, sp))
    #
    return (True, callers)
Example #39
0
def launch_depgraph():
    global graphs, comments, sol_nb, settings, addr, ir_arch, ircfg
    # Get the current function
    addr = idc.ScreenEA()
    func = ida_funcs.get_func(addr)

    # Init
    machine = guess_machine(addr=func.startEA)
    mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira

    bs = bin_stream_ida()
    mdis = dis_engine(bs, dont_dis_nulstart_bloc=True)
    ir_arch = ira(mdis.loc_db)

    # Populate symbols with ida names
    for ad, name in idautils.Names():
        if name is None:
            continue
        mdis.loc_db.add_location(name, ad)

    asmcfg = mdis.dis_multiblock(func.startEA)

    # Generate IR
    ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

    # Get settings
    settings = depGraphSettingsForm(ir_arch, ircfg)
    settings.Execute()

    loc_key, elements, line_nb = settings.loc_key, settings.elements, settings.line_nb
    # Simplify affectations
    for irb in ircfg.blocks.values():
        irs = []
        offset = ir_arch.loc_db.get_location_offset(irb.loc_key)
        fix_stack = offset is not None and settings.unalias_stack
        for assignblk in irb:
            if fix_stack:
                stk_high = m2_expr.ExprInt(idc.GetSpd(assignblk.instr.offset), ir_arch.sp.size)
                fix_dct = {ir_arch.sp: mn.regs.regs_init[ir_arch.sp] + stk_high}

            new_assignblk = {}
            for dst, src in assignblk.iteritems():
                if fix_stack:
                    src = src.replace_expr(fix_dct)
                    if dst != ir_arch.sp:
                        dst = dst.replace_expr(fix_dct)
                dst, src = expr_simp(dst), expr_simp(src)
                new_assignblk[dst] = src
            irs.append(AssignBlock(new_assignblk, instr=assignblk.instr))
        ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs)

    # Get dependency graphs
    dg = settings.depgraph
    graphs = dg.get(loc_key, elements, line_nb,
                    set([ir_arch.loc_db.get_offset_location(func.startEA)]))

    # Display the result
    comments = {}
    sol_nb = 0

    # Register and launch
    ida_kernwin.add_hotkey("Shift-N", next_element)
    treat_element()