Skip to content

Commit

Permalink
doesn't work for stacked IMemoryMapping. more work to do for rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
trolldbois committed Feb 25, 2016
1 parent a1368ea commit fe032a9
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 22 deletions.
2 changes: 1 addition & 1 deletion haystack/allocators/win32/win7heapwalker.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def _make_dual_arch_ctypes(self):
_constraints_64 = parser.read(constraint_filename)

# KERNEL AS
kas32 = (0xFFFF080000000000, 0xFFFFFFFFFFFFFFFF)
kas32 = (0x8000000, 0xFFFFFFFF)
kas64 = (0xFFFF080000000000, 0xFFFFFFFFFFFFFFFF)

_cpu = dict()
Expand Down
21 changes: 15 additions & 6 deletions haystack/allocators/win32/winheapwalker.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ def _find_heap(self, mapping):
Funny enough, a X64 process could have 32 bits and 64 bits heaps.
"""
for addr in range(mapping.start, mapping.end, 0x1000):
map_start = mapping.start
# offset of Signature in 32 and 64 bits
for bits in [32, 64]:
offset = self._cpu[bits]['signature_offset']
Expand All @@ -299,14 +300,14 @@ def _find_heap(self, mapping):
self._cpu[bits]['constraints'],
addr)
elif self.__is_kernel_heap(mapping, addr, bits):
# FIXME
addr = mapping.start
_heap_offset = addr - map_start
heap_addr = mapping.start + _heap_offset
return self._walker_type()(self._memory_handler,
self._cpu[bits]['target'],
self._cpu[bits]['module'],
mapping,
self._cpu[bits]['constraints'],
addr)
heap_addr)
# otherwise try another combination
return None

Expand Down Expand Up @@ -337,6 +338,7 @@ def __is_kernel_heap(self, mapping, address, bits):
"""
if not isinstance(mapping, interfaces.IMemoryMapping):
raise TypeError('Feed me a IMemoryMapping object')
offset = self._cpu[bits]['signature_offset']
# switch to the right target
heap_module = self._cpu[bits]['module']
target_platform = self._cpu[bits]['target']
Expand All @@ -352,17 +354,24 @@ def __is_kernel_heap(self, mapping, address, bits):
old_start = mapping.start
# start = kernel_ptr & 0xFFFFFFFFFFFF0000
start = kernel_ptr & ((1 << bits) - 0x10000)
print '[!] KERNEL SPACE HEAP FOUND ! USER:0x%x => KERNEL:0x%x' % (address, start)
#print '[!] POSSIBLE KERNEL SPACE HEAP FOUND ! USER:0x%x => KERNEL:0x%x' % (address, start)
## print hex(struct.unpack('I', mapping.read_bytes(address+offset, 4))[0])
# FIXME: rebase must be recursive on mappings
#import pdb
#pdb.set_trace()
self._memory_handler.rebase_mapping(mapping, start)
self._memory_handler.reset_mappings()
## print hex(struct.unpack('I', mapping.read_bytes(start+offset, 4))[0])
heap = mapping.read_struct(start, heap_module.HEAP)
# validator is (should be) then target-bound
validator = self._validator_type()(self._memory_handler, constraints, target_platform, heap_module)
load = validator.load_members(heap, 3)
log.debug('HeapFinder._is_heap %s %s', mapping, load)
if not load:
#import code
#code.interact(local=locals())
self._memory_handler.rebase_mapping(mapping, old_start)
self._memory_handler.reset_mappings()
else:
print '[!] KERNEL SPACE HEAP FOUND ! USER:0x%x => KERNEL:0x%x' % (address, start)
return load

def _get_heap_possible_kernel_pointer_from_heap(self, target_platform, heap):
Expand Down
2 changes: 1 addition & 1 deletion haystack/allocators/win32/winxpheapwalker.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def _make_dual_arch_ctypes(self):
_constraints_64 = parser.read(constraint_filename)

# KERNEL AS
kas32 = (0xFFFF080000000000, 0xFFFFFFFFFFFFFFFF)
kas32 = (0x8000000, 0xFFFFFFFF)
kas64 = (0xFFFF080000000000, 0xFFFFFFFFFFFFFFFF)

_cpu = dict()
Expand Down
4 changes: 1 addition & 3 deletions haystack/dump_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,7 @@ def _load_memory_mappings(self):
log.warning(
'Using a local memory mapping . Zipfile sux. thx ruby.')
mmap = AMemoryMapping(start, end, permissions, offset, major_device, minor_device, inode, pathname=pathname)
mmap = LocalMemoryMapping.fromBytebuffer(
mmap,
mmap_content_file.read())
mmap = LocalMemoryMapping.fromBytebuffer(mmap, mmap_content_file.read())
# use file mmap when file is too big
elif end - start > haystack.MAX_MAPPING_SIZE_FOR_MMAP:
log.warning('Using a file backed memory mapping. no mmap in memory for this memorymap (%s).' % (pathname) +
Expand Down
16 changes: 11 additions & 5 deletions haystack/mappings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ def read_struct(self, address, struct):
def read_array(self, address, basetype, count):
raise NotImplementedError(self)

def rebase(self, new_start_address):
end = new_start_address + len(self)
self.start = new_start_address
self.end = end


class MemoryHandler(interfaces.IMemoryHandler, interfaces.IMemoryCache):
"""
Expand Down Expand Up @@ -268,8 +273,6 @@ def reset_mappings(self):
# reset the mappings
for m in self.get_mappings():
m.reset()
# reset the caches too
self.__optim_get_mapping_for_address()

def __optim_get_mapping_for_address(self):
self.__optim_get_mapping_for_address_cache = dict()
Expand Down Expand Up @@ -431,10 +434,13 @@ def rebase_mapping(self, user_mapping, new_start_address):
if user_mapping not in self._mappings:
raise ValueError("User mapping not found")
user_mapping = self._mappings[self._mappings.index(user_mapping)]
end = new_start_address + len(user_mapping)
user_mapping.start = new_start_address
user_mapping.end = end
user_mapping.rebase(new_start_address)
# end = new_start_address + len(user_mapping)
# user_mapping.start = new_start_address
# user_mapping.end = end
self._mappings.sort()
# reset the caches too
self.__optim_get_mapping_for_address()
return user_mapping


Expand Down
13 changes: 7 additions & 6 deletions haystack/mappings/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ def __init__(self, address, start, end, permissions, offset,
def _vtop(self, vaddr):
ret = vaddr - self.start + self._address
if ret < self._address or ret > (self._address + len(self)):
raise ValueError(
'0x%0.8x/0x%0.8x is not a valid vaddr for me' %
(vaddr, ret))
raise ValueError('0x%0.8x/0x%0.8x is not a valid vaddr for me' % (vaddr, ret))
return ret

def mmap(self):
Expand Down Expand Up @@ -202,6 +200,11 @@ def mmap(self):
def unmmap(self):
raise NotImplementedError

def rebase(self, new_start_address):
super(MemoryDumpMemoryMapping, self).rebase(new_start_address)
if self.is_mmaped():
self._base.rebase(new_start_address)

def _mmap(self):
""" protected api """
# mmap.mmap has a full bytebuffer API, so we can use it as is for bytebuffer.
Expand Down Expand Up @@ -245,9 +248,7 @@ def _mmap(self):
self._memdump.close()
log.warning('MemoryHandler Mapping content copied to ctypes array : %s', self)
# make that _base
self._base = LocalMemoryMapping.fromAddress(
self, ctypes.addressof(
self._local_mmap_content))
self._base = LocalMemoryMapping.fromAddress(self, ctypes.addressof(self._local_mmap_content))
log.debug('%s done.' % self.__class__)
# redirect function calls
self.read_word = self._base.read_word
Expand Down

0 comments on commit fe032a9

Please sign in to comment.