def test_get_chunks_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) self.assertTrue(finder._is_heap(h, addr)) validator = finder.get_heap_validator() allocated, free = validator.HEAP_get_chunks(heap) s_allocated = sum([c[1] for c in allocated]) s_free = sum([c[1] for c in free]) total = sorted(allocated + free) s_total = sum([c[1] for c in total]) # HEAP counters committed_size = heap.Counters.TotalMemoryCommitted reserved_size = heap.Counters.TotalMemoryReserved ucr_size = reserved_size - committed_size # in some segments, they are non-contiguous segments chunks_size = sum([chunk[1] for chunk in total]) # chunks are in all segments alloc_size = 0 for segment in validator.HEAP_get_segment_list(heap): valid_alloc_size = (segment.LastValidEntry.value - segment.FirstEntry.value) alloc_size += valid_alloc_size # 1 chunk is 8 bytes. self.assertEquals(s_free / 8, heap.TotalFreeSize) # sum of allocated size for every segment should amount to the # sum of all allocated chunk self.assertEquals(alloc_size, chunks_size + ucr_size)
def test_search(self): """ Testing the loading of _HEAP in each memory mapping. Compare load_members results with known offsets. expect failures otherwise. """ finder = win7heapwalker.Win7HeapFinder(self._memory_handler) found = [] for heap_walker in finder.list_heap_walkers(): validator = heap_walker.get_heap_validator() addr = heap_walker.get_heap_address() heap = heap_walker.get_heap() if addr in map(lambda x: x[0], putty_1_win7.known_heaps): self.assertTrue( validator.load_members( heap, 50), "We expected a valid hit at @ 0x%0.8x" % (addr)) found.append(addr, ) else: try: ret = validator.load_members(heap, 1) self.assertFalse( ret, "We didnt expected a valid hit at @%x" % addr) except Exception as e: # should not raise an error self.fail( 'Haystack should not raise an Exception. %s' % e) found.sort() self.assertEqual(list(map(lambda x: x[0], putty_1_win7.known_heaps)), found) return
def test_get_UCR_segment_list_all(self): # FIXME: look at previous version to debug what was going on with UCR # get an UCR refresher too. is it linked to holes in memory mappings? finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) self.assertTrue(finder._is_heap(h, addr)) validator = finder.get_heap_validator() # get free UCRS from heap reserved_ucrs = validator.HEAP_get_free_UCR_segment_list(heap) all_ucrs = [] # UCR size should add on all UCR for all segments for segment in validator.HEAP_get_segment_list(heap): all_ucrs.extend(validator.get_UCR_segment_list(segment)) total_ucr_size = sum([ucr.Size for ucr in all_ucrs]) # sum of all existing UCR. not just free UCR # FIXME, HEAP_SEGMENT_get_UCR_segment_list is not working self.assertEquals(len(all_ucrs), heap.Counters.TotalUCRs) # check numbers. reserved_size = heap.Counters.TotalMemoryReserved committed_size = heap.Counters.TotalMemoryCommitted ucr_size = reserved_size - committed_size self.assertEquals(total_ucr_size, ucr_size)
def test_get_segment_list_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) walker = finder.get_heap_walker(h) validator = walker.get_heap_validator() heap = walker.get_heap() segments = validator.get_segment_list(heap) self.assertEquals(len(segments), heap.Counters.TotalSegments) pages = 0 total_size = 0 for segment in segments: self.assertEquals(segment.SegmentSignature, 0xffeeffee) self.assertEquals( validator._utils.get_pointee_address(segment.Heap), addr) base_addr = validator._utils.get_pointee_address( segment.BaseAddress) first_entry_addr = validator._utils.get_pointee_address( segment.FirstEntry) last_entry_addr = validator._utils.get_pointee_address( segment.LastValidEntry) self.assertLess(base_addr, first_entry_addr) self.assertLess(first_entry_addr, last_entry_addr) valid_alloc_size = (last_entry_addr - first_entry_addr) meta_size = first_entry_addr - base_addr pages += segment.NumberOfPages total_size += valid_alloc_size + meta_size # Heap resutls for all segments committed_size = heap.Counters.TotalMemoryCommitted reserved_size = heap.Counters.TotalMemoryReserved self.assertEquals(pages * 4096, reserved_size) self.assertEquals(total_size, reserved_size)
def test_get_UCR_segment_list(self): # You have to import after ctypes has been tuned ( mapping loader ) finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) walker = finder.get_heap_walker(mapping) addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) validator = walker.get_heap_validator() heap = walker.get_heap() ucrs = validator.HEAP_get_UCRanges_list(heap) self.assertEquals(heap.UCRIndex.value, 0x5c0590) self.assertEquals(heap.Counters.TotalUCRs, 1) # in this example, there is one UCR in 1 segment. self.assertEquals(len(ucrs), heap.Counters.TotalUCRs) ucr = ucrs[0] # UCR will point to non-mapped space. But reserved address space. self.assertEquals(ucr.Address.value, 0x6b1000) self.assertEquals(ucr.Size, 0xf000) # bytes self.assertEquals(ucr.Address.value + ucr.Size, 0x6c0000) # check numbers. reserved_size = heap.Counters.TotalMemoryReserved committed_size = heap.Counters.TotalMemoryCommitted ucr_size = reserved_size - committed_size self.assertEquals(ucr.Size, ucr_size)
def test_get_segment_list(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) self.assertEqual(h, mapping) walker = finder.get_heap_walker(h) validator = walker.get_heap_validator() heap = walker.get_heap() segments = validator.get_segment_list(heap) self.assertEquals(heap.Counters.TotalSegments, 1) self.assertEquals(len(segments), heap.Counters.TotalSegments) segment = segments[0] self.assertEquals(segment.SegmentSignature, 0xffeeffee) self.assertEquals(segment.FirstEntry.value, 0x5c0588) self.assertEquals(segment.LastValidEntry.value, 0x06c0000) # only segment is self heap here self.assertEquals(segment.Heap.value, addr) self.assertEquals(segment.BaseAddress.value, addr) # checkings size. a page is 4096 in this example. valid_alloc_size = (heap.LastValidEntry.value - heap.FirstEntry.value) meta_size = (heap.FirstEntry.value - heap.BaseAddress.value) committed_size = heap.Counters.TotalMemoryCommitted reserved_size = heap.Counters.TotalMemoryReserved ucr_size = reserved_size - committed_size self.assertEquals(segment.NumberOfPages * 4096, reserved_size) self.assertEquals(segment.NumberOfPages * 4096, 0x100000) # example self.assertEquals(reserved_size, meta_size + valid_alloc_size)
def test_get_chunks_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) walker = finder.get_heap_walker(mapping) win7heap = walker._heap_module for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) validator = walker.get_heap_validator() heap = walker.get_heap() # BUG is here !!! allocated, free = validator.get_backend_chunks(heap) s_allocated = sum([c[1] for c in allocated]) s_free = sum([c[1] for c in free]) total = sorted(allocated | free) s_total = sum([c[1] for c in total]) # HEAP counters committed_size = heap.Counters.TotalMemoryCommitted reserved_size = heap.Counters.TotalMemoryReserved ucr_size = reserved_size - committed_size # in some segments, they are non-contiguous segments chunks_size = sum([chunk[1] for chunk in total]) # chunks are in all segments alloc_size = 0 for segment in validator.get_segment_list(heap): valid_alloc_size = (segment.LastValidEntry.value - segment.FirstEntry.value) alloc_size += valid_alloc_size # 1 chunk is 8 bytes. self.assertEquals(s_free / 8, heap.TotalFreeSize) # sum of allocated size for every segment should amount to the # sum of all allocated chunk self.assertEquals(alloc_size, chunks_size + ucr_size)
def test_HEAP_get_UCRanges_list(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) # get an example for heap_addr, ucr_list in putty_1_win7.known_ucr.items(): # get the heap h = self.memory_handler.get_mapping_for_address(heap_addr) walker = finder.get_heap_walker(h) validator = walker.get_heap_validator() heap = walker.get_heap() # get UCRList from heap # TODO TotalUCRs == Total UCRS from UCRSegments. Not from Heap UCRList reserved_ucrs = validator.HEAP_get_UCRanges_list(heap) if len(reserved_ucrs) != heap.Counters.TotalUCRs: _tmp_ucrs = validator.collect_all_ucrs(heap) self.assertEquals(len(_tmp_ucrs), heap.Counters.TotalUCRs ) # , "Bad count for heap 0x%x" % heap_addr) self.assertEquals(len(ucr_list), heap.Counters.TotalUCRs) # check numbers. reserved_size = heap.Counters.TotalMemoryReserved committed_size = heap.Counters.TotalMemoryCommitted ucr_size = reserved_size - committed_size self.assertEquals(ucr_size, ucr_size) # TODO: what is a LargeUCR ucr_total_size = sum( [ucr.Size for ucr in reserved_ucrs if ucr.Size >= 512 * 1024]) self.assertEquals(ucr_total_size, heap.Counters.TotalMemoryLargeUCR)
def test_get_UCR_segment_list(self): # You have to import after ctypes has been tuned ( mapping loader ) finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) # a load_member by validator occurs in heapwalker._is_heap self.assertTrue(finder._is_heap(h, addr)) validator = finder.get_heap_validator() ucrs = validator.HEAP_get_free_UCR_segment_list(heap) self.assertEquals(heap.UCRIndex.value, 0x5c0590) self.assertEquals(heap.Counters.TotalUCRs, 1) # in this example, there is one UCR in 1 segment. self.assertEquals(len(ucrs), heap.Counters.TotalUCRs) ucr = ucrs[0] # UCR will point to non-mapped space. But reserved address space. self.assertEquals(ucr.Address.value, 0x6b1000) self.assertEquals(ucr.Size, 0xf000) # bytes self.assertEquals(ucr.Address.value + ucr.Size, 0x6c0000) # check numbers. reserved_size = heap.Counters.TotalMemoryReserved committed_size = heap.Counters.TotalMemoryCommitted ucr_size = reserved_size - committed_size self.assertEquals(ucr.Size, ucr_size)
def test_get_segment_list_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) self.assertTrue(finder._is_heap(h, addr)) validator = finder.get_heap_validator() segments = validator.HEAP_get_segment_list(heap) self.assertEquals(len(segments), heap.Counters.TotalSegments) pages = 0 total_size = 0 for segment in segments: self.assertEquals(segment.SegmentSignature, 0xffeeffee) self.assertEquals(segment.Heap.value, addr) self.assertLess(segment.BaseAddress.value, segment.FirstEntry.value) self.assertLess(segment.FirstEntry.value, segment.LastValidEntry.value) valid_alloc_size = (segment.LastValidEntry.value - segment.FirstEntry.value) meta_size = segment.FirstEntry.value - \ segment.BaseAddress.value pages += segment.NumberOfPages total_size += valid_alloc_size + meta_size # Heap resutls for all segments committed_size = heap.Counters.TotalMemoryCommitted reserved_size = heap.Counters.TotalMemoryReserved self.assertEquals(pages * 4096, reserved_size) self.assertEquals(total_size, reserved_size)
def test_get_chunks(self): # You have to import after ctypes has been tuned ( mapping loader ) finder = win7heapwalker.Win7HeapFinder(self.memory_handler) addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) walker = finder.get_heap_walker(h) validator = walker.get_heap_validator() heap = walker.get_heap() allocated, free = validator.get_backend_chunks(heap) s_allocated = sum([c[1] for c in allocated]) s_free = sum([c[1] for c in free]) total = sorted(allocated | free) s_total = sum([c[1] for c in total]) # in this example, its a single continuous segment for i in range(len(total) - 1): if total[i][0] + total[i][1] != total[i + 1][0]: self.fail('Chunk Gap between %s %s ' % (total[i], total[i + 1])) chunks_size = total[-1][0] + total[-1][1] - total[0][0] # HEAP segment was aggregated into HEAP valid_alloc_size = (heap.LastValidEntry.value - heap.FirstEntry.value) meta_size = (heap.FirstEntry.value - heap.BaseAddress.value) committed_size = heap.Counters.TotalMemoryCommitted reserved_size = heap.Counters.TotalMemoryReserved ucr_size = reserved_size - committed_size # 1 chunk is 8 bytes. self.assertEquals(s_free / 8, heap.TotalFreeSize) self.assertEquals(committed_size, meta_size + chunks_size) self.assertEquals(reserved_size, meta_size + chunks_size + ucr_size)
def test_ctypes_sizes(self): """putty.1.dump is a win7 32 bits memory dump""" finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x00390000) walker = finder.get_heap_walker(mapping) win7heap = walker._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() my_utils = self.memory_handler.get_target_platform( ).get_target_ctypes_utils() self.assertEquals(my_ctypes.sizeof(win7heap.HEAP_SEGMENT), 64) self.assertEquals(my_ctypes.sizeof(win7heap.HEAP_ENTRY), 8) self.assertEquals(my_ctypes.sizeof(my_ctypes.POINTER(None)), 4) self.assertEquals( my_ctypes.sizeof(my_ctypes.POINTER(win7heap.HEAP_TAG_ENTRY)), 4) self.assertEquals(my_ctypes.sizeof(win7heap.LIST_ENTRY), 8) self.assertEquals( my_ctypes.sizeof(my_ctypes.POINTER(win7heap.HEAP_LIST_LOOKUP)), 4) self.assertEquals( my_ctypes.sizeof(my_ctypes.POINTER( win7heap.HEAP_PSEUDO_TAG_ENTRY)), 4) self.assertEquals( my_ctypes.sizeof(my_ctypes.POINTER(win7heap.HEAP_LOCK)), 4) self.assertEquals(my_ctypes.sizeof(my_ctypes.c_ubyte), 1) self.assertEquals(my_ctypes.sizeof((my_ctypes.c_ubyte * 1)), 1) self.assertEquals(my_ctypes.sizeof(win7heap.HEAP_COUNTERS), 84) self.assertEquals(my_ctypes.sizeof(win7heap.HEAP_TUNING_PARAMETERS), 8) self.assertEquals(my_ctypes.sizeof(win7heap.HEAP), 312) self.assertEquals(my_utils.offsetof(win7heap.HEAP, 'Signature'), 100)
def test_freelists(self): """ List all free blocks """ # TODO test 0x0061a000 for overflow self.assertNotEqual(self._memory_handler, None) # test the heaps _heaps = self._heap_finder.get_heap_mappings() heap_sums = dict([(heap, list()) for heap in _heaps]) child_heaps = dict() for heap in _heaps: heap_addr = heap.get_marked_heap_address() log.debug( '==== walking heap num: %0.2d @ %0.8x', self._heap_finder._read_heap(heap, heap_addr).ProcessHeapsListIndex, heap_addr) walker = self._heap_finder.get_heap_walker(heap) for x, s in walker._get_freelists(): m = self._memory_handler.get_mapping_for_address(x) # Found new mmap outside of heaps mmaps if m not in heap_sums: heap_sums[m] = [] heap_sums[m].append((x, s)) #self.assertEquals( free_size, walker.HEAP().TotalFreeSize) # save mmap hierarchy child_heaps[heap] = walker.get_heap_children_mmaps() # calcul cumulates for heap, children in child_heaps.items(): # for each heap, look at all children freeblocks = map(lambda x: x[0], heap_sums[heap]) free_size = sum(map(lambda x: x[1], heap_sums[heap])) finder = win7heapwalker.Win7HeapFinder(self._memory_handler) cheap = finder._read_heap(heap, heap.get_marked_heap_address()) log.debug('-- heap 0x%0.8x \t free:%0.5x \texpected: %0.5x' % (heap.start, free_size, cheap.TotalFreeSize)) total = free_size for child in children: freeblocks = map(lambda x: x[0], heap_sums[child]) self.assertEquals(len(freeblocks), len(set(freeblocks))) # print heap_sums[child] free_size = sum(map(lambda x: x[1], heap_sums[child])) log.debug(' \_ mmap 0x%0.8x\t free:%0.5x ' % (child.start, free_size)) self.assertEquals(len(freeblocks), len(set(freeblocks))) total += free_size log.debug(' \= total: \t\t free:%0.5x ' % (total)) maxlen = len(heap) cheap = finder._read_heap(heap, heap.get_marked_heap_address()) self.assertEquals(cheap.TotalFreeSize * 8, total) log.debug( 'heap: 0x%0.8x free: %0.5x \texpected: %0.5x \tmmap len:%0.5x' % (heap.start, total, cheap.TotalFreeSize, maxlen)) return
def test_get_frontendheap(self): finder = win7heapwalker.Win7HeapFinder(self._memory_handler) # heap = self._memory_handler.get_mapping_for_address(0x00390000) # for heap in finder.get_heap_mappings(): for heap in [self._memory_handler.get_mapping_for_address(0x005c0000)]: allocs = list() walker = finder.get_heap_walker(heap) # helper win7heap = walker._heap_module heap_children = walker.list_used_mappings() committed, free = walker._get_frontend_chunks() # page 37 # each UserBlock contain a 8 byte header ( first 4 encoded ) # and then n-bytes of user data # # (in a free chunk) # the user data's first two bytes hold the next free chunk offset # UserBlocks + 8*NextOffset # Its basically a forward pointer, offset. # # commited frontend chunks should have a flag at 0x5 # previous chunk is at - 8*Chunk.SegmentOffset for chunk_addr, chunk_size in committed: self.assertGreaterEqual(chunk_size, 0x8, 'too small chunk_addr == 0x%0.8x' % chunk_addr) m = self._memory_handler.get_mapping_for_address(chunk_addr) if m != heap: self.assertIn(m, heap_children) # should be aligned self.assertEqual(chunk_addr & 7, 0) # page 40 st = m.read_struct(chunk_addr, win7heap.HEAP_ENTRY) # HEAP_ENTRY # st.UnusedBytes == 0x5 ? if st._0._1.UnusedBytes == 0x05: prev_header_addr -= 8 * st._0._1._0.SegmentOffset log.debug('UnusedBytes == 0x5, SegmentOffset == %d' % st._0._1._0.SegmentOffset) # FIXME, in child of 0x005c0000. LFH. What are the flags already ? print(hex(chunk_addr)) self.assertTrue(st._0._1.UnusedBytes & 0x80, 'UnusedBytes said this is a BACKEND chunk , Flags | 2') allocs.append((chunk_addr, chunk_size)) # with header # FIXME - UNITTEST- you need to validate that NextOffset in # userblock gives same answer oracle = committed[0] # TODO for chunk_addr, chunk_size in committed: m = self._memory_handler.get_mapping_for_address(chunk_addr) if m != heap: self.assertIn(m, heap_children) # should be aligned self.assertEqual(chunk_addr & 7, 0) # page 40 st = m.read_struct(chunk_addr, win7heap.HEAP_ENTRY) # NextOffset in userblock gives same answer for addr, s in allocs: m = self._memory_handler.get_mapping_for_address(addr) if addr + s > m.end: self.fail('OVERFLOW @%0.8x-@%0.8x, @%0.8x size:%d end:@%0.8x' % (m.start, m.end, addr, s, addr + s)) return
def test_sorted_heaps(self): """ check if memory_mapping gives heaps sorted by index. """ # self.skipTest('known_ok') finder = win7heapwalker.Win7HeapFinder(self._memory_handler) walkers = finder.list_heap_walkers() self.assertEqual(len(walkers), len(putty_1_win7.known_heaps)) last = 0 for i, walker in enumerate(walkers): this = walker.get_heap_address() self.assertLess(last, this, "Heaps are ordered by base address") last = this return
def test_sorted_heaps(self): """ check if memory_mapping gives heaps sorted by index. """ # self.skipTest('known_ok') finder = win7heapwalker.Win7HeapFinder(self._memory_handler) heaps = finder.get_heap_mappings() self.assertEquals(len(heaps), len(putty_1_win7.known_heaps)) for i, m in enumerate(heaps): # print '%d @%0.8x'%(finder._read_heap(m).ProcessHeapsListIndex, m.start) self.assertEquals( finder._read_heap( m, m.get_marked_heap_address()).ProcessHeapsListIndex, i + 1, 'ProcessHeaps should have correct indexes') return
def test_get_vallocs_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) walker = finder.get_heap_walker(mapping) win7heap = walker._heap_module for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) validator = walker.get_heap_validator() heap = walker.get_heap() valloc_committed = validator.HEAP_get_virtual_allocated_blocks_list( heap) size = sum([x.ReserveSize for x in valloc_committed]) self.assertEquals(heap.Counters.TotalSizeInVirtualBlocks, size)
def test_get_user_allocations(self): """ For each known _HEAP, load all user Allocation and compare the number of allocated bytes. """ finder = win7heapwalker.Win7HeapFinder(self._memory_handler) for m in finder.get_heap_mappings(): # walker = finder.get_heap_walker(m) total = 0 for chunk_addr, chunk_size in walker.get_user_allocations(): self.assertTrue(chunk_addr in self._memory_handler) self.assertGreater(chunk_size, 0, 'chunk_addr == 0x%0.8x' % (chunk_addr)) total += chunk_size return
def test_is_heap_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) # check heap.Signature self.assertEquals(heap.Signature, 4009750271) # 0xeeffeeff # a load_member by validator occurs in heapwalker._is_heap self.assertTrue(finder._is_heap(h, addr)) finder = self.memory_handler.get_heap_finder() heaps = sorted([(h.start, len(h)) for h in finder.get_heap_mappings()]) self.assertEquals(heaps, putty_1_win7.known_heaps) self.assertEquals(len(heaps), len(putty_1_win7.known_heaps))
def test_get_vallocs_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) self.assertTrue(finder._is_heap(h, addr)) validator = finder.get_heap_validator() valloc_committed = validator.HEAP_get_virtual_allocated_blocks_list( heap) size = sum([x.ReserveSize for x in valloc_committed]) self.assertEquals(heap.Counters.TotalSizeInVirtualBlocks, size)
def test_is_heap_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) walker = finder.get_heap_walker(h) heap = walker.get_heap() # check heap.Signature self.assertEquals(heap.Signature, 4009750271) # 0xeeffeeff finder = self.memory_handler.get_heap_finder() heaps = sorted([(h.get_heap_address(), len(h.get_heap_mapping())) for h in finder.list_heap_walkers()]) self.assertEquals(heaps, putty_1_win7.known_heaps) self.assertEquals(len(heaps), len(putty_1_win7.known_heaps))
def test_get_frontend_chunks(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) walker = finder.get_heap_walker(mapping) win7heap = walker._heap_module addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) validator = walker.get_heap_validator() heap = walker.get_heap() fth_committed, fth_free = validator.get_frontend_chunks(heap) # SizeInCache : 59224L, # not much to check... lfh = h.read_struct(heap.FrontEndHeap.value, win7heap.LFH_HEAP) self.assertEquals(lfh.Heap.value, addr)
def test_get_frontend_chunks(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) self.assertTrue(finder._is_heap(h, addr)) validator = finder.get_heap_validator() fth_committed, fth_free = validator.HEAP_get_frontend_chunks(heap) # SizeInCache : 59224L, # not much to check... lfh = h.read_struct(heap.FrontEndHeap.value, win7heap.LFH_HEAP) self.assertEquals(lfh.Heap.value, addr)
def test_get_vallocs(self): # test/dumps/keepass.live.prod 0x00410000 finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) walker = finder.get_heap_walker(mapping) win7heap = walker._heap_module addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) validator = walker.get_heap_validator() heap = walker.get_heap() valloc_committed = validator.HEAP_get_virtual_allocated_blocks_list( heap) size = sum([x.ReserveSize for x in valloc_committed]) # FIXME Maybe ?? self.assertEquals(heap.Counters.TotalSizeInVirtualBlocks, size)
def test_get_freelists_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) walker = finder.get_heap_walker(mapping) win7heap = walker._heap_module for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) validator = walker.get_heap_validator() heap = walker.get_heap() allocated, free = validator.get_backend_chunks(heap) freelists = validator.HEAP_get_freelists(heap) free_size = sum( [x[1] for x in [(hex(x[0]), x[1]) for x in freelists]]) free_size2 = sum([x[1] for x in free]) self.assertEquals(heap.TotalFreeSize * 8, free_size) self.assertEquals(free_size, free_size2)
def test_get_freelists(self): # You have to import after ctypes has been tuned ( mapping loader ) finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) walker = finder.get_heap_walker(mapping) win7heap = walker._heap_module addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) validator = walker.get_heap_validator() heap = walker.get_heap() allocated, free = validator.get_backend_chunks(heap) freelists = validator.HEAP_get_freelists(heap) free_size = sum([x[1] for x in [(hex(x[0]), x[1]) for x in freelists]]) free_size2 = sum([x[1] for x in free]) self.assertEquals(heap.TotalFreeSize * 8, free_size) self.assertEquals(free_size, free_size2)
def test_get_freelists(self): # You have to import after ctypes has been tuned ( mapping loader ) finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() addr = 0x005c0000 h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) self.assertTrue(finder._is_heap(h, addr)) validator = finder.get_heap_validator() allocated, free = validator.HEAP_get_chunks(heap) freelists = validator.HEAP_get_freelists(heap) free_size = sum([x[1] for x in [(hex(x[0]), x[1]) for x in freelists]]) free_size2 = sum([x[1] for x in free]) self.assertEquals(heap.TotalFreeSize * 8, free_size) self.assertEquals(free_size, free_size2)
def test_get_freelists_all(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() for addr, size in putty_1_win7.known_heaps: h = self.memory_handler.get_mapping_for_address(addr) heap = h.read_struct(addr, win7heap.HEAP) self.assertTrue(finder._is_heap(h, addr)) validator = finder.get_heap_validator() allocated, free = validator.HEAP_get_chunks(heap) freelists = validator.HEAP_get_freelists(heap) free_size = sum( [x[1] for x in [(hex(x[0]), x[1]) for x in freelists]]) free_size2 = sum([x[1] for x in free]) self.assertEquals(heap.TotalFreeSize * 8, free_size) self.assertEquals(free_size, free_size2)
def test_is_heap(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) mapping = self.memory_handler.get_mapping_for_address(0x005c0000) walker = finder.get_heap_walker(mapping) win7heap = walker._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() h = self.memory_handler.get_mapping_for_address(0x005c0000) self.assertEquals(h.get_byte_buffer()[0:10], '\xc7\xf52\xbc\xc9\xaa\x00\x01\xee\xff') addr = h.start self.assertEquals(addr, 6029312) heap = walker.get_heap() # heap = h.read_struct(addr, win7heap.HEAP) # check that haystack memory_mapping works self.assertEquals(my_ctypes.addressof(h._local_mmap_content), my_ctypes.addressof(heap)) # check heap.Signature self.assertEquals(heap.Signature, 4009750271) # 0xeeffeeff
def test_is_heap(self): finder = win7heapwalker.Win7HeapFinder(self.memory_handler) win7heap = finder._heap_module my_ctypes = self.memory_handler.get_target_platform( ).get_target_ctypes() h = self.memory_handler.get_mapping_for_address(0x005c0000) self.assertEquals(h.get_byte_buffer()[0:10], '\xc7\xf52\xbc\xc9\xaa\x00\x01\xee\xff') addr = h.start self.assertEquals(addr, 6029312) heap = h.read_struct(addr, win7heap.HEAP) # check that haystack memory_mapping works self.assertEquals(my_ctypes.addressof(h._local_mmap_content), my_ctypes.addressof(heap)) # check heap.Signature self.assertEquals(heap.Signature, 4009750271) # 0xeeffeeff # we need to initialize the heaps for _is_heap ## mappings = finder.get_heap_mappings() # a load_member by validator occurs in heapwalker._is_heap self.assertTrue(finder._is_heap(h, addr))