Beispiel #1
0
 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)
Beispiel #2
0
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))
Beispiel #4
0
    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
Beispiel #5
0
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")
Beispiel #6
0
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"
Beispiel #7
0
    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
Beispiel #8
0
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)
Beispiel #9
0
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
Beispiel #10
0
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()
Beispiel #11
0
    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)
Beispiel #12
0
    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)
Beispiel #13
0
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)
Beispiel #14
0
 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)
Beispiel #15
0
 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)