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 add_member(self, offset, name, size): if get_member_name(self._sid, 0) == "Dummy": del_struc_member(self._sid, 0) flag = {1: FF_BYTE, 2: FF_WORD, 4: FF_DWORD, 8: FF_QWORD}.get(size) if flag is None: raise ValueError("size") err_code = add_struc_member(self._sid, name, offset, flag | FF_DATA, -1, size) if err_code != 0: raise Exception("err_code = %d" % err_code)
def write_vtbl_struct(self, vtbl_name, struct_member_names): struct_name = "{0}_struct".format(vtbl_name) sid = idc.get_struc_id(struct_name) if sid == idc.BADADDR: # Doesn't exist sid = idc.add_struc(-1, struct_name, is_union=0) else: # Clear existing member_offset = idc.get_first_member(sid) while member_offset != idc.BADADDR: idc.del_struc_member(sid, member_offset) member_offset = idc.get_first_member(sid) for member_name in struct_member_names: idc.add_struc_member(sid, member_name, offset=-1, flag=idc.FF_DATA | idc.FF_QWORD, typeid=-1, nbytes=8, reftype=idc.REF_OFF64) member_offset = idc.get_last_member(sid) member_id = idc.get_member_id(sid, member_offset) idc.SetType(member_id, "void*")
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))
def resolve_type(like, die_offset, log_fp, alias=None): if die_offset is None: return 'void' type = like.get(str(die_offset)) if type is None: return DEFAULT_TYPE kind = type[0] if kind in ('struct', 'union'): if type[1] is None: if alias is None: struct_name = '{}_{}'.format(kind, hex(die_offset)) else: struct_name = alias else: struct_name = type[1] if (not _is_uname(str(struct_name)) or (get_struc_id(str(struct_name)) == BADADDR and get_name_ea(BADADDR, str(struct_name)) != BADADDR)): struct_name = '_' + struct_name struct_id = get_struc_id(str(struct_name)) if struct_id != BADADDR: if len(type) == 4: type.append(struct_id) return struct_name log_fp.write('{}: ...\n'.format(struct_name)) log_fp.flush() struct_id = add_struc(BADADDR, str(struct_name), kind == 'union') log_fp.write('... id={}\n'.format(hex(struct_id))) log_fp.flush() if struct_id == BADADDR: return DEFAULT_TYPE type.append(struct_id) if kind == 'struct' and type[2] != 0: ret = add_end_member(struct_id, struct_name, type[2], log_fp) have_end_member = ret == 0 else: have_end_member = False for member_type_die_offset, member_name, member_offset in type[3]: if member_name is None: if kind == 'struct': field_n = member_offset else: field_n = sum(1 for _ in StructMembers(struct_id)) member_name = 'field_{:X}'.format(field_n) elif not _is_uname(str(member_name)): member_name = '_' + member_name member_type_str = str(resolve_type( like, member_type_die_offset, log_fp)) member_size = get_type_size(like, member_type_die_offset) if have_end_member and member_offset + member_size == type[2]: del_struc_member(struct_id, type[2] - 1) have_end_member = False log_fp.write('{} {}.{}: ...\n'.format( member_type_str, struct_name, member_name)) log_fp.flush() ret = add_struc_member( struct_id, str(member_name), member_offset, DEFAULT_TYPE_FLAGS, DEFAULT_TYPE_ID, DEFAULT_TYPE_SIZE, ) log_fp.write('... ret={}\n'.format(ret)) log_fp.flush() if ret == 0: member_id = get_name_ea( BADADDR, '{}.{}'.format(struct_name, member_name)) apply_type(member_id, parse_decl(member_type_str, 0)) return struct_name if kind == 'typedef': return resolve_type(like, type[2], log_fp, type[1]) if kind == 'pointer': return resolve_type(like, type[1], log_fp) + '*' if kind == 'base': if type[1]: return '__int' + str(type[2] * 8) else: return 'unsigned __int' + str(type[2] * 8) if kind in ('const', 'volatile'): return resolve_type(like, type[1], log_fp) if kind == 'array': return '{}[{}]'.format(resolve_type(like, type[1], log_fp), type[2]) return DEFAULT_TYPE