def structure_info_create(vtbs): for vtb in vtbs: vtb_name = "vtb_" + (hex(vtb.get("vtb_start_addr"))[2:-1]).upper() # 创建结构体 udt_data = idaapi.udt_type_data_t() # 函数名称记录列表 func_name_records_list = [] # 添加结构体的成员 for mem in vtb.get('vtb_func_lists'): # 创建成员 udt_member = idaapi.udt_member_t() udt_member.type = ptr_type("DWORD") udt_member.name = name_filter(mem.get('func_name')) # 如果名字为空,需要进行特殊的处理 # MEMORY[xxxx] # print udt_member.name if udt_member.name == None or udt_member.name == "": udt_member.name = "memory_" + (hex( mem.get("func_addr"))[2:]).upper() # 防止函数名称重复 if udt_member.name in func_name_records_list: udt_member.name += "1" func_name_records_list.append(udt_member.name) # print udt_member.name # 插入结构体 udt_data.push_back(udt_member) build_structure_in_ida(udt_data, vtb_name)
def type_equals_to(self, tinfo): udt_data = idaapi.udt_type_data_t() if tinfo.is_ptr() and tinfo.get_pointed_object().get_udt_details( udt_data): if udt_data[0].type.is_funcptr(): return True return False
def find_containing_structures(self, type_library): """ Given the type library creates a list of structures from this library, that contains this structure and satisfy offset conditions. :param type_library: idaapi.til_t :returns: ordinal, offset, member_name, containing structure name """ min_offset = min(self.offsets) min_offset = min_offset if min_offset < 0 else 0 max_offset = max(self.offsets) max_offset = max_offset if max_offset > 0 else self.tinfo.get_size() # TODO: Check if all offsets are legal # Least acceptable size of the containing structure min_struct_size = max_offset - min_offset result = [] parent_tinfo = idaapi.tinfo_t() udt_data = idaapi.udt_type_data_t() target_tinfo = idaapi.tinfo_t() if not target_tinfo.get_named_type(type_library, self.tinfo.dstr()): print "[Warning] Such type doesn't exist in '{0}' library".format( type_library.name) return result for ordinal in xrange(1, idaapi.get_ordinal_qty(type_library)): parent_tinfo.create_typedef(type_library, ordinal) if parent_tinfo.get_size() >= min_struct_size: for offset, name in find_deep_members(parent_tinfo, target_tinfo): # print "[DEBUG] Found {0} at {1} in {2}".format(name, offset, parent_tinfo.dstr()) if offset + min_offset >= 0 and offset + max_offset <= parent_tinfo.get_size( ): result.append( (ordinal, offset, name, parent_tinfo.dstr())) return result
def get_fields_at_offset(tinfo, offset): """ Given tinfo and offset of the structure or union, returns list of all tinfo at that offset. This function helps to find appropriate structures by type of the offset """ result = [] if offset == 0: result.append(tinfo) udt_data = idaapi.udt_type_data_t() tinfo.get_udt_details(udt_data) udt_member = idaapi.udt_member_t() udt_member.offset = offset * 8 idx = tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member) if idx != -1: while idx < tinfo.get_udt_nmembers( ) and udt_data[idx].offset <= offset * 8: udt_member = udt_data[idx] if udt_member.offset == offset * 8: if udt_member.type.is_ptr(): result.append(idaapi.get_unk_type(Const.EA_SIZE)) result.append(udt_member.type) result.append(idaapi.dummy_ptrtype(Const.EA_SIZE, False)) elif not udt_member.type.is_udt(): result.append(udt_member.type) if udt_member.type.is_array(): if (offset - udt_member.offset / 8 ) % udt_member.type.get_array_element().get_size() == 0: result.append(udt_member.type.get_array_element()) elif udt_member.type.is_udt(): result.extend( get_fields_at_offset(udt_member.type, offset - udt_member.offset / 8)) idx += 1 return result
def visit_expr(self, expression): if expression.op == idaapi.cot_call and expression.x.op == idaapi.cot_helper and len( expression.a) == 3: if expression.x.helper == "CONTAINING_RECORD": if expression.a[0].op == idaapi.cot_var: idx = expression.a[0].v.idx if expression.a[1].op == idaapi.cot_helper and expression.a[ 2].op == idaapi.cot_helper: parent_name = expression.a[1].helper member_name = expression.a[2].helper parent_tinfo = idaapi.tinfo_t() if not parent_tinfo.get_named_type( idaapi.cvar.idati, parent_name): return 0 udt_data = idaapi.udt_type_data_t() parent_tinfo.get_udt_details(udt_data) udt_member = filter(lambda x: x.name == member_name, udt_data) if udt_member: tinfo = udt_member[0].type self.result[idx] = NegativeLocalInfo( tinfo, parent_tinfo, udt_member[0].offset // 8, member_name) return 1 return 0
def type(self): self.ti = idaapi.tinfo_t() self.sti = idaapi.udt_type_data_t() if idaapi.guess_tinfo(self.id, self.ti) != idaapi.GUESS_FUNC_OK: print "[-] can't guess `%s` type" % self.name return return Type(self.ti)
def activate(self, ctx): hx_view = idaapi.get_widget_vdui(ctx.widget) ri = self.extract_recast_info(hx_view.cfunc, hx_view.item) if not ri: return 0 if isinstance(ri, RecastLocalVariable): hx_view.set_lvar_type(ri.local_variable, ri.recast_tinfo) elif isinstance(ri, RecastGlobalVariable): idaapi.apply_tinfo2(ri.global_variable_ea, ri.recast_tinfo, idaapi.TINFO_DEFINITE) elif isinstance(ri, RecastArgument): if ri.recast_tinfo.is_array(): ri.recast_tinfo.convert_array_to_ptr() helper.set_func_argument(ri.func_tinfo, ri.arg_idx, ri.recast_tinfo) idaapi.apply_tinfo2(ri.func_ea, ri.func_tinfo, idaapi.TINFO_DEFINITE) elif isinstance(ri, RecastReturn): cfunc = helper.decompile_function(ri.func_ea) if not cfunc: return 0 func_tinfo = idaapi.tinfo_t() cfunc.get_func_type(func_tinfo) helper.set_func_return(func_tinfo, ri.recast_tinfo) idaapi.apply_tinfo2(cfunc.entry_ea, func_tinfo, idaapi.TINFO_DEFINITE) elif isinstance(ri, RecastStructure): tinfo = idaapi.tinfo_t() tinfo.get_named_type(idaapi.cvar.idati, ri.structure_name) ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati, ri.structure_name) if ordinal == 0: return 0 udt_member = idaapi.udt_member_t() udt_member.offset = ri.field_offset * 8 idx = tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member) if udt_member.offset != ri.field_offset * 8: print("[Info] Can't handle with arrays yet") elif udt_member.type.get_size() != ri.recast_tinfo.get_size(): print("[Info] Can't recast different sizes yet") else: udt_data = idaapi.udt_type_data_t() tinfo.get_udt_details(udt_data) udt_data[idx].type = ri.recast_tinfo tinfo.create_udt(udt_data, idaapi.BTF_STRUCT) tinfo.set_numbered_type(idaapi.cvar.idati, ordinal, idaapi.NTF_REPLACE, ri.structure_name) else: raise NotImplementedError hx_view.refresh_view(True) return 0
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 filter(lambda x: x.enabled, self.items[start:stop]): # Filter disabled members gap_size = item.offset - offset if gap_size: udt_data.push_back(TemporaryStructureModel.get_padding_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.structure_name, None) cdecl = idaapi.asktext(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 = QtGui.QMessageBox.question( None, "HexRaysPyTools", "Structure already exist. Do you want to overwrite it?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No ) if reply == QtGui.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 get_members_ordinals(tinfo): ordinals = [] if tinfo.is_udt(): udt_data = idaapi.udt_type_data_t() tinfo.get_udt_details(udt_data) for udt_member in udt_data: ordinal = StructureGraph.get_ordinal(udt_member.type) if ordinal: ordinals.append(ordinal) return ordinals
def update_local_type(self): if self.modified: for vtable in list(self.vtables.values()): vtable.update_local_type() udt_data = idaapi.udt_type_data_t() tinfo = idaapi.tinfo_t() self.tinfo.get_udt_details(udt_data) tinfo.create_udt(udt_data, idaapi.BTF_STRUCT) tinfo.set_numbered_type(idaapi.cvar.idati, self.ordinal, idaapi.NTF_REPLACE, self.name) self.modified = False
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 offset = origin for item in filter(lambda x: x.enabled, self.items[start:stop]): # Filter disabled members gap_size = item.offset - offset if gap_size: udt_data.push_back( TemporaryStructureModel.get_padding_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.structure_name, None) cdecl = idaapi.asktext(0x10000, cdecl, "The following new type will be created") if cdecl: structure_name = idaapi.idc_parse_decl(idaapi.cvar.idati, cdecl, idaapi.PT_TYP)[0] 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_scanned_variables(origin): scanned_var.apply_type(ptr_tinfo) return tinfo else: print "[ERROR] Structure {0} probably already exist".format( structure_name) return None
def create_tinfo(self): # print "(Virtual table) at address: 0x{0:08X} name: {1}".format(self.address, self.name) udt_data = idaapi.udt_type_data_t() for function in self.virtual_functions: udt_data.push_back(function.get_udt_member()) final_tinfo = idaapi.tinfo_t() if final_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT): # print "\n\t(Final structure)\n" + idaapi.print_tinfo('\t', 4, 5, idaapi.PRTYPE_MULTI | idaapi.PRTYPE_TYPE # | idaapi.PRTYPE_SEMI, final_tinfo, self.name, None) return final_tinfo print "[ERROR] Virtual table creation failed"
def find_deep_members(parent_tinfo, target_tinfo): udt_data = idaapi.udt_type_data_t() parent_tinfo.get_udt_details(udt_data) result = [] for udt_member in udt_data: if udt_member.type.equals_to(target_tinfo): result.append((udt_member.offset / 8, udt_member.name)) elif udt_member.type.is_udt(): for offset, name in find_deep_members(udt_member.type, target_tinfo): final_name = udt_member.name + '.' + name if udt_member.name else name result.append((udt_member.offset / 8 + offset, final_name)) return result
def create(tinfo, class_): ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati, tinfo.dstr()) result = all_virtual_tables.get(ordinal) if result: result.class_.append(class_) else: udt_data = idaapi.udt_type_data_t() tinfo.get_udt_details(udt_data) result = VirtualTable(ordinal, tinfo, class_) virtual_functions = [VirtualMethod.create(func.type, func.name, result) for func in udt_data] result.virtual_functions = virtual_functions all_virtual_functions[ordinal] = result return result
def update(self): if self.modified: vtable_tinfo = idaapi.tinfo_t() udt_data = idaapi.udt_type_data_t() vtable_tinfo.get_numbered_type(idaapi.cvar.idati, self.ordinal) vtable_tinfo.get_udt_details(udt_data) self.tinfo = vtable_tinfo self.name = vtable_tinfo.dstr() self.modified = False if len(self.virtual_functions) == len(udt_data): for current_function, other_function in zip(self.virtual_functions, udt_data): current_function.update(other_function.name, other_function.type) else: print("[ERROR] Something have been modified in Local types. Please refresh this view")
def tinfo(self): udt = idaapi.udt_type_data_t() for m in self.members: new_member = idaapi.udt_member_t() new_member.name = m.name new_member.type = m.tinfo new_member.size = m.size new_member.offset = m.offset udt.push_back(new_member) final_tinfo = idaapi.tinfo_t() if final_tinfo.create_udt(udt, idaapi.BTF_STRUCT): return final_tinfo
def __init__(self, ti): self.ti = ti self.extra = None if self.ti.is_func(): self.extra = idaapi.func_type_data_t() if not self.ti.get_func_details(self.extra): print "[-] can't get function's type details" return elif self.ti.is_struct(): self.extra = idaapi.udt_type_data_t() if not self.ti.get_udt_details(self.extra): print "[-] can't get struct's type details" return
def update_local_type(self): if self.modified: final_tinfo = idaapi.tinfo_t() udt_data = idaapi.udt_type_data_t() self.tinfo.get_udt_details(udt_data) if len(udt_data) == len(self.virtual_functions): for udt_member, virtual_function in zip(udt_data, self.virtual_functions): udt_member.name = virtual_function.name udt_member.type = virtual_function.tinfo virtual_function.commit() final_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT) final_tinfo.set_numbered_type(idaapi.cvar.idati, self.ordinal, idaapi.NTF_REPLACE, self.name) self.modified = False else: print("[ERROR] Something have been modified in Local types. Please refresh this view")
def create_class(ordinal): tinfo = idaapi.tinfo_t() tinfo.get_numbered_type(idaapi.cvar.idati, ordinal) vtables = {} if tinfo.is_struct(): udt_data = idaapi.udt_type_data_t() tinfo.get_udt_details(udt_data) for field_udt in udt_data: if field_udt.type.is_ptr(): possible_vtable = field_udt.type.get_pointed_object() if possible_vtable.is_struct(): v_udt_data = idaapi.udt_type_data_t() possible_vtable.get_udt_details(v_udt_data) for possible_func_udt in v_udt_data: if not possible_func_udt.type.is_funcptr(): break else: vtables[field_udt.offset // 8] = possible_vtable if vtables: class_ = Class(tinfo.dstr(), tinfo, ordinal) for offset, vtable_tinfo in vtables.items(): vtables[offset] = VirtualTable.create(vtable_tinfo, class_) class_.vtables = vtables return class_
def unpack_substructure(self, indices): if indices is None or len(indices) != 1: return item = self.items[indices[0].row()] if item.tinfo is not None and item.tinfo.is_udt(): self.remove_items(indices) offset = item.offset udt_data = idaapi.udt_type_data_t() if item.tinfo.get_udt_details(udt_data): for udt_item in udt_data: member = Member(offset + udt_item.offset / 8, udt_item.type, None) member.name = udt_item.name self.add_row(member)
def create(tinfo, class_): ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati, tinfo.dstr()) if ordinal == 0: if idaapi.import_type(idaapi.cvar.idati, -1, tinfo.dstr(), 0) == idaapi.BADNODE: raise ImportError("unable to import type to idb ({})".format(tinfo.dstr())) ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati, tinfo.dstr()) result = all_virtual_tables.get(ordinal) if result: result.class_.append(class_) else: udt_data = idaapi.udt_type_data_t() tinfo.get_udt_details(udt_data) result = VirtualTable(ordinal, tinfo, class_) virtual_functions = [VirtualMethod.create(func.type, func.name, result) for func in udt_data] result.virtual_functions = virtual_functions all_virtual_functions[ordinal] = result return result
def create_tinfo(self): # print "(Virtual table) at address: 0x{0:08X} name: {1}".format(self.address, self.name) udt_data = idaapi.udt_type_data_t() for function in self.virtual_functions: udt_data.push_back(function.get_udt_member()) for duplicates in Helper.search_duplicate_fields(udt_data): first_entry_idx = duplicates.pop(0) print "[Warning] Found duplicate virtual functions", udt_data[first_entry_idx].name for num, dup in enumerate(duplicates): udt_data[dup].name = "duplicate_{0}_{1}".format(first_entry_idx, num + 1) tinfo = idaapi.tinfo_t() tinfo.create_ptr(Const.DUMMY_FUNC) udt_data[dup].type = tinfo final_tinfo = idaapi.tinfo_t() if final_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT): # print "\n\t(Final structure)\n" + idaapi.print_tinfo('\t', 4, 5, idaapi.PRTYPE_MULTI | idaapi.PRTYPE_TYPE # | idaapi.PRTYPE_SEMI, final_tinfo, self.name, None) return final_tinfo print "[ERROR] Virtual table creation failed"
def __init__(self, type): self.logger = logging.getLogger(__name__) self.name = "" self.size = 0 self.element_num = 0 self.is_union = False self.elements = [] self.type_info = type self.udt_type_data = idaapi.udt_type_data_t() try: if self.getStructData(): self.getElements() except Exception as ex: self.logger.exception("Error while extracting Struct data: %s", idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, type, '', ''), ex) return False
def __init__(self, type): self.logger = logging.getLogger(__name__) self.name = "" self.size = 0 self.element_num = 0 self.is_union = False self.elements = [] self.type_info = type self.udt_type_data = idaapi.udt_type_data_t() try: if self.getStructData(): self.getElements() except Exception as ex: self.logger.exception( "Error while extracting Struct data: %s", idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, type, '', ''), ex) return False
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)
def activate(self, ctx): hx_view = idaapi.get_tform_vdui(ctx.form) result = self.check(hx_view.cfunc, hx_view.item) if result: if result[0] == RECAST_LOCAL_VARIABLE: tinfo, lvar = result[1:] if hx_view.set_lvar_type(lvar, tinfo): hx_view.refresh_view(True) elif result[0] == RECAST_GLOBAL_VARIABLE: tinfo, address = result[1:] if idaapi.apply_tinfo2(address, tinfo, idaapi.TINFO_DEFINITE): hx_view.refresh_view(True) elif result[0] == RECAST_ARGUMENT: arg_index, func_tinfo, arg_tinfo, address = result[1:] func_data = idaapi.func_type_data_t() func_tinfo.get_func_details(func_data) func_data[arg_index].type = arg_tinfo new_func_tinfo = idaapi.tinfo_t() new_func_tinfo.create_func(func_data) if idaapi.apply_tinfo2(address, new_func_tinfo, idaapi.TINFO_DEFINITE): hx_view.refresh_view(True) elif result[0] == RECAST_RETURN: return_type, func_address = result[1:] try: cfunc = idaapi.decompile( func_address) if func_address else hx_view.cfunc except idaapi.DecompilationFailure: print "[ERROR] Ida failed to decompile function" return function_tinfo = idaapi.tinfo_t() cfunc.get_func_type(function_tinfo) func_data = idaapi.func_type_data_t() function_tinfo.get_func_details(func_data) func_data.rettype = return_type function_tinfo.create_func(func_data) if idaapi.apply_tinfo2(cfunc.entry_ea, function_tinfo, idaapi.TINFO_DEFINITE): hx_view.refresh_view(True) elif result[0] == RECAST_STRUCTURE: structure_name, field_offset, new_type = result[1:] tinfo = idaapi.tinfo_t() tinfo.get_named_type(idaapi.cvar.idati, structure_name) ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati, structure_name) if ordinal: udt_member = idaapi.udt_member_t() udt_member.offset = field_offset * 8 idx = tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member) if udt_member.offset != field_offset * 8: print "[Info] Can't handle with arrays yet" elif udt_member.type.get_size() != new_type.get_size(): print "[Info] Can't recast different sizes yet" else: udt_data = idaapi.udt_type_data_t() tinfo.get_udt_details(udt_data) udt_data[idx].type = new_type tinfo.create_udt(udt_data, idaapi.BTF_STRUCT) tinfo.set_numbered_type(idaapi.cvar.idati, ordinal, idaapi.NTF_REPLACE, structure_name) hx_view.refresh_view(True)
def activate(self, ctx): hx_view = idaapi.get_tform_vdui(ctx.widget) result = self.check(hx_view.cfunc, hx_view.item) if result is None: return struct_tinfo, offset, idx = result 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" else: default_field_type = "_DWORD" declaration = idaapi.asktext( 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: 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(idaapi.STRMEM_OFFSET, udt_member) gap_size = udt_member.size // 8 gap_leftover = gap_size - idx - field_size if gap_leftover < 0: print "[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, TemporaryStructureModel.get_padding_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, TemporaryStructureModel.get_padding_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)