Example #1
0
def _collect_xrefs_from_func(pfn, ea, out_ref_eas):
    """Collect cross-references at `ea` in `pfn` that target code/data
  outside of `pfn`. Save them into `out_ref_eas`."""
    for ref_ea in _xref_generator(ea, ida_xref.get_first_cref_from, \
                                  ida_xref.get_next_cref_from):
        if not ida_funcs.func_contains(pfn, ref_ea):
            out_ref_eas.add(ref_ea)

    for ref_ea in _xref_generator(ea, ida_xref.get_first_dref_from, \
                                  ida_xref.get_next_dref_from):
        if not ida_funcs.func_contains(pfn, ref_ea):
            out_ref_eas.add(ref_ea)
Example #2
0
 def data(self, index, role=Qt.DisplayRole):
     # Check if disabled by the user
     cursors = self._plugin.config["cursors"]
     if role == Qt.BackgroundRole and cursors["funcs"]:
         func_ea = int(index.sibling(index.row(), 2).data(), 16)
         func = ida_funcs.get_func(func_ea)
         for user in self._plugin.core.get_users().values():
             if ida_funcs.func_contains(func, user["ea"]):
                 r, g, b = StatusWidget.ida_to_python(user["color"])
                 return QColor(StatusWidget.python_to_qt(r, g, b))
     index = self._model.index(index.row(), index.column())
     return self._model.data(index, role)
Example #3
0
    def refresh_pseudocode_view(ea):
        """Refreshes the pseudocode view in IDA."""
        names = ["Pseudocode-%c" % chr(ord("A") + i) for i in range(5)]
        for name in names:
            widget = ida_kernwin.find_widget(name)
            if widget:
                vu = ida_hexrays.get_widget_vdui(widget)

                # Check if the address is in the same function
                func_ea = vu.cfunc.entry_ea
                func = ida_funcs.get_func(func_ea)
                if ida_funcs.func_contains(func, ea):
                    vu.refresh_view(True)
Example #4
0
def _collect_xrefs_from_func(pfn, ea, out_ref_eas, seg_ref):
    """Collect cross-references at `ea` in `pfn` that target code/data
  outside of `pfn`. Save them into `out_ref_eas`."""
    global _OPERANDS_NUMS

    # TODO(pag): Decode instruction at `ea`, iterate over operands, and try
    #            to build up operand-specific refs, using a mechanism similar
    #            to McSema's `get_instruction_references`. Might want to pass
    #            in a boolean argument to tell us if IDA thinks this is an
    #            instruction head.
    for ref_ea in _xref_generator(ea, seg_ref):
        if not ida_funcs.func_contains(pfn, ref_ea):
            out_ref_eas.add(ref_ea)
            _add_real_xref(ea, ref_ea, out_ref_eas)
Example #5
0
    def _set_tooltip(self, obj, ev):
        cursors = self._plugin.config["cursors"]
        if not cursors["funcs"]:
            return

        obj.setToolTip("")
        index = obj.parent().indexAt(ev.pos())
        func_ea = int(index.sibling(index.row(), 2).data(), 16)
        func = ida_funcs.get_func(func_ea)

        # Find the corresponding username
        for name, user in self._plugin.core.get_users().items():
            if ida_funcs.func_contains(func, user["ea"]):
                # Set the tooltip
                obj.setToolTip(name)
                break
Example #6
0
 def node_contained(node):
     return (ida_funcs.func_contains(func, node.startEA)
             and ida_funcs.func_contains(func, node.endEA - 1))
Example #7
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
Example #8
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