def test_subtype(self):
        start = self.offsets['start_list'][0]
        _record = structure.AnonymousRecord(self.memory_handler, start, 40)
        word_size = self._target.get_word_size()

        f1 = fieldtypes.Field('f1', 0 * word_size, fieldtypes.ZEROES,
                              word_size, False)
        f4 = fieldtypes.Field('f2', 3 * word_size, fieldtypes.ZEROES,
                              word_size, False)
        # offset in the substruct
        fs2 = fieldtypes.PointerField('Back', 0, word_size)
        fs2.value = start
        fs3 = fieldtypes.PointerField('Next', 1 * word_size, word_size)
        fs3.value = start
        # the new field sub record
        new_field = fieldtypes.RecordField(_record, 1 * word_size, 'list',
                                           'LIST_ENTRY', [fs2, fs3])
        # fieldtypes.FieldType.makeStructField(_record, 1*word_size, 'LIST_ENTRY', [fs2, fs3], 'list')
        # add them
        fields = [f1, new_field, f4]
        #_record.add_fields(fields)
        _record_type = structure.RecordType('struct_text', 40, fields)
        _record.set_record_type(_record_type)
        self.assertEqual(len(_record), 40)
        f1, f2, f3 = _record.get_fields()
        self.assertEqual(len(f1), word_size)
        self.assertEqual(len(f2), word_size * 2)
        self.assertEqual(len(f3), word_size)

        self.assertEqual(f2.name, 'list')
        self.assertIsInstance(f2.field_type, fieldtypes.FieldTypeStruct)
        self.assertEqual(f2.field_type.name, 'LIST_ENTRY')

        print _record.to_string()
Esempio n. 2
0
    def reverse_record(self, _context, _record):
        if not _record.resolvedPointers:
            raise ValueError('I should be resolved')
        _record._dirty = True
        _record._fields.sort()
        myfields = []

        signature = _record.get_type_signature()
        pencoder = pattern.PatternEncoder(signature, minGroupSize=2)
        patterns = pencoder.makePattern()

        txt = _record.get_type_signature(text=True)
        p = pattern.findPatternText(txt, 1, 2)

        log.debug('substruct typeSig: %s' % txt)
        log.debug('substruct findPatterntext: %s' % p)
        log.debug('substruct came up with pattern %s' % patterns)

        # pattern is made on FieldType,
        # so we need to dequeue _record.fields at the same time to enqueue in
        # myfields
        for nb, fieldTypes in patterns:
            if nb == 1:
                field = _record._fields.pop(0)
                myfields.append(field)  # single el
                # log.debug('simple field:%s '%(field) )
            elif len(fieldTypes) > 1:  # array of subtructure DEBUG XXX TODO
                log.debug('fieldTypes:%s' % fieldTypes)
                log.debug('substructure with sig %s',
                          ''.join([ft.sig[0] for ft in fieldTypes]))
                myelements = []
                for i in range(nb):
                    fields = [
                        _record._fields.pop(0) for i in range(len(fieldTypes))
                    ]  # nb-1 left
                    # otherFields = [ _record.fields.pop(0) for i in range((nb-1)*len(fieldTypesAndSizes)) ]
                    # need global ref to compare substructure signature to
                    # other anonstructure
                    firstField = fieldtypes.RecordField(
                        _record, fields[0].offset, 'unk', 'typename', fields)
                    myelements.append(firstField)
                array = fieldtypes.ArrayField(myelements)
                myfields.append(array)
                # log.debug('array of structure %s'%(array))
            # make array of elements obase on same base type
            elif len(fieldTypes) == 1:
                log.debug('found array of %s',
                          _record._fields[0].typename.basename)
                fields = [_record._fields.pop(0) for i in range(nb)]
                array = fieldtypes.ArrayField(fields)
                myfields.append(array)
                # log.debug('array of elements %s'%(array))
            else:  # TODO DEBUG internal struct
                raise ValueError('fields patterns len is incorrect %d' %
                                 (len(fieldTypes)))

        log.debug('done with findSubstructure')
        _record._fields = myfields
        # print 'final', _record.fields
        return
Esempio n. 3
0
    def get_fields(self):
        """
        Return the reversed fields for this record

        :return: list(Field)
        """
        # we have to check for RecordField
        # return [f for f in self.__record_type.get_fields()]
        from haystack.reverse import fieldtypes
        _fields = []
        for f in self.__record_type.get_fields():
            if f.is_record():
                _fields.append(fieldtypes.RecordField(self, f.offset, f.name, f.field_type.name, f.get_fields()))
            else:
                _fields.append(f)
        return _fields
Esempio n. 4
0
    def reverse_record(self, _context, _record):
        """
            Aggregate fields of similar type into arrays in the record.
        """
        if _record.get_reverse_level() < 30:
            raise ValueError('The record reverse level needs to be >30')

        log.debug('0x%x: %s', _record.address, _record.get_signature_text())

        _record._dirty = True

        _record._fields.sort()
        myfields = []

        signature = _record.get_signature()
        pencoder = pattern.PatternEncoder(signature, minGroupSize=3)
        patterns = pencoder.makePattern()

        #txt = self.getSignature(text=True)
        #log.warning('signature of len():%d, %s'%(len(txt),txt))
        #p = pattern.findPatternText(txt, 2, 3)
        # log.debug(p)

        #log.debug('aggregateFields came up with pattern %s'%(patterns))

        # pattern is made on FieldType,
        # so we need to dequeue self.fields at the same time to enqueue in
        # myfields
        for nb, fieldTypesAndSizes in patterns:
            # print 'fieldTypesAndSizes:',fieldTypesAndSizes
            if nb == 1:
                fieldType = fieldTypesAndSizes[0]  # its a tuple
                field = _record._fields.pop(0)
                myfields.append(field)  # single el
                #log.debug('simple field:%s '%(field) )
            # array of subtructure DEBUG XXX TODO
            elif len(fieldTypesAndSizes) > 1:
                log.debug('substructure with sig %s' % (fieldTypesAndSizes))
                myelements = []
                for i in range(nb):
                    fields = [
                        _record._fields.pop(0)
                        for i in range(len(fieldTypesAndSizes))
                    ]  # nb-1 left
                    #otherFields = [ self.fields.pop(0) for i in range((nb-1)*len(fieldTypesAndSizes)) ]
                    # need global ref to compare substructure signature to
                    # other anonstructure
                    firstField = fieldtypes.RecordField(
                        _record, fields[0].offset, 'unk', 'typename', fields)
                    myelements.append(firstField)
                array = fieldtypes.ArrayField(myelements)
                myfields.append(array)
                #log.debug('array of structure %s'%(array))
            elif len(fieldTypesAndSizes) == 1:  # make array of elements or
                log.debug("found array of %s",
                          _record._fields[0].typename.basename)
                fields = [_record._fields.pop(0) for i in range(nb)]
                array = fieldtypes.ArrayField(fields)
                myfields.append(array)
                #log.debug('array of elements %s'%(array))
            else:  # TODO DEBUG internal struct
                raise ValueError("fields patterns len is incorrect %d" %
                                 len(fieldTypesAndSizes))

        log.debug('done with aggregateFields')
        _record.reset()
        # _record.add_fields(myfields)
        _record_type = structure.RecordType('struct_%x' % _record.address,
                                            len(_record), myfields)
        _record.set_record_type(_record_type)
        _record.set_reverse_level(self._reverse_level)
        # print 'final', self.fields
        log.debug('0x%x: %s', _record.address, _record.get_signature_text())
        return
Esempio n. 5
0
    def rename_record_type(self, _members, offset):
        """
        Change the type of the 2 pointers to a substructure.
        Rename the field to reflect this .
        Rename the _record ?

        :param _context:
        :param _members:
        :param offset:
        :param head_addr:
        :return:
        """
        # we look at each item and get the most common signature between all items
        best_member = self.find_common_type_signature(_members)

        # use member[1] instead of head, so that we have a better chance for field types.
        # in head, back pointer is probably a zero value, not a pointer field type.
        _context = self._process_context.get_context_for_address(best_member)
        _record = _context.get_record_for_address(best_member)
        # we need two pointer fields to create a substructure.
        ## Check if field at offset is a pointer, If so change it name, otherwise split
        old_next = _record.get_field_at_offset(offset)
        old_back = _record.get_field_at_offset(offset + self._word_size)
        #
        next_field = fieldtypes.PointerField('Next', 0, self._word_size)
        back_field = fieldtypes.PointerField('Back', self._word_size,
                                             self._word_size)
        sub_fields = [next_field, back_field]
        # make a substructure
        new_field = fieldtypes.RecordField(_record, offset, 'list',
                                           'LIST_ENTRY', sub_fields)
        fields = [x for x in _record.get_fields()]
        fields.remove(old_next)
        if old_next == old_back:
            # its probably a LIST_ENTRY btw.
            log.debug("old_next == old_back, aborting")
            return _record.record_type
        fields.remove(old_back)
        fields.append(new_field)
        fields.sort()

        # create a new type
        head_addr = _members[0]
        _record_type = structure.RecordType('list_%x' % head_addr,
                                            len(_record), fields)
        log.debug("Created Record Type %s", _record_type.to_string())

        # apply the fields template to all members of the list
        for list_item_addr in _members:
            _context = self._process_context.get_context_for_address(
                list_item_addr)
            _item = _context.get_record_for_address(list_item_addr)
            ### KEEP THIS
            if len(_item) != len(_record):
                log.warning("x2 linked reverser: len(_item) != len(_record)")
            else:
                _item.set_record_type(_record_type, True)

        # push the LIST_ENTRY type into the context/memory_handler
        rev_context = self._memory_handler.get_reverse_context()
        rev_context.add_reversed_type(_record_type, _members)

        # change the list_head name back
        _context = self._process_context.get_context_for_address(head_addr)
        _context.get_record_for_address(head_addr).set_name('list_head')
        return _record_type