def mt_ascii(self): ri = refinfo_t() ri.flags = ASCSTR_C ri.target = -1 mt = opinfo_t() mt.ri = ri return mt
def getFieldName(ea, offset): ''' Get an IDA Structure field for a given offset into a structure at a given field. Display as full element name, qualified with array indices as appropriate. We assume that "offset" is into the sid alone, not relative to the start of the parent structure. First get the sid of the top-level struct as given by ea. Then loop: get name of struct at current offset into current sid if name is none, we are in an array, and past the first element get last member of current sid get the next offset after the last member assume that offset is the size of the array elements use MOD to get offset into element strcture get name can continue; if no name, bail ''' print('getFieldName 0x%x' % ea) full_name = None ti = idaapi.opinfo_t() f = idaversion.get_full_flags(ea) if idaversion.get_opinfo(ti, ea, 0, f): #print ("tid=%08x - %s" % (ti.tid, idaversion.get_struc_name(ti.tid))) sid = ti.tid full_name = idaversion.get_struc_name(sid) cur_offset = offset while True: element = None prev = idaversion.get_prev_offset(sid, cur_offset) #print('prev is %d ' % (prev)) mn = idaversion.get_member_name(sid, cur_offset) #print('get_member_name sid 0x%x offset %d got %s' % (sid, cur_offset, mn)) if mn is None: #print('mn none') last = idaversion.get_last_member(sid) over = idaversion.get_next_offset(sid, last) #print('last %d over %d' % (last, over)) element = int(cur_offset / over) cur_offset = cur_offset % over mn = idaversion.get_member_name(sid, cur_offset) #print('in array get_member_name sid 0x%x offset %d got %s array element %d' % (sid, cur_offset, mn, element)) if mn is None: break mem_off = idaversion.get_member_offset(sid, mn) #print('mn now %s offset %d' % (mn, mem_off)) if element is None: full_name = full_name+'.'+mn else: full_name = '%s[%d].%s' % (full_name, element, mn) sid = idaversion.get_member_strid(sid, cur_offset) #print('new sid 0x%x cur_offset %d' % (sid, cur_offset)) cur_offset = cur_offset - mem_off if sid < 0: #print('sid bad') break #print('full name: %s' % full_name) else: print('failed to get opinfo for 0x%x' % ea) return full_name
def mt_address(self): ri = refinfo_t() ri.flags = self.REF_OFF ri.target = 0 mt = opinfo_t() mt.ri = ri return mt
def dissolve(cls, flag, typeid, size): dt = flag & cls.FF_MASKSIZE sf = -1 if flag & idaapi.FF_SIGN == idaapi.FF_SIGN else +1 if dt == idaapi.FF_STRU and isinstance(typeid, six.integer_types): # FIXME: figure out how to fix this recursive module dependency t = sys.modules.get('structure', __import__('structure')).instance(typeid) sz = t.size return t if sz == size else [t, size // sz] if dt not in cls.inverted: logging.warn( "{:s}.dissolve({!r}, {!r}, {!r}) : Unable to identify a pythonic type." .format('.'.join(('internal', __name__, cls.__name__)), dt, typeid, size)) t, sz = cls.inverted[dt] # if the type and size are the same, then it's a string or pointer type if not isinstance(sz, six.integer_types): count = size // idaapi.get_data_elsize(idaapi.BADADDR, dt, idaapi.opinfo_t()) return [t, count] if count > 1 else t # if the size matches, then we assume it's a single element elif sz == size: return t, (sz * sf) # otherwise it's an array return [(t, sz * sf), size // sz]
def yacheck_reference_views(self): addr = yaunit.load('reference_view_addr') ti = idaapi.opinfo_t() f = idc.GetFlags(addr) self.assertTrue(idaapi.get_opinfo(addr, self.operand, f, ti)) self.assertTrue(ti.ri.type()) self.assertEqual(ti.ri.base, self.reference_addr)
def __setstate__(self, state): ownername, index, name, (cmtt, cmtf), ofs, t = state fullname = '.'.join((owername, name)) identifier = idaapi.get_struc_id(ownername) if identifier == idaapi.BADADDR: logging.warn( "{:s}.instance({:s}).member_t : Creating structure {:s} -- [{:#x}] {:s}{:s}" .format( __name__, ownername, ownername, ofs, name, " // {:s}".format(cmtt or cmtf) if cmtt or cmtf else '')) identifier = idaapi.add_struc(idaapi.BADADDR, ownername) self.__owner = owner = instance(identifier, offset=0) flag, mytype, nbytes = t # FIXME: handle .strtype (strings), .ec (enums), .cd (custom) opinfo = idaapi.opinfo_t() opinfo.tid = 0 if mytype is None else mytype.id res = idaapi.add_struc_member(owner.ptr, name, ofs, flag, opinfo, nbytes) # FIXME: handle these errors properly # duplicate name if res == idaapi.STRUC_ERROR_MEMBER_NAME: if idaapi.get_member_by_name(owner.ptr, name).soff != ofs: newname = "{:s}_{:x}".format(name, ofs) logging.warn( "{:s}.instace({:s}).member_t : Duplicate name found for {:s}, renaming to {:s}." .format(__name__, ownername, name, newname)) idaapi.set_member_name(owner.ptr, ofs, newname) else: logging.info( "{:s}.instance({:s}).member_t : Field at {:+#x} contains the same name {:s}." .format(__name__, ownername, ofs, name)) # duplicate field elif res == idaapi.STRUC_ERROR_MEMBER_OFFSET: logging.info( "{:s}.instance({:s}).member_t : Field already found at {:+#x}. Overwriting with {:s}." .format(__name__, ownername, ofs, name)) idaapi.set_member_type(owner.ptr, ofs, flag, opinfo, nbytes) idaapi.set_member_name(owner.ptr, ofs, name) # invalid size elif res == idaapi.STRUC_ERROR_MEMBER_SIZE: logging.warn( "{:s}.instance({:s}).member_t : Issue creating structure member {:s} : {:#x}" .format(__name__, ownername, fullname, res)) # unknown elif res != idaapi.STRUC_ERROR_MEMBER_OK: logging.warn( "{:s}.instance({:s}).member_t : Issue creating structure member {:s} : {:#x}" .format(__name__, ownername, fullname, res)) self.__index = index self.__owner = owner idaapi.set_member_cmt(self.ptr, cmtt, True) idaapi.set_member_cmt(self.ptr, cmtf, False) return
def yacheck_apply_struct(self): addrs = yaunit.load('apply_struct') for k in range(-1, 4): # retrieve struct id addr = addrs[k + 1] sid = idc.GetStrucIdByName('apply_struct_%x' % (k + 1)) self.assertNotEqual(sid, idaapi.BADADDR) # begin to check if something is applied flags = idaapi.get_flags_novalue(addr) self.assertTrue(idaapi.isStroff(flags, 1)) ti = idaapi.opinfo_t() flags = idc.GetFlags(addr) self.assertTrue(idaapi.get_opinfo(addr, 1, flags, ti)) # apply struct only if k == -1: # check struct is applied self.assertEqual(ti.path.ids[0], sid) continue # check union is selected & applied at target address uid = idc.GetStrucIdByName('apply_union_%x' % (k + 1)) self.assertNotEqual(uid, idaapi.BADADDR) fid = idc.GetMemberId(uid, k) self.assertNotEqual(fid, -1) # check union is applied self.assertEqual([x for x in ti.path.ids if x], [sid, fid])
def apply(ea, st): '''Apply the structure ``st`` to the address at ``ea``.''' ea = interface.address.inside(ea) ti, fl = idaapi.opinfo_t(), database.type.flags(ea) res = idaapi.get_opinfo(ea, 0, fl, ti) ti.tid = st.id return idaapi.set_opinfo(ea, 0, fl | idaapi.struflag(), ti)
def type(self, type): '''Set the member's type.''' flag, typeid, size = interface.typemap.resolve(type) opinfo = idaapi.opinfo_t() opinfo.tid = typeid return idaapi.set_member_type( self.__owner.ptr, self.offset - self.__owner.members.baseoffset, flag, opinfo, size)
def apply(ea, st): """Apply the structure ``st`` to the address at ``ea``""" ti = idaapi.opinfo_t() res = idaapi.get_opinfo(ea, 0, idaapi.getFlags(ea), ti) ti.tid = st.id return idaapi.set_opinfo(ea, 0, idaapi.getFlags(ea) | idaapi.struflag(), ti)
def __setstate__(self, state): ownername, index, name, (cmtt, cmtf), ofs, t = state identifier = idaapi.get_struc_id(ownername) if identifier == idaapi.BADADDR: logging.warn('member_t : Creating structure %s -- [%x] %s%s' % (ownername, ofs, name, ' // %s' % (cmtt or cmtf) if cmtt or cmtf else '')) identifier = idaapi.add_struc(idaapi.BADADDR, ownername) self.__owner = owner = instance(identifier, offset=0) flag, mytype, nbytes = t # FIXME: handle .strtype (strings), .ec (enums), .cd (custom) opinfo = idaapi.opinfo_t() opinfo.tid = 0 if mytype is None else mytype.id res = idaapi.add_struc_member(owner.ptr, name, ofs, flag, opinfo, nbytes) # FIXME: handle these errors properly # duplicate name if res == idaapi.STRUC_ERROR_MEMBER_NAME: if idaapi.get_member_by_name(owner.ptr, name).soff != ofs: newname = '%s_%x' % (name, ofs) logging.warn( 'structure_t(%s).member_t : Duplicate name found for %s, renaming to %s' % (ownername, name, newname)) idaapi.set_member_name(owner.ptr, ofs, newname) else: logging.info( 'structure_t(%s).member_t : Field at %x contains the same name %s' % (ownername, ofs, name)) # duplicate field elif res == idaapi.STRUC_ERROR_MEMBER_OFFSET: logging.info( 'structure_t(%s).member_t : Field already found at %x. Overwriting with %s' % (ownername, ofs, name)) idaapi.set_member_type(owner.ptr, ofs, flag, opinfo, nbytes) idaapi.set_member_name(owner.ptr, ofs, name) # invalid size elif res == idaapi.STRUC_ERROR_MEMBER_SIZE: logging.warn( 'member_t : Issue creating structure member %s.%s : %x' % (ownername, name, res)) # unknown elif res != idaapi.STRUC_ERROR_MEMBER_OK: logging.warn( 'member_t : Issue creating structure member %s.%s : %x' % (ownername, name, res)) self.__index = index self.__owner = owner idaapi.set_member_cmt(self.ptr, cmtt, True) idaapi.set_member_cmt(self.ptr, cmtf, False) return
def typeid(self): '''Return the `.tid` of the member's type.''' opinfo = idaapi.opinfo_t() if idaapi.__version__ < 7.0: res = idaapi.retrieve_member_info(self.ptr, opinfo) return None if res is None else res.tid if res.tid != idaapi.BADADDR else None else: res = idaapi.retrieve_member_info(opinfo, self.ptr) return None if opinfo.tid == idaapi.BADADDR else opinfo.tid
def id(ea): """Return the identifier of the structure at address ``ea``""" assert type( ea ) == idaapi.FF_STRU, 'Specified IDA Type is not an FF_STRU(%x) : %x' % ( idaapi.FF_STRU, type(ea)) ti = idaapi.opinfo_t() res = idaapi.get_opinfo(ea, 0, idaapi.getFlags(ea), ti) assert res, 'idaapi.get_opinfo returned %x at %x' % (res, ea) return ti.tid
def yacheck_reference_views(self): eas = yaunit.load('reference_views') idx = 0 for ea in eas: (operand, is_num, reference) = tests[idx] idx += 1 ti = idaapi.opinfo_t() f = idc.GetFlags(ea) self.assertTrue(idaapi.get_opinfo(ea, operand, f, ti)) self.assertTrue(ti.ri.type()) self.assertEqual(ti.ri.base, reference)
def applied_structs(): dataseg = sark.Segment(name='seg004') for line in dataseg.lines: ti = idaapi.opinfo_t() f = idaapi.getFlags(line.ea) if idaapi.get_opinfo(line.ea, 0, f, ti): struct_name = idaapi.get_struc_name(ti.tid) if struct_name: print (line.ea - dataseg.ea, struct_name) yield line.ea - dataseg.ea, struct_name
def __call__(self): mt = idaapi.opinfo_t() if idaapi.isStruct(self.flag): mt.tid = self.extra['id'] if idaapi.isOff0(self.flag) or idaapi.isOff1(self.flag): mt.ri = idaapi.refinfo_t(self.extra['flags'], self.extra['base'], self.extra['target'], self.extra['tdelta']) if idaapi.isASCII(self.flag): mt.strtype = self.extra['strtype'] sptr = idaapi.get_struc(self.sid) idaapi.set_member_type(sptr, self.soff, self.flag, mt, self.eoff - self.soff)
def __call__(self): mt = idaapi.opinfo_t() if idaapi.isStruct(self.flag): mt.tid = self.extra['id'] if idaapi.isOff0(self.flag) or idaapi.isOff1(self.flag): mt.ri = idaapi.refinfo_t(self.extra['flags'], self.extra['base'], self.extra['target'], self.extra['tdelta']) if idaapi.isASCII(self.flag): mt.strtype = self.extra['strtype'] sptr = idaapi.get_struc(self.sid) idaapi.add_struc_member(sptr, self.fieldname.encode('utf-8'), self.offset, self.flag, mt, self.nbytes)
def get_reference_xrefs_at_ea(base_address, ea, references): # # REFERENCE # # we consider we have 2 operands max for op_index in xrange(0, 2): ti = idaapi.opinfo_t() f = idc.GetFlags(ea) if idaapi.get_opinfo(ea, op_index, f, ti): if ti.ri.type() != 0 and ti.ri.base != 0: if ea - base_address not in references: references[ea - base_address] = list() s = {'flags': ti.ri.flags} references[ea - base_address].append((op_index, s, ti.ri.base))
def resolve(cls, type): """Return ida's (flag,typeid,size) given the type (type,size) or (type/instance) (int,4) -- a dword ([int,4],8) -- an array of 8 dwords (str,10) -- an ascii string of 10 characters (int,2) -- a word (chr,4) -- an array of 4 characters """ # FIXME: Array definitions seem awkward, I think they should look # like [type, length] and so an array of 4 words should be # [(int,2), 4] # return idaapi.FF_xxx, typeid, and size given a tuple (type,size) or just a type/instance type, nbytes = type if isinstance(type, tuple) else (type, None) # FIXME: this explicit checking of nbytes being None is sloppy size = 0 if nbytes is None else abs(nbytes) # structure -- structure_t if isinstance(type, structure_t): flag, typeid = idaapi.struflag(), type.id elif type is None: flag, typeid = idaapi.alignflag(), -1 elif isinstance(type, [].__class__): flag, typeid, nb = cls.resolve( tuple(type)) if len(type) > 1 else cls.resolve(*type) size = nb if nbytes is None else (size * nb) # FIXME # defined in typemap -- (type,size) else: table = cls.typemap[type] if type in (int, long, float, type): flag, typeid = table[None if nbytes is None else size] # FIXME else: flag, typeid = table[type] # automatically determine the size for the requested typeid if nbytes is None: opinfo = idaapi.opinfo_t() opinfo.tid = typeid size = idaapi.get_data_type_size(flag, opinfo) elif nbytes < 0: flag |= idaapi.signed_data_flag() return flag, typeid, size
def add(self, name, type, offset): """Add a member at ``offset`` with the given ``name`` and ``type``. To specify a particular size, ``type`` can be a tuple with the second element referring to the size. """ flag, typeid, nbytes = interface.typemap.resolve(type) # FIXME: handle .strtype (strings), .ec (enums), .cd (custom) opinfo = idaapi.opinfo_t() opinfo.tid = typeid realoffset = offset - self.baseoffset if name is None: logging.warn( "{:s}.instance({:s}).members.add : name is undefined, defaulting to offset {:+#x}" .format(__name__, self.owner.name, realoffset)) name = 'v', realoffset if isinstance(name, tuple): name = interface.tuplename(*name) res = idaapi.add_struc_member(self.owner.ptr, name, realoffset, flag, opinfo, nbytes) if res == idaapi.STRUC_ERROR_MEMBER_OK: logging.info( "{:s}.instance({:s}).members.add : idaapi.add_struc_member(sptr={!r}, fieldname={:s}, offset={:+#x}, flag={:#x}, mt={:#x}, nbytes={:#x}) : Success" .format(__name__, self.owner.name, self.owner.name, name, realoffset, flag, typeid, nbytes)) else: error = { idaapi.STRUC_ERROR_MEMBER_NAME: 'Duplicate field name', idaapi.STRUC_ERROR_MEMBER_OFFSET: 'Invalid offset', idaapi.STRUC_ERROR_MEMBER_SIZE: 'Invalid size', } callee = "idaapi.add_struc_member(sptr={!r}, fieldname={:s}, offset={:+#x}, flag={:#x}, mt={:#x}, nbytes={:#x})".format( self.owner.name, name, realoffset, flag, typeid, nbytes) logging.fatal(' : '.join( ('members_t.add', callee, error.get(res, "Error code {:#x}".format(res))))) return None res = idaapi.get_member(self.owner.ptr, realoffset) if res is None: logging.fatal( "{:s}.instance({:s}.members.add : Failed creating member {!r} {:s}:{:+#x}" .format(__name__, self.owner.name, name, realoffset, nbytes)) # sloppily figure out what the correct index is idx = self.index(idaapi.get_member(self.owner.ptr, realoffset)) return member_t(self.owner, idx)
def _f1(idx, ctx): import idc import ida_bytes obj = ctx.get_memref('stroff') print "%x" % obj.ea ti = idaapi.opinfo_t() f = idc.GetFlags(obj.ea) if idaapi.get_opinfo(obj.ea, 0, f, ti): print("tid=%08x - %s" % (ti.tid, idaapi.get_struc_name(ti.tid))) print "Offset: {}".format(obj.offset) import ida_struct obj2 = ctx.get_obj('fcn') print "%x" % obj2.addr name_str = ida_name.get_name(obj2.addr) print "Name {}".format(name_str) ida_struct.set_member_name(ida_struct.get_struc(ti.tid), obj.offset, name_str)
def add(self, name, offset, type): """Add a member at ``offset`` with the given ``name`` and ``type``. To specify a particular size, ``type`` can be a tuple with the second element referring to the size. """ flag, typeid, nbytes = typemap.resolve(type) # FIXME: handle .strtype (strings), .ec (enums), .cd (custom) opinfo = idaapi.opinfo_t() opinfo.tid = typeid realoffset = offset - self.baseoffset if name is None: logging.warn( 'members_t.add : name is undefined, defaulting to offset %x' % (realoffset)) name = 'v_%x' % realoffset res = idaapi.add_struc_member(self.owner.ptr, name, realoffset, flag, opinfo, nbytes) if res == idaapi.STRUC_ERROR_MEMBER_OK: logging.info( 'members_t.add : idaapi.add_struc_member(sptr=%s, fieldname=%s, offset=%x, flag=%x, mt=%x, nbytes=%x) : Success' % (self.owner.name, name, realoffset, flag, typeid, nbytes)) else: error = { idaapi.STRUC_ERROR_MEMBER_NAME: 'Duplicate field name', idaapi.STRUC_ERROR_MEMBER_OFFSET: 'Invalid offset', idaapi.STRUC_ERROR_MEMBER_SIZE: 'Invalid size', } callee = 'idaapi.add_struc_member(sptr=%s, fieldname=%s, offset=%x, flag=%x, mt=%x, nbytes=%x)' % ( self.owner.name, name, realoffset, flag, typeid, nbytes) logging.fatal(' : '.join( ('members_t.add', callee, error.get(res, 'Error code %x' % res)))) return None res = idaapi.get_member(self.owner.ptr, realoffset) if res is None: logging.fatal("member_t.create : Failed creating member %s %x:+%x", name, realoffset, nbytes) # sloppily figure out what the correct index is idx = self.index(idaapi.get_member(self.owner.ptr, realoffset)) return member_t(self.owner, idx)
def resolve(cls, pythonType): """Return ida's (flag,typeid,size) given the type (type,size) or (type/instance) (int,4) -- a dword [(int,4),8] -- an array of 8 dwords (str,10) -- an ascii string of 10 characters (int,2) -- a word [chr,4] -- an array of 4 characters """ sz, count = None, 1 # FIXME: figure out how to fix this recursive module dependency # figure out what format pythonType is in if isinstance(pythonType, ().__class__): (t, sz), count = pythonType, 1 table = cls.typemap[t] flag, typeid = table[abs(sz) if t in (int, long, float, type) else t] elif isinstance(pythonType, [].__class__): # an array, which requires us to recurse... res, count = pythonType flag, typeid, sz = cls.resolve(res) elif isinstance( pythonType, sys.modules.get('structure', __import__('structure')).structure_t): # it's a structure, pass it through. flag, typeid, sz = idaapi.struflag( ), pythonType.id, pythonType.size else: # default size that we can lookup in the typemap table table = cls.typemap[pythonType] flag, typeid = table[None] opinfo = idaapi.opinfo_t() opinfo.tid = typeid return flag, typeid, idaapi.get_data_elsize( idaapi.BADADDR, flag, opinfo) return flag | (idaapi.FF_SIGN if sz < 0 else 0), typeid, abs(sz) * count
def struc_member_created(self, sptr, mptr): extra = {} sname = idaapi.get_struc_name(sptr.id) fieldname = idaapi.get_member_name2(mptr.id) offset = 0 if mptr.unimem() else mptr.soff flag = mptr.flag nbytes = mptr.eoff if mptr.unimem() else mptr.eoff - mptr.soff mt = idaapi.opinfo_t() is_not_data = idaapi.retrieve_member_info(mt, mptr) if is_not_data: if idaapi.isOff0(flag) or idaapi.isOff1(flag): extra['target'] = mt.ri.target extra['base'] = mt.ri.base extra['tdelta'] = mt.ri.tdelta extra['flags'] = mt.ri.flags self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) # Is it really possible to create an enum? elif idaapi.isEnum0(flag): extra['serial'] = mt.ec.serial self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) elif idaapi.isStruct(flag): extra['id'] = mt.tid self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) elif idaapi.isASCII(flag): extra['strtype'] = mt.strtype self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) else: self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) return 0
def getOperandView(ea): operands = list() fl = idaapi.get_flags_novalue(ea) flags = [idaapi.get_optype_flags0(fl), idaapi.get_optype_flags1(fl) >> 4] for i in xrange(0, len(flags)): if flags[i] != 0: if (flags[i] & idaapi.FF_0STRO) != idaapi.FF_0STRO: # Offset property is independent : handle it first if flags[i] == idaapi.FF_0OFF: ti = idaapi.opinfo_t() if idaapi.get_opinfo(ea, i, fl, ti): try: offset_name = "-" + OFFSET_TYPE_MAP_NAMES[ti.ri.flags] except KeyError: logger.error( "OperandView at 0x%08X : no valid offset found for flags 0x%08X" % (ea, ti.ri.flags)) offset_name = "" operands.append((i, "offset" + offset_name)) elif flags[i] == idaapi.FF_0NUMD: value = "" operand = i if idaapi.is_invsign(ea, fl, i): value = "signeddecimal" else: value = "unsigneddecimal" operands.append((operand, value)) elif flags[i] == idaapi.FF_0NUMH: if idaapi.is_invsign(ea, fl, i): operands.append((i, "signedhexadecimal")) else: operands.append((i, "unsignedhexadecimal")) elif flags[i] == idaapi.FF_0CHAR: operands.append((i, "char")) elif flags[i] == idaapi.FF_0NUMB: operands.append((i, "binary")) elif flags[i] == idaapi.FF_0NUMO: operands.append((i, "octal")) return operands
def check_field(self, sid, ftype, strid, offset, size, name): if ftype is None: for i in range(offset, offset + size): self.assertIsNone(idc.GetMemberName(sid, i)) self.assertEqual(idc.GetMemberFlag(sid, i), -1) return try: self.assertNotEqual(idc.GetMemberName(sid, offset - 1), name) except: pass for k in range(offset, offset + size): self.assertEqual(idc.GetMemberName(sid, k), name) self.assertEqual(idc.GetMemberSize(sid, k), size) self.assertEqual(idc.GetMemberFlag(sid, k) & idaapi.DT_TYPE, ftype & 0xFFFFFFFF) if strid != -1: st = idaapi.get_struc(sid) mb = idaapi.get_member(st, offset) op = idaapi.opinfo_t() idaapi.retrieve_member_info(op, mb) self.assertEqual(op.tid, strid) self.assertNotEqual(idc.GetMemberName(sid, offset + size), name)
def struc_member_changed(self, sptr, mptr): extra = {} soff = 0 if mptr.unimem() else mptr.soff flag = mptr.flag mt = idaapi.opinfo_t() is_not_data = idaapi.retrieve_member_info(mt, mptr) if is_not_data: if idaapi.isOff0(flag) or idaapi.isOff1(flag): extra['target'] = mt.ri.target extra['base'] = mt.ri.base extra['tdelta'] = mt.ri.tdelta extra['flags'] = mt.ri.flags self._send_event(StrucMemberChangedEvent(sptr.id, soff, mptr.eoff, flag, extra)) # Is it really possible to create an enum? elif idaapi.isEnum0(flag): extra['serial'] = mt.ec.serial self._send_event(StrucMemberChangedEvent(sptr.id, soff, mptr.eoff, flag, extra)) elif idaapi.isStruct(flag): extra['id'] = mt.tid self._send_event(StrucMemberChangedEvent(sptr.id, soff, mptr.eoff, flag, extra)) elif idaapi.isASCII(flag): extra['strtype'] = mt.strtype self._send_event(StrucMemberChangedEvent(sptr.id, soff, mptr.eoff, flag, extra)) else: self._send_event(StrucMemberChangedEvent(sptr.id, soff, mptr.eoff, flag, extra)) return 0
def getStructureId(ea): assert getType(ea) == idaapi.FF_STRU ti = idaapi.opinfo_t() res = idaapi.get_opinfo(ea, 0, idaapi.getFlags(ea), ti) assert res, 'idaapi.get_opinfo returned %x at %x'% (res,ea) return ti.tid
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 typeid(self): opinfo = idaapi.opinfo_t() res = idaapi.retrieve_member_info(self.ptr, opinfo) return None if res is None else res.tid if res.tid != idaapi.BADADDR else None
def type(self, type): flag, typeid, size = typemap.resolve(type) opinfo = idaapi.opinfo_t() opinfo.tid = typeid return idaapi.set_member_type(self.__owner.ptr, self.offset, flag, opinfo, size)
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