def get_mptr_by_member_id(mid): if mid is None or mid == BADADDR: return None res = ida_struct.get_member_by_id(mid) if not res: return None return res[0]
def expand_struct(struct_id, new_size): struct = ida_struct.get_struc(struct_id) if struct is None: logging.warning("Struct id 0x%x wasn't found", struct_id) return logging.debug( "Expanding struc %s 0x%x -> 0x%x", ida_struct.get_struc_name(struct_id), ida_struct.get_struc_size(struct_id), new_size, ) if ida_struct.get_struc_size(struct_id) > new_size - WORD_LEN: return fix_list = [] xrefs = idautils.XrefsTo(struct.id) for xref in xrefs: if xref.type == ida_xref.dr_R and xref.user == 0 and xref.iscode == 0: member, full_name, x_struct = ida_struct.get_member_by_id(xref.frm) if x_struct is not None: old_name = ida_struct.get_member_name(member.id) offset = member.soff marker_name = "marker_%d" % random.randint(0, 0xFFFFFF) idc.add_struc_member( x_struct.id, marker_name, member.soff + new_size, idaapi.FF_DATA | idaapi.FF_BYTE, -1, 0, ) logging.debug( "Delete member (0x%x-0x%x)", member.soff, member.soff + new_size - 1 ) ida_struct.del_struc_members( x_struct, member.soff, member.soff + new_size - 1 ) fix_list.append( [ x_struct.id, old_name, offset, idaapi.FF_STRUCT | idaapi.FF_DATA, struct_id, new_size, ] ) else: logging.warning("Xref wasn't struct_member 0x%x", xref.frm) ret = push_ptr_member_to_struct( ida_struct.get_struc(struct_id), None, None, new_size - WORD_LEN ) logging.debug("Now fix args:") for fix_args in fix_list: ret = idc.add_struc_member(*fix_args) logging.debug("%s = %d", fix_args, ret) x_struct_id = fix_args[0] idc.del_struc_member(x_struct_id, ida_struct.get_struc_size(x_struct_id))
def get_member_by_id(mid): # Replacement for the ida_struct.get_member_by_id(), # which in IDA7.0 returns incorrect sptr res = ida_struct.get_member_by_id(mid) if not res: return None mptr, member_fullname, _ = res sptr = ida_struct.get_member_struc(ida_struct.get_member_fullname(mptr.id)) return mptr, member_fullname, sptr
def post_func_name_change(new_name, ea): xrefs = idautils.XrefsTo(ea, ida_xref.XREF_USER) xrefs = filter(lambda x: x.type == ida_xref.dr_I and x.user == 1, xrefs) args_list = [] for xref in xrefs: member, old_name, struct = ida_struct.get_member_by_id(xref.frm) if member is not None and struct is not None: args_list.append([struct, member.get_soff(), new_name]) return utils.set_member_name, args_list
def ti_changed(self, ea, typeinf, fnames): res = ida_struct.get_member_by_id(ea) if res is not None: m, name, sptr = res if sptr.is_frame(): func = ida_funcs.get_func(ida_frame.get_func_by_frame(sptr.id)) if func is not None: return self.func_updated(func) elif utils.is_func(ea): return self.func_updated(ida_funcs.get_func(ea)) return 0
def post_func_type_change(pfn): ea = pfn.start_ea xrefs = idautils.XrefsTo(ea, ida_xref.XREF_USER) xrefs = list(filter(lambda x: x.type == ida_xref.dr_I and x.user == 1, xrefs)) args_list = [] if len(xrefs) == 0: return None, [] try: xfunc = ida_hexrays.decompile(ea) func_ptr_typeinf = utils.get_typeinf_ptr(xfunc.type) for xref in xrefs: member, old_name, struct = ida_struct.get_member_by_id(xref.frm) if member is not None and struct is not None: args_list.append( [struct, member, 0, func_ptr_typeinf, idaapi.TINFO_DEFINITE] ) except Exception: pass return ida_struct.set_member_tinfo, args_list
def install_vtables_union(class_name, class_vtable_member=None, vtable_member_tinfo=None, offset=0): # pylint: disable=too-many-locals # TODO: this function is too big and must be refactored log.debug( "install_vtables_union(%s, %s, %s)", class_name, class_vtable_member, str(vtable_member_tinfo), ) if class_vtable_member and vtable_member_tinfo: old_vtable_sptr = utils.extract_struct_from_tinfo(vtable_member_tinfo) old_vtable_class_name = ida_struct.get_struc_name(old_vtable_sptr.id) else: old_vtable_class_name = get_class_vtable_struct_name(class_name, offset) old_vtable_sptr = utils.get_sptr_by_name(old_vtable_class_name) vtables_union_name = old_vtable_class_name if old_vtable_sptr and not ida_struct.set_struc_name( old_vtable_sptr.id, old_vtable_class_name + "_orig" ): # FIXME: why log exception? log.exception( "Failed changing %s->%s_orig", old_vtable_class_name, old_vtable_class_name, ) # FIXME: why -1 and not None? return -1 vtables_union_id = utils.get_or_create_struct_id(vtables_union_name, True) vtable_member_tinfo = utils.get_typeinf(old_vtable_class_name + "_orig") if vtables_union_id == BADADDR: log.exception( "Cannot create union vtable for %s()%s", class_name, vtables_union_name, ) # FIXME: why -1 and not None? return -1 vtables_union = ida_struct.get_struc(vtables_union_id) if not vtables_union: log.exception("Could retrieve vtables union for %s", class_name) # FIXME: return -1? if vtable_member_tinfo is not None: vtables_union_vtable_field_name = get_class_vtables_field_name(class_name) else: vtables_union_vtable_field_name = get_interface_empty_vtable_name() utils.add_to_struct(vtables_union, vtables_union_vtable_field_name, vtable_member_tinfo) parent_struct = utils.get_sptr_by_name(class_name) flag = idaapi.FF_STRUCT mt = idaapi.opinfo_t() mt.tid = vtables_union_id struct_size = ida_struct.get_struc_size(vtables_union_id) vtables_union_ptr_type = utils.get_typeinf_ptr(vtables_union_name) if class_vtable_member: member_ptr = class_vtable_member else: # FIXME: add_struc_member returns error code, not member id member_id = ida_struct.add_struc_member( parent_struct, get_class_vtable_field_name(class_name), offset, flag, mt, struct_size, ) # FIXME: get_member_by_id returns tuple, not member ptr member_ptr = ida_struct.get_member_by_id(member_id) ida_struct.set_member_tinfo( parent_struct, member_ptr, 0, vtables_union_ptr_type, idaapi.TINFO_DEFINITE, ) # FIXME: might be None! Is this OK, considering we return -1 everywhere else? return vtables_union
def install_vtables_union( class_name, class_vtable_member=None, vtable_member_tinfo=None, offset=0 ): logging.debug( "install_vtables_union(%s, %s, %s)", class_name, class_vtable_member, str(vtable_member_tinfo), ) if class_vtable_member and vtable_member_tinfo: old_vtable_sptr = utils.extract_struct_from_tinfo(vtable_member_tinfo) old_vtable_class_name = ida_struct.get_struc_name(old_vtable_sptr.id) else: old_vtable_class_name = get_class_vtable_struct_name(class_name, offset) old_vtable_sptr = utils.get_sptr_by_name(old_vtable_class_name) vtables_union_name = old_vtable_class_name if old_vtable_sptr and not ida_struct.set_struc_name( old_vtable_sptr.id, old_vtable_class_name + "_orig" ): logging.exception( f"Failed changing {old_vtable_class_name}->" f"{old_vtable_class_name+'orig'}" ) return -1 vtables_union_id = utils.get_or_create_struct_id(vtables_union_name, True) vtable_member_tinfo = utils.get_typeinf(old_vtable_class_name + "_orig") if vtables_union_id == BADADDR: logging.exception( f"Cannot create union vtable for {class_name}(){vtables_union_name}" ) return -1 vtables_union = ida_struct.get_struc(vtables_union_id) if not vtables_union: logging.exception(f"Could retrieve vtables union for {class_name}") if vtable_member_tinfo is not None: vtables_union_vtable_field_name = get_class_vtables_field_name(class_name) else: vtables_union_vtable_field_name = get_interface_empty_vtable_name() utils.add_to_struct( vtables_union, vtables_union_vtable_field_name, vtable_member_tinfo ) parent_struct = utils.get_sptr_by_name(class_name) flag = idaapi.FF_STRUCT mt = idaapi.opinfo_t() mt.tid = vtables_union_id struct_size = ida_struct.get_struc_size(vtables_union_id) vtables_union_ptr_type = utils.get_typeinf_ptr(vtables_union_name) if class_vtable_member: member_ptr = class_vtable_member else: member_id = ida_struct.add_struc_member( parent_struct, get_class_vtable_field_name(class_name), offset, flag, mt, struct_size, ) member_ptr = ida_struct.get_member_by_id(member_id) ida_struct.set_member_tinfo( parent_struct, member_ptr, 0, vtables_union_ptr_type, idaapi.TINFO_DEFINITE ) return vtables_union
def expand_struct(struct_id, new_size): struct = ida_struct.get_struc(struct_id) if struct is None: log.warning("Struct id 0x%X wasn't found", struct_id) return log.debug( "Expanding struc %s, size: 0x%X -> 0x%X", ida_struct.get_struc_name(struct_id), ida_struct.get_struc_size(struct_id), new_size, ) if ida_struct.get_struc_size(struct_id) > new_size - WORD_LEN: return fix_list = [] xrefs = idautils.XrefsTo(struct.id) for xref in xrefs: if xref.type == ida_xref.dr_R and xref.user == 0 and xref.iscode == 0: res = ida_struct.get_member_by_id(xref.frm) if not res or not res[0]: log.warning("Xref from %08X wasn't struct_member", xref.frm) continue member = res[0] x_struct = ida_struct.get_member_struc(ida_struct.get_member_fullname(member.id)) assert x_struct old_name = ida_struct.get_member_name(member.id) offset = member.soff # FIXME: why use random here? marker_name = "marker_%d" % random.randint(0, 0xFFFFFF) # FIXME: check if add_struc_member actually added a member idc.add_struc_member( x_struct.id, marker_name, member.soff + new_size, idaapi.FF_DATA | idaapi.FF_BYTE, -1, 0, ) log.debug( "Delete member (0x%X-0x%X)", member.soff, member.soff + new_size - 1, ) # FIXME: check if struc member actually deleted ida_struct.del_struc_members(x_struct, member.soff, member.soff + new_size - 1) fix_list.append( [ x_struct.id, old_name, offset, idaapi.FF_STRUCT | idaapi.FF_DATA, struct_id, new_size, ] ) ret = add_to_struct(ida_struct.get_struc(struct_id), None, None, new_size - WORD_LEN) log.debug("Now fix args:") for fix_args in fix_list: ret = idc.add_struc_member(*fix_args) log.debug("%s = %d", fix_args, ret) x_struct_id = fix_args[0] idc.del_struc_member(x_struct_id, ida_struct.get_struc_size(x_struct_id))