示例#1
0
    def test_complex_text(self):
        # struct a - basic types
        offset = self.offsets['struct_d'][0]
        m = self.memory_handler.get_mapping_for_address(offset)
        # d = m.read_struct(offset, self.ctypes5_gen32.struct_d)
        results, validated = api.load_record(self.memory_handler,
                                             self.ctypes5_gen32.struct_d,
                                             offset)

        self.assertTrue(results)
        parser = text.RecursiveTextOutputter(self.memory_handler)
        out = parser.parse(results)
        # should not fail
        x = eval(out)

        self.assertEqual(len(x.keys()), 15)  # 14 + padding
        # its an byte string, that is a hex value.
        self.assertEqual(self.values['struct_d.a'], hex(x['a']).encode())
        self.assertEqual(len(x['b'].keys()), 9)
        self.assertEqual(len(x['b2'].keys()), 8)
        self.assertEqual(int(self.values['struct_d.b.e']), x['b']['e'])
        self.assertEqual(int(self.values['struct_d.b2.e']), x['b2']['e'])

        for i in range(9):
            self.assertEqual(int(self.values['struct_d.c[%d].a' % (i)]),
                             x['c'][i]['a'])
            self.assertEqual(int(self.values['struct_d.f[%d]' % (i)]),
                             x['f'][i])
        self.assertEqual(int(self.values['struct_d.e']), x['e'])
        self.assertEqual(self.values['struct_d.i'], x['i'])
        return
示例#2
0
    def toPyObject(self):
        d = OpenSSHStruct.toPyObject(self)

        #log.info('self.send_context.evp.app_data: 0x%lx'%(self.send_context.evp.app_data))

        # populate AppData.
        try:
            if d.receive_context.evp.cipher.nid == 0:
                d.receive_context.evp.app_data = self.receive_context.getEvpAppData(
                ).toPyObject()
                d.send_context.evp.app_data = self.send_context.getEvpAppData(
                ).toPyObject()

            #log.debug('self.send_context.evp.app_data: %s'%(self.send_context.getEvpAppData()))
            #log.debug('d.send_context.evp.app_data: %s'%(d.send_context.evp.app_data))
            ## TODO find a better way to pass a void_p for that cipher data
            #d.receive_context.evp.cipher_data = self.receive_context.getEvpAppData().toPyObject()
            #d.send_context.evp.cipher_data = self.send_context.getEvpAppData().toPyObject()
            if (type(d.send_context.evp.cipher_data) == tuple
                    and d.send_context.evp.cipher_data[0] is not None
                    and d.send_context.evp.cipher_data[1] is not None):
                from haystack.outputters import text
                parser = text.RecursiveTextOutputter(mappings)
                log.debug("cipher_data has %s" %
                          (parser.parse(d.send_context.evp.cipher_data)))

        except AttributeError as e:
            log.error('Error while populating receive/send context')

        return d
示例#3
0
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
示例#4
0
def EVP_CIPHER_CTX_loadMembers(self, mappings, maxDepth):
    if not super(EVP_CIPHER_CTX, self).loadMembers(mappings, maxDepth):
        return False
    log.debug('trying to load cipher_data Structs.')
    '''
    if bool(cipher) and bool(self.cipher.nid) and mappings.is_valid_address(cipher_data):
        memcopy( self.cipher_data, cipher_data_addr, self.cipher.ctx_size)
        # cast possible on cipher.nid -> cipherType
    '''
    cipher = mappings.getRef(evp_cipher_st, get_pointee_address(self.cipher))
    if cipher.nid == 0:  # NID_undef, not openssl doing
        log.info(
            'The cipher is home made - the cipher context data should be application dependant (app_data)'
        )
        return True

    struct = getCipherDataType(cipher.nid)
    log.debug('cipher type is %s - loading %s' %
              (getCipherName(cipher.nid), struct))
    if (struct is None):
        log.warning("Unsupported cipher %s" % (cipher.nid))
        return True

    # c_void_p is a basic type.
    attr_obj_address = self.cipher_data
    memoryMap = mappings.is_valid_address_value(attr_obj_address, struct)
    log.debug("cipher_data CAST into : %s " % (struct))
    if not memoryMap:
        log.warning(
            'in CTX On second toughts, cipher_data seems to be at an invalid address. That should not happen (often).'
        )
        log.warning('%s addr:0x%lx size:0x%lx addr+size:0x%lx ' %
                    (mappings.is_valid_address_value(attr_obj_address),
                     attr_obj_address, ctypes.sizeof(struct),
                     attr_obj_address + ctypes.sizeof(struct)))
        return True
    #ok
    st = memoryMap.readStruct(attr_obj_address, struct)
    mappings.keepRef(st, struct, attr_obj_address)
    self.cipher_data = ctypes.c_void_p(ctypes.addressof(st))
    ###print 'self.cipher_data in loadmembers',self.cipher_data
    # check debug
    attr = getattr(self, 'cipher_data')
    log.debug('Copied 0x%lx into %s (0x%lx)' %
              (ctypes.addressof(st), 'cipher_data', attr))
    log.debug(
        'LOADED cipher_data as %s from 0x%lx (%s) into 0x%lx' %
        (struct, attr_obj_address,
         mappings.is_valid_address_value(attr_obj_address, struct), attr))
    from haystack.outputters import text
    parser = text.RecursiveTextOutputter(mappings)
    log.debug('\t\t---------\n%s\t\t---------' % (parser.parse(st)))
    return True
示例#5
0
    def loadMembers(self, mappings, maxDepth):
        if not ctypes.Structure.loadMembers(self, mappings, maxDepth):
            return False
        #log.debug('evp        app_data        attr_obj_address=0x%lx'%(self.evp.app_data) )
        #log.debug('evp        cipher_data attr_obj_address=0x%lx'%(self.evp.cipher_data) )    ##none
        cipher = mappings.getRef(Cipher, get_pointee_address(self.cipher))
        ciphername = mappings.getRef(ctypes.CString,
                                     get_pointee_address(cipher.name.ptr))
        # cast evp.app_data into a valid struct
        if ciphername in self.cipherContexts:
            # evp.cipher.nid should be 0
            struct = self.cipherContexts[ciphername]
            if (struct is None):
                log.warning("Unsupported cipher %s" % (ciphername))
                return True
            attr_obj_address = get_pointee_address(self.evp.app_data)
            memoryMap = mappings.is_valid_address_value(
                attr_obj_address, struct)
            log.debug("CipherContext CAST app_data into : %s " % (struct))
            if not memoryMap:
                log.warning(
                    'On second toughts, app_data seems to be at an invalid address. That should not happen (often).'
                )
                log.warning('%s addr:0x%lx size:0x%lx addr+size:0x%lx ' %
                            (mappings.is_valid_address_value(attr_obj_address),
                             attr_obj_address, ctypes.sizeof(struct),
                             attr_obj_address + ctypes.sizeof(struct)))
                return False  # DEBUG kill it
            # read the void * and keep a ref
            st = memoryMap.readStruct(attr_obj_address, struct)
            mappings.keepRef(st, struct, attr_obj_address)
            # yeah... no. "self.evp.app_data = xx" means SEGFAULT.
            address_evp_app_data = ctypes.addressof(st)

            log.debug('Copied 0x%lx into app_data (0x%lx)' %
                      (attr_obj_address, address_evp_app_data))
            log.debug('LOADED app_data as %s from 0x%lx (%s) into 0x%lx' %
                      (struct, attr_obj_address,
                       mappings.is_valid_address_value(
                           attr_obj_address, struct), address_evp_app_data))
            from haystack.outputters import text
            parser = text.RecursiveTextOutputter(mappings)
            log.debug('\t\t---------\n%s\t\t---------' % (parser.parse(st)))
        else:
            log.debug(
                "Unknown cipher %s, can't load a data struct for the EVP_CIPHER_CTX->app_data"
                % (ciphername))
        return True
示例#6
0
def output_to_string(memory_handler, results):
    """
    Transform ctypes results in a string format
    :param memory_handler: IMemoryHandler
    :param results: results from the search_record
    :return:
    """
    if not isinstance(results, list):
        raise TypeError('Feed me a list of results')
    parser = text.RecursiveTextOutputter(memory_handler)
    ret = '['
    for ss, addr in results:
        ret += "# --------------- 0x%lx \n%s" % (addr, parser.parse(ss))
        pass
    ret += ']'
    return ret
示例#7
0
 def getEvpAppData(self, mappings):
     cipher = self.getCipher(mappings)
     ciphername = cipher.getName(mappings)
     if ciphername in self.cipherContexts:
         struct = self.cipherContexts[ciphername]
         from haystack.outputters import text
         parser = text.RecursiveTextOutputter(mappings)
         if (struct is None):
             log.warning("Unsupported cipher %s" % (ciphername))
             log.warning("%s" % (parser.parse(cipher)))
             return None
         log.debug('CAST evp.app_data Into %s' % (struct))
         attr_obj_address = get_pointee_address(self.evp.app_data)
         st = mappings.getRef(struct, attr_obj_address)
         #st = struct.from_address(attr)
         log.debug('app_data value is : 0x%lx' % (attr_obj_address))
         log.debug(parser.parse(st))
         return st
     return None
def main(argv):
    parser = argparse.ArgumentParser(prog='haystack-find-heap',
                                     description="Find heaps in a dumpfile")
    parser.add_argument('--host',
                        action='store',
                        default='winxp',
                        help='winxp,win7')
    parser.add_argument('dumpname',
                        type=argparse_utils.readable,
                        help='process memory dump name')
    parser.add_argument('address',
                        nargs='?',
                        type=argparse_utils.int16,
                        default=None,
                        help='Load Heap from address (hex)')

    opts = parser.parse_args(argv)

    #if 'libc' == opts.host:
    #    my_finder = LibcHeapFinder()
    #el
    if 'winxp' == opts.host:
        my_finder = WinXPHeapFinder()
    elif 'win7' == opts.host:
        my_finder = Win7HeapFinder()
    else:
        raise ValueError('not such heap finder for %s' % opts.host)

    memdumpname = opts.dumpname
    if opts.address is None:
        if my_finder.search_heap(memdumpname) is not None:
            return
    else:
        address = opts.address
        # just return the heap
        ret = my_finder.search_heap_direct(memdumpname, address)
        out = text.RecursiveTextOutputter(my_finder.memory_handler)
        #out = python.PythonOutputter(my_finder.memory_handler)
        print out.parse(ret[0], depth=4)
        print 'Valid=', ret[1]
        return
 def setUp(self):
     self._heap_finder = self._memory_handler.get_heap_finder()
     self.parser = text.RecursiveTextOutputter(self._memory_handler)
     return
示例#10
0
 def p(self, ss):
     # FIXME DEBUG
     from haystack.outputters import text
     parser = text.RecursiveTextOutputter(self._memory_handler)
     return parser.parse(ss)