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()
 def test_is_types(self):
     # def __init__(self, astruct, offset, typename, size, isPadding):
     ptr = fieldtypes.PointerField('ptr_0', 8, 4)
     self.assertFalse(ptr.is_string())
     self.assertTrue(ptr.is_pointer())
     self.assertFalse(ptr.is_zeroes())
     self.assertFalse(ptr.is_array())
     self.assertFalse(ptr.is_integer())
 def test_is_types(self):
     from haystack.reverse import fieldtypes
     #def __init__(self, astruct, offset, typename, size, isPadding):
     ptr = fieldtypes.PointerField(self.st, 8, fieldtypes.FieldType.POINTER,
                                   4, False)
     self.assertFalse(ptr.isString())
     self.assertTrue(ptr.isPointer())
     self.assertFalse(ptr.isZeroes())
     self.assertFalse(ptr.isArray())
     self.assertFalse(ptr.isInteger())
Example #4
0
    def make_fields(self, _record, offset, size):
        # iterate on all offsets . NOT assert( size ==
        # self._target_platform.get_word_size())
        assert (offset % self._word_size == 0
                )  # vaddr and offset should be aligned
        log.debug('checking Pointer')
        _bytes = _record.bytes
        fields = []
        ctypes_utils = self._target.get_target_ctypes_utils()
        while size >= self._word_size:
            value = ctypes_utils.unpackWord(_bytes[offset:offset +
                                                   self._word_size])
            # check if pointer value is in range of _memory_handler and set self.comment to pathname value of pointer
            # TODO : if bytes 1 & 3 == \x00, maybe utf16 string
            if not self._memory_handler.is_valid_address(value):
                size -= self._word_size
                offset += self._word_size
                continue
            # FIXME 20151103 dont ignore it
            # what will it break ?
            if False:
                # 20151026 - if aligned, ignore it
                if value % self._target.get_word_size():
                    size -= self._word_size
                    offset += self._word_size
                    continue
            # we have a pointer
            log.debug('checkPointer offset:%s value:%s' % (offset, hex(value)))
            field = fieldtypes.PointerField('ptr_%d' % offset, offset,
                                            self._word_size)
            # TODO: leverage the context._function_names
            # if value in structure._context._function_names:
            #    field.comment = ' %s::%s' % (os.path.basename(self._memory_handler.get_mapping_for_address(value).pathname),
            #                                 structure._context._function_names[value])
            # else:
            #    field.comment = self._memory_handler.get_mapping_for_address(value).pathname
            field.comment = self._memory_handler.get_mapping_for_address(
                value).pathname

            fields.append(field)
            size -= self._word_size
            offset += self._word_size
        return fields
    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