Пример #1
0
def _get_type(ty, context):
    """Type class that gives access to type sizes, printings, etc."""

    if isinstance(ty, Type):
        return ty

    elif isinstance(ty, Function):
        return ty.type()

    elif isinstance(ty, Location):
        return ty.type()

    elif isinstance(ty, ida_typeinf.tinfo_t):
        return _convert_ida_type(ty, {}, 0, context)

    tif = ida_typeinf.tinfo_t()
    try:
        if not ida_nalt.get_tinfo(tif, ty):
            ida_typeinf.guess_tinfo(tif, ty)
    except:
        pass

    if not tif.empty():
        return _convert_ida_type(tif, {}, 0, context)

    if not ty:
        return VoidType()

    raise UnhandledTypeException("Unrecognized type passed to `Type`.", ty)
Пример #2
0
    def __process_function_typeinfo(self, info, func):

        tinfo = ida_typeinf.tinfo_t()
        func_type_data = ida_typeinf.func_type_data_t()
        if ida_pro.IDA_SDK_VERSION >= 740:
            ida_typeinf.guess_tinfo(tinfo,func.start_ea)
        else:
            ida_typeinf.guess_tinfo(func.start_ea,tinfo)
        tinfo.get_func_details(func_type_data)

        #calling convention
        info['calling_convention'] = self.__describe_callingconvention(func_type_data.cc)
        func_type_data.rettype
        
        #return tpye
        info['return_type'] = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, func_type_data.rettype, '', '')

        #arguments
        arguments = list()
        
        for funcarg in func_type_data:
            arginfo = {
                'name'              : funcarg.name,
                'type'              : ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, funcarg.type, '', ''),
                'argument_location' : self.__describe_argloc(funcarg.argloc.atype())
            }
            
            arguments.append(arginfo)

        info['arguments'] = arguments
Пример #3
0
    def get_variable(self, address):
        """Given an address, return a `Variable` instance, or
    raise an `InvalidVariableException` exception."""
        if address in self._variables:
            return self._variables[address]

        arch = self._arch

        seg_ref = [None]
        if not _find_segment_containing_ea(address, seg_ref):
            raise InvalidVariableException(
                "No variable defined at or containing address {:x}".format(
                    address))

        seg = seg_ref[0]

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

        # Try to handle a variable type, otherwise make it big and empty.
        try:
            var_type = get_type(tif)
        except UnhandledTypeException as e:
            # TODO(pag): Make it a big empty array type? (especially if it's in .bss)
            raise InvalidVariableException(
                "Could not assign type to function at address {:x}: {}".format(
                    address, str(e)))

        var = IDAVariable(arch, address, var_type, seg)
        self._variables[address] = var
        return var
Пример #4
0
def processFunctionTypeinfo(function):

    tinfo = ida_typeinf.tinfo_t()
    func_type_data = ida_typeinf.func_type_data_t()
    tinfo.get_named_type
    ida_typeinf.guess_tinfo(function['start_ea'], tinfo)
    tinfo.get_func_details(func_type_data)

    #calling convention
    function['calling_convention'] = describe_callingconvention(
        func_type_data.cc)
    func_type_data.rettype

    #return tpye
    function['return_type'] = ida_typeinf.print_tinfo('', 0, 0,
                                                      ida_typeinf.PRTYPE_1LINE,
                                                      func_type_data.rettype,
                                                      '', '')

    #arguments
    arguments = list()

    for funcarg in func_type_data:
        arginfo = {
            'name':
            funcarg.name,
            'type':
            ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE,
                                    funcarg.type, '', ''),
            'argument_location':
            describe_argloc(funcarg.argloc.atype())
        }

        arguments.append(arginfo)

    function['arguments'] = arguments
Пример #5
0
    def get_at(ea=None):
        """
            Function which will create an object which inherit from
            :class:`BipType` representing the type at the current address.
            This function will **not** set the type at the address given and
            it may not be set if it was guess by ida.

            Internally this function will first try to get the type at the
            address, if no type are defined it will try to guess it. If ida
            is not able to guess it it will return ``None``.

            .. todo:: make something better when no type are set ?

            .. note:: **Implementation**

                Ida allow to guess the type but this "guess" ignore the fact
                that this may have been set. It seems necessary to use
                ida_nalt.get_tinfo for recuperating the type set, it will fail
                if no type has been set. If no type were set the guess_tinfo
                is then used, it will typically fail if the data is undefined,
                in this case None will be return. This may change in the
                future as by default a tinfo_t ``empty`` is true (but not the
                tinfo_t.is_unknown).

            :param ea: The address at which to get the type. If ``None``
                the screen address will be used.
            :return: An object which inherit from :class:`BipType`
                representing the type at the address given in argument.
                ``None`` will be return if no type is define and ida was not
                able to guess it .
        """
        if ea is None:
            ea = ida_kernwin.get_screen_ea()
        tif = tinfo_t()
        # try to get the define type
        # this seems to be define in ida_nalt...
        if ida_nalt.get_tinfo(tif, ea):
            # no need to make a copy in this case
            return BipType.from_tinfo_no_copy(tif)

        # no type define, try to guess it
        # don't know when GUESS_FUNC_TRIVIAL is return so consider failure
        if guess_tinfo(tif, ea) == GUESS_FUNC_OK:
            return BipType.from_tinfo_no_copy(tif)

        # not able to guess, this should be a tinfo_t empty ? (tif.empty() ?)
        return None
Пример #6
0
    def get_variable(self, address):
        """Given an address, return a `Variable` instance, or
    raise an `InvalidVariableException` exception."""
        if address in self._variables:
            return self._variables[address]

        arch = self._arch

        seg_ref = [None]
        address, backup_var_type = _invent_var_type(address, seg_ref)
        if not backup_var_type:
            raise InvalidVariableException(
                "No variable defined at or containing address {:x}".format(
                    address))

        assert not isinstance(backup_var_type, VoidType)

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

        # Try to handle a variable type, otherwise make it big and empty.
        try:
            var_type = get_type(tif, TYPE_CONTEXT_GLOBAL_VAR)
            if isinstance(var_type, VoidType):
                var_type = backup_var_type

        except UnhandledTypeException as e:
            print(
                "Could not assign type to variable at address {:x}: {}".format(
                    address, str(e)))
            var_type = backup_var_type

        assert not isinstance(var_type, VoidType)
        assert not isinstance(var_type, FunctionType)

        var = IDAVariable(arch, address, var_type,
                          _find_segment_containing_ea(address, seg_ref))
        self._variables[address] = var
        return var
Пример #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
Пример #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
Пример #9
0
def guess_tinfo(ea):
    """@return: tuple(type, fields) just like idc.get_tinfo()"""
    tif = ida_typeinf.tinfo_t()
    if ida_typeinf.guess_tinfo(tif, ea):
        return tif.serialize()[:-1]
    return None