示例#1
0
 def yatest_create_struct_in_stack_vars_with_renaming(self):
     """
     test creation of struct from stack vars
     used to find a bug (structure is correctly applied on var if renamed)
     """
     # create structure
     ident, sida = self.get_function_sid_without_del(
         True, local_size=complex_struc3_size, count_from_first_var=True)
     self.assertNotEqual(sida, -1)
     sidb = idc.AddStrucEx(0, 'create_struct_in_stack_vars_with_renaming',
                           0)
     self.assertNotEqual(sidb, -1)
     size = self.create_complex2(sidb, complex_struc3)
     self.assertEqual(complex_struc3_size, size)
     # set first var prototype
     offset = idc.GetFirstMember(sida)
     member_id = idc.GetMemberId(sida, offset)
     self.assertNotEqual(member_id, -1)
     self.assertTrue(
         idc.SetType(member_id,
                     "create_struct_in_stack_vars_with_renaming* x;"))
     self.assertEqual("create_struct_in_stack_vars_with_renaming *",
                      idc.GetType(idc.GetMemberId(sida, offset)))
     idc.SetMemberName(sida, offset, "var1")
     yaunit.save("create_struct_in_stack_vars_with_renaming", sida)
     yaunit.save("create_struct_in_stack_vars_with_renaming_offset", offset)
示例#2
0
 def fields(self, reload=False):
     if reload or not self._fields:
         self._fields = {}
         m = 0
         while True:
             if m >= idc.GetStrucSize(self.id):
                 break
             n = idc.GetMemberName(self.id, m)
             if n == idc.BADADDR:
                 break
             sz = idc.GetMemberSize(self.id, m)
             mid = idc.GetMemberId(self.id, m)
             tp = idc.GetType(mid)
             fld = {
                 'offset': m,
                 'id': mid,
                 'name': n,
                 'size': sz,
                 'type': [tp, None]
             }
             if n != '':
                 fld['type'][1] = idc.GetMemberFlag(self.id, m)
             self._fields[m] = fld
             m = idc.GetStrucNextOff(self.id, m)
             if m == idc.BADADDR:
                 break
     return self._fields
示例#3
0
    def yacheck_apply_struct(self):
        addrs = yaunit.load('apply_struct')
        for k in range(-1, 4):
            # retrieve struct id
            addr = addrs[k + 1]
            sid = idc.GetStrucIdByName('apply_struct_%x' % (k + 1))
            self.assertNotEqual(sid, idaapi.BADADDR)

            # begin to check if something is applied
            flags = idaapi.get_flags_novalue(addr)
            self.assertTrue(idaapi.isStroff(flags, 1))
            ti = idaapi.opinfo_t()
            flags = idc.GetFlags(addr)
            self.assertTrue(idaapi.get_opinfo(addr, 1, flags, ti))

            # apply struct only
            if k == -1:
                # check struct is applied
                self.assertEqual(ti.path.ids[0], sid)
                continue

            # check union is selected & applied at target address
            uid = idc.GetStrucIdByName('apply_union_%x' % (k + 1))
            self.assertNotEqual(uid, idaapi.BADADDR)
            fid = idc.GetMemberId(uid, k)
            self.assertNotEqual(fid, -1)

            # check union is applied
            self.assertEqual([x for x in ti.path.ids if x], [sid, fid])
示例#4
0
def get_struc_offset(ea, opn):
    path = idaapi.tid_array(1)
    delta = idaapi.sval_pointer()
    idaapi.get_stroff_path(ea, opn, path.cast(), delta.cast())
    struct = path[0]
    if idaapi.decode_insn(ea) == 0:
        print 'error in {0}'.format(GetDisasm(ea))
    else:
        op = idaapi.cmd.Operands[opn]
        offset = op.value
        result = []
        idaapi.get_stroff_path(ea, opn, path.cast(), delta.cast())
        struct = path[0]
        while offset:
            member_id = idc.GetMemberId(struct, offset)
            member_name = idc.GetMemberName(member_id)
            field_struct_id = idc.GetMemberStrId(struct, offset)
            if field_struct_id != idc.BADADDR:
                result.append(
                    [field_struct_id,
                     idc.GetStrucName(field_struct_id)])
            else:
                result.append([member_name, idc.GetMemberFlag(struct, offset)])
                return result
            offset -= idc.GetMemberOffset(member_name)
示例#5
0
def get_object_id_of_union_member_id(hash_provider, member_id):
    try:
        return union_member_object_ids[member_id]
    except KeyError:

        idx = idc.GetFirstStrucIdx()
        while idx != idc.BADADDR:
            struc_id = idc.GetStrucId(idx)
            if idc.IsUnion(struc_id):

                offset = idc.GetFirstMember(struc_id)

                while offset != idc.BADADDR:
                    smember_id = idc.GetMemberId(struc_id, offset)
                    if smember_id == member_id:
                        name = idc.GetMemberName(struc_id, offset)
                        if name is not None:
                            struc_name = idc.GetStrucName(struc_id)
                            logger.debug("found member id 0x%016X in union %s/%s" % (member_id, struc_name, name))
                            return hash_provider.get_struc_member_id_for_name(struc_name, offset)

                    # next member
                    offset = idc.GetStrucNextOff(struc_id, offset)
            idx = idc.GetNextStrucIdx(idx)

        logger.error("Could not find member id 0x%016X in unions" % member_id)

        return None
示例#6
0
 def fillStruct(self, sid, data):
     for i in data:
         new_type = None
         #(i1, i2, i3) = self.stepper.parseField(i[1])
         name = i[1]
         if name[0] == "*":
             name = name[1:]
         if i[1] != "uintptr":
             i1, i2, i3 = (idc.FF_BYTE | idc.FF_DATA, -1, 1)
         else:
             i1, i2, i3 = self.uintptr
         if name == i[1]:
             new_type = i[1]
         else:
             new_type = name + " *"
         res = idc.AddStrucMember(sid, i[0], -1, i1, i2, i3)
         use_name = i[0]
         if res == -1:  #Bad name
             #print "Bad name %s for struct member" % i[0]
             use_name = i[0] + "_autogen_" + id_generator()
             idc.AddStrucMember(sid, use_name, -1, i1, i2, i3)
         if new_type is not None:
             offset = idc.GetMemberOffset(sid, use_name)
             #print "Setting %s as %s" % (i[0], new_type)
             idc.SetType(idc.GetMemberId(sid, offset), new_type)
示例#7
0
 def yacheck_set_field_prototype(self):
     for field_type, name, prototype in set_field_prototype:
         sid = idc.GetStrucIdByName(name)
         self.assertNotEqual(sid, idaapi.BADADDR)
         for k in range(0, get_size(field_type, -1) - 1):
             self.assertEqual(field_type, idc.GetMemberFlag(sid, k) & idaapi.DT_TYPE)
             mid = idc.GetMemberId(sid, k)
             self.assertEqual(prototype, idc.GetType(mid))
示例#8
0
 def yacheck_reference_loop(self):
     for k in range(0, 2):
         sid = idc.GetStrucIdByName('refloop' + str(k))
         self.assertNotEqual(sid, idaapi.BADADDR)
         self.assertEqual(idc.GetMemberName(sid, 0), 'refloop_field' + str(k))
         mid = idc.GetMemberId(sid, 0)
         self.assertNotEqual(mid, -1)
         self.assertEqual(idc.GetType(mid), 'refloop' + str(1 - k) + ' *')
示例#9
0
    def yacheck_create_struct_in_stack_vars_with_renaming(self):
        sida = yaunit.load("create_struct_in_stack_vars_with_renaming")
        offset = yaunit.load("create_struct_in_stack_vars_with_renaming_offset")
        self.assertEqual("var1", idc.GetMemberName(sida, offset))

        stype = fix_ptr_type(idc.GetType(idc.GetMemberId(sida, offset)))
        self.assertEqual("create_struct_in_stack_vars_with_renaming*",
                         stype)
示例#10
0
 def yatest_set_field_prototype(self):
     for field_type, name, prototype in set_field_prototype:
         sid = idc.AddStrucEx(-1, name, 0)
         self.assertNotEqual(sid, -1)
         self.assertEqual(idc.AddStrucMember(sid, 'field', 0, field_type | idaapi.FF_DATA, -1, get_size(field_type, -1)), 0)
         mid = idc.GetMemberId(sid, 0)
         self.assertNotEqual(mid, -1)
         self.assertTrue(idc.SetType(mid, prototype))
示例#11
0
    def build_struct(self):
        ''' Creates an IDA structure for this Type.
        '''
        if self.struct is not None:
            return

        for p in self.parents:
            p.build_struct()

        self.struct = idc.AddStrucEx(-1, self.name, 0)

        if as_signed(self.struct, TARGET_ADDRESS_SIZE) == -1:
            raise RuntimeError("Unable to make struct `{}`".format(self.name))
        else:
            #TODO: either come up with another way of showing this, or
            #      sync it with the actual function names
            cmt = "constructors: "
            for c in self.constructors():
                cmt += "{}(0x{:02x}), ".format(idc.Name(c), c)
            cmt = cmt.strip(", ")
            idaapi.set_struc_cmt(self.struct, cmt, False)

        if TARGET_ADDRESS_SIZE == 8:
            mask = idc.FF_QWRD
        else:
            mask = idc.FF_DWRD

        # Only bases get the magic _vptr member
        if len(self.parents) == 0:
            idc.AddStrucMember(self.struct, "_vptr", 0, idc.FF_DATA | mask, -1,
                               TARGET_ADDRESS_SIZE)
            idc.SetType(idc.GetMemberId(self.struct, 0), "_vfunc**")

        for i, parent in enumerate(self.parents):
            try:
                #TODO: for non-itanium ABI, this may not be available
                #      when RTTI is disabled
                offset = self.tablegroup.tables[i].offset_to_top
            except:
                break

            idc.AddStrucMember(self.struct, "parent_{}".format(i),
                               -offset, idc.FF_DATA, -1,
                               idc.GetStrucSize(parent.struct))

            idc.SetType(idc.GetMemberId(self.struct, -offset), parent.name)
示例#12
0
 def yacheck_create_struct_in_stack_vars(self):
     sida = yaunit.load("create_struct_in_stack_vars")
     offset = yaunit.load("create_struct_in_stack_vars_offset")
     stype = idc.GetType(idc.GetMemberId(sida, offset))
     self.assertNotEqual(None, stype)
     stype = fix_ptr_type(stype)
     
     self.assertEqual("create_struct_in_stack_vars*", stype)
示例#13
0
 def yatest_reference_loop(self):
     mids = []
     for k in range(0, 2):
         sid = idc.AddStrucEx(-1, 'refloop' + str(k), 0)
         self.assertNotEqual(sid, -1)
         self.assertEqual(idc.AddStrucMember(sid, 'refloop_field' + str(k), 0, idaapi.FF_DWRD, -1, 4), 0)
         mid = idc.GetMemberId(sid, 0)
         self.assertNotEqual(mid, -1)
         mids.append(mid)
     for k in range(0, 2):
         self.assertTrue(idc.SetType(mids[k], 'refloop' + str(1 - k) + ' *'))
示例#14
0
def get_struct_mids(sid):
    m_ids = []
    m_offset = 0
    while not (m_offset == -1 or m_offset == idaapi.BADADDR):
        m_id = idc.GetMemberId(sid, m_offset)
        if not m_id == -1:
            m_ids.append(m_id)

        m_offset = idc.GetStrucNextOff(sid, m_offset)

    return m_ids
示例#15
0
 def yatest_create_struct_in_stack_vars(self):
     """
     test creation of struct from stack vars
     used to find a bug when creating struct for stack vars and naming vars
     """
     # create structure
     ident, sida = self.get_function_sid_without_del(True, local_size=complex_struc3_size, count_from_first_var=True)
     self.assertNotEqual(sida, -1)
     sidb = idc.AddStrucEx(0, 'create_struct_in_stack_vars', 0)
     self.assertNotEqual(sidb, -1)
     size = self.create_complex2(sidb, complex_struc3)
     self.assertEqual(complex_struc3_size, size)
     # set first var prototype
     offset = idc.GetFirstMember(sida)
     member_id = idc.GetMemberId(sida, offset)
     self.assertNotEqual(member_id, -1)
     self.assertTrue(idc.SetType(member_id, "create_struct_in_stack_vars* x;"))
     self.assertEqual("create_struct_in_stack_vars *",
                      idc.GetType(idc.GetMemberId(sida, offset)))
     yaunit.save("create_struct_in_stack_vars", sida)
     yaunit.save("create_struct_in_stack_vars_offset", offset)
示例#16
0
    def yatest_apply_struct(self):
        addrs = []
        # -1: struct, n: union
        for k in range(-1, 4):
            # find an integer operand in any function
            addr = self.find_operand_addr()
            addrs.append(addr)

            # create struct
            sid = idc.AddStrucEx(-1, 'apply_struct_%x' % (k + 1), 0)
            self.assertNotEqual(sid, -1)
            ftype = idaapi.FF_BYTE | idaapi.FF_DATA

            # apply struct only
            if k == -1:
                # add struct fields
                for x in xrange(0, 0x60):
                    self.assertEqual(
                        idc.AddStrucMember(sid, 'field_%x' % x, -1, ftype, -1,
                                           1), 0)
                path = idaapi.tid_array(1)
                path[0] = sid
                self.assertNotEqual(
                    self.custom_op_stroff(addr, path.cast(), 1),
                    idaapi.BADADDR)
                continue

            # create union
            uid = idc.AddStrucEx(-1, 'apply_union_%x' % (k + 1), 1)
            self.assertNotEqual(uid, -1)
            for x in xrange(1, 0x10):
                self.assertEqual(
                    idc.AddStrucMember(uid, 'union_%x' % x, -1, ftype, -1, 1),
                    0)

            # add struct fields
            for x in xrange(0, 0x60):
                self.assertEqual(
                    idc.AddStrucMember(sid, 'field_%x' % x, -1,
                                       idaapi.struflag(), uid, 1), 0)

            # apply selected union field
            fid = idc.GetMemberId(uid, k)
            self.assertNotEqual(fid, -1)
            path = idaapi.tid_array(2)
            path[0] = sid
            path[1] = fid
            self.assertNotEqual(self.custom_op_stroff(addr, path.cast(), 2),
                                idaapi.BADADDR)
        yaunit.save('apply_struct', addrs)
示例#17
0
 def setStrucPntr(self, sid, ofs, name, tp=None):
     vnm = idc.GetMemberName(sid, ofs)
     if not vnm or vnm in (idc.BADADDR, -1):
         idc.AddStrucMember(sid, name, ofs, idc.FF_QWRD, -1, 8)
         vnm = name
     if vnm != name:
         idc.SetMemberName(sid, ofs, name)
     sz = idc.GetMemberSize(sid, ofs)
     if sz != 8:
         idc.SetMemberType(sid, ofs, idc.FF_QWRD, -1, 1)
     mid = idc.GetMemberId(sid, ofs)
     t = idc.GetType(mid) or ''
     if tp and t.replace(' ', '') != tp.replace(' ', ''):
         idc.SetType(mid, tp + ';')
示例#18
0
def struct_add_ptr(sid, name, offset, count=1, type=None):
    """Add a pointer to a structure.

    If sid is a union, offset must be -1.
    """
    ptr_flag = idc.FF_DATA | word_flag(WORD_SIZE) | idaapi.offflag()
    ret = idc.AddStrucMember(sid, name, offset, ptr_flag, 0, WORD_SIZE)
    if ret == 0 and type is not None:
        if offset == -1:
            offset = struct_member_offset(sid, name)
            assert offset is not None
        mid = idc.GetMemberId(sid, offset)
        idc.SetType(mid, type)
    return ret
示例#19
0
 def getTypeVtbl(self, descr):
     if not descr.get('id'):
         return descr
     mid = idc.GetMemberId(descr['id'], 0)
     if not mid or mid == idc.BADADDR:
         return descr
     t = idc.GetType(mid) or ''
     t = t.replace('*', '').replace(' ', '')
     if 'VTABLE' not in t:
         return descr
     svid = idc.GetStrucIdByName(t)
     if not svid or svid == idc.BADADDR:
         return descr
     idc.SetStrucName(svid, descr['name'] + 'Vtbl')
     descr['vtblid'] = svid
     descr['vtblnm'] = descr['name'] + 'Vtbl'
     return descr
示例#20
0
def _propagate_virtual_method_type_for_method(classinfo, class_vindex, vmethod):
    """Propagate the type of a class's virtual method to the vtable struct."""
    if not idau.is_function_start(vmethod):
        _log(2, 'Not a function start: {:x}', vmethod)
        return False
    vmethod_type = idc.GuessType(vmethod)
    if not vmethod_type:
        _log(2, 'No guessed type: {:x}', vmethod)
        return False
    vmethod_ptr_type = symbol.convert_function_type_to_function_pointer_type(vmethod_type)
    if not vmethod_ptr_type:
        _log(2, 'Could not convert to function pointer type: {:x}', vmethod)
        return False
    vmethods_sid = idau.struct_open(classinfo.classname + '::vmethods')
    vmethod_offset = class_vindex * idau.WORD_SIZE
    vmethod_mid = idc.GetMemberId(vmethods_sid, vmethod_offset)
    if not bool(idc.SetType(vmethod_mid, vmethod_ptr_type)):
        _log(2, 'Could not set vmethod field type: {:x}, {}, {}', vmethod, classinfo.classname,
                class_vindex)
        return False
    return True
示例#21
0
def get_struc_id_from_member_if(member_id):
    try:
        return member_struc_ids[member_id]
    except KeyError:

        idx = idc.GetFirstStrucIdx()
        while idx != idc.BADADDR:
            struc_id = idc.GetStrucId(idx)
            if idc.IsUnion(struc_id):
                offset = idc.GetFirstMember(struc_id)

                while offset != idc.BADADDR:
                    smember_id = idc.GetMemberId(struc_id, offset)
                    if smember_id == member_id:
                        member_struc_ids[member_id] = struc_id
                        return struc_id
                    offset = idc.GetStrucNextOff(struc_id, offset)
            idx = idc.GetNextStrucIdx(idx)
        logger.error("Could not find struc id from member id 0x%08X (name=%s)" %
                     (member_id, idaapi.get_struc_name(member_id)))
        return None
示例#22
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)
示例#23
0
    def make_struc_member(self,
                          object_version,
                          address,
                          member_type=ya.OBJECT_TYPE_STRUCT_MEMBER):
        struc_object_id = object_version.get_parent_object_id()

        struc_id = 0
        try:
            struc_id = self.struc_ids[struc_object_id]
        except:
            return
        is_union = struc_id in self.union_ids

        offset = address

        if is_union:
            last_offset = idc.GetLastMember(struc_id)
            if last_offset == idc.BADADDR:
                last_offset = -1
            if last_offset < offset:
                for i in xrange(last_offset + 1, offset + 1):
                    idc.AddStrucMember(struc_id, "yaco_filler_%d" % i, 0,
                                       idc.FF_BYTE | idc.FF_DATA, -1, 1)
                    # ensure that 'offset' fields are present

        member_size = object_version.get_size()
        member_name = object_version.get_name()

        flags = object_version.get_object_flags()
        if idc.isStruct(flags):
            # if the sub field is a struct, it must have a single Xref field with the struct object id
            try:
                sub_struc_object_id = object_version.getXRefIdsAt(0, 0)[0]
                sub_struc_id = self.struc_ids[sub_struc_object_id]

                #                 logger.debug("%20s: adding sub member at offset 0x%08X,
                #                               size=0x%08X (sub=0x%.016X, size=0x%08X) with name %s" %
                #                             (
                #                                 idc.GetStrucName(struc_id), offset, member_size, sub_struc_id,
                #                                               idc.GetStrucSize(sub_struc_id), object_version.get_name()
                #                             ))

                sub_struc_size = idc.GetStrucSize(sub_struc_id)
                if sub_struc_size == 0:
                    logger.error(
                        "%20s: adding sub member at offset 0x%08X, size=0x%08X "
                        "(sub=0x%.016X, size=0x%08X) with name %s : sub struc size is ZERO"
                        % (idc.GetStrucName(struc_id), offset, member_size,
                           sub_struc_id, idc.GetStrucSize(sub_struc_id),
                           object_version.get_name()))

                else:
                    nitems = member_size / sub_struc_size

                    YaToolIDATools.SetStrucmember(struc_id, member_name,
                                                  offset, flags, sub_struc_id,
                                                  nitems)

            except KeyError:
                logger.error(
                    "Error while looking for sub struc in struc %s, offset 0x%08X (field name='%s')"
                    % (self.hash_provider.hash_to_string(struc_object_id),
                       offset, object_version.get_name()))
                traceback.print_exc()
        elif idc.isEnum0(flags):
            # an enum is applied here
            try:
                sub_enum_object_id = object_version.getXRefIdsAt(0, 0)[0]
                sub_enum_id = self.enum_ids[sub_enum_object_id]

                name_ok = idc.SetMemberName(struc_id, offset, member_name)
                if name_ok is not True:
                    logger.debug(
                        "Error while setting member name (enum) : "
                        "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X"
                        % (name_ok, idc.GetStrucName(struc_id), member_name,
                           offset, flags, member_size, sub_struc_id))
                else:
                    sub_enum_size = idc.GetEnumWidth(sub_enum_id)
                    if sub_enum_size == 0:
                        sub_enum_size = member_size

                    nitems = member_size / sub_enum_size
                    ret = idc.SetMemberType(struc_id, offset, flags,
                                            sub_enum_id, nitems)
                    if ret == 0:
                        logger.debug(
                            "Error while setting member type (enum) : "
                            "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X"
                            % (ret, idc.GetStrucName(struc_id), member_name,
                               offset, flags, member_size, sub_struc_id))

            except KeyError:
                logger.error(
                    "Error while looking for sub enum in struc %s, offset 0x%08X (field name='%s')"
                    % (struc_object_id, offset, member_name))
                traceback.print_exc()

        else:
            #             logger.debug("%20s: adding member at offset 0x%08X, size=0x%08X with name %s" %
            #                         (
            #                         idc.GetStrucName(struc_id), offset, member_size, object_version.get_name()
            #                         ))
            tid = -1
            if idc.isASCII(flags):
                logger.debug(
                    "object: %s : %s" % (self.hash_provider.hash_to_string(
                        object_version.get_id()), object_version.get_name()))
                try:
                    tid = object_version.get_string_type()
                except KeyError:
                    tid = idc.ASCSTR_C

            name_ok = idc.SetMemberName(struc_id, offset, member_name)
            if name_ok is not True:
                logger.debug(
                    "Error while setting member name :" +
                    " (struc_id=0x%08X, struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)"
                    % (struc_id, idc.GetStrucName(struc_id), member_name,
                       offset, flags, member_size))
            else:
                item_size = YaToolIDATools.get_field_size(flags, tid)
                nitems = member_size / item_size
                # IDA BUG : 4-byte chars are stored as 2 double words, thus me must
                # multiply nitem by 2!
                ret = idc.SetMemberType(struc_id, offset, flags, tid, nitems)
                if ret == 0:
                    logger.debug(
                        "Error while setting member type :" +
                        " (struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)"
                        % (idc.GetStrucName(struc_id), member_name, offset,
                           flags, member_size))

        try:
            repeatable_headercomment = self.sanitize_comment_to_ascii(
                object_version.get_header_comment(True))
            idc.SetMemberComment(struc_id, offset, repeatable_headercomment, 1)
        except KeyError:
            pass

        try:
            nonrepeatable_headercomment = self.sanitize_comment_to_ascii(
                object_version.get_header_comment(False))
            idc.SetMemberComment(struc_id, offset, nonrepeatable_headercomment,
                                 0)
        except KeyError:
            pass

        member_id = idc.GetMemberId(struc_id, offset)

        self.set_struct_member_type(object_version, member_id)
        if object_version.get_type() == ya.OBJECT_TYPE_STRUCT_MEMBER:
            self.strucmember_ids[object_version.get_id()] = member_id
示例#24
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)
示例#25
0
文件: hooks.py 项目: silverf0x/YaCo
    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)