Ejemplo n.º 1
0
def add_struc_member_retry(struct_ptr, member_name, offset, flag, mt, member_size):
    """
    @return: tuple(error_code, member_ptr)
    @note: use print_struc_error(error_code) to get error message
    """
    assert struct_ptr, offset
    assert member_name, offset
    assert member_size, offset

    error_code = ida_struct.add_struc_member(struct_ptr, member_name, offset, flag, mt, member_size)
    i = 0
    member_base_name = member_name
    while error_code == ida_struct.STRUC_ERROR_MEMBER_NAME:
        member_name = "%s%s%d" % (member_base_name, MEMBER_INDEX_SPLITTER, i)
        i += 1
        if i > MAX_MEMBER_INDEX:
            return None
        error_code = ida_struct.add_struc_member(
            struct_ptr, member_name, offset, flag, mt, member_size
        )

    if error_code == ida_struct.STRUC_ERROR_MEMBER_OK:
        member_ptr = ida_struct.get_member_by_name(struct_ptr, member_name)
        assert member_ptr, offset
    else:
        member_ptr = None

    return error_code, member_ptr
Ejemplo n.º 2
0
def set_ida_struct(struct: Struct, controller) -> bool:
    # first, delete any struct by the same name if it exists
    sid = ida_struct.get_struc_id(struct.name)
    if sid != 0xffffffffffffffff:
        sptr = ida_struct.get_struc(sid)
        ida_struct.del_struc(sptr)

    # now make a struct header
    ida_struct.add_struc(ida_idaapi.BADADDR, struct.name, False)
    sid = ida_struct.get_struc_id(struct.name)
    sptr = ida_struct.get_struc(sid)

    # expand the struct to the desired size
    # XXX: do not increment API here, why? Not sure, but you cant do it here.
    ida_struct.expand_struc(sptr, 0, struct.size)

    # add every member of the struct
    for off, member in struct.struct_members.items():
        # convert to ida's flag system
        mflag = convert_size_to_flag(member.size)

        # create the new member
        ida_struct.add_struc_member(
            sptr,
            member.member_name,
            member.offset,
            mflag,
            None,
            member.size,
        )

    return True
Ejemplo n.º 3
0
 def apply(self):
     func_frame = self.func_frame_pointer
     if self.new:
         ida_struct.add_struc_member(func_frame, self.data, self.offset, 0,
                                     ida_nalt.opinfo_t(), self.var_size)
     else:
         ida_struct.set_member_name(func_frame, self.offset, self.data)
     return True
Ejemplo n.º 4
0
 def apply_member(cls, struct, data):
     ida_struct.add_struc_member(struct, data['name'], data['offset'],
                                 data['flag'], data['opinfo'], data['size'])
     member = ida_struct.get_member(struct, data['offset'])
     if 'comment' in data and data['comment']:
         ida_struct.set_member_cmt(member, data['comment'], False)
     if 'repeatable_comment' in data and data['repeatable_comment']:
         ida_struct.set_member_cmt(member, data['repeatable_comment'], True)
Ejemplo n.º 5
0
def push_ptr_member_to_struct(
    struct, member_name, member_type, offset=BADADDR, overwrite=False
):
    mt = None
    flag = idaapi.FF_DWORD
    member_size = WORD_LEN
    if member_type is not None and (member_type.is_struct() or member_type.is_union()):
        logging.debug("Is struct!")
        substruct = extract_struct_from_tinfo(member_type)
        if substruct is not None:
            flag = idaapi.FF_STRUCT
            mt = ida_nalt.opinfo_t()
            mt.tid = substruct.id
            logging.debug(
                f"Is struct: {ida_struct.get_struc_name(substruct.id)}/{substruct.id}"
            )
            member_size = ida_struct.get_struc_size(substruct.id)
            member_type = None
    elif WORD_LEN == 4:
        flag = idaapi.FF_DWORD
    elif WORD_LEN == 8:
        flag = idaapi.FF_QWORD

    new_member_name = member_name
    if overwrite and ida_struct.get_member(struct, offset):
        logging.debug("Overwriting!")
        ret_val = ida_struct.set_member_name(struct, offset, member_name)
        i = 0
        while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME:
            new_member_name = "%s_%d" % (member_name, i)
            i += 1
            if i > 250:
                return
            ret_val = ida_struct.set_member_name(struct, offset, new_member_name)

    else:
        ret_val = ida_struct.add_struc_member(
            struct, new_member_name, offset, flag, mt, member_size
        )
        i = 0
        while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME:
            new_member_name = "%s_%d" % (member_name, i)
            i += 1
            if i > 250:
                return
            ret_val = ida_struct.add_struc_member(
                struct, new_member_name, offset, flag, mt, member_size
            )
        if ret_val != 0:
            logging.debug(f"ret_val: {ret_val}")
    member_ptr = ida_struct.get_member_by_name(struct, new_member_name)
    if member_ptr is None:
        logging.debug("member is None")
    if member_type is not None and member_ptr is not None:
        ida_struct.set_member_tinfo(
            struct, member_ptr, 0, member_type, idaapi.TINFO_DEFINITE
        )
    return member_ptr
Ejemplo n.º 6
0
def defENTENT():
    sid = ida_struct.get_struc_id("ENTENT")
    if sid != ida_idaapi.BADADDR:
        struc = ida_struct.get_struc(sid)
        ida_struct.del_struc(struc)
    sid = ida_struct.add_struc(ida_idaapi.BADADDR, "ENTENT", 0)
    struc = ida_struct.get_struc(sid)

    ida_struct.add_struc_member(struc, "flags", ida_idaapi.BADADDR, FF_BYTE,
                                None, 1)
    ida_struct.add_struc_member(struc, "addr", ida_idaapi.BADADDR, FF_WORD,
                                None, 2)
    return sid
Ejemplo n.º 7
0
 def __call__(self):
     mt = ida_nalt.opinfo_t()
     if ida_bytes.is_struct(self.flag):
         mt.tid = self.extra['id']
     if ida_bytes.is_off0(self.flag) or ida_bytes.is_off1(self.flag):
         mt.ri = ida_nalt.refinfo_t(self.extra['flags'], self.extra['base'],
                                    self.extra['target'],
                                    self.extra['tdelta'])
     if ida_bytes.is_strlit(self.flag):
         mt.strtype = self.extra['strtype']
     struc = ida_struct.get_struc_id(Event.encode(self.sname))
     sptr = ida_struct.get_struc(struc)
     ida_struct.add_struc_member(sptr, Event.encode(self.fieldname),
                                 self.offset, self.flag, mt, self.nbytes)
Ejemplo n.º 8
0
def create_struct(name, fields, size):

    struct_id = idaapi.get_struc_id(name)
    # print struct_id
    if struct_id != idaapi.BADADDR:
        i = ida_kernwin.ask_yn(
            0,
            "A class structure for %s already exists. Are you sure you want to remake it?"
            % name)
        if i == idaapi.BADADDR:
            return
        if i == 1:
            idaapi.del_struc_members(idaapi.get_struc(struct_id), 0,
                                     idaapi.get_struc_size(struct_id))
            # struct_id = idc.AddStrucEx(idaapi.BADADDR, name + "_vtbl", 0)
    else:
        struct_id = idaapi.add_struc(idaapi.BADADDR, name, 0)
    if struct_id == idaapi.BADADDR:
        Warning(
            "Could not create the class structure!.\nPlease check something.")
        return
    sptr = idaapi.get_struc(struct_id)
    for off in fields:
        off, type_name, type_kind, field_name = fields[off]
        print(
            "Process field. Off = 0x%04X, type_name = %s (%d: %s), field_name = %s"
            %
            (off, type_name, type_kind, type_sizes[type_kind][0], field_name))
        type_size = type_sizes[type_kind][1]
        ret = ida_struct.add_struc_member(sptr, field_name.decode(), off,
                                          flags_dict[type_size], None,
                                          type_size)
        if ret != 0:
            ida_kernwin.warning("Unknown error! Err = %d" % ret)
            return
        mptr = ida_struct.get_member(sptr, off)
        ida_struct.set_member_cmt(
            mptr, " --> %s (%d: %s)" %
            (type_name.decode(), type_kind, type_sizes[type_kind][0]), False)
    struct_size = ida_struct.get_struc_size(sptr)
    if size < struct_size:
        ida_kernwin.warning(
            "Struct create error! final size (%d) > instanse size (%d)" %
            (struct_size, size))
    elif size > struct_size:
        for i in range(size - struct_size):
            ida_struct.add_struc_member(sptr, "dummy%d" % i, idaapi.BADADDR,
                                        idaapi.FF_BYTE, None, 1)
Ejemplo n.º 9
0
class RTTIBaseClassDescriptor(RTTIStruc):
    msid = get_struc_id("RTTIBaseClassDescriptor")
    if msid != BADADDR:
        del_struc(get_struc(msid))
    msid = add_struc(0xFFFFFFFF, "RTTIBaseClassDescriptor", False)
    add_struc_member(get_struc(msid), "pTypeDescriptor", BADADDR,
                     FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4)
    add_struc_member(get_struc(msid), "numContainerBases", BADADDR,
                     FF_DWRD | FF_DATA, None, 4)
    add_struc_member(get_struc(msid), "PMD", BADADDR,
                     FF_DATA | FF_DWRD | FF_0OFF, u.mt_rva(), 4)
    add_struc_member(get_struc(msid), "attributes", BADADDR, FF_DWRD | FF_DATA,
                     None, 4)
    tid = msid
    struc = get_struc(tid)
    size = get_struc_size(tid)
    print "Completed Registering RTTIBaseClassDescriptor"
Ejemplo n.º 10
0
    def update_idb(self):
        sid = ida_struct.get_struc_id(self._name)
        if sid != -1:
            sptr = ida_struct.get_struc(sid)
            ida_struct.del_struc(sptr)

        sid = ida_struct.add_struc(idc.BADADDR, self._name, 0)
        sptr = ida_struct.get_struc(sid)

        for f in self._fields:
            ida_struct.add_struc_member(sptr, f.name, idc.BADADDR,
                                        (idc.FF_BYTE | idc.FF_DATA)
                                        & 0xFFFFFFFF, None, 1)
            member_name = "{}.{}".format(self._name, f.name)
            idc.SetType(
                idaapi.get_member_by_fullname(member_name)[0].id, f.type)

        ida_auto.auto_wait()
Ejemplo n.º 11
0
def get_guid_tid():
    tid = ida_struct.get_struc_id('GUID')
    if tid == idaapi.BADADDR:
        print("[*] create GUID struct")
        tid = ida_struct.add_struc(0xffffffff, 'GUID', 0)
        sptr = ida_struct.get_struc(tid)
        ida_struct.add_struc_member(sptr, 'Data1', 0x0, 0x20000000, None, 4)
        ida_struct.add_struc_member(sptr, 'Data2', 0x4, 0x10000000, None, 2)
        ida_struct.add_struc_member(sptr, 'Data3', 0x6, 0x10000000, None, 2)
        ida_struct.add_struc_member(sptr, 'Data4', 0x8, 0x00000000, None, 8)
    return tid
Ejemplo n.º 12
0
    def load(infos):
        insn = ida_ua.insn_t()

        for info in infos:
            # Find or create struct.
            struct_id = ida_struct.get_struc_id(info['name'])
            if struct_id == BADADDR:
                print('[IDA-Sync] Creating new struct %s.' % info['name'])
                struct_id = ida_struct.add_struc(info['idx'], info['name'])
            struct = ida_struct.get_struc(struct_id)

            ida_struct.set_struc_idx(struct, info['idx'])

            # Create struct members.
            for member in info['members']:
                ida_struct.add_struc_member(
                    struct,
                    member['name'],
                    member['offset'],
                    # flag
                    0,
                    # opinfo_t instance... maybe it should sometimes be
                    # something?
                    None,
                    member['size'],
                )

            # Create xrefs to members of the struct as offsets.
            for xref in info['xrefs']:
                typ = xref['type']

                # Offset xref.
                if typ == 1:
                    # TODO figure out what second argument does.
                    idc.op_plain_offset(xref['from'], 1, xref['offset'])

                # Read/write xrefs.
                elif typ in [2, 3]:
                    ida_ua.create_insn(xref['from'], insn)
                    idc.op_stroff(insn, 1, struct.id, 0)

                # TODO do the other cases come up?
                else:
                    pass
Ejemplo n.º 13
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)
Ejemplo n.º 14
0
    def update_idb(self, delete_existing_members=True):
        sid = ida_struct.get_struc_id(self._name)
        sptr = ida_struct.get_struc(sid)

        if sid == idc.BADADDR:
            sid = ida_struct.add_struc(idc.BADADDR, self._name, 0)
            sptr = ida_struct.get_struc(sid)
        else:
            if delete_existing_members:
                ida_struct.del_struc_members(sptr, 0, 0xffffffff)

        for f in self._fields:
            ida_struct.add_struc_member(sptr, f.name, f.offset,
                                        (idc.FF_BYTE | idc.FF_DATA)
                                        & 0xFFFFFFFF, None, 1)
            member_name = "{}.{}".format(self._name, f.name)
            idc.SetType(
                idaapi.get_member_by_fullname(member_name)[0].id, f.type)

        ida_auto.auto_wait()
Ejemplo n.º 15
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
Ejemplo n.º 16
0
def import_structures(structures):
    """
    Import structures

    :param structures: Dict containing structure information
    """

    curr_idx = ida_struct.get_last_struc_idx() + 1
    for struct_name, struct_info in structures.items():
        # Create structure
        tid = ida_struct.add_struc(curr_idx, struct_name)

        # Get struct object and add members
        struct = ida_struct.get_struc(tid)
        for member_name, member_info in struct_info['members'].items():
            flag = get_flag_from_type(member_info['type'])
            ida_struct.add_struc_member(
                struct, member_name, member_info['offset'],
                flag, None, member_info['size']
            )

        curr_idx += 1
Ejemplo n.º 17
0
 def implement(self):
     id_of_struct = ida_struct.get_struc_id(self._id)
     sturct_obj = ida_struct.get_struc(long(id_of_struct))
     val_type = ""
     size = 0
     if self._variable_type == "db":
         val_type = ida_bytes.FF_BYTE
         size = 1
     elif self._variable_type == "dw":
         val_type = ida_bytes.FF_WORD
         size = 2
     elif self._variable_type == "dd":
         val_type = ida_bytes.FF_DWORD
         size = 4
     elif self._variable_type == "dq":
         val_type = ida_bytes.FF_QWORD
         size = 8
     else:
         val_type = ida_bytes.FF_STRUCT
         size = 0
     ida_struct.add_struc_member(sturct_obj, self._value, int(self._offset),
                                 val_type, None, size)
Ejemplo n.º 18
0
 def __call__(self):
     mt = ida_nalt.opinfo_t()
     if ida_bytes.is_struct(self.flag):
         mt.tid = self.extra["id"]
     if ida_bytes.is_off0(self.flag) or ida_bytes.is_off1(self.flag):
         mt.ri = ida_nalt.refinfo_t(
             self.extra["flags"],
             self.extra["base"],
             self.extra["target"],
             self.extra["tdelta"],
         )
     if ida_bytes.is_strlit(self.flag):
         mt.strtype = self.extra["strtype"]
     struc = ida_struct.get_struc_id(Event.encode(self.sname))
     sptr = ida_struct.get_struc(struc)
     ida_struct.add_struc_member(
         sptr,
         Event.encode(self.fieldname),
         self.offset,
         self.flag,
         mt,
         self.nbytes,
     )
Ejemplo n.º 19
0
    def _prepare_ida_type(self):
        sptr = self.struct.sptr

        # Create structure member
        if ida_struct.add_struc_member(
                sptr, self.name, self.offset, 0, None,
                self.size) != ida_struct.STRUC_ERROR_MEMBER_OK:
            raise RuntimeError("Could not create struct member '{}'".format(
                self.name))

        # Get member pointer
        self.mptr = ida_struct.get_member_by_name(sptr, self.name)

        # set type
        ida_struct.set_member_tinfo(sptr, self.mptr, self.offset, self.tif, 0)

        self.log.info("Created struct member '%s' of size %d at offset %d",
                      self.hierarchy, self.size, self.offset)
Ejemplo n.º 20
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)
                className = strip(rtd.class_name)
                classes[className] = [strip(b) for b in rchd.bases]
                vtables[className] = vtable
                MakeNameEx(vtable, "vtable__" + className, 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)
Ejemplo n.º 21
0
def defSEGENT():
    sid = ida_struct.get_struc_id("SEGENT")
    if sid != ida_idaapi.BADADDR:
        struc = ida_struct.get_struc(sid)
        ida_struct.del_struc(struc)
    sid = ida_struct.add_struc(ida_idaapi.BADADDR, "SEGENT", 0)
    struc = ida_struct.get_struc(sid)

    ida_struct.add_struc_member(struc, "flags", ida_idaapi.BADADDR,
                                ida_bytes.FF_WORD, None, 2)
    ida_struct.add_struc_member(struc, "oSegment", ida_idaapi.BADADDR,
                                ida_bytes.FF_WORD, None, 2)
    ida_struct.add_struc_member(struc, "nParagraphs", ida_idaapi.BADADDR,
                                ida_bytes.FF_WORD, None, 2)
    ida_struct.add_struc_member(struc, "nReloc", ida_idaapi.BADADDR,
                                ida_bytes.FF_WORD, None, 2)
    ida_struct.add_struc_member(struc, "minAlloc", ida_idaapi.BADADDR,
                                ida_bytes.FF_WORD, None, 2)
    ida_struct.add_struc_member(struc, "unused", ida_idaapi.BADADDR,
                                ida_bytes.FF_WORD, None, 2)
    return sid
Ejemplo n.º 22
0
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
Ejemplo n.º 23
0
def add_to_struct(
    struct,
    member_name,
    member_type=None,
    offset=BADADDR,
    is_offset=False,
    overwrite=False,
):
    mt = None
    flag = idaapi.FF_DWORD
    member_size = WORD_LEN
    if member_type is not None and (member_type.is_struct()
                                    or member_type.is_union()):
        logging.debug("Is struct!")
        substruct = extract_struct_from_tinfo(member_type)
        if substruct is not None:
            flag = idaapi.FF_STRUCT
            mt = ida_nalt.opinfo_t()
            mt.tid = substruct.id
            logging.debug(
                f"Is struct: {ida_struct.get_struc_name(substruct.id)}/{substruct.id}"
            )
            member_size = ida_struct.get_struc_size(substruct.id)
    elif WORD_LEN == 4:
        flag = idaapi.FF_DWORD
    elif WORD_LEN == 8:
        flag = idaapi.FF_QWORD
    if is_offset:
        flag |= idaapi.FF_0OFF
        mt = ida_nalt.opinfo_t()
        r = ida_nalt.refinfo_t()
        r.init(
            ida_nalt.get_reftype_by_size(WORD_LEN) | ida_nalt.REFINFO_NOBASE)
        mt.ri = r

    new_member_name = member_name
    member_ptr = ida_struct.get_member(struct, offset)
    if overwrite and member_ptr:
        if ida_struct.get_member_name(member_ptr.id) != member_name:
            logging.debug("Overwriting!")
            ret_val = ida_struct.set_member_name(struct, offset, member_name)
            i = 0
            while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME:
                new_member_name = "%s_%d" % (member_name, i)
                i += 1
                if i > 250:
                    logging.debug("failed change name")
                    return
                ret_val = ida_struct.set_member_name(struct, offset,
                                                     new_member_name)

    else:
        ret_val = ida_struct.add_struc_member(struct, new_member_name, offset,
                                              flag, mt, member_size)
        i = 0
        while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME:
            new_member_name = "%s_%d" % (member_name, i)
            i += 1
            if i > 250:
                return
            ret_val = ida_struct.add_struc_member(struct, new_member_name,
                                                  offset, flag, mt,
                                                  member_size)
        if ret_val != 0:
            logging.debug(f"ret_val: {ret_val}")
        member_ptr = ida_struct.get_member_by_name(struct, new_member_name)
    if member_type is not None and member_ptr is not None:
        ida_struct.set_member_tinfo(struct, member_ptr, 0, member_type,
                                    idaapi.TINFO_DEFINITE)
    return member_ptr
Ejemplo n.º 24
0
"""
    This file is part of Polichombr
        (c) ANSSI-FR 2018

    Description:
        Semi automated test that add some data in the IDA database,
        that should be reflected in the second database
"""

import ida_name, ida_bytes, ida_struct
import idc

ida_name.set_name(0x401000, "TESTFUNCTION")
ida_bytes.set_cmt(0x40100A, "TEST COMMENT", 0)
ida_bytes.set_cmt(0x40100F, "TEST RPT COMMENT", 1)

struct_1 = ida_struct.add_struc(0, "TESTSTRUCT1")

struct_pointer = ida_struct.get_struc(struct_1)

ida_struct.add_struc_member(struct_pointer, "TESTMEMBER", 0, 0, None, 0)

idc.SetType(0x401000, "int __cdecl start(char *lpszTestArg);")
Ejemplo n.º 25
0
    def analyze_function_frame(self, function: Function) -> None:
        """
        inspect the given function to determine the frame layout and set references appropriately.

        args:
          function (Function): function instance.
        """
        # given a function prologue like the following:
        #
        #     23 80 80 80 80 00       get_global          $global0
        #     21 04                   set_local           $local4
        #     41 20                   i32.const           0x20
        #     21 05                   set_local           $local5
        #     20 04                   get_local           $local4
        #     20 05                   get_local           $local5
        #     6B                      i32.sub
        #     21 06                   set_local           $local6
        #
        # recognize that the function frame is 0x20 bytes.

        if not self.has_llvm_prologue(function):
            return

        bc = self.get_prologue_bc(function['offset'])
        if len(bc) == 0:
            return

        global_frame_pointer = bc[0].imm.global_index
        frame_size = bc[2].imm.value
        local_frame_pointer = bc[7].imm.local_index

        # add a frame structure to the function
        f = ida_funcs.get_func(function['offset'])
        ida_frame.add_frame(f, 0x0, 0x0, frame_size)
        ida_struct.set_struc_name(f.frame, 'frame%d' % function['index'])

        # ensure global variable $frame_stack is named appropriately
        ida_name.set_name(self.proc.globals[global_frame_pointer]['offset'],
                          '$frame_stack')

        # re-map local variable to $frame_pointer
        ida_frame.add_regvar(f, function['offset'],
                             function['offset'] + function['size'],
                             '$local%d' % local_frame_pointer,
                             '$frame_pointer', '')

        # define the frame structure layout by scanning for references within this function
        frame_references = self.find_function_frame_references(
            function, local_frame_pointer)
        for frame_offset, refs in frame_references.items():

            member_name = 'field_%x' % frame_offset
            for ref in refs:
                if 'parameter' in ref:
                    member_name = 'param%d' % (ref['parameter'])

            # pick largest element size for the element type
            flags = 0
            size = 0
            for ref in refs:
                fl = {
                    'i8': ida_bytes.FF_BYTE | ida_bytes.FF_DATA,
                    'i16': ida_bytes.FF_WORD | ida_bytes.FF_DATA,
                    'i32': ida_bytes.FF_DWORD | ida_bytes.FF_DATA,
                    'i64': ida_bytes.FF_QWORD | ida_bytes.FF_DATA,
                    'f32': ida_bytes.FF_FLOAT | ida_bytes.FF_DATA,
                    'f64': ida_bytes.FF_DOUBLE | ida_bytes.FF_DATA,
                }[ref['element_size']]

                s = {
                    'i8': 1,
                    'i16': 2,
                    'i32': 4,
                    'i64': 8,
                    'f32': 4,
                    'f64': 8,
                }[ref['element_size']]

                # by luck, FF_BYTE < FF_WORD < FF_DWORD < FF_QWORD,
                # so we can order flag values.
                if fl > flags:
                    flags = fl
                    size = s

            logger.debug('adding frame member %s to function %d', member_name,
                         function['index'])
            ida_struct.add_struc_member(ida_struct.get_struc(f.frame),
                                        member_name, frame_offset,
                                        flags & 0xFFFFFFFF, None, size)

        # mark struct references
        for refs in frame_references.values():
            for ref in refs:
                # set type of operand 0 to function frame structure offset
                # ref: https://github.com/idapython/src/blob/a3855ab969fd16758b3de007525feeba3a920344/tools/inject_pydoc/bytes.py#L5
                insn = ida_ua.insn_t()
                if not ida_ua.decode_insn(insn, ref['offset']):
                    continue

                path = ida_pro.tid_array(1)
                path[0] = f.frame
                ida_bytes.op_stroff(insn, 0, path.cast(), 1, 0)
Ejemplo n.º 26
0
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