Пример #1
0
async def filereader_test(connection_string, filename, proxy=None):
    #target = SMBTarget.from_connection_string(connection_string)
    #if proxy is not None:
    #	target.proxy = SMBTargetProxy.from_connection_string(proxy)
    #	print(str(target))
    #
    #credential = SMBCredential.from_connection_string(connection_string)
    cu = SMBConnectionURL(connection_string)
    credential = cu.get_credential()
    target = cu.get_target()

    print(credential)
    print(target)
    input()

    spneg = AuthenticatorBuilder.to_spnego_cred(credential, target)

    async with SMBConnection(spneg, target) as connection:
        await connection.login()

        async with SMBFileReader(connection) as reader:
            await reader.open(filename)
            data = await reader.read()
            print(data)
            """
Пример #2
0
class SMBClient(aiocmd.PromptToolkitCmd):
	def __init__(self, url = None, silent = False, no_dce = False):
		aiocmd.PromptToolkitCmd.__init__(self, ignore_sigint=False) #Setting this to false, since True doesnt work on windows...
		self.conn_url = None
		if url is not None:
			self.conn_url = SMBConnectionURL(url)
		self.connection = None
		self.machine = None
		self.is_anon = False
		self.silent = silent
		self.no_dce = no_dce # diables ANY use of the DCE protocol (eg. share listing) This is useful for new(er) windows servers where they forbid the users to use any form of DCE

		self.shares = {} #name -> share
		self.__current_share = None
		self.__current_directory = None
	
	async def do_coninfo(self):
		try:
			from aiosmb._version import __version__ as smbver
			from asysocks._version import __version__ as socksver
			from minikerberos._version import __version__ as kerbver
			from winsspi._version import __version__ as winsspiver
			from winacl._version import __version__ as winaclver

			print(self.conn_url)
			print('AIOSMB: %s' % smbver)
			print('ASYSOCKS: %s' % socksver)
			print('MINIKERBEROS: %s' % kerbver)
			print('WINSSPI: %s' % winsspiver)
			print('WINACL: %s' % winaclver)
			return True, None
		
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_login(self, url = None):
		"""Connects to the remote machine"""
		try:
			if self.conn_url is None and url is None:
				print('No url was set, cant do logon')
			if url is not None:
				self.conn_url = SMBConnectionURL(url)

			cred = self.conn_url.get_credential()
			
			if cred.secret is None and cred.username is None and cred.domain is None:
				self.is_anon = True			
			
			self.connection  = self.conn_url.get_connection()
			
			logger.debug(self.conn_url.get_credential())
			logger.debug(self.conn_url.get_target())

			_, err = await self.connection.login()
			if err is not None:
				raise err
			self.machine = SMBMachine(self.connection)
			if self.silent is False:
				print('Login success')
			return True, None
		except Exception as e:
			traceback.print_exc()
			print('Login failed! Reason: %s' % str(e))
			return False, e

	async def do_logout(self):
		if self.machine is not None:
			await self.machine.close()
		self.machine = None

		if self.connection is not None:
			try:
				await self.connection.terminate()
			except Exception as e:
				logger.exception('connection.close')
		self.connection = None

	async def _on_close(self):
		await self.do_logout()

	async def do_nodce(self):
		"""Disables automatic share listing on login"""
		self.no_dce = True

	async def do_shares(self, show = True):
		"""Lists available shares"""
		try:
			if self.machine is None:
				print('Not logged in! Use "login" first!')
				return False, Exception('Not logged in!')
			async for share, err in self.machine.list_shares():
				if err is not None:
					raise err
				self.shares[share.name] = share
				if show is True:
					print(share.name)
			return True, None
				
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e
		

	async def do_sessions(self):
		"""Lists sessions of connected users"""
		try:
			async for sess, err in self.machine.list_sessions():
				if err is not None:
					raise err
				print("%s : %s" % (sess.username, sess.ip_addr))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()


	async def do_wsessions(self):
		"""Lists sessions of connected users"""
		try:
			async for sess, err in self.machine.wkstlist_sessions():
				if err is not None:
					raise err
				print("%s" % sess.username)
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_domains(self):
		"""Lists domain"""
		try:
			async for domain, err in self.machine.list_domains():
				if err is not None:
					raise err
				print(domain)
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_localgroups(self):
		"""Lists local groups"""
		try:
			async for name, sid, err in self.machine.list_localgroups():
				if err is not None:
					raise err
				print("%s : %s" % (name, sid))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()
	
	async def do_domaingroups(self, domain_name):
		"""Lists groups in a domain"""
		try:
			async for name, sid, err in self.machine.list_groups(domain_name):
				if err is not None:
					raise err
				print("%s : %s" % (name, sid))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()
	
	async def do_groupmembers(self, domain_name, group_name):
		"""Lists members of an arbitrary group"""
		try:
			async for domain, username, sid, err in self.machine.list_group_members(domain_name, group_name):
				if err is not None:
					raise err
				print("%s\\%s : %s" % (domain, username, sid))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_localgroupmembers(self, group_name):
		"""Lists members of a local group"""
		try:
			async for domain, username, sid, err in self.machine.list_group_members('Builtin', group_name):
				if err is not None:
					raise err
				print("%s\\%s : %s" % (domain, username, sid))
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_addsidtolocalgroup(self, group_name, sid):
		"""Add member (by SID) to a local group"""
		try:
			result, err = await self.machine.add_sid_to_group('Builtin', group_name, sid)
			if err is not None:
				raise err
			if result:
				print('Modification OK!')
			else:
				print('Something went wrong, status != ok')
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_use(self, share_name):
		"""selects share to be used"""
		try:
			if self.is_anon is False or self.no_dce:
				#anonymous connection might not have access to IPC$ so we are skipping the check
				if len(self.shares) == 0:
					_, err = await self.do_shares(show = False)
					if err is not None:
						raise err

				if share_name not in self.shares:
					if share_name.upper() not in self.shares:
						print('Error! Uknown share name %s' % share_name)
						return
					share_name = share_name.upper()

				self.__current_share = self.shares[share_name]
			else:
				self.__current_share = SMBShare.from_unc('\\\\%s\\%s' % (self.connection.target.get_hostname_or_ip(), share_name))
			_, err = await self.__current_share.connect(self.connection)
			if err is not None:
				raise err
			self.__current_directory = self.__current_share.subdirs[''] #this is the entry directory
			self.prompt = '[%s]$ ' % self.__current_directory.unc_path
			_, err = await self.do_refreshcurdir()
			if err is not None:
				raise err
			return True, None

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e
			
	async def do_dir(self):
		return await self.do_ls()

	async def do_ls(self):
		try:
			if self.__current_share is None:
				print('No share selected!')
				return
			if self.__current_directory is None:
				print('No directory selected!')
				return
			
			for entry in self.__current_directory.get_console_output():
				print(entry)
			
			return True, None
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_refreshcurdir(self):
		try:
			async for entry in self.machine.list_directory(self.__current_directory):
				#no need to put here anything, the dir bject will store the refreshed data
				a = 1
			
			return True, None
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_cd(self, directory_name):
		try:
			if self.__current_share is None:
				print('No share selected!')
				return False, None
			if self.__current_directory is None:
				print('No directory selected!')
				return False, None
			
			if directory_name not in self.__current_directory.subdirs:
				if directory_name == '..':
					self.__current_directory = self.__current_directory.parent_dir
					self.prompt = '[%s] $' % (self.__current_directory.unc_path)
					return True, None
				else:
					print('The directory "%s" is not in parent directory "%s"' % (directory_name, self.__current_directory.fullpath))
					return False, None
			
			else:
				self.__current_directory = self.__current_directory.subdirs[directory_name]
				self.prompt = '[%s] $' % (self.__current_directory.unc_path)
				_, err = await self.do_refreshcurdir()
				if err is not None:
					raise err

				return True, None
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	def get_current_dirs(self):
		if self.__current_directory is None:
			return []
		return list(self.__current_directory.subdirs.keys())

	def get_current_files(self):
		if self.__current_directory is None:
			return []
		return list(self.__current_directory.files.keys())

	async def do_getfilesd(self, file_name):
		try:
			if file_name not in self.__current_directory.files:
				print('file not in current directory!')
				return False, None
			file_obj = self.__current_directory.files[file_name]
			sd, err = await file_obj.get_security_descriptor(self.connection)
			if err is not None:
				raise err
			print(sd.to_sddl())
			return True, None

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_getdirsd(self):
		try:
			sd, err = await self.__current_directory.get_security_descriptor(self.connection)
			if err is not None:
				raise err
			print(str(sd.to_sddl()))
			return True, None
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	def _cd_completions(self):
		return SMBPathCompleter(get_current_dirs = self.get_current_dirs)

	def _get_completions(self):
		return SMBPathCompleter(get_current_dirs = self.get_current_files)
	
	def _del_completions(self):
		return SMBPathCompleter(get_current_dirs = self.get_current_files)
	
	def _sid_completions(self):
		return SMBPathCompleter(get_current_dirs = self.get_current_files)
	
	def _dirsid_completions(self):
		return SMBPathCompleter(get_current_dirs = self.get_current_dirs)


	async def do_services(self):
		"""Lists remote services"""
		try:
			async for service, err in self.machine.list_services():
				if err is not None:
					raise err
				print(service)
			
			return True, None
			
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_serviceen(self, service_name):
		"""Enables a remote service"""
		try:
			res, err = await self.machine.enable_service(service_name)
			if err is not None:
				raise err
			print(res)
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_servicecreate(self, service_name, command, display_name = None):
		"""Creates a remote service"""
		try:
			_, err = await self.machine.create_service(service_name, command, display_name)
			if err is not None:
				raise err
			print('Service created!')
			return True, None

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e
	
	async def do_servicecmdexec(self, command, timeout = 1):
		"""Executes a shell command as a service and returns the result"""
		try:
			buffer = b''
			if timeout is None or timeout == '':
				timeout = 1
			timeout = int(timeout)
			async for data, err in self.machine.service_cmd_exec(command):
				if err is not None:
					raise err
				if data is None:
					break
				
				try:
					print(data.decode())
				except:
					print(data)
			return True, None

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_servicedeploy(self, path_to_exec, remote_path):
		"""Deploys a binary file from the local system as a service on the remote system"""
		#servicedeploy /home/devel/Desktop/cmd.exe /shared/a.exe
		try:
			basename = ntpath.basename(remote_path)
			remote_path = '\\\\%s\\%s\\%s\\%s' % (self.connection.target.get_hostname_or_ip(), self.__current_share.name, self.__current_directory.fullpath , basename)
			_, err = await self.machine.deploy_service(path_to_exec, remote_path = remote_path)
			if err is not None:
				raise err
			print('Service deployed!')
			return True, None

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_put(self, file_name):
		"""Uploads a file to the remote share"""
		try:
			basename = ntpath.basename(file_name)
			dst = '\\%s\\%s\\%s' % (self.__current_share.name, self.__current_directory.fullpath , basename)
			_, err = await self.machine.put_file(file_name, dst)
			if err is not None:
				print('Failed to put file! Reason: %s' % err)
				return False, err
			print('File uploaded!')
			_, err = await self.do_refreshcurdir()
			if err is not None:
				raise err
			
			return True, None

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_del(self, file_name):
		"""Removes a file from the remote share"""
		try:
			basename = ntpath.basename(file_name)
			dst = '\\%s\\%s\\%s' % (self.__current_share.name, self.__current_directory.fullpath , basename)
			_, err = await self.machine.del_file(dst)
			if err is not None:
				raise err
			print('File deleted!')
			_, err = await self.do_refreshcurdir()
			if err is not None:
				raise err
			return True, None

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_regsave(self, hive_name, file_path):
		"""Saves a registry hive to a file on remote share"""
		try:
			_, err = await self.machine.save_registry_hive(hive_name, file_path)
			if err is not None:
				raise err
			print('Hive saved!')
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_reglistusers(self):
		"""Saves a registry hive to a file on remote share"""
		try:
			users, err = await self.machine.reg_list_users()
			if err is not None:
				raise err
			for user in users:
				print(user)
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e


	


	async def do_get(self, file_name):
		"""Download a file from the remote share to the current folder"""
		try:
			matched = []
			if file_name not in self.__current_directory.files:
				
				for fn in fnmatch.filter(list(self.__current_directory.files.keys()), file_name):
					matched.append(fn)
				if len(matched) == 0:
					print('File with name %s is not present in the directory %s' % (file_name, self.__current_directory.name))
					return False, None
			else:
				matched.append(file_name)
			
			for file_name in matched:
				file_obj = self.__current_directory.files[file_name]
				with tqdm.tqdm(desc = 'Downloading %s' % file_name, total=file_obj.size, unit='B', unit_scale=True, unit_divisor=1024) as pbar:
					with open(file_name, 'wb') as outfile:
						async for data, err in self.machine.get_file_data(file_obj):
							if err is not None:
								raise err
							if data is None:
								break
							outfile.write(data)
							pbar.update(len(data))
			return True, None
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e


	
	async def do_mkdir(self, directory_name):
		"""Creates a directory on the remote share"""
		try:
			_, err = await self.machine.create_subdirectory(directory_name, self.__current_directory)
			if err is not None:
				raise err
			print('Directory created!')
			_, err = await self.do_refreshcurdir()
			if err is not None:
				raise err
			return True, None

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_dcsync(self, username = None):
		"""It's a suprse tool that will help us later"""
		try:
			users = []
			if username is not None:
				users.append(username)
			async for secret, err in self.machine.dcsync(target_users=users):
				if err is not None:
					raise err
				if secret is None:
					continue
				print(str(secret))
			
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_users(self, domain = None):
		"""List users in domain"""
		try:
			async for username, user_sid, err in self.machine.list_domain_users(domain):
				if err is not None:
					print(str(err))
				print('%s %s' % (username, user_sid))
			
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_lsass(self):
		try:
			res, err = await self.machine.task_dump_lsass()
			if err is not None:
				print(str(err))
			print(res)

			await res.close()
		
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e

	async def do_printerbug(self, attacker_ip):
		"""Printerbug"""
		try:
			res, err = await self.machine.printerbug(attacker_ip)
			if err is not None:
				print(str(err))
			print(res)
		
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_tasks(self):
		"""List scheduled tasks """
		try:
			async for taskname, err in self.machine.tasks_list():
				if err is not None:
					raise err
				print(taskname)
			
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_taskregister(self, template_file, task_name = None):
		"""Registers a new scheduled task"""
		try:
			with open(template_file, 'r') as f:
				template = f.read()

			res, err = await self.machine.tasks_register(template, task_name = task_name)
			if err is not None:
				logger.info('[!] Failed to register new task!')
				raise err
		
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_taskdel(self, task_name):
		"""Deletes a scheduled task	"""
		try:
			_, err = await self.machine.tasks_delete(task_name)
			if err is not None:
				raise err

			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e


	async def do_taskcmdexec(self, command, timeout = 1):
		""" Executes a shell command using the scheduled tasks service"""
		try:
			buffer = b''
			if timeout is None or timeout == '':
				timeout = 1
			timeout = int(timeout)
			async for data, err in self.machine.tasks_cmd_exec(command, timeout):
				if err is not None:
					raise err
				if data is None:
					break
				
				try:
					print(data.decode())
				except:
					print(data)
			return True, None
			
			#await self.machine.tasks_execute_commands([command])
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_interfaces(self):
		""" Lists all network interfaces of the remote machine """
		try:
			interfaces, err = await self.machine.list_interfaces()
			if err is not None:
				raise err
			for iface in interfaces:
				print('%d: %s' % (iface['index'], iface['address']))
			
			return True, None
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_enumall(self, depth = 3):
		""" Enumerates all shares for all files and folders recursively """
		try:
			depth = int(depth)
			async for path, otype, err in self.machine.enum_all_recursively(depth = depth):
				if otype is not None:
					print('[%s] %s' % (otype[0].upper(), path))
				if err is not None:
					print('[E] %s %s' % (err, path))

			return True, None
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_printerenumdrivers(self):
		""" Enumerates all shares for all files and folders recursively """
		try:
			drivers, err = await self.machine.enum_printer_drivers()
			if err is not None:
				raise err
			for driver in drivers:
				print(driver)
			return True, None
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e

	async def do_printnightmare(self, share, driverpath = ''):
		""" printnightmare bug using the RPRN protocol """
		try:
			if len(driverpath) == 0:
				driverpath = None
			_, err = await self.machine.printnightmare(share, driverpath)
			if err is not None:
				raise err
			return True, None
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e
	
	async def do_parprintnightmare(self, share, driverpath = ''):
		""" printnightmare bug using the PAR protocol """
		try:
			if len(driverpath) == 0:
				driverpath = None
			_, err = await self.machine.par_printnightmare(share, driverpath)
			if err is not None:
				raise err
			return True, None
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
			return None, e
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
			return None, e
		except Exception as e:
			traceback.print_exc()
			return None, e
Пример #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
Пример #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
Пример #5
0
class SMBClient(aiocmd.PromptToolkitCmd):
	def __init__(self, url = None):
		aiocmd.PromptToolkitCmd.__init__(self, ignore_sigint=False) #Setting this to false, since True doesnt work on windows...
		self.conn_url = None
		if url is not None:
			self.conn_url = SMBConnectionURL(url)
		self.connection = None
		self.machine = None

		self.shares = {} #name -> share
		self.__current_share = None
		self.__current_directory = None

	async def do_login(self, url = None):
		"""Connects to the remote machine"""
		try:
			if self.conn_url is None and url is None:
				print('No url was set, cant do logon')
			if url is not None:
				self.conn_url = SMBConnectionURL(url)
			
			self.connection  = self.conn_url.get_connection()
			
			logger.debug(self.conn_url.get_credential())
			logger.debug(self.conn_url.get_target())

			await self.connection.login()
			self.machine = SMBMachine(self.connection)
		except Exception as e:
			traceback.print_exc()
		else:
			print('Login success')

	async def do_shares(self, show = True):
		"""Lists available shares"""
		try:
			async for share, err in ef_gen(self.machine.list_shares()):
				if err is not None:
					raise err
				self.shares[share.name] = share
				if show is True:
					print(share.name)
				
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_sessions(self):
		"""Lists sessions of connected users"""
		try:
			async for sess, err in ef_gen(self.machine.list_sessions()):
				if err is not None:
					raise err
				print("%s : %s" % (sess.username, sess.ip_addr))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_domains(self):
		"""Lists domain"""
		try:
			async for domain, err in self.machine.list_domains():
				if err is not None:
					raise err
				print(domain)
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_localgroups(self):
		"""Lists local groups"""
		try:
			async for name, sid, err in self.machine.list_localgroups():
				if err is not None:
					raise err
				print("%s : %s" % (name, sid))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()
	
	async def do_domaingroups(self, domain_name):
		"""Lists groups in a domain"""
		try:
			async for name, sid, err in self.machine.list_groups(domain_name):
				if err is not None:
					raise err
				print("%s : %s" % (name, sid))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()
	
	async def do_groupmembers(self, domain_name, group_name):
		"""Lists members of an arbitrary group"""
		try:
			async for domain, username, sid, err in self.machine.list_group_members(domain_name, group_name):
				if err is not None:
					raise err
				print("%s\\%s : %s" % (domain, username, sid))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_localgroupmembers(self, group_name):
		"""Lists members of a local group"""
		try:
			async for domain, username, sid, err in self.machine.list_group_members('Builtin', group_name):
				if err is not None:
					raise err
				print("%s\\%s : %s" % (domain, username, sid))
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_use(self, share_name):
		"""selects share to be used"""
		try:
			if len(self.shares) == 0:
				await self.do_shares(show = False)

			if share_name not in self.shares:
				if share_name.upper() not in self.shares:
					print('Error! Uknown share name %s' % share_name)
					return
				share_name = share_name.upper()

			self.__current_share = self.shares[share_name]
			await self.__current_share.connect(self.connection)
			self.__current_directory = self.__current_share.subdirs[''] #this is the entry directory
			self.prompt = '[%s] $' % self.__current_directory.unc_path
			await self.do_ls(False)

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()
			
	
	async def do_ls(self, show = True):
		try:
			if self.__current_share is None:
				print('No share selected!')
				return
			if self.__current_directory is None:
				print('No directory selected!')
				return
			
			#print(self.__current_directory)
			async for entry in self.machine.list_directory(self.__current_directory):
				if show == True:
					print(entry)
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_cd(self, directory_name):
		try:
			if self.__current_share is None:
				print('No share selected!')
				return
			if self.__current_directory is None:
				print('No directory selected!')
				return
			
			if directory_name not in self.__current_directory.subdirs:
				if directory_name == '..':
					self.__current_directory = self.__current_directory.parent_dir
					self.prompt = '[%s] $' % (self.__current_directory.unc_path)
					return
				else:
					print('The directory "%s" is not in parent directory "%s"' % (directory_name, self.__current_directory.fullpath))
			
			else:
				self.__current_directory = self.__current_directory.subdirs[directory_name]
				self.prompt = '[%s] $' % (self.__current_directory.unc_path)
				await self.do_ls(False)
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	def get_current_dirs(self):
		if self.__current_directory is None:
			return []
		return list(self.__current_directory.subdirs.keys())

	def get_current_files(self):
		if self.__current_directory is None:
			return []
		return list(self.__current_directory.files.keys())

	async def do_sid(self, file_name):
		if file_name not in self.__current_directory.files:
			print('file not in current directory!')
			return
		file_obj = self.__current_directory.files[file_name]
		sid = await file_obj.get_security_descriptor(self.connection)
		print(str(sid))

	async def do_dirsid(self):
		sid = await self.__current_directory.get_security_descriptor(self.connection)
		print(str(sid))

	def _cd_completions(self):
		return SMBPathCompleter(get_current_dirs = self.get_current_dirs)

	def _get_completions(self):
		return SMBPathCompleter(get_current_dirs = self.get_current_files)

	async def do_services(self):
		"""Lists remote services"""
		try:
			async for service, err in self.machine.list_services():
				if err is not None:
					raise err
				print(service)
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_serviceen(self, service_name):
		"""Enables a remote service"""
		try:
			res, err = await self.machine.enable_service(service_name)
			if err is not None:
				raise err
			print(res)
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_servicecreate(self, service_name, command, display_name = None):
		"""Creates a remote service"""
		try:
			res, err = await self.machine.create_service(service_name, command, display_name)
			if err is not None:
				raise err
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_servicedeploy(self, path_to_exec, remote_path):
		"""Deploys a binary file from the local system as a service on the remote system"""
		#servicedeploy /home/devel/Desktop/cmd.exe /shared/a.exe
		try:
			basename = ntpath.basename(remote_path)
			remote_path = '\\\\%s\\%s\\%s\\%s' % (self.connection.target.get_hostname_or_ip(), self.__current_share.name, self.__current_directory.fullpath , basename)
			await rr(self.machine.deploy_service(path_to_exec, remote_path = remote_path))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_put(self, file_name):
		"""Uploads a file to the remote share"""
		try:
			basename = ntpath.basename(file_name)
			dst = '\\%s\\%s\\%s' % (self.__current_share.name, self.__current_directory.fullpath , basename)
			print(basename)
			print(dst)
			await self.machine.put_file(file_name, dst)
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_del(self, file_name):
		"""Removes a file from the remote share"""
		try:
			basename = ntpath.basename(file_name)
			dst = '\\%s\\%s\\%s' % (self.__current_share.name, self.__current_directory.fullpath , basename)
			print(dst)
			await self.machine.del_file(dst)
			
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_regsave(self, hive_name, file_path):
		"""Saves a registry hive to a file on remote share"""
		try:
			await rr(self.machine.save_registry_hive(hive_name, file_path))
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_get(self, file_name):
		"""Download a file from the remote share to the current folder"""
		try:
			matched = []
			if file_name not in self.__current_directory.files:
				
				for fn in fnmatch.filter(list(self.__current_directory.files.keys()), file_name):
					matched.append(fn)
				if len(matched) == 0:
					print('File with name %s is not present in the directory %s' % (file_name, self.__current_directory.name))
					return
			else:
				matched.append(file_name)
			
			for file_name in matched:
				file_obj = self.__current_directory.files[file_name]
				with tqdm.tqdm(desc = 'Downloading %s' % file_name, total=file_obj.size, unit='B', unit_scale=True, unit_divisor=1024) as pbar:
					with open(file_name, 'wb') as outfile:
						async for data in self.machine.get_file_data(file_obj):
							if data is None:
								break
							outfile.write(data)
							pbar.update(len(data))
	
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	
	async def do_mkdir(self, directory_name):
		"""Creates a directory on the remote share"""
		try:
			await self.machine.create_subdirectory(directory_name, self.__current_directory)

		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_dcsync(self):
		"""It's a suprse tool that will help us later"""
		try:
			async for secret, err in self.machine.dcsync():
				if err is not None:
					raise err
				print(str(secret))
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()

	async def do_users(self, domain = None):
		"""List users in domain"""
		try:
			async for username, user_sid, err in self.machine.list_domain_users(domain):
				if err is not None:
					print(str(err))
				print('%s %s' % (username, user_sid))
		
		except SMBException as e:
			logger.debug(traceback.format_exc())
			print(e.pprint())
		except SMBMachineException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except DCERPCException as e:
			logger.debug(traceback.format_exc())
			print(str(e))
		except Exception as e:
			traceback.print_exc()
Пример #6
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
Пример #7
0
async def amain(url, service, template, altname, onbehalf, cn = None, pfx_file = None, pfx_password = None, enroll_cert = None, enroll_password = None):
	try:
		if pfx_file is None:
			pfx_file = 'cert_%s.pfx' % os.urandom(4).hex()
		if pfx_password is None:
			pfx_password = '******'
		
		print('[+] Parsing connection parameters...')
		su = SMBConnectionURL(url)
		ip = su.get_target().get_hostname_or_ip()

		if cn is None:
			cn = '%s@%s' % (su.username, su.domain)
		
		print('[*] Using CN: %s' % cn)
		
		print('[+] Generating RSA privat key...')
		key = rsa.generate_private_key(0x10001, 2048)

		print('[+] Building certificate request...')
		attributes = {
			"CertificateTemplate": template,
		}
		csr = x509.CertificateSigningRequestBuilder()
		csr = csr.subject_name(
				x509.Name(
					[
						x509.NameAttribute(NameOID.COMMON_NAME, cn),
					]
				)
			)

		if altname:
			altname = core.UTF8String(altname).dump()
			csr = csr.add_extension(
				x509.SubjectAlternativeName(
					[
						x509.OtherName(PRINCIPAL_NAME, altname),
					]
				),
				critical=False,
			)

		csr = csr.sign(key, hashes.SHA256())
		
		if onbehalf is not None:
			agent_key = None
			agent_cert = None
			with open(enroll_cert, 'rb') as f:
				agent_key, agent_cert, _ = pkcs12.load_key_and_certificates(f.read(), enroll_password)
				
			pkcs7builder = pkcs7.PKCS7SignatureBuilder().set_data(csr).add_signer(agent_key, agent_cert, hashes.SHA1())
			csr = pkcs7builder.sign(Encoding.DER, options=[pkcs7.PKCS7Options.Binary])
		else:
			csr = csr.public_bytes(Encoding.DER)
		
		print('[+] Connecting to EPM...')
		target, err = await EPM.create_target(ip, ICPRRPC().service_uuid, dc_ip = su.get_target().dc_ip, domain = su.get_target().domain)
		if err is not None:
			raise err
		
		print('[+] Connecting to ICRPR service...')
		gssapi = AuthenticatorBuilder.to_spnego_cred(su.get_credential(), target)
		auth = DCERPCAuth.from_smb_gssapi(gssapi)
		connection = DCERPC5Connection(auth, target)
		rpc, err = await ICPRRPC.from_rpcconnection(connection, perform_dummy=True)
		if err is not None:
			raise err
		logger.debug('DCE Connected!')
		
		print('[+] Requesting certificate from the service...')
		res, err = await rpc.request_certificate(service, csr, attributes)
		if err is not None:
			print('[-] Request failed!')
			raise err
		
		
		if res['encodedcert'] in [None, b'']:
			raise Exception('No certificate was returned from server!. Full message: %s' % res)
		
		print('[+] Got certificate!')
		cert = x509.load_der_x509_certificate(res['encodedcert'])
		print("[*]   Cert subject: {}".format(cert.subject.rfc4514_string()))
		print("[*]   Cert issuer: {}".format(cert.issuer.rfc4514_string()))
		print("[*]   Cert Serial: {:X}".format(cert.serial_number))
		
		try:
			ext = cert.extensions.get_extension_for_oid(ExtensionOID.EXTENDED_KEY_USAGE)
			for oid in ext.value:
				print("[*]   Cert Extended Key Usage: {}".format(EKUS_NAMES.get(oid.dotted_string, oid.dotted_string)))
		except:
			print('[-]   Could not verify extended key usage')

		try:
			ext = cert.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
			for name in ext.value.get_values_for_type(x509.OtherName):
				if name.type_id == x509.ObjectIdentifier("1.3.6.1.4.1.311.20.2.3"):
					print('[*]   Certificate ALT NAME: %s' % core.UTF8String.load(name.value).native)
					break
			else:
				print('[-]   Certificate doesnt have ALT NAME')
		except:
			print('[-]   Certificate doesnt have ALT NAME')
		
		print('[+] Writing certificate to disk (file:"%s" pass: "******")...' % (pfx_file, pfx_password))
		
		# Still waiting for the day oscrypto will have a pfx serializer :(
		# Until that we'd need to use cryptography
		with open(pfx_file, 'wb') as f:
			data = pkcs12.serialize_key_and_certificates(
				name=b"",
				key=key,
				cert=cert,
				cas=None,
				encryption_algorithm=BestAvailableEncryption(pfx_password.encode())
			)
			f.write(data)

		print('[+] Finished!')
		return True, None
	except Exception as e:
		traceback.print_exc()
		return False, e
Пример #8
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
Пример #9
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
Пример #10
0
class SMBClient(aiocmd.PromptToolkitCmd):
    def __init__(self, url=None):
        aiocmd.PromptToolkitCmd.__init__(
            self, ignore_sigint=False
        )  #Setting this to false, since True doesnt work on windows...
        self.conn_url = None
        if url is not None:
            self.conn_url = SMBConnectionURL(url)
        self.connection = None
        self.machine = None

        self.shares = {}  #name -> share
        self.__current_share = None
        self.__current_directory = None

    async def do_login(self, url=None):
        try:
            if self.conn_url is None and url is None:
                print('No url was set, cant do logon')
            if url is not None:
                self.conn_url = SMBConnectionURL(url)

            self.connection = self.conn_url.get_connection()

            logger.debug(self.conn_url.get_credential())
            logger.debug(self.conn_url.get_target())

            await self.connection.login()
            self.machine = SMBMachine(self.connection)
        except Exception as e:
            traceback.print_exc()
        else:
            print('Login success')

    async def do_shares(self, show=True):
        try:
            async for share in self.machine.list_shares():
                self.shares[share.name] = share
                if show is True:
                    print(share.name)

        except Exception as e:
            traceback.print_exc()

    async def do_sessions(self):
        try:
            async for sess in self.machine.list_sessions():
                print("%s : %s" % (sess.username, sess.ip_addr))
        except Exception as e:
            traceback.print_exc()

    async def do_domains(self):
        try:
            async for domain in self.machine.list_domains():
                print(domain)
        except Exception as e:
            traceback.print_exc()

    async def do_localgroups(self):
        try:
            async for name, sid in self.machine.list_localgroups():
                print("%s : %s" % (name, sid))
        except Exception as e:
            traceback.print_exc()

    async def do_domaingroups(self, domain_name):
        try:
            async for name, sid in self.machine.list_groups(domain_name):
                print("%s : %s" % (name, sid))
        except Exception as e:
            traceback.print_exc()

    async def do_groupmembers(self, domain_name, group_name):
        try:
            async for domain, username, sid in self.machine.list_group_members(
                    domain_name, group_name):
                print("%s\\%s : %s" % (domain, username, sid))
        except Exception as e:
            traceback.print_exc()

    async def do_localgroupmembers(self, group_name):
        try:
            async for domain, username, sid in self.machine.list_group_members(
                    'Builtin', group_name):
                print("%s\\%s : %s" % (domain, username, sid))
        except Exception as e:
            traceback.print_exc()

    async def do_use(self, share_name):
        try:
            if len(self.shares) == 0:
                await self.do_shares(show=False)

            if share_name in self.shares:
                self.__current_share = self.shares[share_name]
                await self.__current_share.connect(self.connection)
                self.__current_directory = self.__current_share.subdirs[
                    '']  #this is the entry directory

            else:
                print('Error! Uknown share name %s' % share_name)
        except Exception as e:
            traceback.print_exc()

    async def do_ls(self):
        try:
            if self.__current_share is None:
                print('No share selected!')
                return
            if self.__current_directory is None:
                print('No directory selected!')
                return

            print(self.__current_directory)
            async for entry in self.machine.list_directory(
                    self.__current_directory):
                print(entry)
        except Exception as e:
            traceback.print_exc()

    async def do_cd(self, directory_name):
        try:
            if self.__current_share is None:
                print('No share selected!')
                return
            if self.__current_directory is None:
                print('No directory selected!')
                return

            if directory_name not in self.__current_directory.subdirs:
                print('The directory "%s" is not in parent directory "%s"' %
                      (directory_name, self.__current_directory.fullpath))

            else:
                self.__current_directory = self.__current_directory.subdirs[
                    directory_name]

        except Exception as e:
            traceback.print_exc()

    async def do_services(self):
        try:
            async for service in self.machine.list_services():
                print(service)

        except Exception as e:
            traceback.print_exc()

    async def do_put(self, file_name):
        try:
            basename = ntpath.basename(file_name)
            dst = '\\\\%s\\%s\\%s\\%s' % (
                self.connection.target.get_hostname_or_ip(),
                self.__current_share.name, self.__current_directory.fullpath,
                basename)
            print(basename)
            print(dst)
            await self.machine.put_file_raw(file_name, dst)

        except Exception as e:
            traceback.print_exc()

    async def do_get(self, file_name):
        try:
            if file_name not in self.__current_directory.files:
                print('File with name %s is not present in the directory %s' %
                      (file_name, self.__current_directory.name))
                return

            out_path = file_name
            await self.machine.get_file(
                out_path, self.__current_directory.files[file_name])

        except Exception as e:
            traceback.print_exc()

    async def do_mkdir(self, directory_name):
        try:
            await self.machine.create_subdirectory(directory_name,
                                                   self.__current_directory)

        except Exception as e:
            traceback.print_exc()

    async def do_dcsync(self):
        try:
            async for secret in self.machine.dcsync():
                print(str(secret))
        except Exception as e:
            traceback.print_exc()