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())
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