Beispiel #1
0
def _get_function_bounds(func, seg_ref):
    """Get the bounds of the function containing `ea`. We want to discover jump
  table targets that are missed by IDA, and it's possible that they aren't
  marked as being part of the current function, and perhaps are after the
  assumed range of the current function. Ideally they will fall before the
  beginning of the next function, though.

  We need to be pretty careful with the case that one function tail-calls
  another. IDA will sometimes treat the end of the tail-called function
  (e.g. a thunk) as if it is the end of the caller. For this reason, we start
  with loose bounds using the prev/next functions, then try to narrow with
  the bounds of the function containing `ea`.

  NOTE(pag): This does not handle function chunks.
  """
    ea = func.start_ea
    seg = _find_segment_containing_ea(ea, seg_ref)
    if not seg:
        return ea, ea

    seg_start, seg_end = seg.start_ea, seg.end_ea
    min_ea = seg_start
    max_ea = seg_end

    if not _is_executable_seg(seg):
        return ea, ea

    # Get an upper bound using the next function.
    has_upper = False
    next_func = ida_funcs.get_next_func(ea)
    if next_func:
        next_func_seg = _find_segment_containing_ea(next_func.start_ea,
                                                    seg_ref)
        if next_func_seg and _is_executable_seg(next_func_seg):
            max_ea = min(next_func.start_ea, max_ea)
            has_upper = True

    # Get a lower bound using the previous function.
    has_lower = False
    prev_func = ida_funcs.get_prev_func(ea)
    if prev_func:
        prev_func_seg = _find_segment_containing_ea(prev_func.start_ea,
                                                    seg_ref)
        if prev_func_seg and _is_executable_seg(prev_func_seg):
            min_ea = max(prev_func.end_ea, min_ea)
            has_lower = True

    # Try to tighten the bounds using the function containing `ea`.
    if not has_lower:
        min_ea = max(min_ea, func.start_ea)

    if not has_upper:
        max_ea = min(max_ea, func.end_ea)

    return min_ea, max_ea
Beispiel #2
0
def ProgramAddrRange() :
    return ida_funcs.get_prev_func(ida_idaapi.BADADDR) - ida_funcs.get_next_func(0)
def reanalyze_range_begin(ea):
    return ida_funcs.get_prev_func(ea).end_ea + 1
    "ja", "jb", "jbe", "jg", "jge", "jl", "jle", "jmp", "jnb", "jno", "jnp",
    "jns", "jnz", "jo", "jp", "js", "jz"
]
jump_pairs = [("ja", "jbe"), ("jb", "jnb"), ("jg", "jle"), ("jl", "jge"),
              ("jo", "jno"), ("jp", "jnp"), ("js", "jns"), ("jz", "jnz")]
movs = ["mov", "xchg"]

ida_api_is_new = False
try:
    import ida_auto
    ida_api_is_new = True
except ImportError:
    pass

user_pos = ida_kernwin.get_screen_ea()
after_function_before_user_pos = ida_funcs.get_prev_func(user_pos).end_ea + 1
before_function_after_user_pos = ida_funcs.get_next_func(user_pos).start_ea - 1
hopefully_a_sane_start_of_function = (after_function_before_user_pos
                                      & ~0x0F) + 0x10
make_fun_pos = None
if ida_bytes.is_code(ida_bytes.get_flags(hopefully_a_sane_start_of_function)):
    make_fun_pos = hopefully_a_sane_start_of_function


def re_analyze_relevant_range():
    ida_bytes.del_items(
        after_function_before_user_pos, 0,
        before_function_after_user_pos - after_function_before_user_pos)
    if not make_fun_pos is None:
        assume_code_at(make_fun_pos)
    else:
Beispiel #5
0
    def get_function_impl(self, address):
        """Given an address, return a `Function` instance or
        raise an `InvalidFunctionException` exception."""
        arch = self._arch
        os = self._os

        pfn = ida_funcs.get_func(address)
        if not pfn:
            pfn = ida_funcs.get_prev_func(address)

        seg_ref = [None]
        seg = find_segment_containing_ea(address, seg_ref)

        # Check this function.
        if not pfn or not seg:
            raise InvalidFunctionException(
                "No function defined at or containing address {:x}".format(address)
            )

        elif (
            not ida_funcs.func_contains(pfn, address)
            and not _is_extern_seg(seg)
            and not is_imported_table_seg(seg)
        ):
            raise InvalidFunctionException(
                "No function defined at or containing address {:x}".format(address)
            )

        # Reset to the start of the function, and get the type of the function.
        address = pfn.start_ea

        tif = ida_typeinf.tinfo_t()
        if not ida_nalt.get_tinfo(tif, address):
            if ida_typeinf.GUESS_FUNC_OK != ida_typeinf.guess_tinfo(tif, address):
                raise InvalidFunctionException(
                    "Can't guess type information for function at address {:x}".format(
                        address
                    )
                )

        if not tif.is_func():
            raise InvalidFunctionException(
                "Type information at address {:x} is not a function: {}".format(
                    address, tif.dstr()
                )
            )

        ftd = ida_typeinf.func_type_data_t()
        if not tif.get_func_details(ftd):
            raise InvalidFunctionException(
                "Could not get function details for function at address {:x}".format(
                    address
                )
            )

        # Make sure we can handle the basic signature of the function. This might
        # not be the final signature that we go with, but it's a good way to make
        # sure we can handle the relevant types.
        try:
            func_type = _get_type(tif, TYPE_CONTEXT_FUNCTION)
        except UnhandledTypeException as e:
            raise InvalidFunctionException(
                "Could not assign type to function at address {:x}: {}".format(
                    address, str(e)
                )
            )

        # Get the calling convention. The CC might override `is_variadic`, e.g. how
        # old style C functions declared as `foo()` actually imply `foo(...)`.
        cc, is_variadic = _get_calling_convention(arch, os, ftd)
        if is_variadic:
            func_type.set_is_variadic()

        # Go look into each of the parameters and their types. Each parameter may
        # refer to multiple locations, so we want to split each of those locations
        # into unique
        i = 0
        max_i = ftd.size()
        param_list = []
        while i < max_i:
            funcarg = ftd[i]
            i += 1

            arg_type = _get_type(funcarg.type, TYPE_CONTEXT_PARAMETER)
            arg_type_str = arg_type.serialize(arch, {})

            j = len(param_list)
            _expand_locations(arch, pfn, arg_type, funcarg.argloc, param_list)

            # If we have a parameter name, then give a name to each of the expanded
            # locations associated with this parameter.
            if funcarg.name:
                if (j + 1) == len(param_list):
                    param_list[-1].set_name(funcarg.name)
                else:
                    k = j
                    while k < len(param_list):
                        param_list[-1].set_name("{}_{}".format(funcarg.name, k - j))
                        k += 1

        # Build up the list of return values.
        ret_list = []
        ret_type = _get_type(ftd.rettype, TYPE_CONTEXT_RETURN)
        if not isinstance(ret_type, VoidType):
            _expand_locations(arch, pfn, ret_type, ftd.retloc, ret_list)

        func = IDAFunction(
            arch, address, param_list, ret_list, pfn, ftd.is_noret(), func_type, cc
        )
        self.add_symbol(address, _function_name(address))
        return func
Beispiel #6
0
    def get_function(self, address):
        """Given an address, return a `Function` instance or
    raise an `InvalidFunctionException` exception."""
        arch = self._arch

        pfn = ida_funcs.get_func(address)
        if not pfn:
            pfn = ida_funcs.get_prev_func(address)

        # Check this function.
        if not pfn or not ida_funcs.func_contains(pfn, address):
            raise InvalidFunctionException(
                "No function defined at or containing address {:x}".format(
                    address))

        # Reset to the start of the function, and get the type of the function.
        address = pfn.start_ea
        if address in self._functions:
            return self._functions[address]

        tif = ida_typeinf.tinfo_t()
        if not ida_nalt.get_tinfo(tif, address):
            ida_typeinf.guess_tinfo(tif, address)

        if not tif.is_func():
            raise InvalidFunctionException(
                "Type information at address {:x} is not a function: {}".
                format(address, tif.dstr()))

        ftd = ida_typeinf.func_type_data_t()
        if not tif.get_func_details(ftd):
            raise InvalidFunctionException(
                "Could not get function details for function at address {:x}".
                format(address))

        # Make sure we can handle the basic signature of the function. This might
        # not be the final signature that we go with, but it's a good way to make
        # sure we can handle the relevant types.
        try:
            func_type = get_type(tif)
        except UnhandledTypeException as e:
            raise InvalidFunctionException(
                "Could not assign type to function at address {:x}: {}".format(
                    address, str(e)))

        # Go look into each of the parameters and their types. Each parameter may
        # refer to multiple locations, so we want to split each of those locations
        # into unique
        i = 0
        max_i = ftd.size()
        param_list = []
        while i < max_i:
            funcarg = ftd[i]
            i += 1

            arg_type = get_type(funcarg.type)
            arg_type_str = arg_type.serialize(arch, {})

            j = len(param_list)
            _expand_locations(arch, pfn, arg_type, funcarg.argloc, param_list)

            # If we have a parameter name, then give a name to each of the expanded
            # locations associated with this parameter.
            if funcarg.name:
                if (j + 1) == len(param_list):
                    param_list[-1].set_name(funcarg.name)
                else:
                    k = j
                    while k < len(param_list):
                        param_list[-1].set_name("{}_{}".format(
                            funcarg.name, k - j))
                        k += 1

        # Build up the list of return values.
        ret_list = []
        ret_type = get_type(ftd.rettype)
        if not isinstance(ret_type, VoidType):
            _expand_locations(arch, pfn, ret_type, ftd.retloc, ret_list)

        func = IDAFunction(arch, address, param_list, ret_list, pfn)
        self._functions[address] = func
        return func