def import_c_header(path, pack=0, raw_args=True, silent=False, autoimport=True): """ Import a C header file. :param str path: The path to the C header file to import. :param int pack: The packing for the structure in the header. 0 means default (from compiler/configuration), other values are power of 2 up to 16. No verification is made on that value. :param bool raw_args: Should leave the name of the argument unchanged: do not remove the _ in the name. True by default. :param bool silent: Should silently fails on error and mask warnings. :param bool autoimport: If True (the default), this function will import all new types in the IDB ("Structures", "Enums", ... Views), instead of only keeping them in the type library (til, the "Local Types" view). :return: The number of error which occur during parsing. """ # This use the idc.parse_decls function, which is different of the # ida_typeinf.parse_decls function, this one should be implemented # using the type library flags = ida_typeinf.PT_FILE | ida_typeinf.PT_REPLACE if raw_args: flags |= ida_typeinf.PT_RAWARGS if silent: flags |= ida_typeinf.PT_SIL # handle pack conversion, hugly but should be ok if pack <= 2: flags |= (pack << 4) & ida_typeinf.PT_PACKMASK else: if pack == 4: flags |= (3 << 4) & ida_typeinf.PT_PACKMASK elif pack == 8: flags |= (4 << 4) & ida_typeinf.PT_PACKMASK elif pack == 16: flags |= (5 << 4) & ida_typeinf.PT_PACKMASK if autoimport: tidft = ida_typeinf.get_idati() # default type lib of the idb # we get the nb of ordinal type, before parsing nb_typ = ida_typeinf.get_ordinal_qty(tidft) # now we make the parsing nb_error = idc.parse_decls(path, flags) # get the new number of types after it has been parsed nb_typ_after = ida_typeinf.get_ordinal_qty(tidft) # now we can import all of them for i in range(nb_typ, nb_typ_after): # get the name of the type na = ida_typeinf.get_numbered_type_name(tidft, i) # import the type, put it at the end ida_typeinf.import_type(tidft, -1, na) return nb_error else: return idc.parse_decls(path, flags)
def __call__(self): from .core import Core dll = Core.get_ida_dll() get_idati = dll.get_idati get_idati.argtypes = [] get_idati.restype = ctypes.c_void_p set_numbered_type = dll.set_numbered_type set_numbered_type.argtypes = [ ctypes.c_void_p, ctypes.c_uint32, ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int, ] set_numbered_type.restype = ctypes.c_int py_ti = ida_typeinf.get_idati() ordinal_qty = ida_typeinf.get_ordinal_qty(py_ti) - 1 last_ordinal = self.local_types[-1][0] if ordinal_qty < last_ordinal: ida_typeinf.alloc_type_ordinals(py_ti, last_ordinal - ordinal_qty) else: for py_ordinal in range(last_ordinal + 1, ordinal_qty + 1): ida_typeinf.del_numbered_type(py_ti, py_ordinal) local_types = self.local_types for py_ord, name, type, fields, cmt, fieldcmts, sclass in local_types: if type: ti = get_idati() ordinal = ctypes.c_uint32(py_ord) ntf_flags = ctypes.c_int(ida_typeinf.NTF_REPLACE) name = ctypes.c_char_p(name) type = ctypes.c_char_p(type) fields = ctypes.c_char_p(fields) cmt = ctypes.c_char_p(cmt) fieldcmts = ctypes.c_char_p(fieldcmts) sclass = ctypes.c_int(sclass) set_numbered_type( ti, ordinal, ntf_flags, name, type, fields, cmt, fieldcmts, sclass, ) else: ida_typeinf.del_numbered_type(py_ti, py_ord) ida_kernwin.request_refresh(ida_kernwin.IWID_LOCTYPS)
def local_types_changed(self): from .core import Core dll = Core.get_ida_dll() get_idati = dll.get_idati get_idati.argtypes = [] get_idati.restype = ctypes.c_void_p get_numbered_type = dll.get_numbered_type get_numbered_type.argtypes = [ ctypes.c_void_p, ctypes.c_uint32, ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_int), ] get_numbered_type.restype = ctypes.c_bool local_types = [] py_ti = ida_typeinf.get_idati() for py_ord in range(1, ida_typeinf.get_ordinal_qty(py_ti)): name = ida_typeinf.get_numbered_type_name(py_ti, py_ord) ti = get_idati() ordinal = ctypes.c_uint32(py_ord) type = ctypes.c_char_p() fields = ctypes.c_char_p() cmt = ctypes.c_char_p() fieldcmts = ctypes.c_char_p() sclass = ctypes.c_int() get_numbered_type( ti, ordinal, ctypes.pointer(type), ctypes.pointer(fields), ctypes.pointer(cmt), ctypes.pointer(fieldcmts), ctypes.pointer(sclass), ) local_types.append( ( py_ord, name, type.value, fields.value, cmt.value, fieldcmts.value, sclass.value, ) ) self._send_packet(evt.LocalTypesChangedEvent(local_types)) return 0
def local_types_changed(self): local_types = [] ti = ida_typeinf.get_idati() for ordinal in range(1, ida_typeinf.get_ordinal_qty(ti)): name = ida_typeinf.get_numbered_type_name(ti, ordinal) type_info = ida_typeinf.tinfo_t() type_info.get_numbered_type(ti, ordinal) ret = type_info.serialize() local_types.append((ordinal, name, ret)) self._send_packet(evt.LocalTypesChangedEvent(local_types)) return 0
def local_types_changed(self): local_types = [] for ordinal in range(1, ida_typeinf.get_ordinal_qty(None)): ret = ida_typeinf.idc_get_local_type_raw(ordinal) if ret is not None: type_str, fields_str = ret type_name = ida_typeinf.get_numbered_type_name( ida_typeinf.cvar.idati, ordinal ) cur_ti = ida_typeinf.tinfo_t() cur_ti.deserialize( ida_typeinf.cvar.idati, type_str, fields_str ) type_serialized = cur_ti.serialize() local_types.append( ( ordinal, type_serialized[0], type_serialized[1], type_name, ) ) else: local_types.append(None) if self.last_local_type is None: self.last_local_type = local_types sent_types = local_types else: def differ_local_types(types1, types2): # [(i, types1, types2), ...] ret_types = [] for i in range(max([len(types1), len(types2)])): if i >= len(types1): ret_types.append((i, None, types2[i])) elif i >= len(types2): ret_types.append((i, types1[i], None)) else: if types1[i] != types2[i]: ret_types.append((i, types1[i], types2[i])) return ret_types diff = differ_local_types(self.last_local_type, local_types) self.last_local_type = local_types if len(diff) == 1 and diff[0][2] is None: return 0 elif len(diff) == 0: return 0 sent_types = [t[2] for t in diff] self._send_packet(evt.LocalTypesChangedEvent(sent_types)) return 0
def local_types_changed(self): print("local type changed") return changed_types = [] # self._plugin.logger.trace(self._plugin.core.local_type_map) for i in range(1, ida_typeinf.get_ordinal_qty(ida_typeinf.get_idati())): t = ImportLocalType(i) if t and t.name and ida_struct.get_struc_id( t.name) == ida_idaapi.BADADDR and ida_enum.get_enum( t.name) == ida_idaapi.BADADDR: if i in self._plugin.core.local_type_map: t_old = self._plugin.core.local_type_map[i] if t_old and not t.isEqual(t_old): changed_types.append((t_old.to_tuple(), t.to_tuple())) elif t_old is None and i in self._plugin.core.delete_candidates: if not self._plugin.core.delete_candidates[i].isEqual( t): changed_types.append( (self._plugin.core.delete_candidates[i]. to_tuple(), t.to_tuple())) del self._plugin.core.delete_candidates[i] else: changed_types.append((None, t.to_tuple())) if t is None: assert i in self._plugin.core.local_type_map if i in self._plugin.core.local_type_map: t_old = self._plugin.core.local_type_map[i] if t_old != t: self._plugin.core.delete_candidates[i] = t_old elif i in self._plugin.core.delete_candidates: # changed_types.append((self._plugin.core.delete_candidates[i],None)) del self._plugin.core.delete_candidates[i] # t_old = self._plugin.core.local_type_map[i] # changed_types.append((t_old,None)) # self._plugin.logger.trace(changed_types) if fDebug: pydevd_pycharm.settrace('localhost', port=2233, stdoutToServer=True, stderrToServer=True, suspend=False) self._plugin.logger.trace("Changed_types: %s" % list( map( lambda x: (x[0][0] if x[0] else None, x[1][0] if x[1] else None), changed_types))) if len(changed_types) > 0: self._send_packet(evt.LocalTypesChangedEvent(changed_types)) self._plugin.core.update_local_types_map() return 0
def __process_types(self): localtypes = [] ti_lib_obj = ida_typeinf.get_idati() ti_lib_count = ida_typeinf.get_ordinal_qty(ti_lib_obj) for ti_ordinal in range(1, ti_lib_count + 1): ti_info = ida_typeinf.tinfo_t() if ti_info.get_numbered_type(ti_lib_obj, ti_ordinal): localtypes.append(self.__process_types_tinfo(ti_info)) return localtypes
def local_types_changed(self): local_types = [] for ordinal in range(1, ida_typeinf.get_ordinal_qty(None)): ret = ida_typeinf.idc_get_local_type_raw(ordinal) if ret is not None: type_str, fields_str = ret type_name = ida_typeinf.get_numbered_type_name( ida_typeinf.cvar.idati, ordinal) cur_ti = ida_typeinf.tinfo_t() cur_ti.deserialize(ida_typeinf.cvar.idati, type_str, fields_str) type_serialized = cur_ti.serialize() local_types.append( (type_serialized[0], type_serialized[1], type_name)) else: local_types.append(None) self._send_event(LocalTypesChangedEvent(local_types)) return 0
def __call__(self): ti = ida_typeinf.get_idati() ordinal_qty = ida_typeinf.get_ordinal_qty(ti) last_ordinal = self.local_types[-1][0] if ordinal_qty < last_ordinal: ida_typeinf.alloc_type_ordinals(ti, last_ordinal - ordinal_qty) else: for ordinal in range(last_ordinal + 1, ordinal_qty + 1): ida_typeinf.del_numbered_type(ti, ordinal) for ordinal, name, ret in self.local_types: name = Event.encode_bytes(name) type, fields, fieldcmts = ret type = Event.encode_bytes(type) fields = Event.encode_bytes(fields) fieldcmts = Event.encode_bytes(fieldcmts) type_info = ida_typeinf.tinfo_t() type_info.deserialize(ti, type, fields, fieldcmts) type_info.set_numbered_type(ti, ordinal, 0, name) ida_kernwin.request_refresh(ida_kernwin.IWID_LOCTYPS)
def __call__(self): local_type = [] for t in self.local_type: if t is not None: local_type.append(( Event.encode_bytes(t[0]), Event.encode_bytes(t[1]), Event.encode_bytes(t[2]), )) else: local_type.append(None) missing_ord = len(local_type) - ida_typeinf.get_ordinal_qty(None) + 1 if missing_ord > 0: ida_typeinf.alloc_type_ordinals(None, missing_ord) for i, t in enumerate(local_type): if t is not None: cur_tinfo = ida_typeinf.tinfo_t() cur_tinfo.deserialize(None, t[0], t[1]) cur_tinfo.set_numbered_type(None, i + 1, 0, t[2]) else: ida_typeinf.del_numbered_type(None, i + 1) ida_kernwin.request_refresh(ida_kernwin.IWID_LOCTYPS)
def alloc_oridinal(target_ordinal): # Get_ordinal_qty() will return (current max ordinal + 1) missing_ord = (target_ordinal - ida_typeinf.get_ordinal_qty(None) + 1) if missing_ord > 0: ida_typeinf.alloc_type_ordinals(None, missing_ord)
def export(self): """ Show an export dialog to export symbols and header file for given IDB. :return: None """ class ExportForm(Form): def __init__(self): description = ''' <h2>Export</h2> Select a directory to export IDB data into. ''' Form.__init__(self, r"""BUTTON YES* Save Export {StringLabel} <#Symbols#Symbols filename:{iSymbolsFilename}> <#C Header#C Header filename:{iHeaderFilename}> <#ifdef_macro#ifdef'ed:{iIfdef}> <#Select dir#Browse for dir:{iDir}> """, { 'iDir': Form.DirInput(), 'StringLabel': Form.StringLabel(description, tp=Form.FT_HTML_LABEL), 'iSymbolsFilename': Form.StringInput( value='symbols.txt'), 'iHeaderFilename': Form.StringInput( value='fa_structs.h'), 'iIfdef': Form.StringInput( value='FA_STRUCTS_H'), }) self.__n = 0 def OnFormChange(self, fid): return 1 form = ExportForm() form, args = form.Compile() ok = form.Execute() if ok == 1: # save symbols symbols_filename = os.path.join(form.iDir.value, form.iSymbolsFilename.value) with open(symbols_filename, 'w') as f: results = IdaLoader.extract_all_user_names(None) for k, v in sorted(results.items()): f.write('{} = 0x{:08x};\n'.format(k, v)) # save c header idati = ida_typeinf.get_idati() c_header_filename = os.path.join(form.iDir.value, form.iHeaderFilename.value) consts_ordinal = None ordinals = [] for ordinal in range(1, ida_typeinf.get_ordinal_qty(idati) + 1): ti = ida_typeinf.tinfo_t() if ti.get_numbered_type(idati, ordinal): if ti.get_type_name() == 'FA_CONSTS': # convert into macro definitions consts_ordinal = ordinal elif ti.get_type_name() in ('__va_list_tag', 'va_list'): continue elif '$' in ti.get_type_name(): # skip deleted types continue else: ordinals.append(str(ordinal)) with open(c_header_filename, 'w') as f: ifdef_name = form.iIfdef.value.strip() if len(ifdef_name) > 0: f.write('#ifndef {ifdef_name}\n' '#define {ifdef_name}\n\n' .format(ifdef_name=ifdef_name)) if consts_ordinal is not None: consts = re.findall('\s*(.+?) = (.+?),', idc.print_decls( str(consts_ordinal), 0)) for k, v in consts: f.write('#define {} ({})\n'.format(k, v)) # ida exports using this type f.write('#define _BYTE char\n') f.write('\n') structs_buf = idc.print_decls(','.join(ordinals), idc.PDF_DEF_BASE) for struct_type, struct_name in re.findall( r'(struct|enum) .*?([a-zA-Z0-9_\-]+?)\s+\{', structs_buf): f.write( 'typedef {struct_type} {struct_name} {struct_name};\n' .format(struct_type=struct_type, struct_name=struct_name)) structs_buf = structs_buf.replace('__fastcall', '') f.write('\n') f.write(structs_buf) f.write('\n') if len(ifdef_name) > 0: f.write('#endif // {ifdef_name}\n' .format(ifdef_name=ifdef_name)) form.Free()
def update_local_types_map(self): for i in range(1, ida_typeinf.get_ordinal_qty(ida_typeinf.get_idati())): t = ImportLocalType(i) self.local_type_map[i] = t