def get_or_guess_tinfo(ea): '''ea_t -> tinfo_t''' # XXX mutates (blah_tinfo2, unavoidable) ti = idaapi.tinfo_t() idaapi.get_tinfo2(ea, ti) or idaapi.guess_tinfo2(ea, ti) return ti
def get_func_type(f_start): tif = ida_typeinf.tinfo_t() idaapi.get_tinfo2(f_start, tif) funcdata = idaapi.func_type_data_t() got_data = tif.get_func_details(funcdata) if got_data: return funcdata else: return None
def get_type(addr): tif = idaapi.tinfo_t() idaapi.get_tinfo2(addr, tif) funcdata = idaapi.func_type_data_t() tif.get_func_details(funcdata) func_type = idaapi.print_tinfo("", 0, 0, PRTYPE_1LINE, tif, "", "") ret_type = idaapi.print_tinfo("", 0, 0, PRTYPE_1LINE, funcdata.rettype, "", "") args = [] for i in xrange(funcdata.size()): arg_type = idaapi.print_tinfo("", 0, 0, PRTYPE_1LINE, funcdata[i].type, "", "") args.append([i, funcdata[i].name, arg_type, funcdata[i].argloc.atype()]) return [func_type, ret_type, args]
def scan_functions(self): from mybase import function self.logger.info("For function %s:" % idc.GetFunctionName(self.ea)) for ea in function.iterate(self.ea): for xref in idautils.XrefsFrom(ea, 0): if idautils.XrefTypeName(xref.type) == 'Code_Near_Call' or\ idautils.XrefTypeName(xref.type) == 'Code_Far_Call': self.logger.info("found call at %s --> %s" % (hex(ea), idc.GetFunctionName(xref.to))) #skip constructors fn = FunctionName(idc.GetFunctionName(xref.to)) if fn.namespace == fn.basename: continue tif = idaapi.tinfo_t() if idaapi.get_tinfo2(xref.to, tif): funcdata = idaapi.func_type_data_t() tif.get_func_details(funcdata) #funcdata.get_call_method() if funcdata.size() >= 1 and funcdata[0].name == "this": self.funcs.add( FunctionName(idc.GetFunctionName(xref.to))) self.logger.info("Call to %s found" % idc.GetFunctionName(xref.to)) else: self.logger.info("idaapi.get_tinfo2 failed") self.logger.info("%d subcalls found" % len(self.funcs))
def resolve_objc_self_to_class(self, ea): ''' Get the objective c class for the current function RDI value based on the class of the first argument to the current function ''' f_start = idc.get_func_attr(ea, idc.FUNCATTR_START) tif = ida_typeinf.tinfo_t() idaapi.get_tinfo2(f_start, tif) funcdata = idaapi.func_type_data_t() tif.get_func_details(funcdata) # not happy about casting to a string and then regex replacing... but that's the best I could come up with replace_reg = re.compile(' \*', re.IGNORECASE) objc_self_type = funcdata[0].type return objc_self_type
def _rename_function(self, function_ea, class_name, instance_ptr_ea): # type: (int, str, int) -> None i = 0 function_name = "%s::__auto%d" % (class_name, i) while not idc.MakeNameEx(function_ea, function_name, idaapi.SN_NOWARN): i += 1 function_name = "%s::__auto%d" % (class_name, i) func_tinfo = idaapi.tinfo_t() if not idaapi.get_tinfo2(function_ea, func_tinfo): return arg_tinfo = idaapi.tinfo_t() idaapi.get_tinfo2(instance_ptr_ea, arg_tinfo) func_data = idaapi.func_type_data_t() func_tinfo.get_func_details(func_data) func_data[0].type = arg_tinfo new_func_tinfo = idaapi.tinfo_t() new_func_tinfo.create_func(func_data) idaapi.apply_tinfo2(function_ea, new_func_tinfo, idaapi.TINFO_DEFINITE)
def getArguments(self): """ Retrieve function arguments and populate the object`s args list. """ isGuessed = False # Is function prototype guessed # Get function type info if not idaapi.get_tinfo2(self.proto_ea, self.typeInfo): idaapi.guess_tinfo2(self.proto_ea, self.typeInfo) isGuessed = True if self.typeInfo.empty(): raise RuntimeError("Failed to retrieve function type info for function %s at %s" % (self.funcName, hex(self.ea))) # Get function detail self.typeInfo.get_func_details(self.funcInfo) # TODO: This seems to be creating false positives on 0 argument functions. #if self.funcInfo.empty(): # errStr = "Failed to retrieve function info for function %s" % self.funcName # raise RuntimeError(errStr) self.argNum = len(self.funcInfo) # Iterate function arguments for argIndex in xrange(0, self.argNum): argType = None # arg_type_info_t argLoc = None # argloc_info argName = None #else: # Input Argument argType = self.funcInfo.at(argIndex).type argLoc = self.funcInfo.at(argIndex).argloc argName = self.funcInfo.at(argIndex).name curArg = FuncArg(argType, argLoc, argIndex, argName, isGuessed) self.args.append(curArg) # Set return argument if not self.funcInfo.rettype.empty(): self.retArg = FuncArg(self.funcInfo.rettype, self.funcInfo.retloc, -1, "Ret_Arg", isGuessed)
def getArguments(self): """ Retrieve function arguments and populate the object`s args list. """ isGuessed = False # Is function prototype guessed # Get function type info if not idaapi.get_tinfo2(self.proto_ea, self.typeInfo): idaapi.guess_tinfo2(self.proto_ea, self.typeInfo) isGuessed = True if self.typeInfo.empty(): raise RuntimeError( "Failed to retrieve function type info for function %s at %s" % (self.funcName, hex(self.ea))) # Get function detail self.typeInfo.get_func_details(self.funcInfo) # TODO: This seems to be creating false positives on 0 argument functions. #if self.funcInfo.empty(): # errStr = "Failed to retrieve function info for function %s" % self.funcName # raise RuntimeError(errStr) self.argNum = len(self.funcInfo) # Iterate function arguments for argIndex in xrange(0, self.argNum): argType = None # arg_type_info_t argLoc = None # argloc_info argName = None #else: # Input Argument argType = self.funcInfo.at(argIndex).type argLoc = self.funcInfo.at(argIndex).argloc argName = self.funcInfo.at(argIndex).name curArg = FuncArg(argType, argLoc, argIndex, argName, isGuessed) self.args.append(curArg) # Set return argument if not self.funcInfo.rettype.empty(): self.retArg = FuncArg(self.funcInfo.rettype, self.funcInfo.retloc, -1, "Ret_Arg", isGuessed)
def imp_cb(self, ea, name, ord_nb): """ get import type and add used types in local types to ensure "correct" export """ # Get type imp_t = idaapi.tinfo_t() if idaapi.get_tinfo2(ea, imp_t): if not imp_t.is_func(): self.imports.append(idaapi.print_type(ea, True) + ";") else: # Iterate over ret type and args for i in range(-1, imp_t.get_nargs()): arg_t = imp_t.get_nth_arg(i) if arg_t.is_ptr_or_array(): no_ptr = arg_t no_ptr.remove_ptr_or_array() self.import_name(str(no_ptr)) self.import_name(str(arg_t)) self.imports.append(idaapi.print_type(ea, True) + " {}") return True
import idaapi ti = idaapi.tinfo_t() addrofW32UserProbeAddress = LocByName("_W32UserProbeAddress") addrofProbeForWrite = LocByName("__imp__ProbeForWrite@12") for functionAddr in Functions(): if "memcpy" in GetFunctionName(functionAddr): UserProbeXrefs = [GetFunctionName(UserProbeXref) for UserProbeXref in DataRefsTo(addrofW32UserProbeAddress)] ProbeForWrite = [GetFunctionName(ProbeForWrite) for ProbeForWrite in DataRefsTo(addrofProbeForWrite)] xrefs = CodeRefsTo(functionAddr, False) for xref in xrefs: if GetMnem(xref).lower() == "call": function_head = GetFunctionAttr(xref, idc.FUNCATTR_START) idaapi.get_tinfo2(function_head, ti) fi = idaapi.func_type_data_t() ti.get_func_details(fi) perfunc = [] for i in xrange(fi.size()): if fi[i].name: perfunc.append(fi[i].name) if perfunc: func_name = GetFunctionName(function_head) #Start searching with Nt prefix for SSDT calls if func_name[0:3] == "_Nt": print func_name #Search functions that doesn't have W32UserProbeAddress if func_name not in UserProbeXrefs: print func_name
def get_function_data(offset): """ Obtain a idaapi.func_type_data_t object for the function with the provided start EA. :param int offset: start EA of function :return: idaapi.func_type_data_t object :raise RuntimeError: if func_type_data_t object cannot be obtained """ tif = idaapi.tinfo_t() # First see if a type is already set. if idc.GetType(offset): idaapi.get_tinfo2(offset, tif) else: # Otherwise, try to use the Hexrays decompiler to determine function signature. # (It's better than IDA's GuessType) try: # This requires Hexrays decompiler, load it and make sure it's available before continuing. if not idaapi.init_hexrays_plugin(): idc.RunPlugin("hexrays", 0) or idc.RunPlugin("hexx64", 0) if not idaapi.init_hexrays_plugin(): raise RuntimeError('Unable to load Hexrays decompiler.') # Pull type from decompiled C code. decompiled = idaapi.decompile(offset) if decompiled is None: raise RuntimeError( "Cannot decompile function at 0x{:X}".format(offset)) decompiled.get_func_type(tif) # Save type for next time. format = decompiled.print_dcl2() # The 2's remove the unknown bytes always found at the start and end. idc.SetType(offset, "{};".format(format[2:-2])) # If we fail, resort to using GuessType+ except RuntimeError: # Documentation states the type must be ';' terminated, also the function name must be inserted guessed_type = idc.GuessType(offset) if guessed_type is None: raise RuntimeError( "failed to guess function type for offset 0x{:X}".format( offset)) func_name = idc.GetFunctionName(offset) if func_name is None: raise RuntimeError( "failed to get function name for offset 0x{:X}".format( offset)) guessed_type = re.sub("\(", " {}(".format(func_name), "{};".format(guessed_type)) idc.SetType(offset, guessed_type) # Try one more time to get the tinfo_t object if not idaapi.get_tinfo2(offset, tif): raise RuntimeError( "failed to obtain tinfo_t object for offset 0x{:X}".format( offset)) funcdata = idaapi.func_type_data_t() if not tif.get_func_details(funcdata): raise RuntimeError( "failed to obtain func_type_data_t object for offset 0x{:X}". format(offset)) return funcdata