コード例 #1
0
ファイル: test_dsa.py プロジェクト: yep0/python-haystack
 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
コード例 #2
0
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))
コード例 #3
0
ファイル: api.py プロジェクト: shekkbuilder/python-haystack
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
コード例 #4
0
 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)
コード例 #5
0
ファイル: test_dsa.py プロジェクト: yep0/python-haystack
    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()
コード例 #6
0
 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
コード例 #7
0
    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
コード例 #8
0
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
コード例 #9
0
    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()
コード例 #10
0
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
コード例 #11
0
 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()
コード例 #12
0
 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
コード例 #13
0
ファイル: test_dsa.py プロジェクト: yep0/python-haystack
    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)
コード例 #14
0
    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
コード例 #15
0
    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]
コード例 #16
0
ファイル: test_dsa.py プロジェクト: yep0/python-haystack
    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()
コード例 #17
0
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
コード例 #18
0
    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