def import_to_structures(self, ask=False): """ Imports virtual tables and returns tid_t of new structure :return: idaapi.tid_t """ cdecl_typedef = idaapi.print_tinfo( None, 4, 5, idaapi.PRTYPE_MULTI | idaapi.PRTYPE_TYPE | idaapi.PRTYPE_SEMI, self.create_tinfo(), self.vtable_name, None) if ask: cdecl_typedef = idaapi.ask_text( 0x10000, cdecl_typedef, "The following new type will be created") if not cdecl_typedef: return previous_ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati, self.vtable_name) if previous_ordinal: idaapi.del_numbered_type(idaapi.cvar.idati, previous_ordinal) ordinal = idaapi.idc_set_local_type(previous_ordinal, cdecl_typedef, idaapi.PT_TYP) else: ordinal = idaapi.idc_set_local_type(-1, cdecl_typedef, idaapi.PT_TYP) if ordinal: print("[Info] Virtual table " + self.vtable_name + " added to Local Types") return idaapi.import_type(idaapi.cvar.idati, -1, self.vtable_name) else: print("[Error] Failed to create virtual table " + self.vtable_name) print("*" * 100) print(cdecl_typedef) print("*" * 100)
def pack(self, start=0, stop=None): if self.collisions[start:stop].count(True): print("[Warning] Collisions detected") return final_tinfo = idaapi.tinfo_t() udt_data = idaapi.udt_type_data_t() origin = self.items[start].offset if start else 0 offset = origin for item in [x for x in self.items[start:stop] if x.enabled]: # Filter disabled members gap_size = item.offset - offset if gap_size: udt_data.push_back( helper.create_padding_udt_member(offset - origin, gap_size)) if item.is_array: array_size = self.calculate_array_size( bisect.bisect_left(self.items, item)) if array_size: udt_data.push_back( item.get_udt_member(array_size, offset=origin)) offset = item.offset + item.size * array_size continue udt_data.push_back(item.get_udt_member(offset=origin)) offset = item.offset + item.size final_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT) cdecl = idaapi.print_tinfo( None, 4, 5, idaapi.PRTYPE_MULTI | idaapi.PRTYPE_TYPE | idaapi.PRTYPE_SEMI, final_tinfo, self.get_name(), None) cdecl = idaapi.ask_text(0x10000, '#pragma pack(push, 1)\n' + cdecl, "The following new type will be created") if cdecl: structure_name = idaapi.idc_parse_decl(idaapi.cvar.idati, cdecl, idaapi.PT_TYP)[0] previous_ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati, structure_name) if previous_ordinal: reply = QtWidgets.QMessageBox.question( None, "HexRaysPyTools", "Structure already exist. Do you want to overwrite it?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.Yes: idaapi.del_numbered_type(idaapi.cvar.idati, previous_ordinal) ordinal = idaapi.idc_set_local_type( previous_ordinal, cdecl, idaapi.PT_TYP) else: return else: ordinal = idaapi.idc_set_local_type(-1, cdecl, idaapi.PT_TYP) if ordinal: print("[Info] New type {0} was added to Local Types".format( structure_name)) tid = idaapi.import_type(idaapi.cvar.idati, -1, structure_name) if tid: tinfo = idaapi.create_typedef(structure_name) ptr_tinfo = idaapi.tinfo_t() ptr_tinfo.create_ptr(tinfo) for scanned_var in self.get_unique_scanned_variables( origin): scanned_var.apply_type(ptr_tinfo) return tinfo else: print("[ERROR] Structure {0} probably already exist".format( structure_name))
def activate(self, ctx): hx_view = idaapi.get_widget_vdui(ctx.widget) if not self.check(hx_view): return item = hx_view.item.it.to_specific_type parent = hx_view.cfunc.body.find_parent_of(item).to_specific_type if parent.op != idaapi.cot_idx or parent.y.op != idaapi.cot_num: idx = 0 else: idx = parent.y.numval() struct_tinfo = item.x.type struct_tinfo.remove_ptr_or_array() offset = item.m ordinal = struct_tinfo.get_ordinal() struct_name = struct_tinfo.dstr() if (offset + idx) % 2: default_field_type = "_BYTE" elif (offset + idx) % 4: default_field_type = "_WORD" elif (offset + idx) % 8: default_field_type = "_DWORD" else: default_field_type = "_QWORD" if const.EA64 else "_DWORD" declaration = idaapi.ask_text( 0x10000, "{0} field_{1:X}".format(default_field_type, offset + idx), "Enter new structure member:" ) if declaration is None: return result = self.parse_declaration(declaration) if result is None: logger.warn("Bad member declaration") return field_tinfo, field_name = result field_size = field_tinfo.get_size() udt_data = idaapi.udt_type_data_t() udt_member = idaapi.udt_member_t() struct_tinfo.get_udt_details(udt_data) udt_member.offset = offset * 8 struct_tinfo.find_udt_member(udt_member, idaapi.STRMEM_OFFSET) gap_size = udt_member.size // 8 gap_leftover = gap_size - idx - field_size if gap_leftover < 0: logger.error("Too big size for the field. Type with maximum {0} bytes can be used".format(gap_size - idx)) return iterator = udt_data.find(udt_member) iterator = udt_data.erase(iterator) if gap_leftover > 0: udt_data.insert(iterator, helper.create_padding_udt_member(offset + idx + field_size, gap_leftover)) udt_member = idaapi.udt_member_t() udt_member.offset = offset * 8 + idx udt_member.name = field_name udt_member.type = field_tinfo udt_member.size = field_size iterator = udt_data.insert(iterator, udt_member) if idx > 0: udt_data.insert(iterator, helper.create_padding_udt_member(offset, idx)) struct_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT) struct_tinfo.set_numbered_type(idaapi.cvar.idati, ordinal, idaapi.BTF_STRUCT, struct_name) hx_view.refresh_view(True)