def abi(self): """Return the IDA guessed ABI """ architecture = self.architecture available_abis = self.IDAABI2SibylABI.get(architecture, None) if not available_abis: raise ValueError("No ABI available for architecture %s" % architecture) if isinstance(available_abis, str): return available_abis # Search for IDA guessed type for func_addr in idautils.Functions(): gtype = idc.GuessType(func_addr) if gtype is None: continue match = self.gtype_matcher.match(gtype) if match is None: continue calling_conv = match.group(1) abi = available_abis.get(calling_conv, None) if abi is None: raise ValueError("No ABI matching %s" % calling_conv) return abi raise ValueError("Unable to guess ABI")
def get_type(cls, function): '''Get function type.''' ctype = idc.GetType(function) if not ctype: ctype = idc.GuessType(function) if not ctype: ctype = '' return ctype
def readEA(self, ea): self.name = idc.GetFunctionName(ea) if not self.name: raise self.NotFunctionError(ea) self.ea = ea tp = idc.GetType(ea) or idc.GuessType(ea) if tp: self.parseType(tp, skipName=True) return self
def include(self): t = idc.GetType(self.offset) # if failed getting type, there's no annotation here if t is None: return False # if type equals guessed type, no need to save annotation if t == idc.GuessType(self.offset): return False return True
def make_strings_const(): s = idautils.Strings(False) s.setup(strtypes=idautils.Strings.STR_UNICODE | idautils.Strings.STR_C) for v in s: gt = idc.GetType(v.ea) if not gt: gt = idc.GuessType(v.ea) if gt and not gt.startswith("const "): idc.SetType(v.ea, "const " + gt)
def get_func_type(startEA): """ Parse IDA's guessed type decl returns: tuple of: (return type, [arg types]) (this is a giant hack) """ type_str = idc.GuessType(startEA) if not type_str: # Probably wasn't a function print("ERROR: No function type guess") return None # Parse strings like this: # 'int __cdecl(int argc, const char **argv, const char **envp)' # 'int __cdecl(int)' # Try to make it into a parsable string type_str = re.sub(r"(__cdecl|__fastcall|[0-9_])", '', type_str) try: parser = pycparser.c_parser.CParser() res = parser.parse(type_str + ';') # Need that semicolon of course type_ast = res.ext[0].type # Return type return_type = type_ast.type.type.names[0] # Arguments arg_types = [] if type_ast.args: for param in type_ast.args.params: if type(param.type) is pycparser.c_ast.PtrDecl: # Pointer, return "ptr" for now arg_types.append("ptr") else: arg_types.append(param.type.type.names[0]) return (return_type, arg_types) except: print("ERROR: Couldn't parse function type guess") return None
def _propagate_virtual_method_type_for_method(classinfo, class_vindex, vmethod): """Propagate the type of a class's virtual method to the vtable struct.""" if not idau.is_function_start(vmethod): _log(2, 'Not a function start: {:x}', vmethod) return False vmethod_type = idc.GuessType(vmethod) if not vmethod_type: _log(2, 'No guessed type: {:x}', vmethod) return False vmethod_ptr_type = symbol.convert_function_type_to_function_pointer_type(vmethod_type) if not vmethod_ptr_type: _log(2, 'Could not convert to function pointer type: {:x}', vmethod) return False vmethods_sid = idau.struct_open(classinfo.classname + '::vmethods') vmethod_offset = class_vindex * idau.WORD_SIZE vmethod_mid = idc.GetMemberId(vmethods_sid, vmethod_offset) if not bool(idc.SetType(vmethod_mid, vmethod_ptr_type)): _log(2, 'Could not set vmethod field type: {:x}, {}, {}', vmethod, classinfo.classname, class_vindex) return False return True
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