def define(ea): if CompleteObjectLocator.isDefined(ea): return if not CompleteObjectLocator.isValid(ea): raise RttiError( "%08X: doesn't look like a correct CompleteObjectLocator" % (ea)) # Ensure referenced structs are defined. # An exception will be thrown if something goes wrong. tdPtr = idaapi.get_full_long(ea + 12) td = TypeDescriptor(tdPtr) chdPtr = idaapi.get_full_long(ea + 16) chd = ClassHierarchyDescriptor(chdPtr) strid = idaapi.get_struc_id('_s__RTTICompleteObjectLocator') size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) if chd.isMultipleInheritance: if chd.isVirtualInheritance: print '%08X: Cannot handle virtual inheritance yet.' % (ea) else: # '??_R4' + td.baseMangledName + '6B' + baseClassTd.baseMangledName + '@' # '??_7' + ... print '%08X: Cannot handle multiple inheritance yet.' % (ea) else: idaapi.set_name(ea, '??_R4' + td.baseMangledName + '6B@', 0)
def define(ea): if CompleteObjectLocator.isDefined(ea): return if not CompleteObjectLocator.isValid(ea): raise RttiError("%08X: doesn't look like a correct CompleteObjectLocator" % (ea)) # Ensure referenced structs are defined. # An exception will be thrown if something goes wrong. tdPtr = idaapi.get_full_long(ea + 12) td = TypeDescriptor(tdPtr) chdPtr = idaapi.get_full_long(ea + 16) chd = ClassHierarchyDescriptor(chdPtr) strid = idaapi.get_struc_id("_s__RTTICompleteObjectLocator") size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) if chd.isMultipleInheritance: if chd.isVirtualInheritance: print "%08X: Cannot handle virtual inheritance yet." % (ea) else: # '??_R4' + td.baseMangledName + '6B' + baseClassTd.baseMangledName + '@' # '??_7' + ... print "%08X: Cannot handle multiple inheritance yet." % (ea) else: idaapi.set_name(ea, "??_R4" + td.baseMangledName + "6B@", 0)
def isValid(ea): """ See if this looks like a type descriptor. """ # FIXME: 64-bit compatibility if idaapi.get_full_long(ea) == 0: return False if idaapi.get_full_long(ea + 4) != 0: return False if idaapi.get_full_long(ea + 8) not in TypeDescriptor.typeNameMarkers: return False try: name = TypeDescriptor.makeName(ea) except: return False return True
def scanRtti(): dataBounds = getSegBoundaries(".data") rdataBounds = getSegBoundaries(".rdata") if dataBounds is None: print "No .data section found. Cannot continue." return False print "Scanning for TypeDescriptors (might take a while)..." tds = TypeDescriptor.findAll(dataBounds) print "Found %d descriptor(s)." % len(tds) print "Defining TypeDescriptors..." for ea in tds: x = TypeDescriptor(ea) print x print "Scanning TypeDescriptors for CompleteObjectLocator refs..." cols = [] ea = rdataBounds[0] lastEa = rdataBounds[1] while ea < lastEa: ptr = idaapi.get_full_long(ea) if (dataBounds[0] <= ptr < dataBounds[1]) and (ptr in tds): # print "%08X" % ptr try: # Correct the address. colPtr = ea - 12 col = CompleteObjectLocator(colPtr) print col cols.append(colPtr) except Exception, e: # print traceback.format_exc() pass ea += 4
def isValid(ea): # Signature field must be zero if idaapi.get_full_long(ea) != 0: # print "Signature fail" return False # At offset 12, there should be a pointer to a valid TypeDescriptor tdPtr = idaapi.get_full_long(ea + 12) if not TypeDescriptor.isValid(tdPtr): # print "TD fail" return False # At offset 16, there should be a pointer to a valid ClassHierarchyDescriptor chdPtr = idaapi.get_full_long(ea + 16) if not ClassHierarchyDescriptor.isValid(chdPtr): # print "CHD fail" return False return True
def define(ea, count): # TODO: sanity checks idaapi.do_unknown_range(ea, count * 4, idaapi.DOUNK_DELNAMES) idaapi.doDwrd(ea, 4) idaapi.do_data_ex(ea, idaapi.getFlags(ea), count * 4, idaapi.BADADDR) # TODO: rewrite into idaapi calls idc.SetArrayFormat(ea, idc.AP_INDEX | idc.AP_IDXDEC, 1, 0) # Entry 0 describes the class itself => I can find out the class name. bcd = BaseClassDescriptor(idaapi.get_full_long(ea)) idaapi.set_name(ea, "??_R2" + bcd.typeDescriptor.baseMangledName + "8", 0) i = 1 while i < count: bcd = BaseClassDescriptor(idaapi.get_full_long(ea + i * 4)) i += 1
def define(ea, count): # TODO: sanity checks idaapi.do_unknown_range(ea, count * 4, idaapi.DOUNK_DELNAMES) idaapi.doDwrd(ea, 4) idaapi.do_data_ex(ea, idaapi.getFlags(ea), count * 4, idaapi.BADADDR) # TODO: rewrite into idaapi calls idc.SetArrayFormat(ea, idc.AP_INDEX | idc.AP_IDXDEC, 1, 0) # Entry 0 describes the class itself => I can find out the class name. bcd = BaseClassDescriptor(idaapi.get_full_long(ea)) idaapi.set_name(ea, '??_R2' + bcd.typeDescriptor.baseMangledName + '8', 0) i = 1 while i < count: bcd = BaseClassDescriptor(idaapi.get_full_long(ea + i * 4)) i += 1
def isValid(ea): if idaapi.get_full_long(ea) != 0: return False attrs = ClassHierarchyDescriptor.__attributes(ea) if attrs > 3: return False baseCount = ClassHierarchyDescriptor.__baseClassCount(ea) if baseCount > 1024: return False # TODO: add sanity checks. return True
def __attributes(ea): return idaapi.get_full_long(ea + 20)
def __containedBasesCount(ea): return idaapi.get_full_long(ea + 4)
def __typeDescriptorPtr(ea): return idaapi.get_full_long(ea)
def __getitem__(self, index): if index < 0 or index >= self.count: raise IndexError("Index too large") return BaseClassDescriptor(idaapi.get_full_long(self.ea + index * 4))
def classHierarchyDescriptor(self): at = idaapi.get_full_long(self.ea + 16) return ClassHierarchyDescriptor(at)
def ctorDispOffset(self): return idaapi.get_full_long(self.ea + 8)
def __v2ChdPtr(ea): return idaapi.get_full_long(ea + 24)
def typeDescriptor(self): at = idaapi.get_full_long(self.ea + 12) return TypeDescriptor(at)
def vftableOffset(self): return idaapi.get_full_long(self.ea + 4)
def __baseClassCount(ea): return idaapi.get_full_long(ea + 8)
def __baseClassArrayPtr(ea): return idaapi.get_full_long(ea + 12)
def __getitem__(self, index): if index < 0 or index >= self.count: raise IndexError('Index too large') return BaseClassDescriptor(idaapi.get_full_long(self.ea + index * 4))