Exemplo n.º 1
0
    async def __executor(self, tid, target):
        try:
            for protocol in self.protocols:
                smb_mgr = SMBConnectionURL(
                    'smb2+ntlm-password://%s/?timeout=%s' %
                    (target, self.timeout))
                connection = smb_mgr.create_connection_newtarget(target)
                res, sign_en, sign_req, rply, err = await connection.protocol_test(
                    [protocol])
                if err is not None:
                    raise err

                er = SMBProtocolEnumResultInner(
                    tid, target, (protocol, res, sign_en, sign_req, rply, err))
                await self.res_q.put(er)
                if self.only_signing is True:
                    return
        except asyncio.CancelledError:
            return
        except Exception as e:
            await self.res_q.put(
                SMBProtocolEnumResultInner(tid,
                                           target,
                                           None,
                                           error=e,
                                           status=EnumResultStatus.ERROR))
        finally:
            await self.res_q.put(
                SMBProtocolEnumResultInner(tid,
                                           target,
                                           None,
                                           status=EnumResultStatus.FINISHED))
Exemplo n.º 2
0
 async def __executor(self, tid, target):
     try:
         smb_mgr = SMBConnectionURL('smb2+ntlm-password://%s/?timeout=%s' %
                                    (target, self.timeout))
         connection = smb_mgr.create_connection_newtarget(target)
         res, err = await connection.fake_login()
         if err is not None:
             raise err
         er = EnumResult(tid, target, (res, ))
         await self.res_q.put(er)
     except asyncio.CancelledError:
         return
     except Exception as e:
         await self.res_q.put(
             EnumResult(tid,
                        target,
                        None,
                        error=e,
                        status=EnumResultStatus.ERROR))
     finally:
         await self.res_q.put(
             EnumResult(tid, target, None,
                        status=EnumResultStatus.FINISHED))
Exemplo n.º 3
0
class SMBAdminCheck:
	def __init__(self, smb_url, worker_count = 100, enum_url = True):
		self.target_gens = []
		self.smb_mgr = SMBConnectionURL(smb_url)
		self.worker_count = worker_count
		self.task_q = None
		self.res_q = None
		self.workers = []
		self.result_processing_task = None
		self.enum_url = enum_url
		self.__gens_finished = False
		self.__total_targets = 0
		self.__total_finished = 0

	async def __executor(self, tid, target):
		try:
			connection = self.smb_mgr.create_connection_newtarget(target)
			async with connection:
				_, err = await connection.login()
				if err is not None:
					raise err
				
				res = EnumResult(tid, target)
				share = SMBShare(
					name = 'ADMIN$',
					fullpath = '\\\\%s\\%s' % (connection.target.get_hostname_or_ip(), 'ADMIN$')
				)
				_, err = await share.connect(connection)
				res.share = True if err is None else False

				rrp = RRP(connection)
				_, err = await rrp.connect()
				res.registry = True if err is None else False


				srvmgr = SMBRemoteServieManager(connection)
				_, err = await srvmgr.connect()
				res.servicemgr = True if err is None else False

				await self.res_q.put(res)


		except asyncio.CancelledError:
			return
		except Exception as e:
			await self.res_q.put(EnumResult(tid, target, error = e, status = EnumResultStatus.ERROR))
		finally:
			await self.res_q.put(EnumResult(tid, target, status = EnumResultStatus.FINISHED))

	async def worker(self):
		try:
			while True:
				indata = await self.task_q.get()
				if indata is None:
					return
				
				tid, target = indata
				try:
					await asyncio.wait_for(self.__executor(tid, target), timeout=10)
				except asyncio.CancelledError:
					return
				except Exception as e:
					pass
		except asyncio.CancelledError:
			return
				
		except Exception as e:
			return e

	async def result_processing(self):
		try:
			while True:
				try:
					er = await self.res_q.get()
					if er.status == EnumResultStatus.FINISHED:
						self.__total_finished += 1
						print('[P][%s/%s][%s]' % (self.__total_targets, self.__total_finished, 'False'))
						if self.__total_finished == self.__total_targets and self.__gens_finished is True:
							print('[P][%s/%s][%s]' % (self.__total_targets, self.__total_finished, 'True'))
							asyncio.create_task(self.terminate())
							return
					
					elif er.status == EnumResultStatus.RESULT:
						print('[R][SHARE][%s][%s][%s]' % (er.target, er.target_id, er.share))
						print('[R][REG][%s][%s][%s]' % (er.target, er.target_id, er.registry))
						print('[R][SRV][%s][%s][%s]' % (er.target, er.target_id, er.servicemgr))
					
					elif er.status == EnumResultStatus.ERROR:
						print('[E][%s][%s] %s' % (er.target, er.target_id, er.error))
						
				except asyncio.CancelledError:
					return
				except Exception as e:
					print(e)
					continue
		except asyncio.CancelledError:
			return
		except Exception as e:
			print(e)

	async def terminate(self):
		for worker in self.workers:
			worker.cancel()
		if self.result_processing_task is not None:
			self.result_processing_task.cancel()		

	async def setup(self):
		try:
			if self.res_q is None:
				self.res_q = asyncio.Queue(self.worker_count)
				self.result_processing_task = asyncio.create_task(self.result_processing())
			if self.task_q is None:
				self.task_q = asyncio.Queue()

			for _ in range(self.worker_count):
				self.workers.append(asyncio.create_task(self.worker()))

			return True, None
		except Exception as e:
			return None, e
	
	async def run(self):
		try:
			_, err = await self.setup()
			if err is not None:
				raise err
			
			if self.enum_url is True:
				if self.smb_mgr.get_target().get_hostname_or_ip() is not None or self.smb_mgr.get_target().get_hostname_or_ip() != '':
					self.__total_targets += 1
					await self.task_q.put((str(uuid.uuid4()), self.smb_mgr.get_target().get_hostname_or_ip()))
			
			for target_gen in self.target_gens:
				total, err = await target_gen.run(self.task_q)
				self.__total_targets += total
				if err is not None:
					print('Target gen error! %s' % err)

			self.__gens_finished = True
			
			await asyncio.gather(*self.workers)
			return True, None
		except Exception as e:
			print(e)
			return None, e
Exemplo n.º 4
0
class SMBPrintnightmareEnum:
	def __init__(self, smb_url:SMBConnectionURL, worker_count = 10, enum_url = False, out_file = None, show_pbar = True, max_runtime = None, task_q = None, res_q = None, output_type = 'str', ext_result_q = None):
		self.target_gens = []
		self.smb_mgr = smb_url
		if isinstance(smb_url, str):
			self.smb_mgr = SMBConnectionURL(smb_url)
		self.worker_count = worker_count
		self.task_q = task_q
		self.res_q = res_q
		self.workers = []
		self.result_processing_task = None
		self.enum_url = enum_url
		self.out_file = out_file
		self.show_pbar = show_pbar
		self.max_runtime = max_runtime
		self.output_type = output_type
		self.ext_result_q = ext_result_q
		self.write_buffer_size = 1000

		self.__gens_finished = False
		self.__total_targets = 0
		self.__total_finished = 0
		self.__total_errors = 0

		self.__total_sessions = 0
		self.__current_targets = {}

	async def __executor(self, tid, target):
		try:
			connection = self.smb_mgr.create_connection_newtarget(target)
			async with connection:
				_, err = await connection.login()
				if err is not None:
					raise err

				nonexistentpath = "C:\\doesntexist\\%s.dll" % os.urandom(4).hex()
				async with SMBMachine(connection) as machine:
					_, err = await asyncio.wait_for(machine.printnightmare(nonexistentpath, None, silent=True), 10)
					if err is not None:
						er = EnumResult(tid, target, 'OK')
						if str(err).find('ERROR_PATH_NOT_FOUND') != -1:
							er = EnumResult(tid, target, 'VULN')
						await self.res_q.put(er)

					_, err = await asyncio.wait_for(machine.par_printnightmare(nonexistentpath, None, silent=True), 10)
					if err is not None:
						er = EnumResult(tid, target, 'OK')
						if str(err).find('ERROR_PATH_NOT_FOUND') != -1:
							er = EnumResult(tid, target, 'VULN')
						await self.res_q.put(er)
					

		except asyncio.CancelledError:
			return
		except Exception as e:
			await self.res_q.put(EnumResult(tid, target, None, error = e, status = EnumResultStatus.ERROR))
		finally:
			await self.res_q.put(EnumResult(tid, target, None, status = EnumResultStatus.FINISHED))

	async def worker(self):
		try:
			while True:
				indata = await self.task_q.get()
				if indata is None:
					return
				
				tid, target = indata
				try:
					await asyncio.wait_for(self.__executor(tid, target), timeout=self.max_runtime)
				except asyncio.CancelledError:
					return
				except asyncio.TimeoutError as e:
					await self.res_q.put(EnumResult(tid, target, None, error = e, status = EnumResultStatus.ERROR))
					await self.res_q.put(EnumResult(tid, target, None, status = EnumResultStatus.FINISHED))
					continue
				except Exception as e:
					logger.exception('worker')
					continue
		except asyncio.CancelledError:
			return
				
		except Exception as e:
			return e

	async def result_processing(self):
		try:
			pbar = None
			if self.show_pbar is True:
				pbar = {}
				pbar['targets']    = tqdm(desc='Targets     ', unit='', position=0)
				pbar['vulnerable'] = tqdm(desc='Vulnerable  ', unit='', position=1)
				pbar['connerrors'] = tqdm(desc='Conn Errors ', unit='', position=2)

			out_buffer = []
			final_iter = False
			while True:
				try:
					if self.__gens_finished is True and self.show_pbar is True and pbar['targets'].total is None:
						pbar['targets'].total = self.__total_targets
						for key in pbar:
							pbar[key].refresh()

					if self.ext_result_q is not None:
						out_buffer = []

					if len(out_buffer) >= self.write_buffer_size or final_iter and self.ext_result_q is None:
						out_data = ''
						if self.output_type == 'str':
							out_data = '\r\n'.join([str(x) for x in out_buffer])
						elif self.output_type == 'tsv':
							for res in out_buffer:
								x = res.to_tsv()
								if x == '':
									continue
								out_data += '%s\r\n' % x
						elif self.output_type == 'json':
							for res in out_buffer:
								out_data += '%s\r\n' % res.to_json()
						else:
							out_data = '\r\n'.join(out_buffer)

						if self.out_file is not None:
							with open(self.out_file, 'a+', newline = '') as f:
								f.write(out_data)
						
						else:
							print(out_data)
						
						if self.show_pbar is True:
							for key in pbar:
								pbar[key].refresh()
						
						out_buffer = []
						out_data = ''

					if final_iter:
						asyncio.create_task(self.terminate())
						return
					try:
						er = await asyncio.wait_for(self.res_q.get(), timeout = 5)
					except asyncio.TimeoutError:
						if self.show_pbar is True:
							for key in pbar:
								pbar[key].refresh()

						if self.__total_finished == self.__total_targets and self.__gens_finished is True:
							final_iter = True
						continue

					if er.status == EnumResultStatus.FINISHED:
						self.__total_finished += 1
						if self.show_pbar is True:
							pbar['targets'].update(1)

						obj = EnumProgress(self.__total_targets, self.__total_finished, self.__gens_finished, er.target)
						if self.ext_result_q is not None:
							await self.ext_result_q.put(EnumResultFinal(obj, 'progress', None, er.target, er.target_id))
						out_buffer.append(EnumResultFinal(obj, 'progress', None, er.target, er.target_id))
						if self.__total_finished == self.__total_targets and self.__gens_finished is True:
							final_iter = True
							continue
							
					if er.result is not None:
						if self.ext_result_q is not None:
							await self.ext_result_q.put(EnumResultFinal(er.result, 'result', None, er.target, er.target_id))
						out_buffer.append(EnumResultFinal(er.result, 'result', None, er.target, er.target_id))
						self.__total_sessions += 1
							
						if self.show_pbar is True and er.result.startswith('VULN') is True:
							pbar['vulnerable'].update(1)
					
					if er.status == EnumResultStatus.ERROR:
						self.__total_errors += 1
						if self.show_pbar is True:
							pbar['connerrors'].update(1)


				except asyncio.CancelledError:
					return
				except Exception as e:
					logger.exception('result_processing inner')
					asyncio.create_task(self.terminate())
					return
		except asyncio.CancelledError:
			return
		except Exception as e:
			logger.exception('result_processing')
			asyncio.create_task(self.terminate())
		finally:
			if self.ext_result_q is not None:
				await self.ext_result_q.put(EnumResultFinal(None, 'finished', None, None, None))

	async def terminate(self):
		for worker in self.workers:
			worker.cancel()
		if self.result_processing_task is not None:
			self.result_processing_task.cancel()		

	async def setup(self):
		try:
			if self.res_q is None:
				self.res_q = asyncio.Queue(self.worker_count)
				self.result_processing_task = asyncio.create_task(self.result_processing())
			if self.task_q is None:
				self.task_q = asyncio.Queue(self.worker_count)

			for _ in range(self.worker_count):
				self.workers.append(asyncio.create_task(self.worker()))

			return True, None
		except Exception as e:
			return None, e

	async def __generate_targets(self):
		if self.enum_url is True:
			self.__total_targets += 1
			await self.task_q.put((str(uuid.uuid4()), self.smb_mgr.get_target().get_hostname_or_ip()))
			
		for target_gen in self.target_gens:
			async for uid, target, err in target_gen.generate():
				if err is not None:
					print('Target gen error! %s' % err)
					break
				
				self.__total_targets += 1
				await self.task_q.put((uid, target))
				await asyncio.sleep(0)

		self.__gens_finished = True
	
	async def run(self):
		try:
			_, err = await self.setup()
			if err is not None:
				raise err
			
			gen_task = asyncio.create_task(self.__generate_targets())
			
			await asyncio.gather(*self.workers)
			await self.result_processing_task
			return True, None
		except Exception as e:
			logger.exception('run')
			return None, e
Exemplo n.º 5
0
class SMBGET:
    def __init__(self, smb_url, show_progress=False):
        self.smb_mgr = SMBConnectionURL(smb_url)
        self.target_gens = []
        self.task_q = None
        self.__total_targets = 0
        self.target_gen_task = None
        self.show_progress = show_progress

    async def __target_gen(self):
        for target_gen in self.target_gens:
            total, err = await target_gen.run(self.task_q)
            self.__total_targets += total
            if err is not None:
                print('Target gen error! %s' % err)
            await self.task_q.put(None)

    async def run(self):
        try:
            self.task_q = asyncio.Queue()
            self.target_gen_task = asyncio.create_task(self.__target_gen())

            while True:
                t = await self.task_q.get()
                if t is None:
                    return True, None

                tid, target = t
                unc = PureWindowsPath(target)
                file_name = unc.name
                print()
                connection = self.smb_mgr.create_connection_newtarget(
                    target.replace('\\\\', '').split('\\')[0])
                async with connection:
                    _, err = await connection.login()
                    if err is not None:
                        raise err

                    print(target)
                    smbfile = SMBFile.from_uncpath(target)
                    _, err = await smbfile.open(connection, 'r')
                    if err is not None:
                        logger.info('Error Downloading file %s' % target)
                        continue

                    if self.show_progress is True:
                        pbar = tqdm.tqdm(desc='Downloading %s' % file_name,
                                         total=smbfile.size,
                                         unit='B',
                                         unit_scale=True,
                                         unit_divisor=1024)

                    with open(file_name, 'wb') as f:
                        async for data, err in smbfile.read_chunked():
                            if err is not None:
                                logger.info('Error Downloading file %s' %
                                            target)
                                continue
                            if data is None:
                                break

                            f.write(data)

                            if self.show_progress is True:
                                pbar.update(len(data))

            return True, None
        except Exception as e:
            return False, e
Exemplo n.º 6
0
async def amain():
    import argparse

    parser = argparse.ArgumentParser(description='Secretsdump')
    parser.add_argument('-v', '--verbose', action='count', default=0)
    parser.add_argument('-t',
                        '--target-file',
                        help='file with target hosts, one per line.')
    parser.add_argument(
        '-o',
        '--output-folder',
        default='results',
        help=
        'file to write all results to. please use full path, will create new directories recursively!'
    )
    parser.add_argument('-w',
                        '--worker-count',
                        type=int,
                        default=50,
                        help='Maximum worker count')
    parser.add_argument(
        '-b',
        '--bin-folder',
        default='bins',
        help=
        'Location of the binary utils folder. (where procdump.exe and procdump64.exe is)'
    )
    parser.add_argument('cmd', choices=['dcsync', 'registry', 'lsass', 'all'])
    parser.add_argument('smb_url', help='the SMB connection URL string')

    args = parser.parse_args()

    worker_tasks = []
    process_q = asyncio.Queue()
    out_q = asyncio.Queue()
    #creating results directory
    output_root = Path(args.output_folder)
    output_root.mkdir(parents=True, exist_ok=True)

    connections = []
    # checking if SMB url is parsable
    connection_url = SMBConnectionURL(args.smb_url)
    connections.append(connection_url.get_connection())

    for _ in range(min(len(connections), args.worker_count)):
        wt = asyncio.create_task(worker(process_q, out_q, args, output_root))
        worker_tasks.append(wt)

    # parsing targets
    if args.target_file is not None:
        with open(args.target_file, 'r') as f:
            for line in f:
                line = line.strip()
                connection = connection_url.create_connection_newtarget(line)
                connections.append(connection)

    # main
    for connection in connections:
        await process_q.put(connection)

    for _ in range(len(worker_tasks)):
        await process_q.put(None)

    finished_workers = 0
    while True:
        res = await out_q.get()
        if res is None:
            finished_workers += 1
            if finished_workers >= len(worker_tasks):
                break

    print('Done!')
Exemplo n.º 7
0
class SMBFileEnum:
    def __init__(self, smb_url, worker_count=100, depth=3, enum_url=True):
        self.target_gens = []
        self.smb_mgr = SMBConnectionURL(smb_url)
        self.worker_count = worker_count
        self.task_q = None
        self.res_q = None
        self.depth = depth
        self.workers = []
        self.result_processing_task = None
        self.enum_url = enum_url
        self.__gens_finished = False
        self.__total_targets = 0
        self.__total_finished = 0

    async def __executor(self, tid, target):
        try:
            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err

                machine = SMBMachine(connection)
                async for path, otype, err in machine.enum_all_recursively(
                        depth=self.depth):
                    er = EnumResult(tid, target, (path, otype, err))
                    await self.res_q.put(er)

        except asyncio.CancelledError:
            return
        except Exception as e:
            await self.res_q.put(
                EnumResult(tid,
                           target,
                           None,
                           error=e,
                           status=EnumResultStatus.ERROR))
        finally:
            await self.res_q.put(
                EnumResult(tid, target, None,
                           status=EnumResultStatus.FINISHED))

    async def worker(self):
        try:
            while True:
                indata = await self.task_q.get()
                if indata is None:
                    return

                tid, target = indata
                try:
                    await asyncio.wait_for(self.__executor(tid, target),
                                           timeout=10)
                except asyncio.CancelledError:
                    return
                except Exception as e:
                    pass
        except asyncio.CancelledError:
            return

        except Exception as e:
            return e

    async def result_processing(self):
        try:
            while True:
                try:
                    er = await self.res_q.get()
                    if er.status == EnumResultStatus.FINISHED:
                        self.__total_finished += 1
                        print('[P][%s/%s][%s]' %
                              (self.__total_targets, self.__total_finished,
                               str(self.__gens_finished)))
                        if self.__total_finished == self.__total_targets and self.__gens_finished is True:
                            asyncio.create_task(self.terminate())
                            return

                    if er.result is not None:
                        path, otype, err = er.result
                        if otype is not None:
                            print('[%s] %s' % (otype[0].upper(), path))
                        if err is not None:
                            print('[E] %s %s' % (err, path))
                except asyncio.CancelledError:
                    return
                except Exception as e:
                    print(e)
                    continue
        except asyncio.CancelledError:
            return
        except Exception as e:
            print(e)

    async def terminate(self):
        for worker in self.workers:
            worker.cancel()
        if self.result_processing_task is not None:
            self.result_processing_task.cancel()

    async def setup(self):
        try:
            if self.res_q is None:
                self.res_q = asyncio.Queue(self.worker_count)
                self.result_processing_task = asyncio.create_task(
                    self.result_processing())
            if self.task_q is None:
                self.task_q = asyncio.Queue()

            for _ in range(self.worker_count):
                self.workers.append(asyncio.create_task(self.worker()))

            return True, None
        except Exception as e:
            return None, e

    async def run(self):
        try:
            _, err = await self.setup()
            if err is not None:
                raise err

            if self.enum_url is True:
                self.__total_targets += 1
                await self.task_q.put(
                    (str(uuid.uuid4()),
                     self.smb_mgr.get_target().get_hostname_or_ip()))

            for target_gen in self.target_gens:
                total, err = await target_gen.run(self.task_q)
                self.__total_targets += total
                if err is not None:
                    print('Target gen error! %s' % err)

            self.__gens_finished = True

            await asyncio.gather(*self.workers)
            return True, None
        except Exception as e:
            print(e)
            return None, e
Exemplo n.º 8
0
async def lsassdump(url,
                    method='task',
                    remote_base_path='C:\\Windows\\Temp\\',
                    remote_share_name='\\c$\\Windows\\Temp\\',
                    chunksize=64 * 1024,
                    packages=['all'],
                    targets=[],
                    worker_cnt=5):
    from aiosmb.commons.connection.url import SMBConnectionURL

    base_url = None
    base_conn = None
    mimis = []
    workers = []

    tgens = []
    if targets is not None and len(targets) != 0:
        notfile = []
        if targets is not None:
            for target in targets:
                try:
                    f = open(target, 'r')
                    f.close()
                    tgens.append(FileTargetGen(target))
                except:
                    notfile.append(target)

            if len(notfile) > 0:
                tgens.append(ListTargetGen(notfile))

    if isinstance(url, SMBConnectionURL):
        base_url = url
        base_conn = url.get_connection()
    else:
        base_url = SMBConnectionURL(url)
        base_conn = base_url.get_connection()

    lsassdump_coro = lsassdump_single(base_conn.target.get_hostname_or_ip(),
                                      base_conn,
                                      method=method,
                                      remote_base_path=remote_base_path,
                                      remote_share_name=remote_share_name,
                                      chunksize=chunksize,
                                      packages=packages)
    workers.append(lsassdump_coro)

    for tgen in tgens:
        async for _, target, err in tgen.generate():
            tconn = base_url.create_connection_newtarget(target)
            lsassdump_coro = lsassdump_single(
                tconn.target.get_hostname_or_ip(),
                tconn,
                method=method,
                remote_base_path=remote_base_path,
                remote_share_name=remote_share_name,
                chunksize=chunksize,
                packages=packages)
            workers.append(lsassdump_coro)
            if len(workers) >= worker_cnt:
                tres = await asyncio.gather(*workers)
                for res in tres:
                    yield res
                workers = []

    if len(workers) > 0:
        tres = await asyncio.gather(*workers)
        for res in tres:
            yield res
        workers = []
Exemplo n.º 9
0
async def regdump(url,
                  hives=['HKLM\\SAM', 'HKLM\\SYSTEM', 'HKLM\\SECURITY'],
                  remote_base_path='C:\\Windows\\Temp\\',
                  remote_share_name='\\c$\\Windows\\Temp\\',
                  enable_wait=3,
                  targets=[],
                  worker_cnt=5):
    from aiosmb.commons.connection.url import SMBConnectionURL

    base_url = None
    base_conn = None
    mimis = []
    workers = []

    tgens = []
    if targets is not None and len(targets) != 0:
        notfile = []
        if targets is not None:
            for target in targets:
                try:
                    f = open(target, 'r')
                    f.close()
                    tgens.append(FileTargetGen(target))
                except:
                    notfile.append(target)

            if len(notfile) > 0:
                tgens.append(ListTargetGen(notfile))

    if isinstance(url, SMBConnectionURL):
        base_url = url
        base_conn = url.get_connection()
    else:
        base_url = SMBConnectionURL(url)
        base_conn = base_url.get_connection()

    regdump_coro = regdump_single(base_conn.target.get_hostname_or_ip(),
                                  base_conn,
                                  hives=hives,
                                  remote_base_path=remote_base_path,
                                  remote_share_name=remote_share_name,
                                  enable_wait=enable_wait)
    workers.append(regdump_coro)

    for tgen in tgens:
        async for _, target, err in tgen.generate():
            tconn = base_url.create_connection_newtarget(target)
            regdump_coro = regdump_single(tconn.target.get_hostname_or_ip(),
                                          tconn,
                                          hives=hives,
                                          remote_base_path=remote_base_path,
                                          remote_share_name=remote_share_name,
                                          enable_wait=enable_wait)
            workers.append(regdump_coro)
            if len(workers) >= worker_cnt:
                tres = await asyncio.gather(*workers)
                for res in tres:
                    yield res
                workers = []

    if len(workers) > 0:
        tres = await asyncio.gather(*workers)
        for res in tres:
            yield res
        workers = []
Exemplo n.º 10
0
class SMBAdminCheck:
    def __init__(self,
                 smb_url,
                 worker_count=100,
                 enum_url=True,
                 exclude_target=[],
                 show_pbar=False,
                 ext_result_q=None,
                 output_type='str',
                 out_file=None):
        self.target_gens = []
        self.smb_mgr = SMBConnectionURL(smb_url)
        self.worker_count = worker_count
        self.task_q = None
        self.res_q = None
        self.workers = []
        self.result_processing_task = None
        self.enum_url = enum_url
        self.exclude_target = []
        self.show_pbar = show_pbar
        self.ext_result_q = ext_result_q
        self.output_type = output_type
        self.out_file = out_file
        self.__gens_finished = False
        self.__total_targets = 0
        self.__total_finished = 0

    async def __executor(self, tid, target):
        try:
            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err

                res = SMBAdminEnumResultInner(tid, target)
                share = SMBShare(
                    name='ADMIN$',
                    fullpath='\\\\%s\\%s' %
                    (connection.target.get_hostname_or_ip(), 'ADMIN$'))
                _, err = await share.connect(connection)
                res.share = True if err is None else False

                rrp = RRP(connection)
                _, err = await rrp.connect()
                res.registry = True if err is None else False

                srvmgr = SMBRemoteServieManager(connection)
                _, err = await srvmgr.connect()
                res.servicemgr = True if err is None else False

                await self.res_q.put(res)

        except asyncio.CancelledError:
            return
        except Exception as e:
            await self.res_q.put(
                SMBAdminEnumResultInner(tid,
                                        target,
                                        error=e,
                                        status=EnumResultStatus.ERROR))
        finally:
            await self.res_q.put(
                SMBAdminEnumResultInner(tid,
                                        target,
                                        status=EnumResultStatus.FINISHED))

    async def worker(self):
        try:
            while True:
                indata = await self.task_q.get()
                if indata is None:
                    return

                tid, target = indata
                try:
                    await asyncio.wait_for(self.__executor(tid, target),
                                           timeout=10)
                except asyncio.CancelledError:
                    return
                except Exception as e:
                    logger.debug('worker Error %s' % e)
                    continue

        except asyncio.CancelledError:
            return

        except Exception as e:
            return e

    async def result_processing(self):
        try:
            pbar = None
            if self.show_pbar is True:
                pbar = {}
                pbar['targets'] = tqdm(desc='Targets        ',
                                       unit='',
                                       position=0)
                pbar['share'] = tqdm(desc='C$ Access      ',
                                     unit='',
                                     position=1)
                pbar['reg'] = tqdm(desc='Registry Access', unit='', position=2)
                pbar['svc'] = tqdm(desc='Service  Access', unit='', position=3)
                pbar['connerrors'] = tqdm(desc='Conn Errors    ',
                                          unit='',
                                          position=4)

            out_buffer = []
            final_iter = False

            while True:
                try:
                    if self.__gens_finished is True and self.show_pbar is True and pbar[
                            'targets'].total is None:
                        pbar['targets'].total = self.__total_targets
                        for key in pbar:
                            pbar[key].refresh()
                    if self.ext_result_q is not None:
                        out_buffer = []

                    if len(
                            out_buffer
                    ) >= 1000 or final_iter and self.ext_result_q is None:
                        out_data = ''
                        if self.output_type == 'str':
                            out_data = '\r\n'.join(
                                [str(x) for x in out_buffer])
                        elif self.output_type == 'tsv':
                            for res in out_buffer:
                                x = res.to_tsv()
                                if x is not None and len(x) > 0:
                                    out_data += '%s\r\n' % x
                        elif self.output_type == 'json':
                            for res in out_buffer:
                                out_data += '%s\r\n' % res.to_json()

                        else:
                            out_data = '\r\n'.join(out_buffer)

                        if self.out_file is not None:
                            with open(self.out_file, 'a+', newline='') as f:
                                f.write(out_data)

                        else:
                            print(out_data)

                        if self.show_pbar is True:
                            for key in pbar:
                                pbar[key].refresh()

                        out_buffer = []
                        out_data = ''

                    if final_iter:
                        asyncio.create_task(self.terminate())
                        return

                    try:
                        er = await asyncio.wait_for(self.res_q.get(),
                                                    timeout=5)
                    except asyncio.TimeoutError:
                        if self.show_pbar is True:
                            for key in pbar:
                                pbar[key].refresh()

                        if self.__total_finished == self.__total_targets and self.__gens_finished is True:
                            final_iter = True
                        continue

                    if er.status == EnumResultStatus.FINISHED:
                        self.__total_finished += 1
                        if self.show_pbar is True:
                            pbar['targets'].update(1)

                        obj = SMBAdminEnumProgressResult(
                            self.__total_targets, self.__total_finished,
                            self.__gens_finished, er.target)
                        if self.ext_result_q is not None:
                            await self.ext_result_q.put(
                                SMBAdminEnumResult(obj, 'progress'))
                        out_buffer.append(SMBAdminEnumResult(obj, 'progress'))
                        if self.__total_finished == self.__total_targets and self.__gens_finished is True:
                            final_iter = True
                            continue

                    elif er.status == EnumResultStatus.RESULT:
                        if self.show_pbar is True:
                            if er.share is True:
                                pbar['share'].update(1)
                            if er.registry is True:
                                pbar['reg'].update(1)
                            if er.servicemgr is True:
                                pbar['svc'].update(1)

                        if self.ext_result_q is not None:
                            await self.ext_result_q.put(
                                SMBAdminEnumResult(er, 'result'))
                        out_buffer.append(SMBAdminEnumResult(er, 'result'))

                    elif er.status == EnumResultStatus.ERROR:
                        if self.ext_result_q is not None:
                            await self.ext_result_q.put(
                                SMBAdminEnumResult(er, 'error'))
                        if self.show_pbar is True:
                            pbar['connerrors'].update(1)
                        out_buffer.append(SMBAdminEnumResult(er, 'error'))

                except asyncio.CancelledError:
                    return
                except Exception as e:
                    logger.exception('result_processing inner')
                    continue
        except asyncio.CancelledError:
            return
        except Exception as e:
            logger.exception('result_processing main')

    async def terminate(self):
        for worker in self.workers:
            worker.cancel()
        if self.result_processing_task is not None:
            self.result_processing_task.cancel()

    async def setup(self):
        try:
            if self.res_q is None:
                self.res_q = asyncio.Queue(self.worker_count)
                self.result_processing_task = asyncio.create_task(
                    self.result_processing())
            if self.task_q is None:
                self.task_q = asyncio.Queue()

            for _ in range(self.worker_count):
                self.workers.append(asyncio.create_task(self.worker()))

            return True, None
        except Exception as e:
            return None, e

    async def __generate_targets(self):
        if self.enum_url is True:
            self.__total_targets += 1
            await self.task_q.put(
                (str(uuid.uuid4()),
                 self.smb_mgr.get_target().get_hostname_or_ip()))

        for target_gen in self.target_gens:
            async for uid, target, err in target_gen.generate():
                if err is not None:
                    print('Target gen error! %s' % err)
                    break

                if target in self.exclude_target:
                    continue

                self.__total_targets += 1
                await self.task_q.put((uid, target))
                await asyncio.sleep(0)

        self.__gens_finished = True

    async def run(self):
        try:
            _, err = await self.setup()
            if err is not None:
                raise err

            gen_task = asyncio.create_task(self.__generate_targets())

            await asyncio.gather(*self.workers)
            await self.result_processing_task
            return True, None
        except Exception as e:
            print(e)
            return None, e
Exemplo n.º 11
0
class SMBFileEnum:
    def __init__(self,
                 smb_url,
                 worker_count=10,
                 depth=3,
                 enum_url=False,
                 out_file=None,
                 show_pbar=True,
                 max_items=None,
                 max_runtime=None,
                 fetch_share_sd=False,
                 fetch_dir_sd=False,
                 fetch_file_sd=False,
                 task_q=None,
                 res_q=None,
                 output_type='str',
                 exclude_share=[],
                 exclude_dir=[],
                 exclude_target=[],
                 ext_result_q=None):
        self.target_gens = []
        self.smb_mgr = SMBConnectionURL(smb_url)
        self.worker_count = worker_count
        self.task_q = task_q
        self.res_q = res_q
        self.depth = depth
        self.workers = []
        self.result_processing_task = None
        self.enum_url = enum_url
        self.out_file = out_file
        self.show_pbar = show_pbar
        self.max_items = max_items
        self.max_runtime = max_runtime
        self.fetch_share_sd = fetch_share_sd
        self.fetch_dir_sd = fetch_dir_sd
        self.fetch_file_sd = fetch_file_sd
        self.output_type = output_type
        self.exclude_share = exclude_share
        self.exclude_dir = exclude_dir
        self.exclude_target = exclude_target
        self.ext_result_q = ext_result_q

        self.__gens_finished = False
        self.__total_targets = 0
        self.__total_finished = 0

        self.__total_size = 0
        self.__total_shares = 0
        self.__total_dirs = 0
        self.__total_files = 0
        self.__total_errors = 0
        self.__current_targets = {}

    async def __executor(self, tid, target):
        try:
            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err

                machine = SMBMachine(connection)
                async for obj, otype, err in machine.enum_all_recursively(
                        depth=self.depth,
                        maxentries=self.max_items,
                        fetch_share_sd=self.fetch_share_sd,
                        fetch_dir_sd=self.fetch_dir_sd,
                        fetch_file_sd=self.fetch_file_sd,
                        exclude_share=self.exclude_share,
                        exclude_dir=self.exclude_dir):
                    er = EnumResult(tid, target, (obj, otype, err))
                    await self.res_q.put(er)

        except asyncio.CancelledError:
            return
        except Exception as e:
            await self.res_q.put(
                EnumResult(tid,
                           target,
                           None,
                           error=e,
                           status=EnumResultStatus.ERROR))
        finally:
            await self.res_q.put(
                EnumResult(tid, target, None,
                           status=EnumResultStatus.FINISHED))

    async def worker(self):
        try:
            while True:
                indata = await self.task_q.get()
                if indata is None:
                    return

                tid, target = indata
                try:
                    await asyncio.wait_for(self.__executor(tid, target),
                                           timeout=self.max_runtime)
                except asyncio.CancelledError:
                    return
                except asyncio.TimeoutError as e:
                    await self.res_q.put(
                        EnumResult(tid,
                                   target,
                                   None,
                                   error=e,
                                   status=EnumResultStatus.ERROR))
                    await self.res_q.put(
                        EnumResult(tid,
                                   target,
                                   None,
                                   status=EnumResultStatus.FINISHED))
                    continue
                except Exception as e:
                    logger.exception('worker')
                    continue
        except asyncio.CancelledError:
            return

        except Exception as e:
            return e

    async def result_processing(self):
        try:
            pbar = None
            if self.show_pbar is True:
                pbar = {}
                pbar['targets'] = tqdm(desc='Targets     ',
                                       unit='',
                                       position=0)
                pbar['shares'] = tqdm(desc='Shares      ', unit='', position=1)
                pbar['dirs'] = tqdm(desc='Dirs        ', unit='', position=2)
                pbar['files'] = tqdm(desc='Files       ', unit='', position=3)
                pbar['filesize'] = tqdm(desc='Files (size)',
                                        unit='B',
                                        unit_scale=True,
                                        position=4)
                pbar['maxed'] = tqdm(desc='Maxed       ', unit='', position=5)
                pbar['enumerrors'] = tqdm(desc='Enum Errors ',
                                          unit='',
                                          position=6)
                pbar['connerrors'] = tqdm(desc='Conn Errors ',
                                          unit='',
                                          position=7)

            out_buffer = []
            final_iter = False
            while True:
                try:
                    if self.__gens_finished is True and self.show_pbar is True and pbar[
                            'targets'].total is None:
                        pbar['targets'].total = self.__total_targets
                        for key in pbar:
                            pbar[key].refresh()

                    if self.ext_result_q is not None:
                        out_buffer = []

                    if len(
                            out_buffer
                    ) >= 1000 or final_iter and self.ext_result_q is None:
                        out_data = ''
                        if self.output_type == 'str':
                            out_data = '\r\n'.join(
                                [str(x) for x in out_buffer])
                        elif self.output_type == 'tsv':
                            for res in out_buffer:
                                out_data += '%s\r\n' % res.to_tsv()
                        elif self.output_type == 'json':
                            for res in out_buffer:
                                out_data += '%s\r\n' % res.to_json()

                        else:
                            out_data = '\r\n'.join(out_buffer)

                        if self.out_file is not None:
                            with open(self.out_file, 'a+', newline='') as f:
                                try:
                                    f.write(out_data)
                                except:
                                    for line in out_data.split('\r\n'):
                                        try:
                                            f.write(line + '\r\n')
                                        except:
                                            logger.debug(
                                                'Encoding issue, skipping a line'
                                            )
                                            continue
                        else:
                            print(out_data)

                        if self.show_pbar is True:
                            for key in pbar:
                                pbar[key].refresh()

                        out_buffer = []
                        out_data = ''

                    if final_iter:
                        asyncio.create_task(self.terminate())
                        return
                    try:
                        er = await asyncio.wait_for(self.res_q.get(),
                                                    timeout=5)
                    except asyncio.TimeoutError:
                        if self.show_pbar is True:
                            for key in pbar:
                                pbar[key].refresh()

                        if self.__total_finished == self.__total_targets and self.__gens_finished is True:
                            final_iter = True
                        continue

                    if er.status == EnumResultStatus.FINISHED:
                        self.__total_finished += 1
                        if self.show_pbar is True:
                            pbar['targets'].update(1)

                        obj = EnumProgress(self.__total_targets,
                                           self.__total_finished,
                                           self.__gens_finished, er.target)
                        if self.ext_result_q is not None:
                            await self.ext_result_q.put(
                                EnumResultFinal(obj, 'progress', None,
                                                er.target, er.target_id))
                        out_buffer.append(
                            EnumResultFinal(obj, 'progress', None, er.target,
                                            er.target_id))
                        if self.__total_finished == self.__total_targets and self.__gens_finished is True:
                            final_iter = True
                            continue

                    if er.result is not None:
                        obj, otype, err = er.result
                        if self.ext_result_q is not None:
                            await self.ext_result_q.put(
                                EnumResultFinal(obj, otype, err, er.target,
                                                er.target_id))
                        out_buffer.append(
                            EnumResultFinal(obj, otype, err, er.target,
                                            er.target_id))
                        if otype is not None:
                            if otype == 'file':
                                self.__total_files += 1
                                if isinstance(
                                        obj.size,
                                        int) is True:  #just making sure...
                                    self.__total_size += obj.size
                                    if self.show_pbar is True:
                                        pbar['filesize'].update(obj.size)
                            elif otype == 'dir':
                                self.__total_dirs += 1
                            elif otype == 'share':
                                self.__total_shares += 1

                            if self.show_pbar is True:
                                if otype == 'dir':
                                    pbar['dirs'].update(1)
                                elif otype == 'file':
                                    pbar['files'].update(1)
                                elif otype == 'share':
                                    pbar['shares'].update(1)
                                elif otype == 'maxed':
                                    pbar['maxed'].update(1)

                        if err is not None:
                            self.__total_errors += 1
                            if self.show_pbar is True:
                                pbar['enumerrors'].update(1)

                    if er.status == EnumResultStatus.ERROR:
                        self.__total_errors += 1
                        if self.show_pbar is True:
                            pbar['connerrors'].update(1)

                except asyncio.CancelledError:
                    return
                except Exception as e:
                    logger.exception('result_processing inner')
                    asyncio.create_task(self.terminate())
                    return
        except asyncio.CancelledError:
            return
        except Exception as e:
            logger.exception('result_processing')
            asyncio.create_task(self.terminate())
        finally:
            if self.ext_result_q is not None:
                await self.ext_result_q.put(
                    EnumResultFinal(None, 'finished', None, None, None))

    async def terminate(self):
        for worker in self.workers:
            worker.cancel()
        if self.result_processing_task is not None:
            self.result_processing_task.cancel()

    async def setup(self):
        try:
            if self.res_q is None:
                self.res_q = asyncio.Queue(self.worker_count)
                self.result_processing_task = asyncio.create_task(
                    self.result_processing())
            if self.task_q is None:
                self.task_q = asyncio.Queue(self.worker_count)

            for _ in range(self.worker_count):
                self.workers.append(asyncio.create_task(self.worker()))

            return True, None
        except Exception as e:
            return None, e

    async def __generate_targets(self):
        if self.enum_url is True:
            self.__total_targets += 1
            await self.task_q.put(
                (str(uuid.uuid4()),
                 self.smb_mgr.get_target().get_hostname_or_ip()))

        for target_gen in self.target_gens:
            async for uid, target, err in target_gen.generate():
                if err is not None:
                    print('Target gen error! %s' % err)
                    break

                if target in self.exclude_target:
                    continue

                self.__total_targets += 1
                await self.task_q.put((uid, target))
                await asyncio.sleep(0)

        self.__gens_finished = True

    async def run(self):
        try:
            _, err = await self.setup()
            if err is not None:
                raise err

            gen_task = asyncio.create_task(self.__generate_targets())

            await asyncio.gather(*self.workers)
            await self.result_processing_task
            return True, None
        except Exception as e:
            logger.exception('run')
            return None, e