diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/config.json b/config.json new file mode 100644 index 0000000..c4d07d3 --- /dev/null +++ b/config.json @@ -0,0 +1,11 @@ +{ + "host": "0.0.0.0", + "port": 7777, + "server": { + "password": "", + "hostname": "Python > C", + "max_players": 50, + "mode": "yay", + "language": "spoop" + } +} \ No newline at end of file diff --git a/handlers/__init__.py b/handlers/__init__.py new file mode 100644 index 0000000..dfbee8a --- /dev/null +++ b/handlers/__init__.py @@ -0,0 +1,4 @@ +from . import mainHandler +from . import serverPingHandler + +from . import handshakeHandler \ No newline at end of file diff --git a/handlers/handshakeHandler.py b/handlers/handshakeHandler.py new file mode 100644 index 0000000..f710c77 --- /dev/null +++ b/handlers/handshakeHandler.py @@ -0,0 +1,3 @@ +def handle(client, data): + print("![{}] -> Handshake".format(client.addr)) + return \ No newline at end of file diff --git a/handlers/mainHandler.py b/handlers/mainHandler.py new file mode 100644 index 0000000..6a5cb3f --- /dev/null +++ b/handlers/mainHandler.py @@ -0,0 +1,19 @@ +from . import handshakeHandler + +def handle(client, data): + print("?[{}] -> {} / {}".format(client.addr, data, data.hex())) + + if client.state == 0: # Perform handshake if possible + client.state = 1 + return b"\x1a\x1e\xd1\xd1" + if client.state == 1: + client.state = 2 + return b"\x19\x00" + if client.state == 2: + client.state = 3 + return b"\xe3\x00\x00" + if client.state == 3: + client.state = 4 + return b"\xe3\x00\x00", b"\x00\x00\x42\x98\x0c\x11\x33\x45\x30\x42\x33\x33\x35\x32\x37\x34\x46\x39\x31\x43\x39\x39\x00" + + return b"WUT?" \ No newline at end of file diff --git a/handlers/serverPingHandler.py b/handlers/serverPingHandler.py new file mode 100644 index 0000000..a565b21 --- /dev/null +++ b/handlers/serverPingHandler.py @@ -0,0 +1,38 @@ +import struct +from objects import glob + +def handle(client, data): + ping_ip = ".".join((str(x) for x in struct.unpack(b" Pinging to {}".format(client.addr, ping_ip)) + + if len(data) == 11: # We should add our data ontop + if data[-1:] in RESPONSE: + data += RESPONSE[data[-1:]]() + + return data + +def query_i(): + len_hostname = len(glob.config["server"]["hostname"]) + len_mode = len(glob.config["server"]["mode"]) + len_language = len(glob.config["server"]["language"]) + + packet = struct.pack(b" Loading config") + with open("config.json", "r") as f: + glob.config = json.load(f) + + print("> Starting server") + glob.server = Server(glob.config["host"], glob.config["port"]) + glob.server.start() + + # Terminal loop + while True: + try: + cmd = input("> ") + if cmd == "quit" or cmd == "exit" or cmd == "stop": + exit(0) + else: + print("> Restarting...") + client.restart() + """for module in sys.modules.values(): + reload(module) + glob.server = Server(glob.config["host"], glob.config["port"]) + glob.server.start()""" + except Exception as e: + print(e) diff --git a/objects/__init__.py b/objects/__init__.py new file mode 100644 index 0000000..45f9a58 --- /dev/null +++ b/objects/__init__.py @@ -0,0 +1,3 @@ +from . import glob +from . import client +from . import server \ No newline at end of file diff --git a/objects/client.py b/objects/client.py new file mode 100644 index 0000000..f93ff91 --- /dev/null +++ b/objects/client.py @@ -0,0 +1,50 @@ +from importlib import reload + +import re +import socket +from handlers import serverPingHandler, mainHandler + +class Client: + BUFF_SIZE = 65535 + HANDLERS = { + re.compile(b"SAMP"): serverPingHandler + } + + def __init__(self, server, addr): + self.server = server + self.addr = addr + self.state = 0 + self.__writebuffer = [] + + def handle_data(self, data): + found = False + for pattern, handler in self.HANDLERS.items(): + if pattern.match(data): + queue = handler.handle(self, data) + if queue: + self.write_to_buffer(queue) + found = True + + if not found: + queue = mainHandler.handle(self, data) + if queue: + self.write_to_buffer(queue) + #print("?[{}] -> {} / {}".format(self.addr, data, data.hex())) + + def write_to_buffer(self, data): + if type(data) == bytes: + self.__writebuffer.append(data) + else: + self.__writebuffer += data + + def write_buffer_size(self): + return len(self.__writebuffer) + + def write_socket(self): + if len(self.__writebuffer) > 0: + write_chunk = self.__writebuffer.pop(0) + print("[{}] <- {}".format(self.addr, write_chunk)) + self.server.socket.sendto(write_chunk, self.addr) + +def restart(): + reload(serverPingHandler) \ No newline at end of file diff --git a/objects/glob.py b/objects/glob.py new file mode 100644 index 0000000..66b2b6e --- /dev/null +++ b/objects/glob.py @@ -0,0 +1,2 @@ +config = None +server = None \ No newline at end of file diff --git a/objects/server.py b/objects/server.py new file mode 100644 index 0000000..d9d0dda --- /dev/null +++ b/objects/server.py @@ -0,0 +1,56 @@ +import socket +import select + +from threading import Thread + +from .client import Client + +class Server(Thread): + BUFF_SIZE = 65535 + + def __init__(self, host, port): + super(Server, self).__init__() + self.daemon = True + self.host = host + self.port = port + self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.bind((self.host, self.port)) + self.socket.setblocking(0) + + self.clients = {} + + def run(self): + # Main server loop + while True: + (incomming, _, _) = select.select( + [self.socket], + [], + [], 1) + + if incomming: + data, addr = self.socket.recvfrom(self.BUFF_SIZE) + + if addr in self.clients: + self.clients[addr].handle_data(data) + else: + try: + self.clients[addr] = Client(self, addr) + print("[Server] Accepted connection from {}:{}".format(addr[0], addr[1])) + self.clients[addr].handle_data(data) + except socket.error: + try: + self.socket.close() + except: + pass + print("[Server] Something went very wrong...") + exit() + + clients = [x for x in self.clients.values() + if x.write_buffer_size() > 0] + + for client in clients: + client.write_socket() + + for c in self.clients.values(): + print(c.__writebuffer) \ No newline at end of file diff --git a/proxy.py b/proxy.py new file mode 100644 index 0000000..fc41763 --- /dev/null +++ b/proxy.py @@ -0,0 +1,68 @@ +import sys +import socket +from threading import Thread +import select + +class Proxy(Thread): + BUFF_SIZE = 65535 + def __init__(self, listen, target): + Thread.__init__(self) + self.listen = listen + self.target = target + + self.clients = [] + + def run(self): + client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + client.bind(self.listen) # Listen + #master.listen(5) + + target = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + target.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + target.connect(self.target) # Server + #target. + + #client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + #client.connect(self.listen) + + client.setblocking(0) + target.setblocking(0) + + while True: + (c, _, _) = select.select([client],[],[],0) + + if c: + c_data, c_addr = client.recvfrom(self.BUFF_SIZE) + print("[C] data:{} addr:{}".format(c_data, c_addr)) + if c_data: + if c_data[:2] == b"\x08\x1e": + print("Editing port check: {}".format(c_data.hex())) + c_data = b"\x08\x1e\x77\xda" + print("[C] -> {}".format(c_data.hex())) + target.sendto(c_data, self.target) + + (s, _, _) = select.select([target],[],[],0) + + if s: + s_data = target.recv(self.BUFF_SIZE) + print("[S] data:{}".format(s_data)) + if s_data: + print("[C] <- {}".format(s_data.hex())) + client.sendto(s_data, c_addr) + client.close() + +if len(sys.argv) < 4: + print("Missing arguments.") + print("Usage: $ python proxy.py [proxy_port] [server_ip] [server_port]") + print("Sample: $ python proxy.py 7777 192.168.2.1 7777") + exit() + +LISTEN = ("0.0.0.0", int(sys.argv[1])) +TARGET = (sys.argv[2], int(sys.argv[3])) + +##while True: +proxy = Proxy(LISTEN, TARGET) +proxy.start() +proxy.join() +print("Error?") \ No newline at end of file