Ejemplo n.º 1
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)
Ejemplo n.º 2
0
    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))
Ejemplo n.º 3
0
    def near_offset(self, offset):
        '''Return the member near to the specified ``offset``.'''
        min, max = map(lambda sz: sz + self.baseoffset,
                       (idaapi.get_struc_first_offset(self.owner.ptr),
                        idaapi.get_struc_last_offset(self.owner.ptr)))
        if (offset < min) or (offset >= max):
            logging.warn(
                "{:s}.instance({:s}).members.near_offset : Requested offset {:+#x} not within bounds ({:#x},{:#x}). Trying anyways.."
                .format(__name__, self.owner.name, offset, min, max))

        res = offset - self.baseoffset
        mem = idaapi.get_member(self.owner.ptr, res)
        if mem is None:
            logging.info(
                "{:s}.instance({:s}).members.near_offset : Unable to locate member at offset {:+#x}. Trying get_best_fit_member instead."
                .format(__name__, self.owner.name, res))
            mem = idaapi.get_best_fit_member(self.owner.ptr, res)

        if mem is None:
            raise LookupError(
                "{:s}.instance({:s}).members.near_offset : Unable to find member near offset : {:+#x}"
                .format(__name__, self.owner.name, offset))

        index = self.index(mem)
        return self[index]
Ejemplo n.º 4
0
        def dt_type(self):
            m = idaapi.get_member(self.__owner.ptr, self.offset)
            if m is None:
                return 0
            flag = m.flag & idaapi.DT_TYPE

            # idaapi(swig) and python have different definitions of what constant values are
            max = (sys.maxint + 1) * 2
            return flag if flag < sys.maxint else flag - max
Ejemplo n.º 5
0
def is_gap(structure_name,field_offset):
    sid = idaapi.get_struc_id(structure_name)
    if sid != idaapi.BADADDR:
        sptr = idaapi.get_struc(sid)
        mptr = idaapi.get_member(sptr, field_offset)
        if mptr:
            return False
        else:
            return True
Ejemplo n.º 6
0
        def dt_type(self):
            m = idaapi.get_member(self.__owner.ptr, self.offset)
            if m is None:
                return 0
            flag = m.flag & idaapi.DT_TYPE

            # idaapi(swig) and python have different definitions of what constant values are
            max = (sys.maxint+1)*2
            return flag if flag < sys.maxint else flag - max
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
def get_struct_member_type(structure_name, field_offset):
    sid = idaapi.get_struc_id(structure_name)
    if sid != idaapi.BADADDR:
        sptr = idaapi.get_struc(sid)
        mptr = idaapi.get_member(sptr, field_offset)
        if mptr:
            tif = idaapi.tinfo_t()
            idaapi.get_member_tinfo2(mptr, tif)
            return tif
        return None
Ejemplo n.º 9
0
    def get_stack_variable_name(func_start, offset):
        func = idaapi.get_func(func_start)
        frame = idaapi.get_frame(func)
        if frame is None:
            raise ValueError("couldn't get frame for function @ 0x%x" %
                             func_start)

        offset += func.frsize
        member = idaapi.get_member(frame, offset)
        return idaapi.get_member_name(member.id)
Ejemplo n.º 10
0
def get_stkvar_map(ea):
    '''ea_t -> {int : (str, tinfo_t)}'''
    # NOTE mutates d
    frame = idaapi.get_frame(ea)

    def make_map(d, (off, name, _)):
        mem = idaapi.get_member(frame, off)
        ti = idaapi.tinfo_t()
        idaapi.get_or_guess_member_tinfo2(mem, ti)
        d[off] = (name, ti)
        return d
Ejemplo n.º 11
0
def get_stkvar_map(ea):
    '''ea_t -> {int : (str, tinfo_t)}'''
    # NOTE mutates d
    frame = idaapi.get_frame(ea)

    def make_map(d, (off, name, _)):
        mem = idaapi.get_member(frame, off)
        ti = idaapi.tinfo_t()
        idaapi.get_or_guess_member_tinfo2(mem, ti)
        d[off] = (name, ti)
        return d
Ejemplo n.º 12
0
    def by_offset(self, offset):
        '''Return the member at the specified ``offset``.'''
        min, max = map(lambda sz: sz + self.baseoffset,
                       (idaapi.get_struc_first_offset(self.owner.ptr),
                        idaapi.get_struc_last_offset(self.owner.ptr)))

        mptr = idaapi.get_member(self.owner.ptr, max - self.baseoffset)
        msize = idaapi.get_member_size(mptr)
        if (offset < min) or (offset >= max + msize):
            raise LookupError(
                "{:s}.instance({:s}).members.by_offset : Requested offset {:+#x} not within bounds ({:#x},{:#x})"
                .format(__name__, self.owner.name, offset, min, max + msize))

        mem = idaapi.get_member(self.owner.ptr, offset - self.baseoffset)
        if mem is None:
            raise LookupError(
                "{:s}.instance({:s}).members.by_offset : Unable to find member at offset : {:+#x}"
                .format(__name__, self.owner.name, offset))

        index = self.index(mem)
        return self[index]
Ejemplo n.º 13
0
    def dt_type(self):
        '''Return the member's `.dt_type` attribute.'''
        m = idaapi.get_member(self.__owner.ptr,
                              self.offset - self.__owner.members.baseoffset)
        if m is None:
            return 0
        flag = m.flag & idaapi.DT_TYPE

        # idaapi(swig) and python have different definitions of what constant values are
        max = (sys.maxint + 1) * 2
        return (max + flag) if flag < 0 else (flag -
                                              max) if flag > max else flag
Ejemplo n.º 14
0
def loadMembersIDA7(struc, sid):
    '''Returns list of tuples of (offset, memberName, member)'''
    #mixing idc & idaapi, kinda annoying but need low-level idaapi for a
    # type access, but cant dig into structs...
    members = []
    off = idaapi.get_struc_first_offset(struc)
    while off != idc.BADADDR:
        logger.debug('struc offset: 0x%x (%d)', off, off)
        member = idaapi.get_member(struc, off)
        if (member == 0) or (member is None):
            pass  #not really an error, i guess
        else:
            members.append((off, idc.get_member_name(sid, off), member))
        off = idaapi.get_struc_next_offset(struc, off)
    members.sort(key=lambda mem: mem[0])
    return members
Ejemplo n.º 15
0
def loadMembersIDA7(struc, sid):
    '''Returns list of tuples of (offset, memberName, member)'''
    #mixing idc & idaapi, kinda annoying but need low-level idaapi for a 
    # type access, but cant dig into structs...
    members = []
    off = idaapi.get_struc_first_offset(struc) 
    while off != idc.BADADDR:
        logger.debug('struc offset: 0x%x (%d)', off, off)
        member = idaapi.get_member(struc, off)
        if (member == 0) or (member is None):
            pass    #not really an error, i guess
        else:
            members.append( (off, idc.get_member_name(sid, off), member) )
        off = idaapi.get_struc_next_offset(struc, off )
    members.sort(key = lambda mem: mem[0])
    return members
Ejemplo n.º 16
0
    def byOffset(self, offset):
        min, max = map(lambda sz: sz - self.baseoffset,
                       (idaapi.get_struc_first_offset(self.owner.ptr),
                        idaapi.get_struc_last_offset(self.owner.ptr)))
        if (offset < min) or (offset >= max):
            logging.warn(
                'structure_t(%s).members.byoffset : Requested offset %x not within bounds (%x,%x). Trying anyways..'
                % (self.owner.name, offset, min, max))

        mem = idaapi.get_member(self.owner.ptr, offset - self.baseoffset)
        if mem is None:
            logging.warn(
                'structure_t(%s).members.byoffset : Unable to locate member at offset %x. Trying get_best_fit_member instead.'
                % (self.owner.name, offset - self.baseoffset))
            mem = idaapi.get_best_fit_member(self.owner.ptr,
                                             offset - self.baseoffset)
        if mem is None:
            raise IndexError, offset
        index = self.index(mem)
        return self[index]
Ejemplo n.º 17
0
    def xrefs_to(self):
        """
        Retrieves the xrefs to the stack variable.

        NOTE: This code is very SWIGGY because IDA did not properly expose this functionality.

        :raises ValueError: if frame_id, stack_offset, or string_reference was not provided.
            This is needed to determine what function to use.
        """
        if self._xrefs_to is None:
            if not self.string_reference:
                raise ValueError('Unable to get xrefs without string_reference.')
            if not (self.frame_id and self.stack_offset):
                raise ValueError('Unable to get xrefs without frame_id and stack_offset')
            xrefs = idaapi.xreflist_t()
            frame = idaapi.get_frame(self.frame_id)
            func = idaapi.get_func(self.string_reference)
            member = idaapi.get_member(frame, self.stack_offset)
            idaapi.build_stkvar_xrefs(xrefs, func, member)
            self._xrefs_to = [ref.ea for ref in xrefs]
        return self._xrefs_to
Ejemplo n.º 18
0
    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)
Ejemplo n.º 19
0
    def save_strucs(self, memory_exporter):
        """
        Structures : export modified structures and delete those who have been deleted
        """
        for struc_id in self.structures_to_process:
            self.ida_model.clear_exported_struc_enum_id(struc_id)
            sidx = idc.GetStrucIdx(struc_id)
            if sidx is None or sidx == idc.BADADDR:
                # it is a deleted structure or a stackframe
                # in this last case we need to export the parent (function)
                eaFunc = idaapi.get_func_by_frame(struc_id)
                if eaFunc != idc.BADADDR:
                    # OK, it is a stackframe
                    self.ida_model.accept_struc(
                        memory_exporter, 0, struc_id, ya.OBJECT_TYPE_STACKFRAME, ya.OBJECT_TYPE_STACKFRAME_MEMBER,
                        stackframe_func_addr=eaFunc)
                    self.ida_model.accept_ea(memory_exporter, 0, eaFunc)
                else:
                    # it is a deleted structure
                    self.ida_model.accept_deleted_struc(memory_exporter, struc_id)
            else:

                self.ida_model.accept_struc(memory_exporter, 0, struc_id)

        logger.debug("Walking members")
        """
        Structure members : update modified ones, and remove deleted ones
        We iterate over members :
            -if the parent struc has been deleted, delete the member
            -otherwise, detect if the member has been updated or removed
                -updated : accept struc_member + accept_struc if not already exported!
                -removed : accept struc_member_deleted
        """
        for (struc_id, member_set) in self.strucmember_to_process.iteritems():
            ida_struc = idaapi.get_struc(struc_id)
            logger.debug("Walking struc 0x%08X" % struc_id)
            sidx = idc.GetStrucIdx(struc_id)
            is_stackframe = False
            struc_deleted = False
            if sidx is None or sidx == idc.BADADDR:
                f = idaapi.get_func_by_frame(struc_id)
                if f is not None and f != idc.BADADDR:
                    is_stackframe = True
                else:
                    struc_deleted = True

            if is_stackframe:
                strucmember_type = ya.OBJECT_TYPE_STACKFRAME_MEMBER
                struc_name = None
                struc_type = ya.OBJECT_TYPE_STACKFRAME
                eaFunc = idaapi.get_func_by_frame(struc_id)
                stackframe_func_addr = eaFunc
                func = idaapi.get_func(eaFunc)
                self.ida_model.accept_function(memory_exporter, 0, eaFunc, func)
            else:
                strucmember_type = ya.OBJECT_TYPE_STRUCT_MEMBER
                struc_type = ya.OBJECT_TYPE_STRUCT
                stackframe_func_addr = None
                if not struc_deleted:
                    struc_name = idc.GetStrucName(struc_id)

            if struc_deleted:
                # The structure has been deleted : we need to delete the members
                # Note: at first sight, it is not a stackframe
                # TODO: handle function->stackframe deletion here
                for (member_id, offset) in member_set:
                    self.ida_model.accept_deleted_strucmember(memory_exporter, struc_id, None, offset)
            else:
                # The structure or stackframe has been modified
                is_union = ida_struc.is_union()

                for (member_id, offset) in member_set:
                    ida_member = idaapi.get_member(ida_struc, offset)
                    if ida_member is None:
                        new_member_id = -1
                    else:
                        new_member_id = ida_member.id
                    logger.debug("exporting member %s at offset 0x%02X (mid=0x%016X)" %
                                 (strucmember_type, offset, member_id))
                    self.ida_model.clear_exported_struc_member_id(new_member_id)

                    if new_member_id == -1:
                        # the member has been deleted : delete it
                        self.ida_model.accept_deleted_strucmember(
                            memory_exporter, struc_id, struc_name, offset, struc_type, strucmember_type)
                    elif offset > 0 and idc.GetMemberId(struc_id, offset - 1) == new_member_id:
                        # the member was deleted, and replaced by a member starting above it
                        self.ida_model.accept_deleted_strucmember(
                            memory_exporter, struc_id, struc_name, offset, struc_type, strucmember_type)
                    elif new_member_id != member_id:
                        # the member has been deleted and later recreated
                        name = idaapi.get_member_name(new_member_id)
                        self.ida_model.accept_struc_member(
                            memory_exporter, 0, ida_struc, struc_id, is_union, offset, struc_name, name, struc_type,
                            strucmember_type, stackframe_func_addr=stackframe_func_addr)
                    else:
                        # the member has just been modified
                        name = idaapi.get_member_name(new_member_id)
                        logger.debug("exporting member %s (%s) at offset 0x%02X (mid=0x%016X)" %
                                     (strucmember_type, name, offset, member_id))
                        self.ida_model.accept_struc_member(
                            memory_exporter, 0, ida_struc, struc_id, is_union, offset, struc_name, name, struc_type,
                            strucmember_type, stackframe_func_addr=stackframe_func_addr)
Ejemplo n.º 20
0
def walk_struct_members():
    for (idx, sid, name) in idautils.Structs():
        s = idaapi.get_struc(sid)
        for (offset, name, size) in idautils.StructMembers(sid):
            m = idaapi.get_member(s, offset)
            yield m.id
Ejemplo n.º 21
0
        def visit_expr(self, *args):
            e = args[0]
            dr = idaapi.dr_R | idaapi.XREF_USER
            ea = self.find_addr(e)

            # We wish to know what context a struct usage occurs in
            # so we can determine what kind of xref to create. Unfortunately,
            # a post-order traversal makes this difficult.

            # For assignments, we visit the left, instead
            # Note that immediate lvalues will be visited twice,
            # and will be eronneously marked with a read dref.
            # However, it is safer to overapproximate than underapproximate
            if is_assn(e.op) or is_incdec(e.op):
                e = e.x
                dr = idaapi.dr_W | idaapi.XREF_USER

            # &x
            if e.op == idaapi.cot_ref:
                e = e.x
                dr = idaapi.dr_O | idaapi.XREF_USER

            # x.m, x->m
            if e.op == idaapi.cot_memref or e.op == idaapi.cot_memptr:
                moff = e.m

                # The only way I could figure out how
                # to get the structure/member associated with its use
                typ = e.x.type

                if e.op == idaapi.cot_memptr:
                    typ.remove_ptr_or_array()

                strname = typ.dstr()
                if strname.startswith("struct "):
                    strname = strname[len("struct "):]

                stid = idaapi.get_struc_id(strname)
                struc = idaapi.get_struc(stid)
                mem = idaapi.get_member(struc, moff)

                if struc is not None:
                    self.add_dref(ea, stid, dr)
                    if mem is not None:
                        self.add_dref(ea, stid, dr, mem.id)

                else:
                    log.error(
                        "failure from %08X "
                        "on struct %s (id: 0x%X) %s",
                        ea,
                        strname,
                        stid,
                        flags_to_str(dr),
                    )

            elif idaapi.is_lvalue(e.op) and e.type.is_struct():
                strname = e.type.dstr()
                if strname.startswith("struct "):
                    strname = strname[len("struct "):]

                stid = idaapi.get_struc_id(strname)
                struc = idaapi.get_struc(stid)

                if struc is not None:
                    self.add_dref(ea, stid, dr)

            return 0
Ejemplo n.º 22
0
 def flag(self):
     '''Return the member's `.flag` attribute.'''
     m = idaapi.get_member(self.__owner.ptr,
                           self.offset - self.__owner.members.baseoffset)
     return 0 if m is None else m.flag
Ejemplo n.º 23
0
    def clear_struc_fields(self,
                           struc_id,
                           struc_size,
                           xref_keys,
                           is_union=False,
                           member_type=ya.OBJECT_TYPE_STRUCT_MEMBER,
                           name_offset=0):

        idc.BeginTypeUpdating(idc.UTP_STRUCT)
        last_offset = idc.GetLastMember(struc_id)

        # get existing member offsets
        field_offsets = set()
        for (xref_offset, xref_operand) in xref_keys:
            field_offsets.add(xref_offset)

        new_offsets = set()
        struc = idaapi.get_struc(struc_id)
        # create missing members first (prevent from deleting all members)
        for offset in field_offsets:
            member = idaapi.get_member(struc, offset)
            if member is not None and member.soff < offset:
                # we have a member above this member that is too big and contain this member
                # clear it!
                if DEBUG_EXPORTER:
                    logger.debug(
                        "reduce field : set_member_type(0x%08X, 0x%08X), overlapping 0x%08X",
                        struc_id, member.soff, offset)
                idaapi.set_member_type(struc, member.soff, idc.FF_BYTE, None,
                                       1)
                member = idaapi.get_member(struc, offset)

            if member is None or idaapi.get_member_name(member.id) is None:
                new_offsets.add(offset)
                member_name = YaToolIDATools.get_default_struc_member_name(
                    member_type, offset, name_offset)
                if offset == last_offset and offset == struc_size:
                    field_size = 0
                else:
                    field_size = 1
                if DEBUG_EXPORTER:
                    logger.debug(
                        "AddStrucMember(0x%08X, '%s', 0x%08X, idc.FF_BYTE, -1, 0x%08X), name_offset=%d",
                        struc_id, member_name, offset, field_size, name_offset)
                retval = idc.AddStrucMember(struc_id, member_name, offset,
                                            idc.FF_BYTE, -1, field_size)
                if retval != 0:
                    logger.error(
                        "Error %d with idc.AddStrucMember(0x%08X, '%s', 0x%08X,"
                        "idc.FF_BYTE, -1, 0x%08X), name_offset=%d", retval,
                        struc_id, member_name, offset, field_size, name_offset)
            elif DEBUG_EXPORTER:
                logger.debug("Member exists : (0x%08X, '%s', 0x%08X, 0x%08X)",
                             struc_id, idc.GetMemberName(struc_id,
                                                         offset), offset,
                             idc.GetMemberSize(struc_id, offset))

        kept_offsets = field_offsets - new_offsets
        # clear kept members
        # split the loop since we will modify the structure while iterating
        offsets = set()
        for (offset, member_name) in YaToolIDATools.struc_member_list(
                struc_id, is_union):
            offsets.add(offset)

        for offset in offsets:
            if offset in kept_offsets:
                # This member already existed and is kept
                if offset == last_offset and offset == struc_size:
                    # this is the last field, and it is a variable sized structure
                    field_size = 0
                else:
                    field_size = 1
                if member_type == ya.OBJECT_TYPE_STRUCT_MEMBER:
                    strucmember_id = self.hash_provider.get_struc_member_id(
                        struc_id, offset)
                elif member_type == ya.OBJECT_TYPE_STACKFRAME_MEMBER:
                    strucmember_id = self.hash_provider.get_stackframe_member_object_id(
                        struc_id, offset)
                else:
                    logger.error("Bad member_type : %d" % member_type)

                if strucmember_id not in self.strucmember_ids:
                    # It is not necessary to clear the member if it is presnet in the resolved_objects
                    if DEBUG_EXPORTER:
                        logger.debug(
                            "SetStrucmember(0x%08X, None, 0x%08X, idc.FF_BYTE, -1, 0x%08X, name_offset=%s)",
                            struc_id, offset, field_size, name_offset)
                    YaToolIDATools.SetStrucmember(struc_id,
                                                  None,
                                                  offset,
                                                  idc.FF_BYTE,
                                                  -1,
                                                  field_size,
                                                  member_type=member_type,
                                                  name_offset=name_offset)

                    idc.SetMemberComment(struc_id, offset, "", 0)
                    idc.SetMemberComment(struc_id, offset, "", 1)
            elif offset not in new_offsets:
                if (member_type != ya.OBJECT_TYPE_STACKFRAME_MEMBER
                        or not idaapi.is_special_member(
                            idc.GetMemberId(struc_id, offset))):
                    if DEBUG_EXPORTER:
                        logger.debug(
                            "DelStrucMember(0x%08X, 0x%08X)  (=%s:%s)",
                            struc_id, offset, idc.GetStrucName(struc_id),
                            idc.GetMemberName(struc_id, offset))
                    idc.DelStrucMember(struc_id, offset)
            else:
                # in new_offsets : just created
                pass
        idc.EndTypeUpdating(idc.UTP_STRUCT)
Ejemplo n.º 24
0
    def save_strucs(self, ida_model, memory_exporter):
        """
        Structures : export modified structures and delete those who have been deleted
        """
        for struc_id in self.structures_to_process:
            sidx = idc.GetStrucIdx(struc_id)
            if sidx is None or sidx == idc.BADADDR:
                # it is a deleted structure or a stackframe
                # in this last case we need to export the parent (function)
                eaFunc = idaapi.get_func_by_frame(struc_id)
                if eaFunc != idc.BADADDR:
                    # OK, it is a stackframe
                    ida_model.accept_struct(memory_exporter, eaFunc, struc_id)
                    ida_model.accept_ea(memory_exporter, eaFunc)
                else:
                    # it is a deleted structure
                    ida_model.delete_struct(memory_exporter, struc_id)
            else:

                ida_model.accept_struct(memory_exporter, idc.BADADDR, struc_id)

        logger.debug("Walking members")
        """
        Structure members : update modified ones, and remove deleted ones
        We iterate over members :
            -if the parent struc has been deleted, delete the member
            -otherwise, detect if the member has been updated or removed
                -updated : accept struc_member + accept_struct if not already exported!
                -removed : accept struc_member_deleted
        """
        for (struc_id, member_set) in self.strucmember_to_process.iteritems():
            ida_struc = idaapi.get_struc(struc_id)
            logger.debug("Walking struc 0x%08X" % struc_id)
            sidx = idc.GetStrucIdx(struc_id)
            is_stackframe = False
            struc_deleted = False
            if sidx is None or sidx == idc.BADADDR:
                f = idaapi.get_func_by_frame(struc_id)
                if f is not None and f != idc.BADADDR:
                    is_stackframe = True
                else:
                    struc_deleted = True

            stackframe_func_addr = idc.BADADDR
            if is_stackframe:
                eaFunc = idaapi.get_func_by_frame(struc_id)
                stackframe_func_addr = eaFunc
                ida_model.accept_function(memory_exporter, eaFunc)

            if struc_deleted:
                # The structure has been deleted : we need to delete the members
                # Note: at first sight, it is not a stackframe
                # TODO: handle function->stackframe deletion here
                for (member_id, offset) in member_set:
                    ida_model.delete_struct_member(memory_exporter,
                                                   idc.BADADDR, struc_id,
                                                   offset)
            else:
                # The structure or stackframe has been modified
                for (member_id, offset) in member_set:
                    ida_member = idaapi.get_member(ida_struc, offset)
                    if ida_member is None:
                        new_member_id = -1
                    else:
                        new_member_id = ida_member.id
                    if new_member_id == -1:
                        # the member has been deleted : delete it
                        ida_model.delete_struct_member(memory_exporter,
                                                       stackframe_func_addr,
                                                       struc_id, offset)
                    elif offset > 0 and idc.GetMemberId(
                            struc_id, offset - 1) == new_member_id:
                        # the member was deleted, and replaced by a member starting above it
                        ida_model.delete_struct_member(memory_exporter,
                                                       stackframe_func_addr,
                                                       struc_id, offset)
                    else:
                        # the member has just been modified
                        ida_model.accept_struct_member(memory_exporter,
                                                       stackframe_func_addr,
                                                       ida_member.id)
Ejemplo n.º 25
0
 def flag(self):
     m = idaapi.get_member(self.__owner.ptr,
                           self.offset - self.__owner.members.baseoffset)
     return 0 if m is None else m.flag