Python源码示例:idaapi.tinfo_t()

示例1
def get_winapi_decl(name):
    '''
    fetch the C function declaration for the given Windows API function.
    '''
    tup = idaapi.get_named_type(None, name, idaapi.NTF_SYMM)
    if tup is None:
        raise ValueError("failed to fetch type")
    code, type_str, fields_str, cmt, field_cmts, sclass, value = tup
    ti = idaapi.tinfo_t()
    ti.deserialize(None, type_str, fields_str, cmt)

    # the rendered declaration from IDA doesn't include the function name,
    # so insert the function name, naively.
    #
    # for example;
    #
    #    > DWORD (DWORD a, DWORD b)
    #    < DWORD foo(DWORD a, DWORD b);
    decl = str(ti).replace("(", " " + name + "(") + ";"

    return decl 
示例2
def get_array_data(self):
        """
        Extract the array data from tinfo_t object and populate all relevant class properties.
        @return: True if successful, otherwise False
        """

        try:
            if self.type_info.is_array():
                if self.type_info.get_array_details(self.array_type_data):
                    self.element_type = self.array_type_data.elem_type
                    self.element_num = self.array_type_data.nelems
                    self.element_size = self.element_type.get_size()
                    return True

            return False

        except Exception as ex:
            self.logger.exception("Array: Error while getting array data: %s", ex)
            return False

#######################################################################################################################
#
#  IDA Function Argument class wrapper
# 
示例3
def getStructData(self):
        """
        Extract the struct data from tinfo_t object and populate all relevant class properties.
        @return: True if successful, otherwise False
        """

        if self.type_info.is_udt():
            if self.type_info.get_udt_details(self.udt_type_data):

                self.name = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, self.type_info, '', '')
                self.size = self.udt_type_data.size
                self.element_num = len(self.udt_type_data)
                self.is_union = self.udt_type_data.is_union

                return True

        return False 
示例4
def parse(info):
    '''Parse the string `info` into an ``idaapi.tinfo_t``.'''
    til, ti = idaapi.get_idati(), idaapi.tinfo_t(),

    # Convert info to a string if it's a tinfo_t
    info_s = "{!s}".format(info) if isinstance(info, idaapi.tinfo_t) else info

    # Firstly we need to ';'-terminate the type the user provided in order
    # for IDA's parser to understand it.
    terminated = info_s if info_s.endswith(';') else "{:s};".format(info_s)

    # Ask IDA to parse this into a tinfo_t for us. We pass the silent flag so
    # that we're responsible for raising an exception if there's a parsing
    # error of some sort. If it succeeds, then we can return our typeinfo.
    # Otherwise we return None because of the inability to parse it.
    return None if idaapi.parse_decl(ti, til, terminated, idaapi.PT_SIL) is None else ti 
示例5
def typeinfo(self, info):
        '''Sets the typeinfo of the structure to `info`.'''
        try:
            ti = database.type(self.id, info)

        # If we caught a TypeError, then we received a parsing error that
        # we should re-raise for the user.
        except E.InvalidTypeOrValueError:
            cls = self.__class__
            raise E.InvalidTypeOrValueError(u"{:s}({:#x}).typeinfo : Unable to parse the specified type declaration ({!s}).".format('.'.join((__name__, cls.__name__)), self.id, utils.string.repr(info)))

        # If we caught an exception trying to get the typeinfo for the
        # structure, then port it to our class and re-raise.
        except E.DisassemblerError:
            cls = self.__class__
            raise E.DisassemblerError(u"{:s}({:#x}).typeinfo : Unable to apply `idaapi.tinfo_t()` to structure {:s}.".format('.'.join((__name__, cls.__name__)), self.id, self.name))
        return 
示例6
def test_xx(idx, ctx):
    import ida_typeinf
    uni = ctx.get_expr('union_type')
    var = ctx.get_var('v1')
    tname =  var.typ.dstr().split(' ')[0]
    tinfo = idaapi.tinfo_t()
    if tname == 'class1':
        idaapi.parse_decl2(idaapi.cvar.idati, 'vptr1_1 *;', tinfo, idaapi.PT_TYP)
        uni[0].type = tinfo
        uni[0].m = 0
    elif tname == "class2":
        idaapi.parse_decl2(idaapi.cvar.idati, 'struc_5 *;', tinfo, idaapi.PT_TYP)
        uni[0].type = tinfo
        uni[0].m = 1
    else:
        return False
    return True 
示例7
def processStructIDA7(self, regPrefix, struc, sid):
        members = loadMembers(struc, sid)
        foundFunctions = 0
        for off, name, memb in members:
            funcname  = self.filterName(regPrefix, name)
            tup = idaapi.get_named_type(None, funcname, idaapi.NTF_SYMM)
            if tup is None:
                continue
            code, type_str, fields_str, cmt, field_cmts, sclass, value  = tup
            foundFunctions += 1
            tif = idaapi.tinfo_t()
            tif.deserialize(None, type_str, fields_str, cmt)
            if not tif.is_func():
                logger.debug('Found named type, but not a function: %s', funcname)
                continue
            tif.create_ptr(tif)
            ret = idaapi.set_member_tinfo(struc, memb, off, tif, 0)
            if ret != idaapi.SMT_OK:
                logger.info("Got set_member_tinfo ret code: %d" % ret)
            else:
                logger.info('set_member_tinfo: %s', tif.dstr()) 
示例8
def getBuiltinGlobalTypePython(self):
        logger.debug('Getting GlobalType the Python way')
        sym = idaapi.til_symbol_t()
        if using_ida7api:
            ret = idaapi.choose_named_type(sym, idaapi.get_idati(), 'Choose type to apply', idaapi.NTF_SYMM, None)
        else:
            ret = idaapi.choose_named_type2(idaapi.cvar.idati, 'Choose type to apply', idaapi.NTF_SYMM, None, sym)
        if not ret:
            logger.debug('User canceled. Bailing out')
            return

        tuple = idaapi.get_named_type(sym.til, sym.name, 0)

        if tuple == None:
            logger.debug('Could not find %s', sym.name)
            return

        tinfo = idaapi.tinfo_t()
        tinfo.deserialize(sym.til, tuple[1], tuple[2])

        return tinfo 
示例9
def activate(self, ctx):
        sel = []
        for idx in ctx.chooser_selection:
            # rename the function
            ea = get_name_ea_simple(self.items[idx][2])
            sfname = str(self.items[idx][4])
            #set_name(ea, sfname)
            idaapi.do_name_anyway(ea, sfname)
            success('{:#x}: renamed to {}'.format(ea, sfname))
            # set the function prototype
            sptype = str(self.items[idx][5])
            if sptype != 'None':
                tinfo = idaapi.tinfo_t()
                idaapi.parse_decl2(idaapi.cvar.idati, sptype, tinfo, 0)
                #idaapi.apply_callee_tinfo(ea, tinfo)
                if idaapi.apply_tinfo(ea, tinfo, 0):
                    success('{:#x}: function prototype set to {}'.format(ea, sptype))
                else:
                    error('{:#x}: function prototype set FAILED (maybe you should import the types?)'.format(ea))
                    if ask_yn(0, 'Do you import types from the secondary idb?') == 1:
                        if self.import_types():
                            tinfo = idaapi.tinfo_t()
                            idaapi.parse_decl2(idaapi.cvar.idati, sptype, tinfo, 0)
                            if idaapi.apply_tinfo(ea, tinfo, 0):
                                success('{:#x}: function prototype set to {}'.format(ea, sptype))
                            else:
                                error('{:#x}: function prototype set FAILED again'.format(ea))
                        
            # insert the comment
            score = self.items[idx][0]
            mmatch = self.items[idx][1]
            cmt = 'fn_fuzzy: ssdeep={}, machoc={}'.format(score, mmatch)
            set_func_cmt(ea, cmt, 1)
            #set_decomplier_cmt(ea, cmt) # not sure how to avoid orphan comment

        # update the Choose rows
        ida_kernwin.refresh_chooser(self.title) 
示例10
def export(self):
        if self.existed() and not self.f_update:
            info('{}: The sample records are present in DB. skipped.'.format(self.sha256))
            return False

        self.cur.execute("REPLACE INTO sample values(?, ?)", (self.sha256, self.idb_path))

        pnum = tnum = 0
        records = []
        for fva in idautils.Functions():
            fname = get_func_name(fva)
            tnum += 1
            if self.exclude_libthunk(fva, fname):
                continue
            fhd, bsize = self.calc_fn_ssdeep(fva, fname)
            fhm, cfgnum = self.calc_fn_machoc(fva, fname)
            if fhd and fhm:
                pnum += 1
                f_ana = bool(self.ana_pat.search(fname)) if self.f_ana_exp else False
                tinfo = idaapi.tinfo_t()
                idaapi.get_tinfo(fva, tinfo)
                ptype = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, tinfo, fname, '')
                ptype = ptype + ';' if ptype is not None else ptype
                # fva is 64-bit int causing OverflowError
                records.append((self.sha256, '{:#x}'.format(fva), fname, fhd, fhm, f_ana, bsize, ptype)) 
                self.debug('EXPORT {} at {:#x}: ssdeep={} (size={}), machoc={} (num of CFG={})'.format(fname, fva, fhd, bsize, fhm, cfgnum))

        self.cur.executemany("REPLACE INTO function values (?, ?, ?, ?, ?, ?, ?, ?)", records)
        success ('{} of {} functions exported'.format(pnum, tnum))
        return True 
示例11
def __init__(self, ea, iatEA=None, library_name=None):
        """
        Ctor
        """
        self.logger = logging.getLogger(__name__)

        self.ea = ea        # Effective Address of the function
        self.iatEA = iatEA  # If imported function, the address in the IAT

        try:
            function = sark.Function(ea)
        except sark.exceptions.SarkNoFunction:
            raise DIE.Lib.DIE_Exceptions.DieNoFunction("No Function at 0x%08X" % (ea, ))

        self.funcName = get_function_name(function.ea)
        self.func_start = function.startEA
        self.func_end = function.endEA

        self.proto_ea = self.getFuncProtoAdr()      # Address of function prototype
        self.typeInfo = idaapi.tinfo_t()            # Function type info
        self.funcInfo = idaapi.func_type_data_t()   # Function info
        self.argNum = 0                             # Number of input arguments

        self.args = []      # Function argument list
        self.retArg = None  # Return argument

        self.library_name = library_name  # If library function, name of containing library
        self.isLibFunc = False
        if self.iatEA:
            self.isLibFunc = True  # Is this a library function

        elif sark.Function(ea).flags & (idaapi.FUNC_LIB | idaapi.FUNC_THUNK):
            self.isLibFunc = True

        try:
            self.getArguments()

        except Exception as ex:
            self.logger.error("Failed to get function arguments for function %s: %s", self.funcName, ex) 
示例12
def __new__(cls):
        '''Return the typeinfo for the current function as a ``idaapi.tinfo_t``.'''
        return cls(ui.current.address()) 
示例13
def __new__(cls, func):
        '''Return the typeinfo for the function `func` as a ``idaapi.tinfo_t``.'''
        rt, ea = interface.addressOfRuntimeOrStatic(func)
        try:
            ti = database.type(ea)

        # If we caught an exception trying to get the typeinfo for the
        # function, then port it to our class.
        except E.DisassemblerError:
            raise E.DisassemblerError(u"{:s}.info({:#x}) : Unable to determine `idaapi.tinfo_t()` for function.".format('.'.join((__name__, cls.__name__)), ea))

        # Return it to the caller
        return ti 
示例14
def __new__(cls, func, info):
        '''Apply the ``idaapi.tinfo_t`` typeinfo in `info` to the function `func`.'''
        _, ea = interface.addressOfRuntimeOrStatic(func)

        # In order to apply the typeinfo with idaapi.apply_cdecl, we need the
        # typeinfo as a string. To accomplish this, we need need the typeinfo
        # with its name attached.
        fname = database.name(ea)
        realname = internal.declaration.unmangle_name(fname)

        # Filter out invalid characters from the function name since we're going
        # to use this to render the declaration next.
        valid = {item for item in string.digits}
        valid |= {item for item in ':'}
        filtered = str().join(item if item in valid or idaapi.is_valid_typename(utils.string.to(item)) else '_' for item in realname)

        # Now we have the name and its filtered, we can simply render it.
        try:
            tinfo_s = idaapi.print_tinfo('', 0, 0, 0, info, utils.string.to(filtered), '')

        # If we caught an error, then we couldn't render the string for some reason.
        except Exception:
            raise E.DisassemblerError(u"{:s}({:#x}, \"{:s}\") : Unable to render `idaapi.tinfo_t()` with name (\"{!s}\") to a string.".format('.'.join((__name__, cls.__name__)), ea, utils.string.escape("{!s}".format(info), '"'), utils.string.escape(realname, '"')))

        # Recurse back into ourselves in order to call idaapi.apply_cdecl
        return cls(ea, tinfo_s) 
示例15
def typeinfo(self):
        '''Return the type info of the member.'''
        try:
            ti = database.type(self.id)

        # If we caught an exception trying to get the typeinfo for the
        # structure, then port it to our class.
        except E.DisassemblerError:
            cls = self.__class__
            raise E.DisassemblerError(u"{:s}({:#x}).typeinfo : Unable to determine `idaapi.tinfo_t()` for structure {:s}.".format('.'.join((__name__, cls.__name__)), self.id, self.name))

        # Return the structure type that we guessed back to the caller.
        return ti 
示例16
def typeinfo(self):
        '''Return the type info of the member.'''
        ti = idaapi.tinfo_t()
        ok = idaapi.get_or_guess_member_tinfo2(self.ptr, ti) if idaapi.__version__ < 7.0 else idaapi.get_or_guess_member_tinfo(ti, self.ptr)
        if not ok:
            cls = self.__class__
            logging.fatal(u"{:s}({:#x}).typeinfo : Unable to determine `idaapi.tinfo_t()` for member {:s}.".format('.'.join((__name__, cls.__name__)), self.id, self.name))
        return ti 
示例17
def format_item(self, num_printer, storage, item):
        if item is None or isinstance(item, bool):
            storage.append("{!s}".format(item))
        elif isinstance(item, six.string_types):
            storage.append(self.format_basestring(item))
        elif isinstance(item, six.integer_types):
            storage.append(num_printer(item))
        elif isinstance(item, idaapi.tinfo_t):
            storage.append("{!s}".format(item))
        elif item.__class__ is list:
            self.format_seq(num_printer, storage, item, '[', ']')
        elif item.__class__ is tuple:
            self.format_seq(num_printer, storage, item, '(', ')')
        elif item.__class__ is set:
            self.format_seq(num_printer, storage, item, 'set([', '])')
        elif item.__class__ is dict:
            storage.append('{')
            for idx, pair in enumerate(item.items()):
                if idx > 0:
                    storage.append(', ')
                self.format_item(num_printer, storage, pair[0])
                storage.append(": ")
                self.format_item(num_printer, storage, pair[1])
            storage.append('}')
        else:
            storage.append("{!r}".format(item)) 
示例18
def helper_getTinfoOfFuncName(self, funcName):
        try:
            sym = til_symbol_t()
            sym.til = cvar.idati
            sym.name = funcName
            tinfo = idaapi.tinfo_t()
            namedType = get_named_type(sym.til, sym.name, 0)
            if namedType == None:
                return tinfo, False
            tinfo.deserialize(sym.til, namedType[1], namedType[2])
            return tinfo, True
        except:
            return None, False 
示例19
def getUserDeclType(self, decl):
        tinfo = idaapi.tinfo_t()
        #logger.debug('Trying to parse declaration: %r', decl)
        ret = idaapi.parse_decl2(idaapi.cvar.idati, decl, tinfo, idaapi.PT_TYP)
        #logger.debug('Return from parse_decl2: %r', ret)
        if ret is None:
            logger.info('parse_decl2 failed')
            return None
        return tinfo 
示例20
def getLocalType(self):
        ret = idaapi.choose_local_tinfo(idaapi.cvar.idati, 'Choose local type to apply', None, None)
        if not ret:
            logger.debug('User canceled. Bailing out')
            return
        #ret is a numbered type rather than the name
        tinfo = idaapi.tinfo_t()
        tinfo.get_numbered_type(idaapi.cvar.idati, ret)
        return tinfo 
示例21
def getBuiltinGlobalType(self):

        # Ensure proper IDA Python methods are exposed
        if hasattr(idaapi, "get_named_type") and hasattr(idaapi.tinfo_t, "deserialize"):
            return self.getBuiltinGlobalTypePython()

        # Fall back to calling exports directly with Ctypes
        else:
            return self.getBuiltinGlobalTypeCtypes() 
示例22
def remove_rettype(self, vu):
        if vu.item.citype == idaapi.VDI_FUNC:
            # current function
            ea = vu.cfunc.entry_ea
            old_func_type = idaapi.tinfo_t()
            if not vu.cfunc.get_func_type(old_func_type):
                return False
        elif vu.item.citype == idaapi.VDI_EXPR and vu.item.e.is_expr() and vu.item.e.type.is_funcptr():
            # call xxx
            ea = vu.item.get_ea()
            old_func_type = idaapi.tinfo_t()

            func = idaapi.get_func(ea)
            if func:
                try:
                    cfunc = idaapi.decompile(func)
                except idaapi.DecompilationFailure:
                    return False

                if not cfunc.get_func_type(old_func_type):
                    return False
            else:
                return False
        else:
            return False

        fi = idaapi.func_type_data_t()
        if ea != idaapi.BADADDR and old_func_type.get_func_details(fi):
            # Return type is already void
            if fi.rettype.is_decl_void():
                # Restore ret type
                if ea not in self.ret_type:
                    return True
                ret = self.ret_type[ea]
            else:
                # Save ret type and change it to void
                self.ret_type[ea] = fi.rettype
                ret = idaapi.BT_VOID

            # Create new function info with new rettype
            fi.rettype = idaapi.tinfo_t(ret)

            # Create new function type with function info
            new_func_type = idaapi.tinfo_t()
            new_func_type.create_func(fi)

            # Apply new function type
            if idaapi.apply_tinfo(ea, new_func_type, idaapi.TINFO_DEFINITE):
                return vu.refresh_view(True)

        return False 
示例23
def __new__(cls, func, info):
        '''Parse the typeinfo string in `info` to an ``idaapi.tinfo_t`` and apply it to the function `func`.'''
        til = idaapi.get_idati()
        _, ea = interface.addressOfRuntimeOrStatic(func)
        conventions = {'__cdecl', '__stdcall', '__fastcall', '__thiscall', '__pascal', '__usercall', '__userpurge'}

        # First extract the arguments that we were given, and use that to extract
        # the name of the function (and possibly the usercall register)
        parameters = internal.declaration.extract.arguments(info)
        noparameters = info[:-len(parameters)]

        # Figure out which part of `noparameters` contains the actual name
        if any(item in noparameters for item in conventions):
            components = noparameters.split(' ')
            index = next(index for index, item in enumerate(components) if any(item.endswith(cc) for cc in conventions))
            funcname = ' '.join(components[-index:])

        # If nothing was found, then we have no choice but to chunk it out
        # according to the first space.
        else:
            funcname = noparameters.rsplit(' ', 1)[-1]

        # Filter out invalid characters from the name so that we can apply this
        # as a declaration.
        valid = {item for item in string.digits}
        if '__usercall' in noparameters:
            valid |= {item for item in '<>@'}
        valid |= {item for item in ':'}
        funcname_s = str().join(item if item in valid or idaapi.is_valid_typename(utils.string.to(item)) else '_' for item in funcname)

        # Filter out invalid characters from the parameters so that this can
        # be applied as a declaration
        valid |= {item for item in ', *&[]'}
        parameters_s = str().join(item if item in valid or idaapi.is_valid_typename(utils.string.to(item)) else '_' for item in parameters.lstrip('(').rstrip(')'))

        # Now we can replace both the name and parameters in our typeinfo string
        # with the filtered versions.
        info_s = "{!s} {:s}({:s})".format(noparameters[:-len(funcname)].strip(), funcname_s, parameters_s)

        # Terminate the typeinfo string with a ';' so that IDA can parse it.
        terminated = info_s if info_s.endswith(';') else "{:s};".format(info_s)

        # Now we should just be able to apply it to the function.
        ok = idaapi.apply_cdecl(idaapi.get_idati(), ea, terminated)
        if not ok:
            raise E.InvalidTypeOrValueError(u"{:s}.info({:#x}) : Unable to apply the specified type declaration (\"{!s}\").".format('.'.join((__name__, cls.__name__)), ea, utils.string.escape(info, '"')))

        # Just return the type we applied to the user.
        return cls(ea) 
示例24
def typeinfo(self, info):
        '''Set the type info of the member to `info`.'''
        til, ti = idaapi.get_idati(), idaapi.tinfo_t(),

        # Convert info to a string if it's a tinfo_t
        info_s = "{!s}".format(info) if isinstance(info, idaapi.tinfo_t) else info

        # Firstly we need to ';'-terminate the type the user provided in order
        # for IDA's parser to understand it.
        terminated = info_s if info_s.endswith(';') else "{:s};".format(info_s)

        # Now that we've prepped everything, ask IDA to parse this into a
        # tinfo_t for us. We pass the silent flag so that we can raise an
        # exception if there's a parsing error of some sort.
        res = idaapi.parse_decl(ti, til, terminated, idaapi.PT_SIL)
        if res is None:
            cls = self.__class__
            raise E.InvalidTypeOrValueError(u"{:s}({:#x}).typeinfo : Unable to parse the specified type declaration ({!s}).".format('.'.join((__name__, cls.__name__)), self.id, utils.string.repr(info)))

        # Now we can pass our tinfo_t along with the member information to IDA.
        res = idaapi.set_member_tinfo(self.parent.ptr, self.ptr, self.ptr.get_soff(), ti, 0)
        if res == idaapi.SMT_OK:
            return

        # We failed, so just raise an exception for the user to handle.
        elif res == idaapi.SMT_FAILED:
            cls = self.__class__
            raise E.DisassemblerError(u"{:s}({:#x}).typeinfo : Unable to assign typeinfo ({!s}) to structure member {:s}.".format('.'.join((__name__, cls.__name__)), self.id, utils.string.repr(info), utils.string.repr(self.name)))

        # If we received an alternative return code, then build a relevant
        # message that we can raise with our exception.
        if res == idaapi.SMT_BADARG:
            message = 'invalid parameters'
        elif res == idaapi.SMT_NOCOMPAT:
            message = 'incompatible type'
        elif res == idaapi.SMT_WORSE:
            message = 'worse type'
        elif res == idaapi.SMT_SIZE:
            message = 'invalid type for member size'
        elif res == idaapi.SMT_ARRAY:
            message = 'setting function argument as an array is illegal'
        elif res == idaapi.SMT_OVERLAP:
            message = 'the specified type would result in member overlap'
        elif res == idaapi.SMT_KEEP:
            message = 'the specified type is not ideal'
        else:
            message = "unknown error {:#x}".format(res)

        # Finally we can raise our exception so that the user knows whats up.
        cls = self.__class__
        raise E.DisassemblerError(u"{:s}({:#x}).typeinfo : Unable to assign typeinfo ({!s}) to structure member {:s} ({:s}).".format('.'.join((__name__, cls.__name__)), self.id, utils.string.repr(info), utils.string.repr(self.name), message))