def _create_class_structs__slices(classinfo, endmarkers=True): """Create the IDA structs for a C++ class.""" classname = classinfo.classname # Open or create the structs. sidf = idau.struct_open(classname + '::fields', create=True) sid = idau.struct_open(classname, create=True) if sid is None or sidf is None: _log(0, 'Could not create class structs for {}', classname) return None assert all(not idc.IsUnion(s) for s in (sidf, sid)) # Calculate the size of the ::fields struct. if classinfo.superclass: # If we have a superclass, our fields start after our superclass's fields end. fields_start = classinfo.superclass.class_size else: # If we don't have a superclass, our fields start after our vtable. fields_start = idau.WORD_SIZE fields_size = classinfo.class_size - fields_start # Add an ::end member to the fields struct if requested. if endmarkers: ret = idc.AddStrucMember(sidf, classname + '::end', fields_size, idc.FF_UNK, -1, 0) if ret not in (0, idc.STRUC_ERROR_MEMBER_NAME, idc.STRUC_ERROR_MEMBER_OFFSET): # If that didn't work that's too bad, but continue anyway. _log(0, 'Could not create {}::end', classname) return sid, sidf, fields_start
def get_object_id_of_union_member_id(hash_provider, member_id): try: return union_member_object_ids[member_id] except KeyError: idx = idc.GetFirstStrucIdx() while idx != idc.BADADDR: struc_id = idc.GetStrucId(idx) if idc.IsUnion(struc_id): offset = idc.GetFirstMember(struc_id) while offset != idc.BADADDR: smember_id = idc.GetMemberId(struc_id, offset) if smember_id == member_id: name = idc.GetMemberName(struc_id, offset) if name is not None: struc_name = idc.GetStrucName(struc_id) logger.debug("found member id 0x%016X in union %s/%s" % (member_id, struc_name, name)) return hash_provider.get_struc_member_id_for_name(struc_name, offset) # next member offset = idc.GetStrucNextOff(struc_id, offset) idx = idc.GetNextStrucIdx(idx) logger.error("Could not find member id 0x%016X in unions" % member_id) return None
def struct_open(name, create=False, union=None): """Get the SID of the IDA struct with the given name, optionally creating it.""" sid = idc.GetStrucIdByName(name) if sid == idc.BADADDR: if not create: return None sid = struct_create(name, union=bool(union)) elif union is not None: is_union = bool(idc.IsUnion(sid)) if union != is_union: return None return sid
def struc_created(self, struct): ### we have to maintain our own struct db ## becuse ida sux... sname = idc.GetStrucName(struct) union = idc.IsUnion(struct) idx = idc.GetStrucIdx(struct) self.ctrl._handle_action({ 'action': 'struct_created', 'struct': idx, 'sname': sname, 'union': union }) self.ctrl.db.struct_add(struct, idx) return 0
def read_struct(ea, struct=None, sid=None, members=None, asobject=False): """Read a structure from the given address. This function reads the structure at the given address and converts it into a dictionary or accessor object. Arguments: ea: The linear address of the start of the structure. Options: sid: The structure ID of the structure type to read. struct: The name of the structure type to read. members: A list of the names of the member fields to read. If members is None, then all members are read. Default is None. asobject: If True, then the struct is returned as a Python object rather than a dict. One of sid and struct must be specified. """ # Handle sid/struct. if struct is not None: sid2 = idc.GetStrucIdByName(struct) if sid2 == idc.BADADDR: raise ValueError('Invalid struc name {}'.format(struct)) if sid is not None and sid2 != sid: raise ValueError('Invalid arguments: sid={}, struct={}'.format( sid, struct)) sid = sid2 else: if sid is None: raise ValueError('Invalid arguments: sid={}, struct={}'.format( sid, struct)) if idc.GetStrucName(sid) is None: raise ValueError('Invalid struc id {}'.format(sid)) # Iterate through the members and add them to the struct. union = idc.IsUnion(sid) struct = {} for offset, name, size in idautils.StructMembers(sid): if members is not None and name not in members: continue _read_struct_member(struct, sid, union, ea, offset, name, size, asobject) if asobject: struct = objectview(struct, ea, idc.GetStrucSize(sid)) return struct
def make_struc(self, object_version, address): name = object_version.get_name() object_id = object_version.get_id() size = object_version.get_size() struc_id = idc.GetStrucIdByName(name) if struc_id == idc.BADADDR: try: is_union = object_version.get_object_flags() except KeyError: is_union = 0 struc_id = idc.AddStrucEx(0, name, is_union) # add a dummy field. # This is necessary to avoid an error is idc.SetType(struc*) is used on another struc # member # TODO not for empty strucs if is_union: idc.AddStrucMember(struc_id, "yaco_filler", 0, idc.FF_BYTE, 0, 1) else: is_union = idc.IsUnion(struc_id) # if(is_union): # pass # else: # self.clear_struc_fields(struc_id, object_version['xrefs'], is_union) if not is_union or is_union == 0: self.clear_struc_fields( struc_id, size, object_version.get_xrefed_id_map().iterkeys(), False) else: self.union_ids.add(struc_id) if DEBUG_EXPORTER: logger.debug( "adding struc id %s : '0x%.016X' (%s)" % (self.hash_provider.hash_to_string(object_id), struc_id, name)) self.struc_ids[object_id] = struc_id _yatools_ida_exporter.set_struct_id(object_id, struc_id) self.hash_provider.put_hash_struc_or_enum(struc_id, object_id)
def get_struc_id_from_member_if(member_id): try: return member_struc_ids[member_id] except KeyError: idx = idc.GetFirstStrucIdx() while idx != idc.BADADDR: struc_id = idc.GetStrucId(idx) if idc.IsUnion(struc_id): offset = idc.GetFirstMember(struc_id) while offset != idc.BADADDR: smember_id = idc.GetMemberId(struc_id, offset) if smember_id == member_id: member_struc_ids[member_id] = struc_id return struc_id offset = idc.GetStrucNextOff(struc_id, offset) idx = idc.GetNextStrucIdx(idx) logger.error("Could not find struc id from member id 0x%08X (name=%s)" % (member_id, idaapi.get_struc_name(member_id))) return None
def _set_class_style(style): """Set the global class style.""" global _style_was_set, _create_class_structs, _populate_class_structs assert style in (CLASS_SLICES, CLASS_UNIONS) # Check the current style based on OSObject, a class that should always exist. sid = idau.struct_open('OSObject') want_union = style == CLASS_UNIONS if sid is None: # No global style has been set. idau.struct_create('OSObject', union=want_union) else: # A style already exists. Check that the requested style matches. is_union = bool(idc.IsUnion(sid)) if is_union != want_union: raise ValueError('Incompatible style {}', style) # Set the appropriate functions based on the style. if style == CLASS_SLICES: _create_class_structs = _create_class_structs__slices _populate_class_structs = _populate_class_structs__slices else: _create_class_structs = _create_class_structs__unions _populate_class_structs = _populate_class_structs__unions
def is_union(self): return idc.IsUnion(self.sid)