def members(id): """Yields the members of the structure identified by ``id``. Each iteration yields the ((offset,size),(name,comment,repeatable-comment)) of each member. """ st = idaapi.get_struc(id) if not st: # empty structure return size = idaapi.get_struc_size(st) offset = 0 for i in range(st.memqty): m = st.get_member(i) ms = idaapi.get_member_size(m) left, right = m.soff, m.eoff if offset < left: yield (offset, left - offset), (idaapi.get_member_name(m.id), idaapi.get_member_cmt(m.id, 0), idaapi.get_member_cmt(m.id, 1)) offset = left yield (offset, ms), (idaapi.get_member_name(m.id), idaapi.get_member_cmt(m.id, 0), idaapi.get_member_cmt(m.id, 1)) offset += ms return
def getFuncEAForVTableMember(member): funcEA = None memberId = member.id memberOff = member.soff memberFullName = idaapi.get_member_fullname(memberId) memberName = idaapi.get_member_name(memberId) structName = memberFullName[:-len(memberName)] xref = get_first_dref_from(memberId) if structName.startswith("vtable_"): className = structName[len("vtable_"):] funcEA = xref if xref == None: if className in classNameToVTableAddrMap: vtableStartEA, vtableEndEA = classNameToVTableAddrMap[ className] funcEA = Qword(vtableStartEA + memberOff) else: if className.endswith("::MetaClass"): hostClassName = className[:-len("::MetaClass")] vtableName = "__ZTVN" + str( len(hostClassName)) + hostClassName + "9MetaClassE" else: vtableName = "__ZTV" + str(len(className)) + className vtableEA = get_name_ea(0, vtableName) if vtableEA != BADADDR: funcEA = Qword(vtableEA + 0x10 + memberOff) return funcEA
def set_struct_function_type(struct_name): struct = get_struct(struct_name) for m in enum_members(struct): name = idaapi.get_member_name(m.id) typeinfo = type_for_name(name) if typeinfo: print typeinfo set_member_type_info(struct, m, typeinfo + ";")
def get_stack_variable_name(func_start, offset): func = idaapi.get_func(func_start) frame = idaapi.get_frame(func) if frame is None: raise ValueError("couldn't get frame for function @ 0x%x" % func_start) offset += func.frsize member = idaapi.get_member(frame, offset) return idaapi.get_member_name(member.id)
def renaming_struc_member(self, *args): """ renaming_struc_member(self, sptr, mptr, newname) -> int """ sptr, mptr, newname = args logger.debug("Renaming struct member %s of struct %s", mptr.id, sptr.id) sname = idaapi.get_struc_name(sptr.id) oldname = idaapi.get_member_name(mptr.id) struct_id = self.skel_conn.get_struct_by_name(sname) mid = self.skel_conn.get_member_by_name(struct_id, oldname) self.skel_conn.rename_struct_member(struct_id, mid, newname) return ida_idp.IDB_Hooks.renaming_struc_member(self, *args)
def __init__(self, member, parent): ##These objects below can apparently be mutated by ua stuff. #self.src = member #self.src_parent = parent self.name = idaapi.get_member_name(member.id) self.flags = member.flag self.val = value.get_node_for_member(member, parent) self.eoff = member.eoff self.soff = member.soff self.decl = data.get_decl_for_member(member, parent) self.unit_size = data.get_member_unit_size(member, parent) self.struc_id = None if idaapi.isStruct(self.flags): self.struc_id = util.member_str_id(member, parent)
def add_dref(self, ea, struct_id, flags, member_id=None): if ((ea, struct_id, member_id) not in self.xrefs or flags < self.xrefs[(ea, struct_id, member_id)]): self.xrefs[(ea, struct_id, member_id)] = flags strname = idaapi.get_struc_name(struct_id) if member_id is None: idaapi.add_dref(ea, struct_id, flags) log.debug((" 0x{:X} \t" "struct {} \t" "{}").format(ea, strname, flags_to_str(flags))) else: idaapi.add_dref(ea, member_id, flags) log.debug((" 0x{:X} \t" "member {}.{} \t" "{}").format(ea, strname, idaapi.get_member_name(member_id), flags_to_str(flags))) self.save()
def struc_member_created(self, *args): """ struc_member_created(self, sptr, mptr) -> int """ sptr, mptr = args logger.debug("New member for structure %s", idaapi.get_struc_name(sptr.id)) m_start_offset = mptr.soff # logger.debug("Member start offset 0x%x", m_start_offset) # logger.debug("Member end offset 0x%x", m_end_offset) struct_name = idaapi.get_struc_name(sptr.id) struct_id = self.skel_conn.get_struct_by_name(struct_name) mname = idaapi.get_member_name(mptr.id) self.skel_conn.create_struct_member(struct_id, mname, m_start_offset) return ida_idp.IDB_Hooks.struc_member_created(self, *args)
def add_dref(self, ea, struct_id, flags, member_id=None): if (ea, struct_id, member_id) not in self.xrefs or flags < self.xrefs[ (ea, struct_id, member_id)]: self.xrefs[(ea, struct_id, member_id)] = flags strname = idaapi.get_struc_name(struct_id) if member_id is None: idaapi.add_dref(ea, struct_id, flags) log.debug(" %08X \tstruct %s \t%s", ea, strname, flags_to_str(flags)) else: idaapi.add_dref(ea, member_id, flags) log.debug( " %08X \tmember %s.%s \t%s", ea, strname, idaapi.get_member_name(member_id), flags_to_str(flags), ) self.save()
def members(id): st = idaapi.get_struc(id) if not st: # empty structure return size = idaapi.get_struc_size(st) offset = 0 for i in range(st.memqty): m = st.get_member(i) ms = idaapi.get_member_size(m) left,right = m.soff,m.eoff if offset < left: yield (offset,left-offset), (None,None) offset = left yield (offset,ms),(idaapi.get_member_name(m.id), idaapi.get_member_cmt(m.id, 1)) offset += ms return
def members(id): """Return the ((offset,size),(name,comment)) of each member within the specified structure""" st = idaapi.get_struc(id) if not st: # empty structure return size = idaapi.get_struc_size(st) offset = 0 for i in range(st.memqty): m = st.get_member(i) ms = idaapi.get_member_size(m) left, right = m.soff, m.eoff if offset < left: yield (offset, left - offset), (None, None) offset = left yield (offset, ms), (idaapi.get_member_name(m.id), idaapi.get_member_cmt(m.id, 1)) offset += ms return
def save_strucs(self, memory_exporter): """ Structures : export modified structures and delete those who have been deleted """ for struc_id in self.structures_to_process: self.ida_model.clear_exported_struc_enum_id(struc_id) sidx = idc.GetStrucIdx(struc_id) if sidx is None or sidx == idc.BADADDR: # it is a deleted structure or a stackframe # in this last case we need to export the parent (function) eaFunc = idaapi.get_func_by_frame(struc_id) if eaFunc != idc.BADADDR: # OK, it is a stackframe self.ida_model.accept_struc( memory_exporter, 0, struc_id, ya.OBJECT_TYPE_STACKFRAME, ya.OBJECT_TYPE_STACKFRAME_MEMBER, stackframe_func_addr=eaFunc) self.ida_model.accept_ea(memory_exporter, 0, eaFunc) else: # it is a deleted structure self.ida_model.accept_deleted_struc(memory_exporter, struc_id) else: self.ida_model.accept_struc(memory_exporter, 0, struc_id) logger.debug("Walking members") """ Structure members : update modified ones, and remove deleted ones We iterate over members : -if the parent struc has been deleted, delete the member -otherwise, detect if the member has been updated or removed -updated : accept struc_member + accept_struc if not already exported! -removed : accept struc_member_deleted """ for (struc_id, member_set) in self.strucmember_to_process.iteritems(): ida_struc = idaapi.get_struc(struc_id) logger.debug("Walking struc 0x%08X" % struc_id) sidx = idc.GetStrucIdx(struc_id) is_stackframe = False struc_deleted = False if sidx is None or sidx == idc.BADADDR: f = idaapi.get_func_by_frame(struc_id) if f is not None and f != idc.BADADDR: is_stackframe = True else: struc_deleted = True if is_stackframe: strucmember_type = ya.OBJECT_TYPE_STACKFRAME_MEMBER struc_name = None struc_type = ya.OBJECT_TYPE_STACKFRAME eaFunc = idaapi.get_func_by_frame(struc_id) stackframe_func_addr = eaFunc func = idaapi.get_func(eaFunc) self.ida_model.accept_function(memory_exporter, 0, eaFunc, func) else: strucmember_type = ya.OBJECT_TYPE_STRUCT_MEMBER struc_type = ya.OBJECT_TYPE_STRUCT stackframe_func_addr = None if not struc_deleted: struc_name = idc.GetStrucName(struc_id) if struc_deleted: # The structure has been deleted : we need to delete the members # Note: at first sight, it is not a stackframe # TODO: handle function->stackframe deletion here for (member_id, offset) in member_set: self.ida_model.accept_deleted_strucmember(memory_exporter, struc_id, None, offset) else: # The structure or stackframe has been modified is_union = ida_struc.is_union() for (member_id, offset) in member_set: ida_member = idaapi.get_member(ida_struc, offset) if ida_member is None: new_member_id = -1 else: new_member_id = ida_member.id logger.debug("exporting member %s at offset 0x%02X (mid=0x%016X)" % (strucmember_type, offset, member_id)) self.ida_model.clear_exported_struc_member_id(new_member_id) if new_member_id == -1: # the member has been deleted : delete it self.ida_model.accept_deleted_strucmember( memory_exporter, struc_id, struc_name, offset, struc_type, strucmember_type) elif offset > 0 and idc.GetMemberId(struc_id, offset - 1) == new_member_id: # the member was deleted, and replaced by a member starting above it self.ida_model.accept_deleted_strucmember( memory_exporter, struc_id, struc_name, offset, struc_type, strucmember_type) elif new_member_id != member_id: # the member has been deleted and later recreated name = idaapi.get_member_name(new_member_id) self.ida_model.accept_struc_member( memory_exporter, 0, ida_struc, struc_id, is_union, offset, struc_name, name, struc_type, strucmember_type, stackframe_func_addr=stackframe_func_addr) else: # the member has just been modified name = idaapi.get_member_name(new_member_id) logger.debug("exporting member %s (%s) at offset 0x%02X (mid=0x%016X)" % (strucmember_type, name, offset, member_id)) self.ida_model.accept_struc_member( memory_exporter, 0, ida_struc, struc_id, is_union, offset, struc_name, name, struc_type, strucmember_type, stackframe_func_addr=stackframe_func_addr)
def name(self): '''Return the member's name.''' return idaapi.get_member_name(self.id) or ''
def name(self): return idaapi.get_member_name(self.id)
def clear_struc_fields(self, struc_id, struc_size, xref_keys, is_union=False, member_type=ya.OBJECT_TYPE_STRUCT_MEMBER, name_offset=0): idc.BeginTypeUpdating(idc.UTP_STRUCT) last_offset = idc.GetLastMember(struc_id) # get existing member offsets field_offsets = set() for (xref_offset, xref_operand) in xref_keys: field_offsets.add(xref_offset) new_offsets = set() struc = idaapi.get_struc(struc_id) # create missing members first (prevent from deleting all members) for offset in field_offsets: member = idaapi.get_member(struc, offset) if member is not None and member.soff < offset: # we have a member above this member that is too big and contain this member # clear it! if DEBUG_EXPORTER: logger.debug( "reduce field : set_member_type(0x%08X, 0x%08X), overlapping 0x%08X", struc_id, member.soff, offset) idaapi.set_member_type(struc, member.soff, idc.FF_BYTE, None, 1) member = idaapi.get_member(struc, offset) if member is None or idaapi.get_member_name(member.id) is None: new_offsets.add(offset) member_name = YaToolIDATools.get_default_struc_member_name( member_type, offset, name_offset) if offset == last_offset and offset == struc_size: field_size = 0 else: field_size = 1 if DEBUG_EXPORTER: logger.debug( "AddStrucMember(0x%08X, '%s', 0x%08X, idc.FF_BYTE, -1, 0x%08X), name_offset=%d", struc_id, member_name, offset, field_size, name_offset) retval = idc.AddStrucMember(struc_id, member_name, offset, idc.FF_BYTE, -1, field_size) if retval != 0: logger.error( "Error %d with idc.AddStrucMember(0x%08X, '%s', 0x%08X," "idc.FF_BYTE, -1, 0x%08X), name_offset=%d", retval, struc_id, member_name, offset, field_size, name_offset) elif DEBUG_EXPORTER: logger.debug("Member exists : (0x%08X, '%s', 0x%08X, 0x%08X)", struc_id, idc.GetMemberName(struc_id, offset), offset, idc.GetMemberSize(struc_id, offset)) kept_offsets = field_offsets - new_offsets # clear kept members # split the loop since we will modify the structure while iterating offsets = set() for (offset, member_name) in YaToolIDATools.struc_member_list( struc_id, is_union): offsets.add(offset) for offset in offsets: if offset in kept_offsets: # This member already existed and is kept if offset == last_offset and offset == struc_size: # this is the last field, and it is a variable sized structure field_size = 0 else: field_size = 1 if member_type == ya.OBJECT_TYPE_STRUCT_MEMBER: strucmember_id = self.hash_provider.get_struc_member_id( struc_id, offset) elif member_type == ya.OBJECT_TYPE_STACKFRAME_MEMBER: strucmember_id = self.hash_provider.get_stackframe_member_object_id( struc_id, offset) else: logger.error("Bad member_type : %d" % member_type) if strucmember_id not in self.strucmember_ids: # It is not necessary to clear the member if it is presnet in the resolved_objects if DEBUG_EXPORTER: logger.debug( "SetStrucmember(0x%08X, None, 0x%08X, idc.FF_BYTE, -1, 0x%08X, name_offset=%s)", struc_id, offset, field_size, name_offset) YaToolIDATools.SetStrucmember(struc_id, None, offset, idc.FF_BYTE, -1, field_size, member_type=member_type, name_offset=name_offset) idc.SetMemberComment(struc_id, offset, "", 0) idc.SetMemberComment(struc_id, offset, "", 1) elif offset not in new_offsets: if (member_type != ya.OBJECT_TYPE_STACKFRAME_MEMBER or not idaapi.is_special_member( idc.GetMemberId(struc_id, offset))): if DEBUG_EXPORTER: logger.debug( "DelStrucMember(0x%08X, 0x%08X) (=%s:%s)", struc_id, offset, idc.GetStrucName(struc_id), idc.GetMemberName(struc_id, offset)) idc.DelStrucMember(struc_id, offset) else: # in new_offsets : just created pass idc.EndTypeUpdating(idc.UTP_STRUCT)