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 add_struct(name, size): info = idaapi.get_inf_structure() if info.is_64bit(): step_size = 8 flag = idaapi.FF_DATA | idaapi.FF_QWORD else: step_size = 4 flag = idaapi.FF_DATA | idaapi.FF_DWORD id = idaapi.add_struc(idaapi.BADADDR, name) if id == idaapi.BADADDR: id = idaapi.get_struc_id(name) struc = idaapi.get_struc(id) for off in range(0, size, step_size): idaapi.add_struc_member(struc, f"field_{off:X}", off, flag, None, step_size)
def make_stack_variable(func_start, offset, name, size): func = idaapi.get_func(func_start) frame = idaapi.get_frame(func) if frame is None: if idaapi.add_frame(func, 0, 0, 0) == -1: raise ValueError("couldn't create frame for function @ 0x%x" % func_start) frame = idaapi.get_frame(func) offset += func.frsize member = idaapi.get_member(frame, offset) if member: return 0 else: # No member at the offset, create a new one if idaapi.add_struc_member( frame, name, offset, idaapi.wordflag() if size == 2 else idaapi.byteflag(), None, size) == 0: return 1 else: raise ValueError( "failed to create stack frame member %s @ +0x%x in function @ 0x%x" % (name, offset, func_start))
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
class RTTIBaseClassDescriptor(RTTIStruc): msid = get_struc_id("RTTIBaseClassDescriptor") if msid != BADADDR: del_struc(msid) msid = add_struc(0xFFFFFFFF, "RTTIBaseClassDescriptor", False) add_struc_member(msid, "pTypeDescriptor", BADADDR, FF_DATA | FF_DWORD | FF_0OFF, u.mt_rva().tid, 4) add_struc_member(msid, "numContainerBases", BADADDR, FF_DWORD | FF_DATA, -1, 4) add_struc_member(msid, "PMD", BADADDR, FF_DATA | FF_DWORD | FF_0OFF, u.mt_rva().tid, 4) add_struc_member(msid, "attributes", BADADDR, FF_DWORD | FF_DATA, -1, 4) tid = msid struc = get_struc(tid) size = get_struc_size(tid) print("Completed Registering RTTIBaseClassDescriptor")
class RTTIBaseClassDescriptor(RTTIStruc): msid = get_struc_id("PMD") if msid != BADADDR: del_struc(msid) msid = add_struc(0xFFFFFFFF, "PMD", False) add_struc_member(msid, "mdisp", BADADDR, FF_DATA | FF_DWRD, -1, 4) add_struc_member(msid, "pdisp", BADADDR, FF_DATA | FF_DWRD, -1, 4) add_struc_member(msid, "vdisp", BADADDR, FF_DATA | FF_DWRD, -1, 4) pmdid = msid pmdstruc = get_struc(pmdid) pmdsize = get_struc_size(pmdid) msid = get_struc_id("RTTIBaseClassDescriptor") if msid != BADADDR: del_struc(msid) msid = add_struc(0xFFFFFFFF, "RTTIBaseClassDescriptor", False) add_struc_member(msid, "pTypeDescriptor", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, 00000000, 4) add_struc_member(msid, "numContainerBases", BADADDR, FF_DWRD | FF_DATA, -1, 4) add_struc_member(msid, "PMD", BADADDR, FF_DATA | FF_DWRD | FF_STRU, pmdid, pmdsize) add_struc_member(msid, "attributes", BADADDR, FF_DWRD | FF_DATA, -1, 4) tid = msid struc = get_struc(tid) size = get_struc_size(tid) print "Completed Registering RTTIBaseClassDescriptor"
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
class RTTIClassHierarchyDescriptor(RTTIStruc): bases = None msid = get_struc_id("RTTIClassHierarchyDescriptor") if msid != BADADDR: del_struc(get_struc(msid)) msid = add_struc(0xFFFFFFFF, "RTTIClassHierarchyDescriptor", False) add_struc_member(get_struc(msid), "signature", BADADDR, FF_DWRD | FF_DATA, None, 4) add_struc_member(get_struc(msid), "attribute", BADADDR, FF_DWRD | FF_DATA, None, 4) add_struc_member(get_struc(msid), "numBaseClasses", BADADDR, FF_DWRD | FF_DATA, None, 4) add_struc_member(get_struc(msid), "pBaseClassArray", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) tid = msid struc = get_struc(tid) print "Completed Registering RTTIClassHierarchyDescriptor" def __init__(self, ea): print "Processing Class Hierarchy Descriptor at 0x%x" % ea do_unknown_range(ea, get_struc_size(self.tid), DOUNK_DELNAMES) if doStruct(ea, get_struc_size(self.tid), self.tid): baseClasses = get_32bit( ea + get_member_by_name(get_struc( self.tid), "pBaseClassArray").soff) + u.x64_imagebase() nb_classes = get_32bit( ea + get_member_by_name(get_struc(self.tid), "numBaseClasses").soff) print "Baseclasses array at 0x%x" % baseClasses # Skip the first base class as it is itself (could check) self.bases = [] for i in range(1, nb_classes): baseClass = get_32bit(baseClasses + i * 4) + u.x64_imagebase() print "base class 0x%x" % baseClass doDwrd(baseClasses + i * 4, 4) op_offset(baseClasses + i * 4, -1, u.REF_OFF | REFINFO_RVA, -1, 0, 0) doStruct(baseClass, RTTIBaseClassDescriptor.size, RTTIBaseClassDescriptor.tid) typeDescriptor = get_32bit(baseClass) + u.x64_imagebase() self.bases.append( RTTITypeDescriptor(typeDescriptor).class_name)
class RTTITypeDescriptor(RTTIStruc): class_name = None msid = get_struc_id("RTTITypeDescriptor") if msid != BADADDR: del_struc(get_struc(msid)) msid = add_struc(0xFFFFFFFF, "RTTITypeDescriptor", False) add_struc_member(get_struc(msid), "pVFTable", BADADDR, FF_DATA | u.PTR_TYPE | FF_0OFF, u.mt_address(), u.PTR_SIZE) add_struc_member(get_struc(msid), "spare", BADADDR, FF_DATA | u.PTR_TYPE, None, u.PTR_SIZE) add_struc_member(get_struc(msid), "name", BADADDR, FF_DATA | FF_ASCI, u.mt_ascii(), 0) tid = msid struc = get_struc(tid) size = get_struc_size(tid) print "Completed Registering RTTITypeDescriptor" def __init__(self, ea): name = ea + get_member_by_name(get_struc(self.tid), "name").soff strlen = u.get_strlen(name) if strlen is None: # not a real vtable return self.size = self.size + strlen mangled = get_ascii_contents(name, strlen, 0) if mangled is None: # not a real function name return # print "Mangled: " + mangled demangled = demangle_name('??_R0' + mangled[1:], 0) if demangled: do_unknown_range(ea, self.size, DOUNK_DELNAMES) if doStruct(ea, self.size, self.tid): # print " Made td at 0x%x: %s" % (ea, demangled) self.class_name = demangled return print " FAIL :(" return
class RTTICompleteObjectLocator(RTTIStruc): # Init class statics msid = get_struc_id("RTTICompleteObjectLocator") if msid != BADADDR: del_struc(get_struc(msid)) msid = add_struc(0xFFFFFFFF, "RTTICompleteObjectLocator", False) add_struc_member(get_struc(msid), "signature", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "offset", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "cdOffset", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "pTypeDescriptor", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) add_struc_member(get_struc(msid), "pClassDescriptor", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) if u.x64: add_struc_member(get_struc(msid), "pSelf", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) tid = msid struc = get_struc(tid) size = get_struc_size(tid) print "Completed Registering RTTICompleteObjectLocator" def __init__(self, ea, vtable): filepath = GetIdbPath()[:-4] fp = open(r"{filepath}.txt".format(filepath=filepath), 'a') # fp.write(filepath) print "Create file" do_unknown_range(ea, self.size, DOUNK_DELNAMES) if doStruct(ea, self.size, self.tid): # Get adress of type descriptor from CompleteLocator # print "Complete Object Locator at: 0x%x" % ea offset = get_member_by_name(self.struc, "pTypeDescriptor").soff typeDescriptor = get_32bit(ea + offset) + u.x64_imagebase() # print "Looking for type Descriptor at: 0x%x" % typeDescriptor rtd = RTTITypeDescriptor(typeDescriptor) if rtd.class_name: # print "Type Descriptor at: 0x%x" % typeDescriptor offset = get_member_by_name(self.struc, "pClassDescriptor").soff classHierarchyDes = get_32bit(ea + offset) + u.x64_imagebase() rchd = RTTIClassHierarchyDescriptor(classHierarchyDes) # filter out None entries rchd.bases = filter(lambda x: x, rchd.bases) classes[strip(rtd.class_name)] = [strip(b) for b in rchd.bases] MakeNameEx(vtable, "vtable__" + strip(rtd.class_name), SN_NOWARN) tempStr = hex(vtable).rstrip('L') + '\t' + strip( rtd.class_name) + '\t' + str(GuessType( Dword(vtable + 4))) + '\n' if ('std' not in tempStr[:15] and 'ATL' not in tempStr[:15]): fp.write(tempStr) else: # if the RTTITypeDescriptor doesn't have a valid name for us to # read, then this wasn't a valid RTTICompleteObjectLocator MakeUnknown(ea, self.size, DOUNK_SIMPLE) fp.close()
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 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)
class RTTICompleteObjectLocator(RTTIStruc): # Init class statics msid = get_struc_id("RTTICompleteObjectLocator") if msid != BADADDR: del_struc(get_struc(msid)) msid = add_struc(0xFFFFFFFF, "RTTICompleteObjectLocator", False) add_struc_member(get_struc(msid), "signature", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "offset", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "cdOffset", BADADDR, FF_DATA | FF_DWRD, None, 4) add_struc_member(get_struc(msid), "pTypeDescriptor", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) add_struc_member(get_struc(msid), "pClassDescriptor", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) if u.x64: add_struc_member(get_struc(msid), "pSelf", BADADDR, FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4) tid = msid struc = get_struc(tid) size = get_struc_size(tid) print "Completed Registering RTTICompleteObjectLocator" def __init__(self, ea, vtable): do_unknown_range(ea, self.size, DOUNK_DELNAMES) if doStruct(ea, self.size, self.tid): # Get adress of type descriptor from CompleteLocator print "Complete Object Locator at: 0x%x" % ea offset = get_member_by_name(self.struc, "pTypeDescriptor").soff typeDescriptor = get_32bit(ea + offset) + u.x64_imagebase() print "Looking for type Descriptor at: 0x%x" % typeDescriptor rtd = RTTITypeDescriptor(typeDescriptor) if rtd.class_name: print "Type Descriptor at: 0x%x" % typeDescriptor offset = get_member_by_name(self.struc, "pClassDescriptor").soff classHierarchyDes = get_32bit(ea + offset) + u.x64_imagebase() rchd = RTTIClassHierarchyDescriptor(classHierarchyDes) # filter out None entries rchd.bases = filter(lambda x: x, rchd.bases) classes[strip(rtd.class_name)] = [strip(b) for b in rchd.bases] MakeNameEx(vtable, "vtable__" + strip(rtd.class_name), SN_NOWARN) else: # if the RTTITypeDescriptor doesn't have a valid name for us to # read, then this wasn't a valid RTTICompleteObjectLocator MakeUnknown(ea, self.size, DOUNK_SIMPLE)
def create(cls, owner, name, offset, type, nbytes): flag, typeid = self.__determine_type(type, nbytes) index = idaapi.add_struc_member(owner, name, offset, flag, typeid, nbytes) return cls.fetch(owner, index)
def create(cls, owner, name, offset, type, nbytes): flag,typeid = self.__determine_type(type, nbytes) index = idaapi.add_struc_member(owner, name, offset, flag, typeid, nbytes) return cls.fetch(owner, index)