def infer_function_signature(cfunc, expr, index_interface, index_output): """ This function will infer type of variable present at index_output in function signature by type found in registry in accordance to the GUID set at the index_interface :ivar cfunc_t cfunc: function object that is decompiling :ivar cexpr_t expr: IDA expression AST :ivar int index_interface: index of the GUID parameter into function signature :ivar int index_output: index of the output variable that will be infer """ curent_expr = expr.a[index_output] while curent_expr.op in [idaapi.cot_cast, idaapi.cot_ref]: curent_expr = curent_expr.x variable = curent_expr.v if variable is None: ComIDA.log("Variable name not found") return False ComIDA.log("infer type of variable: (%s)" % cfunc.lvars[variable.idx].name) # try to find type name from third parameter value = idc.get_operand_value(expr.a[index_interface].ea, 1) if value == -1: value = idc.get_operand_value(expr.a[index_interface].ea, 0) # 32 bits case guid_bytes = idc.get_bytes(value, 16) guid = guid_bytes_to_string(guid_bytes) interface = None try: interface = build_com_from_interface_definition( expr.a[index_interface].ea, guid) except WindowsError as e: ComIDA.log("Interface type (%s) not found" % guid) tinfo = idaapi.tinfo_t() if interface is None or not tinfo.get_named_type(idaapi.get_idati(), interface.name): ComIDA.log( "type (%s) not found in registry switch to symbol name base heuristic" % guid) symbol_name = idc.get_name( idc.get_operand_value(expr.a[index_interface].ea, 1)) if symbol_name is None or not tinfo.get_named_type( idaapi.get_idati(), symbol_name[4:]): ComIDA.log("unable to find type for (%s)" % guid) return False cfunc.get_lvars()[variable.idx].set_final_lvar_type( idaapi.make_pointer(tinfo)) return True
def parse(info): '''Parse the string `info` into an ``idaapi.tinfo_t``.''' if idaapi.__version__ < 7.0: til, ti = idaapi.cvar.idati, idaapi.tinfo_t(), else: 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. if idaapi.__version__ < 6.9: return None if idaapi.parse_decl2(til, terminated, None, ti, idaapi.PT_SIL) is None else ti elif idaapi.__version__ < 7.0: return None if idaapi.parse_decl2(til, terminated, ti, idaapi.PT_SIL) is None else ti return None if idaapi.parse_decl(ti, til, terminated, idaapi.PT_SIL) is None else ti
def process_funcs(all_funcs): for func in all_funcs: # rename idc.set_name(func.start_ea, f"string_{func.start_ea:X}") # set type struc_id = idaapi.get_struc_id("std::string") # print(f"{struc_id:x}") if struc_id == idaapi.BADADDR: idc.set_local_type(-1, "struct std::string {char *ptr; size_t length; char buf[0x10];};", idaapi.PT_TYP) print("create std::string") func_tinfo = idaapi.tinfo_t() cfunc = idaapi.decompile(func.start_ea) cfunc.get_func_type(func_tinfo) func_details = idaapi.func_type_data_t() func_tinfo.get_func_details(func_details) std_string_tinfo = idaapi.tinfo_t() std_string_tinfo.get_named_type(idaapi.get_idati(), "std::string") std_string_ptr_tinfo = idaapi.tinfo_t() std_string_ptr_tinfo.create_ptr(std_string_tinfo) func_details[0].type = std_string_ptr_tinfo func_tinfo.create_func(func_details) idaapi.apply_tinfo(func.start_ea, func_tinfo, idaapi.TINFO_DEFINITE)
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
def ParseAMXNativeInfo(): ida_string = idautils.Strings() last_native = "" for string in ida_string: for native in natives: if (str(string) == native and last_native != native): last_native = native for xref in XrefsTo(string.ea): offset = xref.frm + 4 for native_addr in XrefsFrom(offset): # Rename native handler function n_NativeName idc.MakeNameEx(native_addr.to, "n_" + native, idc.SN_NOWARN) # Setup function prototype & automate setting the native's tinfo = idaapi.tinfo_t() ida_typeinf.guess_tinfo(native_addr.to, tinfo) funcdata = idaapi.func_type_data_t() tinfo.get_func_details(funcdata) tinfo2 = idaapi.tinfo_t() tinfo2.get_named_type(idaapi.get_idati(), "Native" + native + "Params") tinfo3 = idaapi.tinfo_t() tinfo3.create_ptr(tinfo2) if ( len(funcdata) ): # For some reason this is 0 for some natives with params? Not sure why... funcdata[len(funcdata) - 1].type = tinfo3 function_tinfo = idaapi.tinfo_t() function_tinfo.create_func(funcdata) idaapi.apply_tinfo2(native_addr.to, function_tinfo, idaapi.TINFO_DEFINITE)
def get_tinfo(name): idati = idaapi.get_idati() ti = idaapi.tinfo_t() for ordinal in range(1, idaapi.get_ordinal_qty(idati) + 1): if ti.get_numbered_type(idati, ordinal) and ti.dstr() == name: return ti return None
def InsertType(type_obj, fReplace=False): # print("Insert type %s." % type_obj.name) wrapperTypeString = b'\x0d\x01\x01' if getTypeOrdinal(type_obj.name) != 0: idx = getTypeOrdinal(type_obj.name) t = ImportLocalType(idx) if (t.TypeFields is None or t.TypeFields == "") and t.is_sue(): fReplace = True if t.isEqual(type_obj) or type_obj.TypeString == wrapperTypeString: return 1 if not fReplace: type_obj = DuplicateResolver(t, type_obj, False) else: idx = ida_typeinf.alloc_type_ordinals(idaapi.get_idati(), 1) tif = ida_typeinf.tinfo_t() ret = tif.deserialize(ida_typeinf.get_idati(), type_obj.GetTypeString(), type_obj.TypeFields, type_obj.fieldcmts) if not ret: idaapi.warning( "Error on tinfo deserilization, type name = %s, ret = %d" % (type_obj.name, ret)) ret = -1 else: ret = tif.set_numbered_type(idaapi.get_idati(), idx, 0x4, type_obj.name) del tif # ret = idaapi.set_numbered_type( # my_ti, # idx, # 0x4, # type_obj.name, # type_obj.GetTypeString(), # type_obj.TypeFields, # type_obj.cmt, # type_obj.fieldcmts # ) # print "Insert type %s. ret = %d"%(type_obj.name,ret) if (ida_pro.IDA_SDK_VERSION < 700 and ret != 1) or (ida_pro.IDA_SDK_VERSION >= 700 and ret != 0): print("bad insert: %s; ret = %d" % (type_obj.name, ret)) return ret
def get_typeinf(typestr): if not typestr: # Passing None to tinfo_t.get_named_type() can crash IDA return None tif = idaapi.tinfo_t() if tif.get_named_type(idaapi.get_idati(), typestr): return tif PT_SILENT = 1 # in IDA7.0 idc.PT_SILENT=2, which is incorrect py_type = idc.parse_decl(typestr, PT_SILENT) if not py_type: return None return deserialize_tinfo(py_type[1:])
def get_local_type(ordinal=None, name=None, til=None): if til is None: til = idaapi.get_idati() tif = idaapi.tinfo_t() if ordinal is not None: found = tif.get_numbered_type(til, ordinal) if not found: raise ValueError("Unknown ordinal type.") elif name is not None: found = tif.get_named_type(til, name) if not found: raise ValueError("Unknown named type.") else: raise ValueError("Must specify type ordinal or name.") return til, tif
def size(string): '''Returns the size of a type described by a C declaration in `string`.''' til = idaapi.cvar.idati if idaapi.__version__ < 7.0 else idaapi.get_idati() string = string.strip() if string.lower() == 'void': return 0 elif string.startswith('class') and string.endswith('&'): res = idaapi.idc_parse_decl(til, 'void*;', 0) else: semicoloned = string if string.endswith(';') else "{:s};".format( string) res = idaapi.idc_parse_decl(til, internal.utils.string.to(semicoloned), 0) if res is None: raise internal.exceptions.DisassemblerError( u"Unable to parse the specified C declaration (\"{:s}\").".format( internal.utils.string.escape(string, '"'))) _, type, _ = res f = idaapi.get_type_size0 if idaapi.__version__ < 6.8 else idaapi.calc_type_size return f(til, type)
def GetTypeString(parsedList, name=""): ti = idaapi.get_idati() # print "GetTypeString: name %s"%self.name the_bytes = [] for thing in parsedList: if type(thing) == int: # if it's a byte, just put it back in the_bytes.append(thing) elif len(thing) == 1: if list(thing.keys())[0] == "local_type": the_bytes.append(ord("=")) # a type starts with = # print type(thing["local_type"]),thing["local_type"] ordinal = idaapi.get_type_ordinal( ti, list(thing.values()) [0]) # get the ordinal of the Local Type based on its name if ordinal > 0: the_bytes = the_bytes + encode_ordinal_to_string(ordinal) else: raise NameError("Depends local type not in IDB") else: raise NameError("Wrong depend record for type: %s!" % name) packed = struct.pack("%dB" % len(the_bytes), *the_bytes) return packed
def find_type_by_name(name): my_ti = idaapi.get_idati() ordinal = idaapi.get_type_ordinal(my_ti, name)
def get_typeinf(typestr): tif = idaapi.tinfo_t() tif.get_named_type(idaapi.get_idati(), typestr) return tif
# Copyright (C) 2020 Alibaba Group Holding Limited import idaapi import idc import shutil import os idb_fp = idc.get_idb_path() modulename = os.path.basename(idb_fp)[:-4] idb_dirpath = os.path.dirname(idb_fp) til_dirpath = os.path.join(idb_dirpath, "tils") if not os.path.isdir(til_dirpath): os.makedirs(til_dirpath) self_til = idaapi.get_idati() ida_typeinf.compact_til(self_til) ida_typeinf.store_til(self_til, None, os.path.join(til_dirpath, modulename + ".til")) #til_fp = modulename + ".til" #shutil.copy(til_fp, til_fp[:-4]+".exported.til") idc.Exit(0)
"short": 's', "char": 'c', "float": 'f', "void": 'p', "_DWORD": "i", "_QWORD": 'j', "_WORD": 's', "_BYTE": 'b', "unsigned __int64": 'j', "unsigned __int16": 's', "double": 'd', "long double": 'D' } size2c = {1: 'b', 2: 's', 4: 'i', 8: 'j'} basec = set(t2c.values()) idaapi.get_idati() MAX_INT32 = (1 << 32) - 1 MAX_INT8 = (1 << 8) - 1 MAX_INT16 = (1 << 16) - 1 _common_dbg = Debugger() _common_dbg.on() Arch = None def get_arch(): global Arch """