def setUpClass(cls): # context.get_context('test/src/test-ctypes3.dump') cls.context = None cls.memory_handler = dump_loader.load(putty_7124_win7.dumpname) cls.putty7124 = context.get_context_for_address(cls.memory_handler, putty_7124_win7.known_heaps[0][0]) cls.dsa = dsa.FieldReverser(cls.putty7124.memory_handler) cls.memory_handler = cls.putty7124.memory_handler
def graphStructureGroups(context, chains, originAddr=None): # TODO change generic fn chains.sort() decoder = dsa.FieldReverser(context.memory_handler) graph = networkx.DiGraph() for chain in chains: log.debug('\t[-] chain len:%d' % len(chain)) if originAddr is not None: if originAddr not in chain: continue # ignore chain if originAddr is not in it for addr in map(long, chain): record = context.get_record_for_address(addr) ## record.decodeFields() # can be long decoder.analyze_fields(record) print context.get_record_for_address(addr).to_string() targets = set() _record = context.get_record_for_address(addr) pointer_fields = [ f for f in _record.get_fields() if f.is_pointer() ] for f in pointer_fields: addr_child = f.get_value_for_field(_record) child = context.get_record_at_address(addr) targets.add(('%x' % addr, '%x' % child.address)) graph.add_edges_from(targets) print '#', '-' * 78 networkx.readwrite.gexf.write_gexf( graph, config.get_cache_filename(config.CACHE_GRAPH, context.dumpname))
def reverse_instances(memory_handler): """ Reverse all heaps in process from memory_handler :param memory_handler: :return: """ assert isinstance(memory_handler, interfaces.IMemoryHandler) process_context = memory_handler.get_reverse_context() #for heap in heaps: # # reverse all fields in all records from that heap # ## reverse_heap(memory_handler, heap_addr) log.info('Reversing Fields') fr = dsa.FieldReverser(memory_handler) fr.reverse() log.info('Fixing Text Fields') tfc = dsa.TextFieldCorrection(memory_handler) tfc.reverse() # try to find some logical constructs. log.info('Reversing DoubleLinkedListReverser') # why is this a reverse_context ? doublelink = reversers.DoubleLinkedListReverser(memory_handler) doublelink.reverse() doublelink.rename_all_lists() # then and only then can we look at the PointerFields # identify pointer relation between allocators log.info('Reversing PointerFields') pfr = pointertypes.PointerFieldReverser(memory_handler) pfr.reverse() # save that log.info('Saving reversed records instances') for heap_context in process_context.list_contextes(): heap_context.save_structures() # save to file save_headers(heap_context) log.info('Saving reversed records types') process_context.save_reversed_types() # graph pointer relations between allocators log.info('Reversing PointerGraph') ptrgraph = reversers.PointerGraphReverser(memory_handler) ptrgraph.reverse() # extract all strings log.info('Reversing strings') strout = reversers.StringsReverser(memory_handler) strout.reverse() log.info('Analysis results are in %s', config.get_cache_folder_name(memory_handler.get_name())) return process_context
def setUp(self): # os.chdir() self.memory_handler = folder.load('test/src/test-ctypes3.32.dump') self._load_offsets_values(self.memory_handler.get_name()) finder = self.memory_handler.get_heap_finder() walkers = finder.list_heap_walkers() self.context = context.get_context_for_address(self.memory_handler, walkers[0]) ## self.dsa = dsa.FieldReverser(self.memory_handler)
def test_utf16_2(self): _record = self.heap_context.get_record_for_address(0xa4028) _record.reset() _dsa = dsa.FieldReverser(self.memory_handler) _dsa.reverse_record(self.heap_context, _record) rev = dsa.TextFieldCorrection(self.memory_handler) rev.reverse_record(self.heap_context, _record) fields = _record.get_fields() print _record.to_string()
def setUpClass(cls): cls.dumpname = 'test/src/test-ctypes3.32.dump' config.remove_cache_folder(cls.dumpname) cls.memory_handler = folder.load(cls.dumpname) finder = cls.memory_handler.get_heap_finder() heap_walker = finder.list_heap_walkers()[0] heap_addr = heap_walker.get_heap_address() cls.context = context.get_context_for_address(cls.memory_handler, heap_addr) cls.target = cls.context.memory_handler.get_target_platform() cls.dsa = dsa.FieldReverser(cls.context.memory_handler) cls.pta = pointertypes.PointerFieldReverser(cls.context.memory_handler) return
def test_reversers(self): # order of resolution should be # FieldReverser # DoubleLinkedListReverser # PointerFieldReverser # TypeReverser struct_d = self._context.get_record_for_address(self.offset) sig_1 = struct_d.get_signature_text() # print '1.', self._v(struct_d) # try to find some logical constructs. doublelink = reversers.DoubleLinkedListReverser(self.memory_handler) doublelink.reverse() sig_2 = struct_d.get_signature_text() # print '2.', self._v(struct_d) # no double linked list in here self.assertEqual('', sig_2) # decode bytes contents to find basic types. fr = dsa.FieldReverser(self.memory_handler) fr.reverse() sig_3 = struct_d.get_signature_text() # print '3.', self._v(struct_d) #self.assertEqual(sig_3, 'P8P8P8z24i8z40i8z8i8z40i8z8i8z40i8z8i8z40i8z8i8z40i8z8i8z40i8z8i8z40i8z8i8z40i8z8i8z40i8z8i8z40i8z8i8z8i8z8i8z8i8z8i8z8i8z8i8z8i8z8i8z8P8P8P8P8P8P8P8P8P8P8P8P8u40P8P8P8P8P8P8P8P8P8P8i8P8T14u2z16P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z8P8z16P8') # identify pointer relation between allocators pfr = pointertypes.PointerFieldReverser(self.memory_handler) pfr.reverse() sig_4 = struct_d.get_signature_text() # print '4.', self._v(struct_d) #logging.getLogger("reversers").setLevel(logging.DEBUG) # aggregate field of same type in an array ## FIXME very very long. #afr = reversers.ArrayFieldsReverser(self._context) #afr.reverse() #sig_5 = struct_d.get_signature_text() # print '5.', self._v(struct_d) tr = signature.TypeReverser(self.memory_handler) tr.reverse() sig_6 = struct_d.get_signature_text() # print '6.', self._v(struct_d) # print "tr._similarities", tr._similarities for a, b in tr._similarities: # print self._context.get_record_for_address(a).to_string() # print self._context.get_record_for_address(b).to_string() #import code #code.interact(local=locals()) pass
def makeReversedTypes(heap_context, sizeCache): ''' Compare signatures for each size groups. Makes a chains out of similar allocators. Changes the structure names for a single typename when possible. Changes the ctypes types of each pointer field.''' log.info( '[+] Build groups of similar instances, create a reversed type for each group.' ) # FIXME - DELETE - already in TypeReverser._rename_similar_records for chains in buildStructureGroup(heap_context, sizeCache): fixType(heap_context, chains) # TODO - move in TypeReverser log.info( '[+] For each instances, fix pointers fields to newly created types.') decoder = dsa.FieldReverser(heap_context.memory_handler) for s in heap_context.listStructures(): s.reset() ## s.decodeFields() decoder.reverse_record(heap_context, s) pointer_fields = [f for f in s.get_fields() if f.is_pointer()] for f in pointer_fields: addr = f.get_value_for_field(s) if addr in heap_context.heap: try: ctypes_type = heap_context.get_record_at_address( addr).get_ctype() # we have escapees, withouth a typed type... saved them from # exception except TypeError as e: ctypes_type = fixInstanceType( heap_context, heap_context.get_record_at_address(addr), getname()) #f.setCtype(ctypes.POINTER(ctypes_type)) f.set_pointee_ctype(ctypes.POINTER(ctypes_type)) f.set_comment('pointer fixed') # TODO - move in TypeReverser log.info('[+] For new reversed type, fix their definitive fields.') for revStructType in heap_context.list_reversed_types(): revStructType.makeFields(heap_context) # TODO - move in TypeReverser # poitners not in the heapv # for s in context.listStructures(): # for f in s.getPointerFields(): # if ctypes.is_void_pointer_type(f.getCtype()): # print s,'has a c_void_p field', f._getValue(0), # print context.getStructureForOffset( f._getValue(0) ) return heap_context
def setUp(self): dumpname = 'test/src/test-ctypes6.64.dump' self.memory_handler = dump_loader.load(dumpname) process_context = self.memory_handler.get_reverse_context() process_context.create_record_cache_folder() # load TU values self._load_offsets_values(self.memory_handler.get_name()) ## self.dllr = reversers.DoubleLinkedListReverser(self.memory_handler) log.debug('Reversing Fields') fr = dsa.FieldReverser(self.memory_handler) fr.reverse()
def printStructureGroups(context, chains, originAddr=None): chains.sort() decoder = dsa.FieldReverser(context.memory_handler) for chain in chains: log.debug('\t[-] chain len:%d' % len(chain)) if originAddr is not None: if originAddr not in chain: continue # ignore chain if originAddr is not in it for addr in map(long, chain): record = context.get_record_for_address(addr) ##record.decodeFields() # can be long decoder.analyze_fields(record) print context.get_record_for_address(addr).to_string() print '#', '-' * 78
def setUpClass(cls): cls.memory_handler = folder.load(zeus_856_svchost_exe.dumpname) cls._context = context.get_context_for_address(cls.memory_handler, 0x90000) cls.process_context = cls.memory_handler.get_reverse_context() fr = dsa.FieldReverser(cls.memory_handler) fr.reverse() tfc = dsa.TextFieldCorrection(cls.memory_handler) tfc.reverse() doublelink = reversers.DoubleLinkedListReverser(cls.memory_handler) doublelink.reverse() doublelink.rename_all_lists() pfr = pointertypes.PointerFieldReverser(cls.memory_handler) pfr.reverse()
def _init_signatures(self): # get text signature for Counter to parse # need to force resolve of allocators self._signatures = [] decoder = dsa.FieldReverser(self._context.memory_handler) for addr in map(long, self._structures_addresses): # decode the fields record = self._context.get_record_for_address(addr) ## record.decodeFields() # can be long decoder.analyze_fields(record) # get the signature for the record self._signatures.append( (addr, self._context.get_record_for_address( addr).get_signature_text())) return
def test_utf16_1(self): # the issue is that if starts a utf16 fields in the middle of a word. # and that the gap before is not separated in a gap field self.assertEqual(self.real, self.test1.bytes) _dsa = dsa.FieldReverser(self.memory_handler) _dsa.reverse_record(self.context, self.test1) fields = self.test1.get_fields() fields.sort() nextoffset = 0 # test is sorted for i, f in enumerate(self.test1.get_fields()): self.assertGreaterEqual(f.offset, nextoffset) nextoffset = f.offset + len(f)
def test_doublelink(self): # reverse first with dsa _record = self._context.get_record_for_address(0xccd00) _record.reset() revdsa = dsa.FieldReverser(self.memory_handler) revdsa.reverse() rev = reversers.DoubleLinkedListReverser(self.memory_handler) # interesting records # SIG:T4i4P4P4i4z12 # struct_bbf78 struct_a6518 struct_cca28 # list goes from 0xccd28, 0xccd00 to 0x98268 #_record = self._context.get_record_for_address(0xccd28) _record = self._context.get_record_for_address(0xccd00) print(_record.to_string()) #_record.set_reverse_level(9) ## rev.reverse_record(self._context, _record) print(_record.to_string()) n1 = self._context.get_record_for_address(0x000ccae8) print(n1.to_string()) tail = self._context.get_record_for_address(0x98268) print(tail.to_string()) expected = [ 0xccd28, 0xccd00, 0xccae8, 0xcca50, 0xcca28, 0xcc428, 0xc6878, 0xdcbc8, 0xdcb40, 0xcd300, 0xbbf78, 0xbefd8, 0xbecd8, 0xbc560, 0xbbee0, 0xbbda8, 0xbbb38, 0xbbae0, 0xa6518, 0xb5d00, 0xb5cd8, 0xb5cb0, 0xb5b70, 0xb1aa8, 0xa20b8, 0x9e2f8, 0xa1920, 0xa1838, 0x98268 ] size_records = len(tail) # offset = 8 offset = 8 rev.rename_all_lists() self.assertEqual(rev.lists[size_records][offset][0], expected) # rename all lists for size, offset_lists in rev.lists.items(): for offset, multiple_lists in offset_lists.items(): for members_list in multiple_lists: nb = len(members_list) rt = rev.rename_record_type(members_list, offset) log.debug('%d members for : %s', nb, rt.to_string()) pass
def setUpClass(cls): #self.context3 = context.get_context('test/src/test-ctypes3.dump') cls.dumpname = 'test/src/test-ctypes6.32.dump' config.remove_cache_folder(cls.dumpname) cls.memory_handler = dump_loader.load(cls.dumpname) cls._target = cls.memory_handler.get_target_platform() finder = cls.memory_handler.get_heap_finder() heap_walker = finder.list_heap_walkers()[0] heap_addr = heap_walker.get_heap_address() cls._load_offsets_values(cls.memory_handler.get_name()) cls.context6 = context.get_context_for_address(cls.memory_handler, heap_addr) cls.dsa = dsa.FieldReverser(cls.context6.memory_handler) cls.st = cls.context6.listStructures()[0]
def test_utf16_1(self): # struct_a4188 SIG:z4T108 # class struct_a4028(ctypes.Structure): # rlevel:50 SIG:T84z4 size:88 # struct_943f8 SIG:T20i4T20z4 # _record = self.heap_context.get_record_for_address(0xb2e38) _record = self.heap_context.get_record_for_address(0x943f8) _record.reset() _dsa = dsa.FieldReverser(self.memory_handler) _dsa.reverse_record(self.heap_context, _record) b = 'D\x00c\x00o\x00m\x00L\x00a\x00u\x00n\x00c\x00h\x00\x00\x00T\x00e\x00r\x00m\x00S\x00e\x00r\x00v\x00i\x00c\x00e\x00\x00\x00\x00\x00' rev = dsa.TextFieldCorrection(self.memory_handler) rev.reverse_record(self.heap_context, _record) fields = _record.get_fields() self.assertEqual(len(fields), 3) self.assertTrue(fields[0].is_string()) self.assertTrue(fields[1].is_string()) self.assertTrue(fields[2].is_zeroes()) print _record.to_string()
def reverse_heap(memory_handler, heap_addr): """ Reverse a specific heap. :param memory_handler: :param heap_addr: :return: """ from haystack.reverse import context log.info('[+] Loading the memory dump for HEAP 0x%x', heap_addr) heap_context = context.get_context_for_address(memory_handler, heap_addr) try: # decode bytes contents to find basic types. log.info('Reversing Fields') fr = dsa.FieldReverser(memory_handler) fr.reverse_context(heap_context) log.info('Fixing Text Fields') tfc = dsa.TextFieldCorrection(memory_handler) tfc.reverse_context(heap_context) # try to find some logical constructs. log.info('Reversing DoubleLinkedListReverser') # why is this a reverse_context ? doublelink = reversers.DoubleLinkedListReverser(memory_handler) doublelink.reverse_context(heap_context) doublelink.rename_all_lists() # save to file save_headers(heap_context) # etc except KeyboardInterrupt as e: # except IOError,e: log.warning(e) log.info('[+] %d structs extracted' % (heap_context.get_record_count())) raise e pass pass return heap_context
def test_reverse_heap(self): #ctx = reversers.reverse_heap(self.memory_handler, zeus_856_svchost_exe.known_heaps[0][0]) struct_d = self._context.get_record_for_address(self.offset) struct_d.reset() sig_1 = struct_d.get_signature_text() # print '1.', self._v(struct_d) #self.assertEqual(sig_1, 'P4P4P4P4P4P4P4i4z4i4i4z8P4P4z8P4i4u16z4i4z4P4P4P4P4z64P4P4P4P4P4P4P4i4z4i4i4z8P4P4z8P4i4u16z4i4z4P4P4P4P4z64P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z8272P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z180u4z176') # decode bytes contents to find basic types. fr = dsa.FieldReverser(self.memory_handler) fr.reverse() sig_2 = struct_d.get_signature_text() # print '2.', self._v(struct_d) # no double linked list in here #self.assertEqual(sig_2, 'P4P4P4P4P4P4P4i4z4i4i4z8P4P4z8P4i4u16z4i4z4P4P4P4P4z64P4P4P4P4P4P4P4i4z4i4i4z8P4P4z8P4i4u16z4i4z4P4P4P4P4z64P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z8272P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z180u4z176') # print struct_d.to_string() #import code #code.interact(local=locals()) # try to find some logical constructs. doublelink = reversers.DoubleLinkedListReverser(self.memory_handler) doublelink.reverse() #self.assertEqual(doublelink.found, 12) sig_3 = struct_d.get_signature_text() # print '3.', self._v(struct_d) #self.assertEqual(sig_3, 'P4P4P4P4P4P4P4i4z4i4i4z8P4P4z8P4i4u16z4i4z4P4P4P4P4z64P4P4P4P4P4P4P4i4z4i4i4z8P4P4z8P4i4u16z4i4z4P4P4P4P4z64P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z8272P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z176P4u4z180u4z176') # print struct_d.to_string() #import code #code.interact(local=locals()) # identify pointer relation between allocators pfr = pointertypes.PointerFieldReverser(self.memory_handler) pfr.reverse() sig_4 = struct_d.get_signature_text() # print '4.', self._v(struct_d) # print struct_d.to_string() #import code #code.interact(local=locals()) # aggregate field of same type in an array #afr = reversers.ArrayFieldsReverser(self._context) #afr.reverse() #sig_5 = struct_d.get_signature_text() # print '5.', self._v(struct_d) # print struct_d.to_string() #import code #code.interact(local=locals()) tr = signature.TypeReverser(self.memory_handler) tr.reverse() sig_6 = struct_d.get_signature_text() # print '6.', self._v(struct_d) # print "tr._similarities", tr._similarities for a, b in tr._similarities: # print self._context.get_record_for_address(a).to_string() # print self._context.get_record_for_address(b).to_string() #import code #code.interact(local=locals()) pass