Skip to content

Commit

Permalink
Work towards python3 compatible codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
trolldbois committed May 14, 2017
1 parent 40f4e35 commit 420510c
Show file tree
Hide file tree
Showing 45 changed files with 404 additions and 356 deletions.
2 changes: 1 addition & 1 deletion haystack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
# travis-ci says
# maxnofile (64000, 64000)
# maxnofile_after (64000, 64000)
except ImportError, e:
except ImportError as e:
pass


Expand Down
12 changes: 7 additions & 5 deletions haystack/allocators/libc/libdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# Copyright (C) 2011 Loic Jaquemet loic.jaquemet+python@gmail.com
#

from __future__ import print_function
import ctypes
import logging

Expand Down Expand Up @@ -108,19 +109,20 @@ def getname(fnaddr):
yield (ptr, dl_name)
else:
continue
print '[-] MIDDLE 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s @%x' % (
print('[-] MIDDLE 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s @%x' % (
ptr, caddr, m.permissions, localm.permissions, localm.permissions == m.permissions,
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name, fnaddr)
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name, fnaddr))
else:
continue
print 'FAIL REBASE (not public ?) 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s ' % (
print('FAIL REBASE (not public ?) 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s ' % (
ptr, caddr, m.permissions, localm.permissions, localm.permissions == m.permissions,
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name)
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name))
pass
break
if not found:
continue
print '[+] not a fn pointer %x\n' % (ptr), m, '\n ---dump Vs local ---- \n', '\n'.join(map(str, localmaps))
print('[+] not a fn pointer %x\n' % (ptr), m, '\n ---dump Vs local ---- \n',
'\n'.join(map(str, localmaps)))
# pass
for name, lib in ldso.items():
ret = libdl.dlclose(lib._handle)
Expand Down
49 changes: 25 additions & 24 deletions haystack/allocators/libc/sandbox.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import print_function

'''
( 'ptr_ext_lib' , ctypes.c_void_p ), # @ b6b3ef68 /usr/lib/libQtCore.so.4.7.2
Expand Down Expand Up @@ -55,7 +56,7 @@ def test1():
os.path.sep) +
1:libname.index('.so') +
3]
print libname2
print(libname2)
libqt = ctypes.CDLL(libname2)

localmappings = getMappings()
Expand All @@ -65,38 +66,38 @@ def test1():
myvaddr = qtmaps[0].start + offset

ret = libdl.dladdr(myvaddr, ctypes.byref(info))
print 'filling dlinfo with', libname, info
print('filling dlinfo with', libname, info)

signed_addr = libdl.dlsym(0, 'dladdr', 'xxx')
vaddr_dladdr = struct.unpack('L', struct.pack('l', signed_addr))[0]
ret = libdl.dladdr(vaddr_dladdr, ctypes.byref(info))
print 'dlsym test', info.dli_sname.string, info.dli_sname.string == 'dladdr'
print('dlsym test', info.dli_sname.string, info.dli_sname.string == 'dladdr')


def test2():
# now for the real deal.
# we need to emulate ELF dl-addr.c

print ''
print('')

#
# define DL_LOOKUP_ADDRESS(addr) _dl_lookup_address (addr)

libssl = ctypes.CDLL('/usr/lib/libssl.so.0.9.8')
localmappings = getMappings()

print 'libssl.ssl3_read by id() is @%x' % (id(libssl.ssl3_read))
print localmappings.get_mapping_for_address(id(libssl.ssl3_read))
print('libssl.ssl3_read by id() is @%x' % (id(libssl.ssl3_read)))
print(localmappings.get_mapping_for_address(id(libssl.ssl3_read)))

print ''
print('')
signed_addr = libssl.dlsym(libssl._handle, 'ssl3_read', 'xxx')
fnaddr = struct.unpack('L', struct.pack('l', signed_addr))[0]
print 'libssl.ssl3_read by dlsym is @%x' % (fnaddr)
print localmappings.get_mapping_for_address(fnaddr)
print('libssl.ssl3_read by dlsym is @%x' % (fnaddr))
print(localmappings.get_mapping_for_address(fnaddr))

info = Dl_info()
ret = libdl.dladdr(fnaddr, ctypes.byref(info))
print 'dladdr test', info.dli_sname.string, info.dli_sname.string == 'ssl3_read'
print('dladdr test', info.dli_sname.string, info.dli_sname.string == 'ssl3_read')
'''
libssl.ssl3_read by id() is @9528ecc
0x0924a000 0x095d1000 rw-p 0x00000000 00:00 0000000 [heap]
Expand All @@ -105,13 +106,13 @@ def test2():
0xb6dc2000 0xb6e0c000 r-xp 0x00000000 08:04 7739090 /lib/libssl.so.0.9.8
dladdr test ssl3_read True
'''
print ''
print('')

# testing low level
# low level call
#(const void *address, Dl_info *info,
# struct link_map **mapp, const ElfW(Sym) **symbolp)
print libdl._dl_addr(fnaddr, ctypes.byref(info), 0, 0)
print(libdl._dl_addr(fnaddr, ctypes.byref(info), 0, 0))
# iterate the struct link_map
# for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
# for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next)
Expand Down Expand Up @@ -143,7 +144,7 @@ def test3():

dumpname = '/home/jal/outputs/dumps/ssh/ssh.1' # 23418'
#dumpname = '/home/jal/outputs/dumps/skype/skype.1/skype.1.a'
print '[+] load context', dumpname
print('[+] load context', dumpname)
ctx = context.get_context(dumpname)
mappings = ctx.mappings
ldso = dict()
Expand All @@ -154,14 +155,14 @@ def test3():
except OSError as e:
IGNORES.append(m.pathname)

print '[+] context loaded'
print('[+] context loaded')
# mmap_libdl = [ m for m in _memory_handler if 'ld-2.13' in m.pathname ] #and 'x' in m.permissions]
#hptrs = ctx._pointers_values_heap
# print '[+] %d pointers in heap to heap '%( len(hptrs) )

# looking in [heap] pointing to elsewhere
all_ptrs = ctx.listPointerValueInHeap()
print '[+] %d pointers in heap to elsewhere ' % (len(all_ptrs))
print('[+] %d pointers in heap to elsewhere ' % (len(all_ptrs)))

localmappings = getMappings()

Expand Down Expand Up @@ -192,25 +193,25 @@ def test3():
#sym = libdl.dlsym( ldso[m.pathname]._handle, dl_name, 'xxx')
#fnaddr = struct.unpack('L',struct.pack('l', sym) )[0]
if fnaddr == caddr: # reverse check
print '[+] REBASE 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s @%x' % (
print('[+] REBASE 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s @%x' % (
ptr, caddr, m.permissions, localm.permissions, localm.permissions == m.permissions,
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name, fnaddr)
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name, fnaddr))
# yield (ptr, m, dl_name)
else:
# continue
print '[-] MIDDLE 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s @%x' % (
print('[-] MIDDLE 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s @%x' % (
ptr, caddr, m.permissions, localm.permissions, localm.permissions == m.permissions,
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name, fnaddr)
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name, fnaddr))
else:
continue
print 'FAIL REBASE (not public ?) 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s ' % (
print('FAIL REBASE (not public ?) 0x%x -> 0x%x p:%s|%s|=%s off:%x|%x|=%s %s fn: %s ' % (
ptr, caddr, m.permissions, localm.permissions, localm.permissions == m.permissions,
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name)
m.offset, localm.offset, m.offset == localm.offset, m.pathname, dl_name))
pass
break
if not found:
continue
print '[+] not a fn pointer %x\n' % (ptr), m, '\n ---dump Vs local ---- \n', '\n'.join(map(str, localmaps))
print('[+] not a fn pointer %x\n' % (ptr), m, '\n ---dump Vs local ---- \n', '\n'.join(map(str, localmaps)))
# pass
for name, lib in ldso.items():
ret = libdl.dlclose(lib._handle)
Expand All @@ -221,12 +222,12 @@ def test3():
def test4():
dumpname = '/home/jal/outputs/dumps/ssh/ssh.1' # 23418'
#dumpname = '/home/jal/outputs/dumps/skype/skype.1/skype.1.a'
print '[+] load context', dumpname
print('[+] load context', dumpname)
ctx = context.get_context(dumpname)
mappings = ctx.mappings

for ptr, name in ctx._function_names.items():
print '@%x -> %s::%s' % (ptr, mappings.get_mapping_for_address(ptr).pathname, name)
print('@%x -> %s::%s' % (ptr, mappings.get_mapping_for_address(ptr).pathname, name))


libdl = ctypes.CDLL('libdl.so')
Expand Down
40 changes: 21 additions & 19 deletions haystack/allocators/win32/win7heap.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
#
from __future__ import print_function

"""
Win 7 heap structure validation
See docs/win32_heap for all supporting documentation.
Expand Down Expand Up @@ -423,20 +425,20 @@ def get_segment_list(self, heap):

def print_heap_analysis_details(self, heap):
# size & space calculated from heap info
print ' Backend:'
print(' Backend:')
ucrs = self.HEAP_get_UCRanges_list(heap)
ucr_list = winheap.UCR_List(ucrs)
# heap.Counters.TotalMemoryReserved.value == heap.LastValidEntry.value - heap.BaseAddress.value
nb_ucr = heap.Counters.TotalUCRs
print '\tUCRList: %d/%d' % (len(ucrs), nb_ucr)
print ucr_list.to_string('\t\t')
print('\tUCRList: %d/%d' % (len(ucrs), nb_ucr))
print(ucr_list.to_string('\t\t'))
# Virtual Allocations
vallocs = self.HEAP_get_virtual_allocated_blocks_list(heap)
print '\tVAllocations: %d' % len(vallocs)
print('\tVAllocations: %d' % len(vallocs))
for addr, c_size, r_size in vallocs:
diff = '' if c_size == r_size else '!!'
# print "vallocBlock: @0x%0.8x commit: 0x%x reserved: 0x%x" % (
print "\t\t%svalloc: 0x%0.8x-0x%0.8x size:0x%x requested:0x%x " % (diff, addr, addr+c_size, c_size, r_size)
print("\t\t%svalloc: 0x%0.8x-0x%0.8x size:0x%x requested:0x%x " % (diff, addr, addr+c_size, c_size, r_size))
return ucrs

def print_segments_analysis(self, heap, walker, ucrs):
Expand All @@ -449,48 +451,48 @@ def print_segments_analysis(self, heap, walker, ucrs):
# get allocated/free stats by segment
occupied_res2 = self.count_by_segment(segments, walker.get_backend_allocations(), overhead_size)
free_res2 = self.count_by_segment(segments, walker.get_backend_free_chunks(), overhead_size)
print "\tSegmentList: %d/%d" % (len(segments), nb_segments)
print("\tSegmentList: %d/%d" % (len(segments), nb_segments))
for segment in segments:
p_segment = winheap.Segment(self._memory_handler, walker, segment)
p_segment.set_ucr(ucr_list)
p_segment.set_resource_usage(occupied_res2, free_res2)
print p_segment.to_string('\t\t')
print(p_segment.to_string('\t\t'))
# if UCR, then
ucrsegments = self.get_UCR_segment_list(heap)
#print "\t\t\tUCRSegmentList: %d {%s}" % (len(ucrsegments), ','.join(sorted([hex(s._orig_address_) for s in ucrsegments])))
print "\t\t\tUCRSegmentList: %d " % len(ucrsegments)
print("\t\t\tUCRSegmentList: %d " % len(ucrsegments))
for ucr in ucrsegments:
_addr = self._utils.get_pointee_address(ucr.Address)
end = _addr + ucr.Size
print "\t\t\t\tUCRSegment 0x%0.8x-0x%0.8x size:0x%x" % (_addr, end, ucr.Size)
print("\t\t\t\tUCRSegment 0x%0.8x-0x%0.8x size:0x%x" % (_addr, end, ucr.Size))
# print ".UCRSegmentList.Blink", hex(heap.UCRSegmentList.Blink.value)

def print_frontend_analysis_details(self, heap):
# Frontend Type == LFH
if heap.FrontEndHeapType == 2:
print ' FrontEnd: LOW_FRAGMENTATION_HEAP'
print(' FrontEnd: LOW_FRAGMENTATION_HEAP')
lfh_heap = self._get_lfh_heap(heap)
lfh_blocks = [x for x in self._get_LFH_SubSegment_from_SubSegmentZones(lfh_heap)]
blocks_2 = [b for b in self._get_LFH_SubSegment_from_CrtZone(lfh_heap)]
print '\t\tLFH Blocks %d/%d' % (len(lfh_blocks), len(blocks_2))
print('\t\tLFH Blocks %d/%d' % (len(lfh_blocks), len(blocks_2)))
_c, _f = self.get_lfh_chunks(heap)
c_size = sum([c[1] for c in _c])
u_size = sum([c[2] for c in _c])
f_size = sum([c[1] for c in _f])
print '\t\tLFH CommittedSize:0x%x FreeSize:0x%x Unused:0x%x' % (c_size, f_size, u_size)
print('\t\tLFH CommittedSize:0x%x FreeSize:0x%x Unused:0x%x' % (c_size, f_size, u_size))
mappings = set()
# we limit the search to UserBlocks, as heap_entries have to be on the same mapping
for b in lfh_blocks:
total_size = 0
start, segments = self.get_lfh_subsegment(b)
if start is None:
print '\t\t\tBlock 0x%0.8x SubSegments: 0' % b._orig_address_
print('\t\t\tBlock 0x%0.8x SubSegments: 0' % b._orig_address_)
continue
print '\t\t\tBlock 0x%0.8x SubSegments: %d' % (b._orig_address_, len(segments))
print('\t\t\tBlock 0x%0.8x SubSegments: %d' % (b._orig_address_, len(segments)))
for segment in segments:
user_blocks_addr = self._utils.get_pointee_address(segment.UserBlocks)
if user_blocks_addr == 0:
print '\t\t\t\tSubSegment->UserBlocks == NULL'
print('\t\t\t\tSubSegment->UserBlocks == NULL')
continue
mappings.add(self._memory_handler.get_mapping_for_address(user_blocks_addr))
allocation_length = segment._3._0.BlockSize * self._word_size_x2
Expand All @@ -499,15 +501,15 @@ def print_frontend_analysis_details(self, heap):
# to the end of last chunk
end = user_blocks_addr + header_size + allocation_length * (block_count + 1)
size = end-user_blocks_addr
print '\t\t\t\tSubSegment 0x%0.8x-0x%0.8x size:0x%x chunks: count:%d size:0x%x' % (user_blocks_addr, end, size, block_count, allocation_length)
print('\t\t\t\tSubSegment 0x%0.8x-0x%0.8x size:0x%x chunks: count:%d size:0x%x' % (user_blocks_addr, end, size, block_count, allocation_length))
total_size += size
# occupied_res3 = self.count_by_segment(segments, walker.get_user_allocations(), overhead_size)
# free_res3 = self.count_by_segment(segments, walker.get_free_chunks(), overhead_size)

# sum of all user blocks for this subsegment
print '\t\t\tTotal_committed_size:0x%0.8x' % total_size
print '\t\tMappings used:'
print('\t\t\tTotal_committed_size:0x%0.8x' % total_size)
print('\t\tMappings used:')
for m in sorted(mappings, key=lambda x: x.start):
print '\t\t\t%s' % m
print('\t\t\t%s' % m)
return

14 changes: 8 additions & 6 deletions haystack/allocators/win32/winheap.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
#
from __future__ import print_function

"""
Contains common code for winXP heap and win7 heap
"""
Expand Down Expand Up @@ -424,11 +426,11 @@ def print_heap_analysis(self, heap, verbose):
if heap_bits != process_bits:
special += ' (!%d bits heap!) ' % heap_bits

print '[+] %sHEAP:0x%0.8x' % (special, addr), m
print(('[+] %sHEAP:0x%0.8x' % (special, addr), m))
if not verbose:
return
#
print ' FrontEndHeapType:', heap.FrontEndHeapType, FrontEndHeapType.get(heap.FrontEndHeapType, 'UNKNOWN')
print(' FrontEndHeapType:', heap.FrontEndHeapType, FrontEndHeapType.get(heap.FrontEndHeapType, 'UNKNOWN'))

finder = self._memory_handler.get_heap_finder()
walker = finder.get_heap_walker(m)
Expand All @@ -454,7 +456,7 @@ def print_mapping_children_analysis(self, heap):
# look at children from free/allocations POV
addr = heap._orig_address_
m = self._memory_handler.get_mapping_for_address(addr)
print '[+] ', m
print('[+] ', m)
finder = self._memory_handler.get_heap_finder()
walker = finder.get_heap_walker(m)
children = walker.list_used_mappings()
Expand All @@ -468,14 +470,14 @@ def print_mapping_children_analysis(self, heap):
free, free_overhead = free_res.get(m, (0, 0))
overhead = allocated_overhead + free_overhead
sum_ = allocated + free + overhead
print "\ta:0x%0.8x \tf:0x%0.8x \to:0x%0.8x Sum:0x%0.8x" % (allocated, free, overhead, sum_)
print("\ta:0x%0.8x \tf:0x%0.8x \to:0x%0.8x Sum:0x%0.8x" % (allocated, free, overhead, sum_))
for child in children:
print '\t[-] ', child
print('\t[-] ', child)
allocated, allocated_overhead = occupied_res.get(child, (0, 0))
free, free_overhead = free_res.get(child, (0, 0))
overhead = allocated_overhead + free_overhead
sum_ = allocated + free + overhead
print "\ta:0x%0.8x \tf:0x%0.8x \to:0x%0.8x Sum:0x%0.8x" % (allocated, free, overhead, sum_)
print("\ta:0x%0.8x \tf:0x%0.8x \to:0x%0.8x Sum:0x%0.8x" % (allocated, free, overhead, sum_))
return

def count_by_mapping(self, chunksize_tuple, overhead_size):
Expand Down
3 changes: 2 additions & 1 deletion haystack/allocators/win32/winheapwalker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Copyright (C) 2011 Loic Jaquemet loic.jaquemet+python@gmail.com
#

from __future__ import print_function
import ctypes
import logging
import struct
Expand Down Expand Up @@ -182,7 +183,7 @@ def _set_chunk_lists(self):
def _check_sizes(self, chunks):
for addr, size in chunks:
if size <= 0:
print self._heap_mapping
print(self._heap_mapping)
raise ValueError("chunk size cannot be negative: 0x%x %d" % (addr,size))

def _get_virtualallocations(self):
Expand Down
Loading

0 comments on commit 420510c

Please sign in to comment.