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))