Пример #1
0
async def run(args):
    print(__banner__)
    if args.verbose == 0:
        logging.basicConfig(level=logging.INFO)
        jdlogger.setLevel(logging.INFO)
        msldaplogger.setLevel(logging.WARNING)
        smblogger.setLevel(logging.CRITICAL)

    elif args.verbose == 1:
        logging.basicConfig(level=logging.DEBUG)
        jdlogger.setLevel(logging.DEBUG)
        msldaplogger.setLevel(logging.INFO)
        smblogger.setLevel(logging.INFO)

    elif args.verbose > 1:
        logging.basicConfig(level=1)
        msldaplogger.setLevel(logging.DEBUG)
        jdlogger.setLevel(1)
        smblogger.setLevel(1)

    if not args.sql:
        print(
            'SQL connection identification is missing! You need to provide the --sql parameter'
        )
        sys.exit()

    db_conn = args.sql
    if args.sql.lower().startswith('sqlite'):
        os.environ['JACKDAW_SQLITE'] = '1'

    if args.command == 'enum':
        smb_mgr = construct_smbdef(args)
        ldap_mgr = construct_ldapdef(args)

        mgr = LDAPEnumeratorManager(db_conn,
                                    ldap_mgr,
                                    agent_cnt=args.ldap_workers)
        adifo_id = await mgr.run()
        jdlogger.info('ADInfo entry successfully created with ID %s' %
                      adifo_id)

        mgr = SMBGathererManager(smb_mgr,
                                 worker_cnt=args.smb_workers,
                                 queue_size=args.smb_queue_size)
        mgr.gathering_type = ['all']
        mgr.db_conn = db_conn
        mgr.target_ad = adifo_id
        await mgr.run()

        if args.smb_share_enum is True:
            settings_base = SMBShareGathererSettings(adifo_id, smb_mgr, None,
                                                     None, None)
            settings_base.dir_depth = args.smb_folder_depth
            mgr = ShareGathererManager(settings_base,
                                       db_conn=db_conn,
                                       worker_cnt=args.smb_workers)
            mgr.run()

    elif args.command == 'dbinit':
        create_db(db_conn)

    elif args.command == 'adinfo':
        session = get_session(db_conn)
        from jackdaw.dbmodel.adinfo import JackDawADInfo
        from jackdaw.utils.table import print_table

        rows = [['Ad ID', 'domain name', 'scantime']]
        for did, distinguishedName, creation in session.query(
                JackDawADInfo).with_entities(JackDawADInfo.id,
                                             JackDawADInfo.distinguishedName,
                                             JackDawADInfo.fetched_at).all():
            name = distinguishedName.replace('DC=', '')
            name = name.replace(',', '.')
            rows.append([str(did), name, creation.isoformat()])
        print_table(rows)

    elif args.command == 'ldap':
        ldap_mgr = construct_ldapdef(args)
        ldap_conn = ldap_mgr.get_client()

        mgr = LDAPEnumeratorManager(db_conn,
                                    ldap_mgr,
                                    agent_cnt=args.ldap_workers,
                                    queue_size=args.ldap_queue_size,
                                    ad_id=args.ad_id)
        adifo_id = await mgr.run()
        jdlogger.info('ADInfo entry successfully created with ID %s' %
                      adifo_id)

    elif args.command in ['shares', 'sessions', 'localgroups', 'smball']:
        if args.command == 'smball':
            args.command = 'all'
        smb_mgr = construct_smbdef(args)
        mgr = SMBGathererManager(smb_mgr,
                                 worker_cnt=args.smb_workers,
                                 queue_size=args.smb_queue_size)
        mgr.gathering_type = [args.command]
        mgr.db_conn = db_conn
        mgr.lookup_ad = args.lookup_ad

        if args.ldap_url:
            ldap_mgr = construct_ldapdef(args)
            ldap_conn = ldap_mgr.get_client()
            mgr.ldap_conn = ldap_conn

        if args.ad_id:
            mgr.target_ad = args.ad_id

        if args.target_file:
            mgr.targets_file = args.target_file

        await mgr.run()

    elif args.command == 'files':
        if args.src == 'domain':
            if not args.ad_id:
                raise Exception('ad-id parameter is mandatory in ldap mode')

            mgr = SMBConnectionURL(args.smb_url)
            settings_base = SMBShareGathererSettings(args.ad_id, mgr, None,
                                                     None, None)
            settings_base.dir_depth = args.smb_folder_depth
            settings_base.dir_with_sd = args.with_sid
            settings_base.file_with_sd = args.with_sid

            mgr = ShareGathererManager(settings_base,
                                       db_conn=db_conn,
                                       worker_cnt=args.smb_workers)
            mgr.run()

    #	elif args.src == 'file':
    #		if not args.target_file:
    #			raise Exception('target-file parameter is mandatory in file mode')
    #
    #		args.target_file
    #		args.lookup_ad
    #		args.with_sid
    #		args.smb_workers
    #
    #	elif args.src == 'ldap':
    #		if not args.ldap_url:
    #			raise Exception('ldap-url parameter is mandatory in ldap mode')
    #		args.lookup_ad
    #		args.with_sid
    #		args.smb_workers
    #
    #
    #
    #	elif args.src == 'cmd':

    elif args.command == 'creds':
        creds = JackDawCredentials(args.db_conn, args.domain_id)
        creds.add_credentials_impacket(args.impacket_file)

    elif args.command == 'passwords':
        creds = JackDawCredentials(args.db_conn)
        creds.add_cracked_passwords(args.potfile, args.disable_usercheck,
                                    args.disable_passwordcheck)

    elif args.command == 'uncracked':
        creds = JackDawCredentials(args.db_conn, args.domain_id)
        creds.get_uncracked_hashes(args.hash_type, args.history)

    elif args.command == 'cracked':
        creds = JackDawCredentials(args.db_conn, args.domain_id)
        creds.get_cracked_info()

    elif args.command == 'nest':
        from jackdaw.nest.wrapper import NestServer

        debug = bool(args.verbose)

        server = NestServer(args.sql,
                            bind_ip=args.ip,
                            bind_port=args.port,
                            debug=debug)
        server.run()
Пример #2
0
                        name = f.name
                        x = f.name.rsplit('.', 1)
                        if len(x) > 1:
                            name = x[0]
                            ext = x[1]
                        nf.name = name
                        nf.ext = ext
                        self.db_session.add(nf)
                        self.db_session.commit()
                        self.db_session.refresh(nf)
                        self.store_sd(f.sid, 'file', nf.id)

                #elif result.type == 'file':

            #if result is None and error is None:
            #	logger.debug('Finished: %s' % target.ip)
            #	if self.use_progress_bar is True:
            #		self.prg_hosts.update()


if __name__ == '__main__':
    db_conn = 'sqlite:///a.db'
    create_db(db_conn)
    smb_mgr = SMBConnectionURL(
        'smb+ntlm-password://TEST\\victim:[email protected]')

    ad_id = 0
    settings = SMBShareGathererSettings(ad_id, smb_mgr, None, None, None)
    ep = ShareGathererManager(settings, db_conn=db_conn, worker_cnt=30)
    ep.run()
    print('done!')
Пример #3
0
async def run_auto(ldap_worker_cnt=None,
                   smb_worker_cnt=500,
                   dns=None,
                   work_dir='./workdir',
                   db_conn=None,
                   show_progress=True,
                   no_work_dir=False):
    try:
        if platform.system() != 'Windows':
            raise Exception('auto mode only works on windows!')

        smblogger.setLevel(100)
        from winacl.functions.highlevel import get_logon_info
        logon = get_logon_info()

        jdlogger.debug(str(logon))
        if logon['domain'] == '' or logon['logonserver'] == '':
            if logon['domain'] == '':
                logon['domain'] = os.environ['USERDOMAIN']
            if logon['logonserver'] == '':
                logon['logonserver'] = os.environ['LOGONSERVER'].replace(
                    '\\', '')

            if logon['domain'] == '' or logon['logonserver'] == '':
                return False, Exception(
                    "Failed to find user's settings! Is this a domain user?")

        try:
            #checking connection can be made over ldap...
            reader, writer = await asyncio.wait_for(
                asyncio.open_connection(logon['logonserver'], 389), 2)
            writer.close()
        except:
            return False, Exception(
                "Failed to connect to server %s over LDAP" %
                (logon['logonserver']))

        if db_conn is None:
            db_loc = '%s_%s.db' % (logon['domain'], datetime.datetime.utcnow().
                                   strftime("%Y%m%d_%H%M%S"))
            db_conn = 'sqlite:///%s' % db_loc
            create_db(db_conn)
        ldap_url = 'ldap+sspi-ntlm://%s\\%s:jackdaw@%s' % (
            logon['domain'], logon['username'], logon['logonserver'])
        smb_url = 'smb2+sspi-kerberos://%s\\%s:jackdaw@%s' % (
            logon['domain'], logon['username'], logon['logonserver'])

        jdlogger.debug('LDAP connection: %s' % ldap_url)
        jdlogger.debug('SMB  connection: %s' % smb_url)
        if dns is None:
            from jackdaw.gatherer.rdns.dnstest import get_correct_dns_win
            srv_domain = '%s.%s' % (logon['logonserver'],
                                    logon['dnsdomainname'])
            dns = await get_correct_dns_win(srv_domain)
            if dns is None:
                jdlogger.debug('Failed to identify DNS server!')
            else:
                dns = str(dns)
                jdlogger.debug('DNS server selected: %s' % str(dns))

        kerb_url = 'auto'
        with multiprocessing.Pool() as mp_pool:
            gatherer = Gatherer(db_conn,
                                work_dir,
                                ldap_url,
                                smb_url,
                                kerb_url=kerb_url,
                                ldap_worker_cnt=ldap_worker_cnt,
                                smb_worker_cnt=smb_worker_cnt,
                                mp_pool=mp_pool,
                                smb_gather_types=['all'],
                                progress_queue=None,
                                show_progress=show_progress,
                                calc_edges=True,
                                dns=dns,
                                no_work_dir=no_work_dir)
            res, err = await gatherer.run()
            if err is not None:
                raise err
            return True, None
    except Exception as e:
        return False, e
Пример #4
0
async def run(args):
    try:
        if args.silent is True:
            print(__banner__)
        if args.verbose == 0:
            logging.basicConfig(level=logging.INFO)
            jdlogger.setLevel(logging.INFO)
            msldaplogger.setLevel(logging.CRITICAL)
            smblogger.setLevel(100)

        elif args.verbose == 1:
            logging.basicConfig(level=logging.DEBUG)
            jdlogger.setLevel(logging.DEBUG)
            msldaplogger.setLevel(logging.WARNING)
            smblogger.setLevel(logging.CRITICAL)

        elif args.verbose > 1:
            logging.basicConfig(level=1)
            msldaplogger.setLevel(logging.DEBUG)
            jdlogger.setLevel(1)
            smblogger.setLevel(1)

        if not args.sql and args.command != 'auto':
            print(
                'SQL connection identification is missing! You need to provide the --sql parameter'
            )
            sys.exit()

        work_dir = './workdir'
        ldap_url = None
        smb_url = None

        if hasattr(args, 'ldap_url'):
            ldap_url = args.ldap_url
        if hasattr(args, 'smb_url'):
            smb_url = args.smb_url

        db_conn = args.sql
        if db_conn is not None:
            os.environ['JACKDAW_SQLITE'] = '0'
            if args.sql.lower().startswith('sqlite'):
                os.environ['JACKDAW_SQLITE'] = '1'
        else:
            os.environ['JACKDAW_SQLITE'] = '1'

        if args.command == 'enum':
            with multiprocessing.Pool() as mp_pool:
                gatherer = Gatherer(db_conn,
                                    work_dir,
                                    ldap_url,
                                    smb_url,
                                    kerb_url=args.kerberoast,
                                    ldap_worker_cnt=args.ldap_workers,
                                    smb_worker_cnt=args.smb_workers,
                                    mp_pool=mp_pool,
                                    smb_gather_types=['all'],
                                    progress_queue=None,
                                    show_progress=args.silent,
                                    calc_edges=True,
                                    ad_id=None,
                                    dns=args.dns,
                                    no_work_dir=args.no_work_dir)
                res, err = await gatherer.run()
                if err is not None:
                    raise err

        elif args.command == 'auto':
            _, err = await run_auto(ldap_worker_cnt=args.ldap_workers,
                                    smb_worker_cnt=args.smb_workers,
                                    dns=args.dns,
                                    work_dir=work_dir,
                                    show_progress=args.silent,
                                    no_work_dir=args.no_work_dir)
            if err is not None:
                print(err)

        elif args.command == 'dbinit':
            create_db(db_conn)

        elif args.command == 'adinfo':
            session = get_session(db_conn)
            from jackdaw.dbmodel.adinfo import ADInfo
            from jackdaw.utils.table import print_table

            rows = [['Ad ID', 'domain name', 'scantime']]
            for did, distinguishedName, creation in session.query(
                    ADInfo).with_entities(ADInfo.id, ADInfo.distinguishedName,
                                          ADInfo.fetched_at).all():
                name = distinguishedName.replace('DC=', '')
                name = name.replace(',', '.')
                rows.append([str(did), name, creation.isoformat()])
            print_table(rows)

        elif args.command == 'ldap':
            with multiprocessing.Pool() as mp_pool:
                gatherer = Gatherer(db_conn,
                                    work_dir,
                                    ldap_url,
                                    smb_url,
                                    ldap_worker_cnt=args.ldap_workers,
                                    smb_worker_cnt=None,
                                    mp_pool=mp_pool,
                                    smb_gather_types=['all'],
                                    progress_queue=None,
                                    show_progress=args.silent,
                                    calc_edges=args.calculate_edges,
                                    ad_id=args.ad_id,
                                    no_work_dir=args.no_work_dir)
                await gatherer.run()

        elif args.command == 'kerberoast':
            gatherer = Gatherer(db_conn,
                                work_dir,
                                None,
                                None,
                                kerb_url=args.kerberos_url,
                                ldap_worker_cnt=None,
                                smb_worker_cnt=None,
                                mp_pool=None,
                                smb_gather_types=[],
                                progress_queue=None,
                                show_progress=False,
                                calc_edges=False,
                                ad_id=args.ad_id)
            await gatherer.run()
            print('Kerberoast Finished!')

        elif args.command in ['shares', 'sessions', 'localgroups', 'smball']:
            if args.command == 'smball':
                args.command = 'all'

            gatherer = Gatherer(
                db_conn,
                work_dir,
                ldap_url,
                smb_url,
                ad_id=args.ad_id,
                ldap_worker_cnt=None,
                smb_worker_cnt=args.smb_workers,
                mp_pool=None,
                smb_gather_types=args.command,
                progress_queue=None,
                show_progress=args.silent,
                calc_edges=False,
                dns=args.dns,
            )
            await gatherer.run()

        elif args.command == 'dns':
            gatherer = Gatherer(
                db_conn,
                work_dir,
                None,
                None,
                ad_id=args.ad_id,
                ldap_worker_cnt=None,
                smb_worker_cnt=None,
                mp_pool=None,
                smb_gather_types=None,
                progress_queue=None,
                show_progress=args.silent,
                calc_edges=False,
                dns=args.dns,
            )
            await gatherer.run()

        elif args.command == 'version':
            print('Jackdaw version: %s' % jdversion)
            print('MSLDAP version : %s' % ldapversion)
            print('AIOSMB version : %s' % smbversion)

        elif args.command == 'files':
            raise Exception('not yet implemented!')
            #if args.src == 'domain':
            #	if not args.ad_id:
            #		raise Exception('ad-id parameter is mandatory in ldap mode')
            #
            #	mgr = SMBConnectionURL(args.smb_url)
            #	settings_base = SMBShareGathererSettings(args.ad_id, mgr, None, None, None)
            #	settings_base.dir_depth = args.smb_folder_depth
            #	settings_base.dir_with_sd = args.with_sid
            #	settings_base.file_with_sd = args.with_sid
            #
            #	mgr = ShareGathererManager(settings_base, db_conn = db_conn, worker_cnt = args.smb_workers)
            #	mgr.run()

        elif args.command == 'creds':
            creds = JackDawCredentials(db_conn, args.domain_id)
            creds.add_credentials_impacket(args.impacket_file)

        elif args.command == 'passwords':
            creds = JackDawCredentials(db_conn)
            creds.add_cracked_passwords(args.potfile, args.disable_usercheck,
                                        args.disable_passwordcheck)

        elif args.command == 'uncracked':
            creds = JackDawCredentials(db_conn, args.domain_id)
            creds.get_uncracked_hashes(args.hash_type, args.history)

        elif args.command == 'cracked':
            creds = JackDawCredentials(db_conn, args.domain_id)
            creds.get_cracked_info()

        elif args.command == 'recalc':
            with multiprocessing.Pool() as mp_pool:
                gatherer = Gatherer(db_conn,
                                    work_dir,
                                    None,
                                    None,
                                    mp_pool=mp_pool,
                                    progress_queue=None,
                                    show_progress=args.silent,
                                    calc_edges=True,
                                    store_to_db=True,
                                    ad_id=None,
                                    graph_id=args.graphid)
                await gatherer.run()

        elif args.command == 'nest':
            from jackdaw.nest.wrapper import NestServer

            debug = bool(args.verbose)

            server = NestServer(
                args.sql,
                bind_ip=args.ip,
                bind_port=args.port,
                debug=debug,
                work_dir=args.work_dir,
                graph_backend=args.backend,
            )
            server.run()

        elif args.command == 'ws':
            from jackdaw.nest.ws.server import NestWebSocketServer
            server = NestWebSocketServer(args.listen_ip,
                                         args.listen_port,
                                         args.sql,
                                         args.work_dir,
                                         args.backend,
                                         ssl_ctx=None)
            await server.run()

        elif args.command == 'bhimport':
            from jackdaw.utils.bhimport import BHImport
            print(
                'DISCLAIMER! This feature is still beta! Bloodhound acquires way less data than Jackdaw therefore not all functionality will work after import. Any errors during import will be silently ignored, use "-vvv" verbosity level to see all errors.'
            )
            bh = BHImport.from_zipfile(args.bhfile)
            bh.db_conn = db_conn
            if args.verbose > 1:
                bh.set_debug(True)
            bh.run()
            print('Import complete!')

    except Exception as e:
        jdlogger.exception('main')
Пример #5
0
def run(args):
    if args.verbose == 0:
        logging.basicConfig(level=logging.INFO)
        jdlogger.setLevel(logging.INFO)
        msldaplogger.setLevel(logging.WARNING)
        smblogger.setLevel(logging.CRITICAL)

    elif args.verbose == 1:
        logging.basicConfig(level=logging.DEBUG)
        jdlogger.setLevel(logging.DEBUG)
        msldaplogger.setLevel(logging.INFO)
        smblogger.setLevel(logging.INFO)

    elif args.verbose > 1:
        logging.basicConfig(level=1)
        msldaplogger.setLevel(logging.DEBUG)
        jdlogger.setLevel(1)
        smblogger.setLevel(1)

    if not args.sql:
        print(
            'SQL connection identification is missing! You need to provide the --sql parameter'
        )
        sys.exit()

    db_conn = args.sql

    if args.command == 'enum':
        smb_mgr = construct_smbdef(args)
        ldap_mgr = construct_ldapdef(args)

        mgr = LDAPEnumeratorManager(db_conn,
                                    ldap_mgr,
                                    agent_cnt=args.ldap_workers)
        adifo_id = mgr.run()
        print('ADInfo entry successfully created with ID %s' % adifo_id)

        mgr = SMBGathererManager(smb_mgr, worker_cnt=args.smb_workers)
        mgr.gathering_type = ['all']
        mgr.db_conn = db_conn
        mgr.target_ad = adifo_id
        mgr.run()

    elif args.command == 'dbinit':
        create_db(db_conn)

    elif args.command == 'adinfo':
        session = get_session(db_conn)
        from jackdaw.dbmodel.adinfo import JackDawADInfo
        from jackdaw.utils.table import print_table

        rows = [['Ad ID', 'domain name', 'scantime']]
        for did, distinguishedName, creation in session.query(
                JackDawADInfo).with_entities(JackDawADInfo.id,
                                             JackDawADInfo.distinguishedName,
                                             JackDawADInfo.fetched_at).all():
            name = distinguishedName.replace('DC=', '')
            name = name.replace(',', '.')
            rows.append([str(did), name, creation.isoformat()])
        print_table(rows)

    elif args.command == 'ldap':
        ldap_mgr = construct_ldapdef(args)
        ldap_conn = ldap_mgr.get_connection()
        ldap_conn.connect()

        mgr = LDAPEnumeratorManager(db_conn,
                                    ldap_mgr,
                                    agent_cnt=args.ldap_workers)
        adifo_id = mgr.run()
        print('ADInfo entry successfully created with ID %s' % adifo_id)

    elif args.command in ['shares', 'sessions', 'localgroups']:
        smb_mgr = construct_smbdef(args)
        mgr = SMBGathererManager(smb_mgr)
        mgr.gathering_type = [args.command]
        mgr.db_conn = db_conn
        mgr.lookup_ad = args.lookup_ad

        if args.ldap_url:
            ldap_mgr = construct_ldapdef(args)
            ldap_conn = ldap_mgr.get_connection()
            ldap_conn.connect()
            mgr.ldap_conn = ldap_conn

        if args.ad_id:
            mgr.target_ad = args.ad_id

        if args.target_file:
            mgr.targets_file = args.target_file

        mgr.run()

    elif args.command == 'creds':
        creds = JackDawCredentials(args.db_conn, args.domain_id)
        creds.add_credentials_impacket(args.impacket_file)

    elif args.command == 'passwords':
        creds = JackDawCredentials(args.db_conn)
        creds.add_cracked_passwords(args.potfile, args.disable_usercheck,
                                    args.disable_passwordcheck)

    elif args.command == 'uncracked':
        creds = JackDawCredentials(args.db_conn, args.domain_id)
        creds.get_uncracked_hashes(args.hash_type, args.history)

    elif args.command == 'cracked':
        creds = JackDawCredentials(args.db_conn, args.domain_id)
        creds.get_cracked_info()

    elif args.command == 'nest':
        from jackdaw.nest.wrapper import NestServer

        debug = bool(args.verbose)

        server = NestServer(args.sql,
                            bind_ip=args.ip,
                            bind_port=args.port,
                            debug=debug)
        server.run()
Пример #6
0
	async def __start_cmd(self, cmd):
		try:
			print('New agent connected to C2! Starting jackdaw...')
			print(cmd.to_dict())
			progress_q = asyncio.Queue()
			progress_task = asyncio.create_task(self.print_progress(cmd.agentid.hex(), progress_q))

			await self.ducky_q.put(self.duckysvc_event['AGENTCONNECTED'])

			wsproto = 'wsnetws' if self.c2_proto == 'ws' else 'wsnetwss'
			domain = cmd.domain
			username = cmd.username
			if username.find('\\') != -1:
				domain, username = username.split('\\')
			
			dns_url = 'dns://%s:53/?proxytype=%s&proxyhost=%s&proxyport=%s&proxyagentid=%s' % (cmd.logonserver, wsproto, self.c2_ip, self.c2_port, cmd.agentid.hex())
			kerberos_url = '%s://%s:%s/?type=sspiproxy&agentid=%s' % (self.c2_proto, self.c2_ip, self.c2_port, cmd.agentid.hex())
			params = 'authhost=%s&authport=%s&authagentid=%s&proxytype=%s&proxyhost=%s&proxyport=%s&proxyagentid=%s' % ( self.c2_ip, self.c2_port, cmd.agentid.hex(), wsproto, self.c2_ip, self.c2_port, cmd.agentid.hex())
			smb_url = 'smb2+sspiproxy-ntlm://%s\\%s:aa@%s/?%s' % (domain, username, cmd.logonserver, params)
			ldap_url = 'ldap+sspiproxy-ntlm://%s\\%s:aa@%s/?%s' % (domain, username, cmd.logonserver, params)

			print('dns %s' % dns_url)
			print('kerberos %s' % kerberos_url)
			print('smb %s' % smb_url)
			print('ldap %s' % ldap_url)

			smb_workers = 10
			ldap_workers = 4
			
			loc_base = '%s_%s' % (datetime.datetime.utcnow().strftime("%Y%m%d_%H%M%S"), cmd.agentid.hex()[:8])
			p = pathlib.Path(self.workdir).joinpath('./workdir_' + loc_base)
			p.mkdir(parents=True, exist_ok=True)
			db_loc = '%s_%s.db' % (cmd.domain, loc_base)
			db_loc = p.joinpath(db_loc)
			print(db_loc)
			db_conn = 'sqlite:///%s' % db_loc
			create_db(db_conn)

			
			
			work_dir = str(p)

			print(work_dir)
			print(db_conn)
			
			await self.ducky_q.put(self.duckysvc_event['JDENUMSTART'])

			with multiprocessing.Pool() as mp_pool:
				gatherer = Gatherer(
					db_conn, 
					work_dir, 
					ldap_url, 
					smb_url,
					kerb_url=kerberos_url,
					ldap_worker_cnt=ldap_workers, 
					smb_worker_cnt=smb_workers, 
					mp_pool=mp_pool, 
					smb_gather_types=['all'],
					progress_queue=progress_q, 
					show_progress=False,
					calc_edges=True,
					ad_id=None,
					dns=dns_url,
					no_work_dir=False
				)
				_, err = await gatherer.run()
				if err is not None:
					raise err
			
			print('%s Jackdaw finished sucsessfully!' % cmd.agentid.hex()[:8])

			progress_task.cancel()

			await self.ducky_q.put(self.duckysvc_event['JDENUMFINISH'])

			web_port = self.get_web_port()
			ws_port = self.get_web_port()
			print('%s Starting webserver on port %s' % (cmd.agentid.hex()[:8], web_port))
			websrv = WebServerProcess(db_conn, '0.0.0.0', web_port, work_dir, graph_backend = self.graph_backend)
			websrv.start()

			#checking if server is up now...
			own_ip = None
			while True:
				try:
					_, writer = await asyncio.open_connection('127.0.0.1', web_port)
					own_ip = writer.get_extra_info('sockname')[0]
				except:
					print('%s Could not connect to webserver, probably not ready yet' % cmd.agentid.hex()[:8])
					await asyncio.sleep(1)
				else:
					print('%s Jackdaw server started!' % cmd.agentid.hex()[:8])
					writer.close()
					break
			
			jd_url = 'http://%s:%s' % (own_ip, web_port)
			try:
				print('%s Asking server to load graph data to memory...' % cmd.agentid.hex()[:8])
				async with aiohttp.ClientSession() as session:
					async with session.post('%s/graph?adids=1' % jd_url) as resp:
						if resp.status != 200:
							raise Exception('Loading graphid failed! Status: %s' % resp.status)
						await resp.text()
			except Exception as e:
				raise e

			
			
			print('%s WEB Service listening on port %s' % (cmd.agentid.hex()[:8], ws_port))
			await self.ducky_q.put(self.duckysvc_event['JDSERVICESTART'])
			await self.ducky_q.put(
				[
					'STRING %s WEB listening on port %s' % (cmd.agentid.hex()[:8], ws_port),
					'DELAY 1000',
					'ENTER'
				]
			)

			server = NestWebSocketServer('127.0.0.1', ws_port, db_conn, work_dir, 'igraph', ssl_ctx = None)
			ws_task = asyncio.create_task(server.run())
			await asyncio.sleep(0)

			while True:
				try:
					_, writer = await asyncio.open_connection('127.0.0.1', ws_port)
					own_ip = writer.get_extra_info('sockname')[0]
				except:
					print('%s Could not connect to ws server, probably not ready yet' % cmd.agentid.hex()[:8])
					await asyncio.sleep(1)
				else:
					print('%s Jackdaw WS server started!' % cmd.agentid.hex()[:8])
					writer.close()
					break

			print('%s WS Service listening on port %s' % (cmd.agentid.hex()[:8], ws_port))
			await self.ducky_q.put(
				[
					'STRING %s WS Service listening on port %s' % (cmd.agentid.hex()[:8], ws_port),
					'DELAY 1000',
					'ENTER'
				]
			)


			await asyncio.sleep(1000)

		except Exception as e:
			print('%s Exception handling agent Reson: %s' % (cmd.agentid.hex()[:8], e))
			await self.ducky_q.put(
				[
					'STRING %s Exception handling agent Reson: %s' % (cmd.agentid.hex()[:8], e),
					'DELAY 1000',
					'ENTER'
				]
			)