def modify_lvars(self, lvars): def log(msg): print("modify_lvars: %s" % msg) log("len(lvars.lvvec) = %d" % len(lvars.lvvec)) log("lvars.lmaps.size() = %d" % lvars.lmaps.size()) log("lvars.stkoff_delta = %d" % lvars.stkoff_delta) log("lvars.ulv_flags = %x" % lvars.ulv_flags) for idx, one in enumerate(lvars.lvvec): def varlog(msg): log("var #%d: %s" % (idx, msg)) varlog("name = '%s'" % one.name) varlog("type = '%s'" % one.type._print()) varlog("cmt = '%s'" % one.cmt) varlog("size = %d" % one.size) varlog("flags = %x" % one.flags) new_type = self.new_types.get(one.name) if new_type: tif = ida_typeinf.tinfo_t() ida_typeinf.parse_decl(tif, None, new_type, 0) one.type = tif one.name = self.name_prefix + one.name one.cmt = self.cmt_prefix + one.cmt return True
def force_variable(ea, type, name): t = ida_typeinf.tinfo_t() ida_typeinf.parse_decl(t, None, '{} a;'.format(type), 0) ida_bytes.del_items( ea, ida_bytes.DELIT_EXPAND | ida_bytes.DELIT_DELNAMES | ida_bytes.DELIT_NOCMT, t.get_size()) ida_name.set_name(ea, name, ida_name.SN_CHECK) idc.apply_type(ea, idc.parse_decl('{} a;'.format(type), 0), idc.TINFO_DEFINITE)
def force_array(ea, type, name, count=None): t = ida_typeinf.tinfo_t() ida_typeinf.parse_decl(t, None, '{} a;'.format(type), 0) ida_bytes.del_items( ea, ida_bytes.DELIT_EXPAND | ida_bytes.DELIT_DELNAMES | ida_bytes.DELIT_NOCMT, t.get_size() * (1 if count is None else count)) ida_name.set_name(ea, name, ida_name.SN_CHECK) idc.apply_type( ea, idc.parse_decl( '{} a[{}];'.format(type, '' if count is None else str(count)), 0), idc.TINFO_DEFINITE)
def _parse_c_name(self): if self.tif is not None: raise RuntimeError("May not call _parse_c_name twice") # use ida_typeinf.parse_decl to obtain a tinfo_t object tif = ida_typeinf.tinfo_t() decl = "{} x;".format(self.c_name) ida_typeinf.parse_decl(tif, None, decl, ida_typeinf.PT_TYP) if tif.empty(): raise RuntimeError("Could not parse type '{}'".format(self.c_name)) self.tif = tif self
def declaration(self, decl): """ Changes the declaration of the function internally. """ # Ensure ends with ';' if not decl.endswith(";"): decl += ";" tif = ida_typeinf.tinfo_t() til = ida_typeinf.get_idati() func_type_data = ida_typeinf.func_type_data_t() ida_typeinf.parse_decl(tif, til, decl, ida_typeinf.PT_SIL) tif.get_func_details(func_type_data) self._tif = tif self._func_type_data = func_type_data
def from_c(cstr, flags=0x401): """ Function which convert a C string declaration into a object which inherit from a :class:`BipType` . If there is no ``;`` at the end of the string provided, one will be added automatically. This is made for parsing **one** declaration and can create problem if several declarations are in the string. :param str cstr: A string representing a declaration in C. :param int flags: ``PT_*`` flags from IDA (see typeinf.hpp). The default is ``0x401`` (``PT_RAWARGS | PT_SIL``) should be enough in most case. :return: An object which inherit from :class:`BipType` equivalent to the C declaration. :raise RuntimeError: if the function was not able to create the type. """ tif = tinfo_t() cstr = cstr.strip() if cstr[-1] != ';': cstr += ';' if parse_decl(tif, None, cstr, flags) is None: raise RuntimeError( "Unable to create a BipType from declaration {}".format( repr(cstr))) return BipType.from_tinfo_no_copy(tif)
def get_struct_size(struct_def): tif = ida_typeinf.tinfo_t() # Prepare a container for the type til = ida_typeinf.get_idati() # Get the "Local types" types library name = ida_typeinf.parse_decl(tif, til, struct_def, 0) # Parse the declaration, return its return tif.get_size()
def create_struct(name, struct_def, ordinal=0, overwrite=True): if overwrite and ordinal: print "overwriting: {}".format(name) tif = ida_typeinf.tinfo_t() # Prepare a container for the type til = ida_typeinf.get_idati() # Get the "Local types" types library name = ida_typeinf.parse_decl( tif, til, struct_def, ida_typeinf.PT_SIL) # Parse the declaration, return its # name and fill the tinfo_t object # for storing it res = tif.set_numbered_type(til, ordinal, ida_typeinf.NTF_REPLACE, name) # ...and store it else: print "Creating new struct - {}".format(name) # Helpful for debugging #print "<start>{}<end>".format(struct_def) tif = ida_typeinf.tinfo_t() # Prepare a container for the type til = ida_typeinf.get_idati() # Get the "Local types" types library name = ida_typeinf.parse_decl( tif, til, struct_def, ida_typeinf.PT_SIL) # Parse the declaration, return its # name and fill the tinfo_t object if not name: print "Failed to create structure" return False ordinal = ida_typeinf.alloc_type_ordinal( til) # Make room in the "Local types" library, # for storing it res = tif.set_numbered_type(til, ordinal, 0, name) # ...and store it if res == -1: print "Failed to create structure" return False ida_typeinf.import_type(idaapi.cvar.idati, -1, name) return True
def build_callinfo(self, blk, type, callinfo): # it is a good idea to skip direct calls. # note that some indirect calls may be resolved and become direct calls, # and will be filtered out here: ida_kernwin.msg("%x: got called for: %s\n" % (blk.tail.ea, blk.tail.dstr())) tail = blk.tail if tail.opcode == ida_hexrays.m_call: return 0 # also, if the type was specified by the user, do not interfere call_ea = tail.ea tif = ida_typeinf.tinfo_t() if ida_nalt.get_op_tinfo(tif, call_ea, 0): return 0 # ok, the decompiler really has to guess the type. # just for the sake of an example, return a predefined prototype. # in real life you will provide the prototype you discovered yourself, # using your magic of yours :) my_proto = "int f();" ida_kernwin.msg("%x: providing prototype %s\n" % (call_ea, my_proto)) ida_typeinf.parse_decl(type, None, my_proto, 0) return 0
def __typedecl_or_tinfo(typedecl_or_tinfo, flags = None): """ Function that accepts a tinfo_t object or type declaration as a string If a type declaration is passed then ida_typeinf.parse_decl() is applied to prepare tinfo_t object @return: - Returns the tinfo_t object - Raises an exception if the declaration cannot be parsed """ # a string? try to parse it if type(typedecl_or_tinfo) == types.StringType: if flags is None: flags = ida_typeinf.PT_SIL|ida_typeinf.PT_NDC|ida_typeinf.PT_TYP tif = ida_typeinf.tinfo_t() if ida_typeinf.parse_decl(tif, None, typedecl_or_tinfo, flags) == None: raise ValueError, "Could not parse type: " + typedecl_or_tinfo else: if not isinstance(typedecl_or_tinfo, ida_typeinf.tinfo_t): raise ValueError, "Invalid argument 'typedecl_or_tinfo'" tif = typedecl_or_tinfo return tif
def parse_struct(struct_def): tif = ida_typeinf.tinfo_t() til = ida_typeinf.get_idati() name = ida_typeinf.parse_decl(tif, til, struct_def, 0) # Parse the declaration, return its return (til, tif, name)
def make_db2meta(ea): ti = ida_typeinf.tinfo_t() ida_typeinf.parse_decl (ti, None, DBMeta + ' a;', 0) def dword_mem(name): m = ida_typeinf.udt_member_t() m.name = name if ti.find_udt_member (m, ida_typeinf.STRMEM_NAME) == -1: raise Exception ('unknown DBMeta member {}'.format (name)) return butil.get_uint32(ea + m.offset // 8) def qword_mem(name): m = ida_typeinf.udt_member_t() m.name = name if ti.find_udt_member (m, ida_typeinf.STRMEM_NAME) == -1: raise Exception ('unknown DBMeta member {}'.format (name)) return butil.get_uint64(ea + m.offset // 8) nameaddr = qword_mem ('tableName') name = butil.get_cstring (nameaddr).decode('utf-8') butil.mark_string (nameaddr, 'dbMeta_{}_tableName'.format(name)) hfc = dword_mem('hotFixFieldCount') for f in ['hotFixField_offsets', 'hotFixField_sizes', 'hotFixField_types', 'hotFixField_flags',]: butil.force_array( qword_mem(f), 'unsigned int const', 'dbMeta_{}_{}'.format(name, f), hfc) fc = dword_mem('fieldCount') for f in ['fieldSizes', 'fieldTypes', 'fieldFlags']: butil.force_array( qword_mem(f), 'unsigned int const', 'dbMeta_{}_{}'.format(name, f), fc) if dword_mem('nbUniqueIdxByInt'): num = dword_mem('nbUniqueIdxByInt') butil.force_array( qword_mem('uniqueIdxByInt'), '{} const'.format (DBMeta_intidx), 'dbMeta_{}_uniqueIdxByInt'.format(name), num) if dword_mem('nbUniqueIdxByString'): num = dword_mem('nbUniqueIdxByString') butil.force_array( qword_mem('uniqueIdxByString'), '{} const'.format (DBMeta_stridx), 'dbMeta_{}_uniqueIdxByString'.format(name), num) rec = tutil.maybe_make_dummy_type_with_known_size ('{}Rec'.format(name), dword_mem ('record_size')) if qword_mem ('sortFunc'): fp = qword_mem ('sortFunc') butil.force_function(fp, 'bool f({rec} const*, {rec} const*)'.format(rec=rec), '{}::sort'.format(rec)) if qword_mem ('sortFuncIndirect'): fp = qword_mem ('sortFuncIndirect') butil.force_function(fp, 'bool f({rec} const* const*, {rec} const* const*)'.format(rec=rec), '{}::sortIndirect'.format(rec)) butil.force_variable (ea, '{} const'.format(DBMeta), 'dbMeta_{}'.format(name)) return name
def convert_type_str_to_ida_type(type_str) -> typing.Optional['ida_typeinf']: ida_type_str = type_str + ";" tif = ida_typeinf.tinfo_t() valid_parse = ida_typeinf.parse_decl(tif, None, ida_type_str, 1) return tif if valid_parse is not None else None