You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
4.8 KiB
132 lines
4.8 KiB
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import logging
|
|
import struct
|
|
import sys
|
|
|
|
from haystack import cli
|
|
from haystack import argparse_utils
|
|
from haystack.outputters import text
|
|
from haystack.mappings import folder
|
|
|
|
# from haystack.outputters import python
|
|
|
|
"""
|
|
Search for HEAP.
|
|
"""
|
|
|
|
log = logging.getLogger('cliwin')
|
|
|
|
|
|
def find_heap():
|
|
argv = sys.argv[1:]
|
|
parser = cli.base_argparser('haystack-find-heap', "Find heaps in a dumpfile")
|
|
parser.add_argument('--verbose', '-v', action='store_true', help='Verbose')
|
|
parser.add_argument('--mappings', '-m', action='store_true', help='Show mappings')
|
|
# only if address is present
|
|
group = parser.add_argument_group('For a specific HEAP')
|
|
group.add_argument('address', nargs='?', type=argparse_utils.int16, default=None, help='Load Heap from address (hex)')
|
|
group.add_argument('--heap', '-p', action='store_true', help='Show the heap content')
|
|
group.add_argument('--frontend', '-f', action='store_true', help='Show the frontend heap content')
|
|
|
|
opts = parser.parse_args(argv)
|
|
cli.set_logging_level(opts)
|
|
|
|
memory_handler = cli.make_memory_handler(opts)
|
|
finder = memory_handler.get_heap_finder()
|
|
|
|
# Show Target information
|
|
if opts.bits or opts.osname:
|
|
print('Forced target resolution:', memory_handler.get_target_platform())
|
|
else:
|
|
print('Automatic target resolution:', memory_handler.get_target_platform())
|
|
|
|
if opts.mappings:
|
|
# show all memory mappings
|
|
print('Process mappings:')
|
|
print('@start @stop File Offset M:m ')
|
|
for m in memory_handler.get_mappings():
|
|
print(m)
|
|
|
|
if opts.address is not None:
|
|
one_heap(opts, finder)
|
|
return
|
|
|
|
print('Probable Process HEAPS:')
|
|
for m in memory_handler.get_mappings():
|
|
for addr in range(m.start, m.end, 0x1000):
|
|
special = ''
|
|
for os, bits, offset in [('winxp', 32, 8), ('winxp', 64, 16),
|
|
('win7', 32, 100), ('win7', 64, 160)]:
|
|
signature = struct.unpack('I', m.read_bytes(addr+offset, 4))[0]
|
|
if signature == 0xeeffeeff:
|
|
if addr != m.start:
|
|
special = ' (!) '
|
|
print('[+] %s %dbits %s 0x%0.8x' % (os, bits, special, addr), m)
|
|
|
|
# Then show heap analysis
|
|
print('Found Heaps:')
|
|
|
|
for walker in finder.list_heap_walkers():
|
|
validator = walker.get_heap_validator()
|
|
validator.print_heap_analysis(walker.get_heap(), opts.verbose)
|
|
|
|
return
|
|
|
|
|
|
def one_heap(opts, finder):
|
|
address = opts.address
|
|
memory_handler = finder._memory_handler
|
|
# just return the heap
|
|
ctypes_heap, valid = finder.search_heap_direct(address)
|
|
out = text.RecursiveTextOutputter(finder._memory_handler)
|
|
# out = python.PythonOutputter(finder._memory_handler)
|
|
if opts.heap:
|
|
print(out.parse(ctypes_heap, depth=2))
|
|
print('Valid =', valid)
|
|
if opts.frontend:
|
|
heap_addr = ctypes_heap._orig_address_
|
|
heap_m = memory_handler.get_mapping_for_address(heap_addr)
|
|
walker = finder.get_heap_walker(heap_m)
|
|
win_heap = walker._heap_module
|
|
_utils = memory_handler.get_target_platform().get_target_ctypes_utils()
|
|
if ctypes_heap.FrontEndHeapType == 0:
|
|
log.error('BACKEND HEAP Type')
|
|
elif ctypes_heap.FrontEndHeapType == 1:
|
|
lal_start_addr = _utils.get_pointee_address(ctypes_heap.FrontEndHeap)
|
|
m = memory_handler.is_valid_address(lal_start_addr, win_heap.HEAP_LOOKASIDE * 128)
|
|
if not m:
|
|
log.error('HEAP.FrontEndHeap has a bad address %x', lal_start_addr)
|
|
return set()
|
|
lal_list = m.read_struct(lal_start_addr, win_heap.HEAP_LOOKASIDE * 128)
|
|
for i, st in enumerate(lal_list):
|
|
out.parse(st, depth=2)
|
|
elif ctypes_heap.FrontEndHeapType == 2 and memory_handler.get_target_platform().get_os_name() != 'winxp':
|
|
lfh_start_addr = _utils.get_pointee_address(ctypes_heap.FrontEndHeap)
|
|
m = memory_handler.is_valid_address(lfh_start_addr, win_heap.LFH_HEAP)
|
|
if not m:
|
|
log.error('HEAP.FrontEndHeap has a bad address %x', lfh_start_addr)
|
|
return set()
|
|
lfh_heap = m.read_struct(lfh_start_addr, win_heap.LFH_HEAP)
|
|
out.parse(lfh_heap, depth=2)
|
|
|
|
pass
|
|
# fake it
|
|
if valid:
|
|
m = memory_handler.get_mapping_for_address(address)
|
|
# we force the mapping to be a heap container because we where asked to
|
|
validator = finder.get_heap_walker(m).get_heap_validator()
|
|
validator.print_heap_analysis(ctypes_heap, opts.verbose)
|
|
else:
|
|
print("Could not load Heap for target", memory_handler.get_target_platform())
|
|
return
|
|
|
|
|
|
if __name__ == '__main__':
|
|
find_heap()
|
|
|