diff --git a/.vscode/settings.json b/.vscode/settings.json index da7c64d..c11f987 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,9 @@ { - "python.pythonPath": "C:\\Users\\Emily\\AppData\\Local\\Programs\\Python\\Python36\\python.exe" + "python.pythonPath": "C:\\Users\\Emily\\AppData\\Local\\Programs\\Python\\Python37\\python.exe", + "files.exclude": { + "**/__pycache__": true, + "**/__pycache__.*": true, + "**/*.pyc": true, + ".vscode": true + } } \ No newline at end of file diff --git a/config.json b/config.json index c4d07d3..a694cb6 100644 --- a/config.json +++ b/config.json @@ -7,5 +7,11 @@ "max_players": 50, "mode": "yay", "language": "spoop" - } + }, + "logging": { + "filename": "", + "level": "DEBUG", + "format": "%(name)s - %(levelname)s - %(message)s", + "datefmt": "%d-%b-%y %H:%M:%S" + } } \ No newline at end of file diff --git a/handlers/__init__.py b/handlers/__init__.py index dfbee8a..b90bb81 100644 --- a/handlers/__init__.py +++ b/handlers/__init__.py @@ -1,4 +1,5 @@ from . import mainHandler -from . import serverPingHandler +from . import serverQueryHandler -from . import handshakeHandler \ No newline at end of file +from . import handshakeHandler +from . import unknownHandler \ No newline at end of file diff --git a/handlers/handshakeHandler.py b/handlers/handshakeHandler.py index f710c77..de8cd8c 100644 --- a/handlers/handshakeHandler.py +++ b/handlers/handshakeHandler.py @@ -1,3 +1,18 @@ -def handle(client, data): - print("![{}] -> Handshake".format(client.addr)) - return \ No newline at end of file +import logging +import struct + +from network.enums import types as TYPE +from objects import glob + +logger = logging.getLogger(__name__) + +def handle(client: "Client", data: bytes) -> bytes: + challenge = (client.ip_uint ^ glob.challenge_short) & TYPE.MAX_USHORT + challenge_solution = challenge ^ 0x6969 + + challenge_answer = struct.unpack_from(b">H", data, 1)[0] + + if challenge_answer != challenge_solution: + return struct.pack(b">BH", 0x1A, challenge) + client.state = 1 # CHALLENGE_PASSED + return b"\x19\x00" # 0x19: Valid_challenge; leading 0x00 byte due to some routers shitting itself if only 1 byte is sent/received diff --git a/handlers/mainHandler.py b/handlers/mainHandler.py index fc72638..c10b969 100644 --- a/handlers/mainHandler.py +++ b/handlers/mainHandler.py @@ -1,16 +1,29 @@ +from importlib import reload + +import random +import logging +import struct + from . import handshakeHandler +from . import unknownHandler -def handle(client, data): - print("?[{}] -> {} / {}".format(client.addr, data, data.hex())) +from helpers.byteFormater import readable_bytes - 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", b"\x00\x00\x42\x98\x0c\x11\x33\x45\x30\x42\x33\x33\x35\x32\x37\x34\x46\x39\x31\x43\x39\x39\x00" +logger = logging.getLogger(__name__) - return b"WUT?" \ No newline at end of file +HANDLERS = { + 0x18: handshakeHandler.handle, + 0x00: unknownHandler.handle +} + +def handle(client: "Client", data: bytes) -> bytes: + out: bytes = HANDLERS.get(data[0], unimplemented)(client, data) + + return out + +def unimplemented(client: "Client", data: bytes) -> bytes: + logger.debug("[%s] sent unhandled data: %s" % (client.addr, readable_bytes(data))) + return bytes([x for x in range(1,32,1)]) + +def restart(): + reload(handshakeHandler) diff --git a/handlers/old_mainHandler.py b/handlers/old_mainHandler.py new file mode 100644 index 0000000..cb05665 --- /dev/null +++ b/handlers/old_mainHandler.py @@ -0,0 +1,53 @@ +""" + 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", b"\x00\x00\x42\x98\x0c\x11\x33\x45\x30\x42\x33\x33\x35\x32\x37\x34\x46\x39\x31\x43\x39\x39\x00" + if client.state == 3: + client.state = 4 + return + if client.state == 4: + client.state = 5 + return b"\xe3\x01\x00", b"\x00\x80\x42\x68\x22\xc0\xa8\x02\x87\xfb\xaa\x00\x00\x04\x41\x00\x00" + if client.state <= 7: + client.state += 1 + return + if client.state == 8: + client.state = 9 + return b"\xe5\x02\x00\x02\x00\x02\x80\x00" + if client.state == 9: + client.state = 10 + return b"\x01\x00\x32\x28\x06\xbf\xf9\xca\x0f\x03\x00\x87\x00\x29\x04\x00\x64\x90\x09\xaa\xf9\xca\x0f\xbf\xf9\xca\x0f\x05\x00\x87\x00\x17", b"\x03\x00\x32\x28\x06\xc5\xf9\xca\x0f" + if client.state == 10: + client.state = 11 + return b"\x03\x80\x32\x48\x09\xb0\xf9\xca\x0f\xd1\xf9\xca\x0f" + if client.state == 11: + client.state = 12 + return b"\xe3\x07\x00" + if client.state == 12: + client.state = 13 + return b"\x04\x00\x48\x80\x00\x11\xe0\x14\x3c\xe2\x0e\x2f\x9c\xa0\xf0\x09\x00\x91\x00\x80\x0f\xc1\x00\x14\x8b\xcb\x61\x00\x00\x80\x38\x8d\x00\x00\x8c\x42\x40\x20\x00\x00\x00\x00\x10\x10\x00\x00\x00\xc0\x16\xf1\x20\x33\xc0\x00\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x00\x00\x08\x00\x00\x00\x04\x00\x00\x00\x05\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + if client.state == 13: + client.state = 14 + return + if client.state == 14: + client.state = 15 + return b"\xe3\x0a\x00", b"\x05\x00\x48\x80\x80\x13\xe0\x14\x0c\xe6\x01\xbc\xcf\x44\x40\x8e\x5a\x74\x45\xdf\xe7\x54\x10\x0b\x00\x91\x01\x80\x27\xc0\x14\x9d\xe6\x01\xbc\xcf\x44\x40\x8e\x5a\x74\x45\xdf\xe7\x54\x10\x0c\x00\x91\x02\x00\x28\x40\x14\x9e\xe6\x81\xbc\xcf\x44\x40\x8e\x5a\x74\x45\xdf\xe7\x54\x10\x20\x0d\x00\x82\x6c\x04\x14\x80\xcf\x00\x20\x3f\xe0\x00\x00\x00\x00\x03\x79\x9e\x88\x81\x1c\xb4\xe8\x8b\xbf\xce\xa8\x27\xb2\x50\xc8\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + if client.state == 15: + client.state = 16 + return + if client.state == 16: + client.state = 17 + return b"\xe3\x0b\x00", b"\x07\x00\x42\x20\x14\x81\xf8\x01" + if client.state == 17: + client.state = 18 + return + if client.state == 18: + #client.state = 19 + return b"\xe3\x0c\x00", b"\x07\x80\x38\x40\x00\x11\x40\xd0\x00\x00\x00\x00" + """ \ No newline at end of file diff --git a/handlers/serverPingHandler.py b/handlers/serverQueryHandler.py similarity index 88% rename from handlers/serverPingHandler.py rename to handlers/serverQueryHandler.py index 497463b..2cd192d 100644 --- a/handlers/serverPingHandler.py +++ b/handlers/serverQueryHandler.py @@ -1,16 +1,24 @@ import struct +import logging + from objects import glob from helpers import dataHelper -def handle(client, data): - ping_ip = ".".join((str(x) for x in struct.unpack(b" Pinging to {}".format(client.addr, ping_ip)) +def handle(client, data): + ping_ip = ".".join((str(x) for x in struct.unpack(b"<4B", data[4:8]))) + ping_port = struct.unpack(b" Pinging to %s:%d" % (client.addr, ping_ip, ping_port)) if len(data) == 11: # We should add our data ontop if data[-1:] in RESPONSE: data += RESPONSE[data[-1:]]() + logger.debug("[%s] <- %s" % (client.addr, data)) + return data def query_i(): @@ -53,7 +61,7 @@ def query_r(): def query_c(): packet_data = [] - + players_scores = get_players_scores() packet_data.append(len(players_scores)) @@ -62,13 +70,13 @@ def query_c(): len(name), name, value ]) - + flat_packet_data = dataHelper.flatten(packet_data) packet = struct.pack(b" bytes: + global index + data = LOOKUP[index] + + client.send_immediate(data[:3]) + + index = (index + 1) % 2 + return data[3:] + +LOOKUP = [ + bytes([int(x,16) for x in "e3 00 00 00 00 42 98 0c 11 33 30 45 39 33 39 33 33 36 39 42 35 36 38 43 32 00".split(" ")]), + bytes([int(x,16) for x in "e3 01 00 00 80 42 68 22 c0 a8 02 85 dc f8 01 00 e0 57 00 00".split(" ")]) +] \ No newline at end of file diff --git a/helpers/TEABlockEncryptor.py b/helpers/TEABlockEncryptor.py new file mode 100644 index 0000000..d233660 --- /dev/null +++ b/helpers/TEABlockEncryptor.py @@ -0,0 +1,58 @@ +import struct +from random import randint + +from helpers.checksumHelper import CheckSum +from network.enums import types as TYPE + +TEA_ROUNDS = 32 +TEA_XOR_MASK = 0x5E94A3CF +KEY = [] + +def EncryptBlock(v0, v1): + sum = 0 + + for i in range(TEA_ROUNDS): + v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + key[sum & 3]) + +def Encrypt(var_input): # bytes + var_input_len = len(var_input) + TYPE.SIZEOF_CHAR * 2 # (checksum, encodedPad) + paddingBytes = 0 + + if var_input_len % 8 != 0: + paddingBytes = 8 - (var_input_len % 8) + + finalLen = var_input_len + paddingBytes + + # Randomize pad size for some reason + encodedPad = randint(0, TYPE.MAX_UCHAR) + encodedPad <<= 4 + encodedPad &= 0xF0 # Remove bits lost from UCHAR size (C) [BYTE MAGIC] + encodedPad |= paddingBytes + + var_output = [0] * finalLen #bytes(finalLen) + var_output[2 + paddingBytes:] = [b for b in var_input] + + # Write the pad size variable + var_output[1] = encodedPad + + # Write the padding + var_output[2:2+len(paddingBytes)] = bytes([randint(0, TYPE.MAX_UCHAR) for _ in range(len(paddingBytes))]) + + # Calculate checksum + checksum = CheckSum() + checksum.add(var_output[1:var_input_len + 1 + paddingBytes]) + + var_checksum = checksum.get() + var_checksum = (var_checksum << 4) ^ var_checksum + var_checksum &= TYPE.MAX_UCHAR # [BYTE MAGIC] + + var_output[0] = var_checksum + + # Encryption + for i in range(0, finalLen, 8): + v0 = var_output[i] + v1 = var_output[i + TYPE.SIZEOF_INT] + + return bytes(var_output) + + \ No newline at end of file diff --git a/helpers/__init__.py b/helpers/__init__.py index e69de29..6cb87f5 100644 --- a/helpers/__init__.py +++ b/helpers/__init__.py @@ -0,0 +1,3 @@ +from . import dataHelper +from . import TEABlockEncryptor +from . import checksumHelper \ No newline at end of file diff --git a/helpers/byteFormater.py b/helpers/byteFormater.py new file mode 100644 index 0000000..21e5a2c --- /dev/null +++ b/helpers/byteFormater.py @@ -0,0 +1,2 @@ +def readable_bytes(byteStream: bytes) -> str: + return " ".join([(hex(b) if b >= 16 else hex(b).replace("x", "x0"))[2:] for b in byteStream]) \ No newline at end of file diff --git a/helpers/checksumHelper.py b/helpers/checksumHelper.py new file mode 100644 index 0000000..c710be8 --- /dev/null +++ b/helpers/checksumHelper.py @@ -0,0 +1,25 @@ +from network.enums import types as TYPE +# TODO: Single function if Object's state is not needed + +class CheckSum: + def __init__(self): + self.clear() + + def clear(self): + self.sum = 0 + self.r = 55665 + self.c1 = 52845 + self.c2 = 22719 + + def add(self, byteArray): + [self._add(b) for b in byteArray] + + def _add(self, byte): + cipher = byte ^ (self.r >> 8) + cipher &= TYPE.MAX_UCHAR # [BYTE MAGIC] + self.r = (cipher + self.r) * self.c1 + self.c2 + self.r &= TYPE.MAX_USHORT # [BYTE MAGIC] + self.sum += cipher + + def get(self): + return self.sum \ No newline at end of file diff --git a/main.py b/main.py index 2065dc3..4f321f2 100644 --- a/main.py +++ b/main.py @@ -1,32 +1,30 @@ from importlib import reload import sys - import socket import json +import logging from objects import glob from objects.server import Server from objects import client -if __name__ == "__main__": - print("> Loading config") - with open("config.json", "r") as f: - glob.config = json.load(f) +logger = logging.getLogger(__name__) - print("> Starting server") +if __name__ == "__main__": + logger.info("> Starting server...") glob.server = Server(glob.config["host"], glob.config["port"]) glob.server.start() # Terminal loop while True: try: - cmd = input("> ") + cmd = input() if cmd == "quit" or cmd == "exit" or cmd == "stop": exit(0) else: - print("> Restarting...") + logger.info("> Restarting...") client.restart() """for module in sys.modules.values(): reload(module) diff --git a/network/__init__.py b/network/__init__.py new file mode 100644 index 0000000..d393879 --- /dev/null +++ b/network/__init__.py @@ -0,0 +1,3 @@ +from . import enums + +from . import compression \ No newline at end of file diff --git a/network/compression.py b/network/compression.py new file mode 100644 index 0000000..704da32 --- /dev/null +++ b/network/compression.py @@ -0,0 +1,50 @@ +import logging + +from objects import glob + +# Found @ addr 0x004C88E0 +LOOKUP_TABLE = b"\xb4b\x07\xe5\x9d\xafc\xdd\xe3\xd0\xcc\xfe\xdc\xdbk.j@\xabG\xc9\xd1S\xd5 \x91\xa5\x0eJ\xdf\x18\x89\xfdo%\x12\xb7\x13w\x00e6mI\xecW*\xa9\x11_\xfax\x95\xa4\xbd\x1e\xd9yD\xcd\xde\x81\xeb\t>\xf6\xee\xda\x7f\xa3\x1a\xa7-\xa6\xad\xc1F\x93\xd2\x1b\x9c\xaa\xd7NKML\xf3\xb84\xc0\xca\x88\xf4\x94\xcb\x0490\x82\xd6s\xb0\xbf\"\x01AnH,\xa8u\xb1\n\xae\x9f\'\x80\x10\xce\xf0)(\x85\r\x05\xf75\xbb\xbc\x15\x06\xf5`q\x03\x1f\xeaZ3\x92\x8d\xe7\x90[\xe9\xcf\x9e\xd3]\xed1\x1c\x0bR\x16Q\x0f\x86\xc5h\x9b!\x0c\x8bB\x87\xffO\xbe\xc8\xe8\xc7\xd4z\xe0U/\x8a\x8e\xba\x987\xe4\xb28\xa1\xb62\x83:{\x84 bytearray: + """Uncompress client packet. + This is actually a deobfuscation as there is no compression involved anymore + as zlib was removed and just swapped with this implementation after the leak. + + Arguments: + byteStream {bytes} -- Bytes sent by client + """ + checksum, data = byteStream[0], bytearray(byteStream[1:]) + + data = xor_every_other_byte(get_port_xor_key(), data) + data = run_though_lookup_table(data) + + if checksum != calc_checksum(data): + logger.error("Checksum failed!\n\tExpected: %d\n\tGot: %d" % (checksum, calc_checksum(data))) + raise Exception("Checksum failed!") + + return data + +def xor_every_other_byte(xor, byteStream: bytearray): + # xor: (server_port ^ 0xCCCC) & 0xFF + for i in range(1, len(byteStream), 2): + byteStream[i] = byteStream[i] ^ xor + return byteStream + +def run_though_lookup_table(byteStream: bytes): + return bytearray([LOOKUP_TABLE[b] for b in byteStream]) + +def calc_checksum(byteStream: bytes): + checksum = 0 + for i in range(len(byteStream)): + checksum = checksum ^ byteStream[i] & 0xAA + return checksum + +# It should be faster to call a function and do an if, then to read the property of a dict and do bit operations after +_port_xor_key = None +def get_port_xor_key(): + global _port_xor_key + if _port_xor_key is None: + _port_xor_key = (glob.config["port"] ^ 0xCCCC) & 0xFF + return _port_xor_key diff --git a/network/consts/datasize.py b/network/consts/datasize.py new file mode 100644 index 0000000..6f74045 --- /dev/null +++ b/network/consts/datasize.py @@ -0,0 +1,2 @@ +MTU_SIZE = 576 +UDP_HEADER_SIZE = 28 diff --git a/network/enums/__init__.py b/network/enums/__init__.py new file mode 100644 index 0000000..0d58a68 --- /dev/null +++ b/network/enums/__init__.py @@ -0,0 +1,4 @@ +from . import packetTypeRaknet +from . import packetTypeSamp +from . import packetRPC +from . import types \ No newline at end of file diff --git a/network/enums/packetRPC.py b/network/enums/packetRPC.py new file mode 100644 index 0000000..8f58646 --- /dev/null +++ b/network/enums/packetRPC.py @@ -0,0 +1,137 @@ +# netrpc (client) +RPC_ServerJoin = "xy" +RPC_ServerQuit = "ab" +RPC_InitGame = "ac" +RPC_VehicleSpawn = "am" +RPC_VehicleDestroy = "an" +RPC_SetCheckpoint = "ao" +RPC_DisableCheckpoint = "ap" +RPC_SetRaceCheckpoint = "aq" +RPC_DisableRaceCheckpoint = "ar" +RPC_GameModeRestart = "at" +RPC_ConnectionRejected = "au" +RPC_ClientMessage = "av" +RPC_WorldTime = "aw" +RPC_Pickup = "ax" +RPC_DestroyPickup = "ay" +RPC_DestroyWeaponPickup = "az" +RPC_Weather = "bb" +RPC_Instagib = "bc" +RPC_SetTimeEx = "be" +RPC_ToggleClock = "bf" + +# netrpc (both) +RPC_Chat = "ad" +RPC_Privmsg = "ae" +RPC_TeamPrivmsg = "af" +RPC_RequestClass = "ag" +RPC_RequestSpawn = "ah" +RPC_Spawn = "ai" +RPC_Death = "aj" +RPC_EnterVehicle = "ak" +RPC_ExitVehicle = "al" +RPC_UpdateScoresPingsIPs = "as" +RPC_SvrStats = "em" +RPC_ScmEvent = "ba" + + +# scriptrpc +RPC_ScrSetSpawnInfo = "bg" +RPC_ScrSetPlayerTeam = "bh" +RPC_ScrSetPlayerSkin = "bi" +RPC_ScrSetPlayerName = "bj" +RPC_ScrSetPlayerPos = "bk" +RPC_ScrSetPlayerPosFindZ = "bl" +RPC_ScrSetPlayerHealth = "bm" +RPC_ScrPutPlayerInVehicle = "bn" +RPC_ScrRemovePlayerFromVehicle = "bo" +RPC_ScrSetPlayerColor = "bp" +RPC_ScrDisplayGameText = "bq" +RPC_ScrSetInterior = "br" +RPC_ScrSetCameraPos = "bs" +RPC_ScrSetCameraLookAt = "bt" +RPC_ScrSetVehiclePos = "bu" +RPC_ScrSetVehicleZAngle = "bv" +RPC_ScrVehicleParams = "bw" +RPC_ScrSetCameraBehindPlayer = "bx" +RPC_ScrTogglePlayerControllable = "by" +RPC_ScrPlaySound = "bz" +RPC_ScrSetWorldBounds = "ca" +RPC_ScrHaveSomeMoney = "cb" +RPC_ScrSetPlayerFacingAngle = "cc" +RPC_ScrResetMoney = "cd" +RPC_ScrResetPlayerWeapons = "ce" +RPC_ScrGivePlayerWeapon = "cf" +RPC_ScrRespawnVehicle = "cg" +RPC_ScrLinkVehicle = "ch" +RPC_ScrSetPlayerArmour = "ci" +RPC_ScrDeathMessage = "cj" +RPC_ScrSetMapIcon = "ck" +RPC_ScrDisableMapIcon = "cl" +RPC_ScrSetWeaponAmmo = "cm" +RPC_ScrSetGravity = "cn" +RPC_ScrSetVehicleHealth = "co" +RPC_ScrAttachTrailerToVehicle = "cp" +RPC_ScrDetachTrailerFromVehicle = "cq" +RPC_ScrCreateObject = "cr" +RPC_ScrSetObjectPos = "cs" +RPC_ScrSetObjectRotation = "ct" +RPC_ScrDestroyObject = "cu" +RPC_ScrSetPlayerVirtualWorld = "cv" +RPC_ScrSetVehicleVirtualWorld = "cw" +RPC_ScrCreateExplosion = "cx" +RPC_ScrShowNameTag = "cy" +RPC_ScrMoveObject = "cz" +RPC_ScrStopObject = "da" +RPC_ScrNumberPlate = "db" +RPC_ScrTogglePlayerSpectating = "dc" +RPC_ScrSetPlayerSpectating = "dd" +RPC_ScrPlayerSpectatePlayer = "de" +RPC_ScrPlayerSpectateVehicle = "df" +RPC_ScrRemoveComponent = "dg" +RPC_ScrForceSpawnSelection = "dh" +RPC_ScrAttachObjectToPlayer = "dt" +RPC_ScrInitMenu = "du" +RPC_ScrShowMenu = "dv" +RPC_ScrHideMenu = "dw" +RPC_ScrSetPlayerWantedLevel = "dz" +RPC_ScrShowTextDraw = "ea" +RPC_ScrHideTextDraw = "eb" +RPC_ScrEditTextDraw = "ee" +RPC_ScrAddGangZone = "ef" +RPC_ScrRemoveGangZone = "eg" +RPC_ScrFlashGangZone = "eh" +RPC_ScrStopFlashGangZone = "ei" +RPC_ScrApplyAnimation = "eo" +RPC_ScrClearAnimations = "eq" +RPC_ScrSetSpecialAction = "ep" +RPC_ScrEnableStuntBonus = "ec" +RPC_ScrUsePlayerPedAnims = "a1" +RPC_ScrToggleVehicleMarker = "a4" +RPC_ScrMoveTextdraw = "a5" +RPC_ScrSetPlayerVisibleInScoreBoard = "a6" + +# netrpc (server) +RPC_ClientJoin = "xx" +RPC_ServerCommand = "dj" +RPC_SetInteriorId = "dk" +RPC_ClickMap = "dl" +RPC_VehicleDestroyed = "dm" +RPC_PickedUpWeapon = "dn" +RPC_PickedUpPickup = "do" +RPC_MenuSelect = "dx" +RPC_MenuQuit = "dy" +RPC_UnderMapTeleport = "a2" +RPC_ResolutionChanged = "a3" + +# rcon +RPC_RconConnect = "dp" +RPC_RconCommand = "dq" +RPC_RconEvent = "dr" +RPC_RconPlayerInfo = "ds" + +# anticheat +RPC_ACAuthRequest = "ej" +RPC_ACAuthResponse = "ek" +RPC_ACAuthEngineLoaded = "el" +RPC_ACServerProtected = "bd" diff --git a/network/enums/packetTypeRaknet.py b/network/enums/packetTypeRaknet.py new file mode 100644 index 0000000..81f3cea --- /dev/null +++ b/network/enums/packetTypeRaknet.py @@ -0,0 +1,113 @@ +INTERNAL_PING = 0x00 +PING = 0x01 +PING_OPEN_CONNECTIONS = 0x02 +CONNECTED_PONG = 0x03 + +REQUEST_STATIC_DATA = 0x04 +CONNECTION_REQUEST = 0x05 + +SECURED_CONNECTION_RESPONSE = 0x06 +SECURED_CONNECTION_CONFIRMATION = 0x07 +RPC_MAPPING = 0x08 + +DETECT_LOST_CONNECTIONS = 0x09 +OPEN_CONNECTION_REQUEST = 0x0a +OPEN_CONNECTION_REPLY = 0x0b + +RPC = 0x0c +RPC_REPLY = 0x0d +BROADCAST_PINGS = 0x0e +SET_RANDOM_NUMBER_SEED = 0x0f + +CONNECTION_REQUEST_ACCEPTED = 0x10 +CONNECTION_ATTEMPT_FAILED = 0x11 + +NEW_INCOMING_CONNECTION = 0x18 + +NO_FREE_INCOMING_CONNECTIONS = 0x13 + +DISCONNECTION_NOTIFICATION = 0x14 + +CONNECTION_LOST = 0x15 + +RSA_PUBLIC_KEY_MISMATCH = 0x16 + +CONNECTION_BANNED = 0x17 + +INVALID_PASSWORD = 0x18 + +MODIFIED_PACKET = 0x19 + +TIMESTAMP = 0x1a + +PONG = 0x1b + +RECEIVED_STATIC_DATA = 0x1c + +REMOTE_DISCONNECTION_NOTIFICATION = 0x1d + +REMOTE_CONNECTION_LOST = 0x1e + +REMOTE_NEW_INCOMING_CONNECTION = 0x1f + +REMOTE_EXISTING_CONNECTION = 0x20 + +REMOTE_STATIC_DATA = 0x21 + +FILE_LIST_TRANSFER_HEADER = 0x22 + +FILE_LIST_TRANSFER_FILE = 0x23 + +DDT_DOWNLOAD_REQUEST = 0x24 + +QUERY_MASTER_SERVER = 0x25 +MASTER_SERVER_DELIST_SERVER = 0x26 +MASTER_SERVER_UPDATE_SERVER = 0x27 +MASTER_SERVER_SET_SERVER = 0x28 +RELAYED_CONNECTION_NOTIFICATION = 0x29 + +ADVERTISE_SYSTEM = 0x2a + +TRANSPORT_STRING = 0x2b + +REPLICA_MANAGER_CONSTRUCTION = 0x2c +REPLICA_MANAGER_DESTRUCTION = 0x2d +REPLICA_MANAGER_SCOPE_CHANGE = 0x2e +REPLICA_MANAGER_SERIALIZE = 0x2f +REPLICA_MANAGER_DOWNLOAD_COMPLETE = 0x30 + +CONNECTION_GRAPH_REQUEST = 0x31 +CONNECTION_GRAPH_REPLY = 0x32 +CONNECTION_GRAPH_UPDATE = 0x33 +CONNECTION_GRAPH_NEW_CONNECTION = 0x34 +CONNECTION_GRAPH_CONNECTION_LOST = 0x35 +CONNECTION_GRAPH_DISCONNECTION_NOTIFICATION = 0x36 + +ROUTE_AND_MULTICAST = 0x37 + +RAKVOICE_OPEN_CHANNEL_REQUEST = 0x38 +RAKVOICE_OPEN_CHANNEL_REPLY = 0x39 +RAKVOICE_CLOSE_CHANNEL = 0x3a +RAKVOICE_DATA = 0x3b + +AUTOPATCHER_GET_CHANGELIST_SINCE_DATE = 0x3c +AUTOPATCHER_CREATION_LIST = 0x3d +AUTOPATCHER_DELETION_LIST = 0x3e +AUTOPATCHER_GET_PATCH = 0x3f +AUTOPATCHER_PATCH_LIST = 0x40 +AUTOPATCHER_REPOSITORY_FATAL_ERROR = 0x41 +AUTOPATCHER_FINISHED = 0x42 +AUTOPATCHER_RESTART_APPLICATION = 0x43 + +NAT_PUNCHTHROUGH_REQUEST = 0x44 +NAT_TARGET_NOT_CONNECTED = 0x45 +NAT_TARGET_CONNECTION_LOST = 0x46 +NAT_CONNECT_AT_TIME = 0x47 +NAT_SEND_OFFLINE_MESSAGE_AT_TIME = 0x48 + +DATABASE_QUERY_REQUEST = 0x49 +DATABASE_UPDATE_ROW = 0x4a +DATABASE_REMOVE_ROW = 0x4b +DATABASE_QUERY_REPLY = 0x4c +DATABASE_UNKNOWN_TABLE = 0x4d +DATABASE_INCORRECT_PASSWORD = 0x4e diff --git a/network/enums/packetTypeSamp.py b/network/enums/packetTypeSamp.py new file mode 100644 index 0000000..e69de29 diff --git a/network/enums/types.py b/network/enums/types.py new file mode 100644 index 0000000..a03a628 --- /dev/null +++ b/network/enums/types.py @@ -0,0 +1,20 @@ +SIZEOF_CHAR = 1 +SIZEOF_SHORT = 2 +SIZEOF_INT = 4 +SIZEOF_LONG = 4 +SIZEOF_LONG_LONG = 8 + +SIZEOF_FLOAT = 4 +SIZEOF_DOUBLE = 8 + + +MAX_CHAR = 0x7F +MAX_UCHAR = 0xFF +MAX_SHORT = 0x7FFF +MAX_USHORT = 0xFFFF +MAX_INT = 0x7FFFFFFF +MAX_UINT = 0xFFFFFFFF # 1 << SIZEOF_INT * 8 - 1 (I had a dream of doing it this way.. but Robin said no >.>) +MAX_LONG = 0x7FFFFFFF +MAX_ULONG = 0xFFFFFFFF +MAX_LONG_LONG = 0x7FFFFFFFFFFFFFFF +MAX_ULONG_LONG = 0xFFFFFFFFFFFFFFFF \ No newline at end of file diff --git a/notes/1.txt b/notes/1.txt new file mode 100644 index 0000000..2533e5c --- /dev/null +++ b/notes/1.txt @@ -0,0 +1,20 @@ +---Packet--- +17 7f 00 00 01 1c fb 00 00 df 2f 00 00 +xx xx xx ?? ?? ?? ?? xx xx xx xx xx xx + +---RTC--- +ID: xx +BitStream: 87 15 00 00 01 05 53 75 6e 70 79 00 00 00 00 00 ee dd 60 3d 00 01 00 80 01 01 00 00 00 00 00 05 12 00 00 00 00 00 00 00 e3 dd 63 3d 00 02 00 88 58 0b b4 00 58 19 b4 00 e8 0d b4 00 08 18 b4 00 e4 dd 66 3d 00 03 00 88 e0 0d b4 00 a8 13 b4 00 90 0b b4 00 20 19 b4 00 + +---Packet--- +26 + +---Packet--- +15 7f 00 00 01 1c fb ff ff +xx xx xx ?? ?? ?? ?? xx xx + ^ Same pattern as earlier + Seem to increment over time? + +C:\Users\Emily\Downloads\samp-1-master\samp-1-master\testbot\.\Debug\bot.exe (process 8620) exited with code 1. +To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops. +Press any key to close this window . . . \ No newline at end of file diff --git a/notes/1_1.txt b/notes/1_1.txt new file mode 100644 index 0000000..54bd3ff --- /dev/null +++ b/notes/1_1.txt @@ -0,0 +1,15 @@ +---Packet--- +17 7f 00 00 01 7e eb 00 00 df 2f 00 00 + +---RTC--- +ID: xx +BitStream: 87 15 00 00 01 05 53 75 6e 70 79 00 00 00 00 00 f7 94 49 05 00 10 00 8c 01 01 00 00 00 00 00 05 14 00 00 00 00 00 00 00 fa 94 44 05 00 11 00 8c 38 18 55 00 08 6f 88 00 00 00 00 00 00 00 00 00 fd 94 47 05 00 12 00 8c c8 17 55 00 4b 5e 88 00 00 00 00 00 00 00 00 00 + +---Packet--- +26 + +---Packet--- +15 7f 00 00 01 7e eb ff ff + +C:\Users\Emily\Downloads\samp-1-master\samp-1-master\testbot\.\Debug\bot.exe (process 16152) exited with code 1. +Press any key to close this window . . . \ No newline at end of file diff --git a/notes/2.txt b/notes/2.txt new file mode 100644 index 0000000..170d823 --- /dev/null +++ b/notes/2.txt @@ -0,0 +1,25 @@ +---RTC SEND--- +BitStream: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 17 44 5a 5c 00 05 00 8c 53 00 45 00 52 00 4e 00 41 00 4d 00 45 00 3d 00 1a 44 59 5c 69 06 00 80 79 00 00 00 55 00 53 00 45 00 52 00 50 00 52 00 4f 00 46 00 49 00 4c 00 60 05 d3 00 43 00 3a 00 1f 44 42 5c 73 06 00 88 80 39 2c 6f a8 c3 2c 6f 00 00 00 00 00 00 00 00 78 59 ad eb 72 c1 d7 4a a2 fb 1d bd 77 96 84 a5 00 00 00 00 d4 5e 00 00 78 59 ad eb 72 c1 d7 4a a2 fb 1d bd 77 96 84 a5 e7 45 4a 5c 3d 07 00 88 80 6e 2a 6f 30 05 2b 6f 00 00 00 00 00 00 00 00 37 7f 1f f3 e0 ed ce 44 ab 10 eb 1d 44 e7 81 bf 00 00 00 00 d4 5e 00 00 37 7f 1f f3 e0 ed ce 44 ab 10 eb 1d 44 e7 81 bf ef 45 32 5c 42 08 00 88 80 6e 2a 6f f0 03 2b 6f 00 00 00 00 00 00 00 00 cf 81 bc bb 19 e2 9c 46 a4 05 f8 20 ee 49 61 94 00 00 00 00 d4 5e 00 00 cf 81 bc bb 19 e2 9c 46 a4 05 f8 20 ee 49 61 94 f7 45 3a 5c 6f 09 00 88 80 6e 2a 6f 80 05 2b 6f 00 00 00 00 00 00 00 00 73 6c 8d 0f d5 6b af 45 8f 1f 19 07 0a 40 43 9c 00 00 00 00 d4 5e 00 00 73 6c 8d 0f d5 6b af 45 8f 1f 19 07 0a 40 43 9c ff 45 22 5c 00 0a 00 88 4e 00 54 00 20 00 41 00 75 00 74 00 68 00 6f 00 72 00 69 00 74 00 79 00 5c 00 4e 00 65 00 74 00 77 00 6f 00 72 00 6b 00 + +---Packet--- +17 7f 00 00 01 00 fd 00 00 78 38 00 00 + +---RTC--- +ID: xx +BitStream: 87 15 00 00 01 05 53 75 6e 70 79 00 00 00 00 00 5e 01 4d 5c 00 12 00 88 10 0e d6 00 70 15 d6 00 38 0f d6 00 10 18 d6 00 21 01 48 5c 00 13 00 88 f8 0d d6 00 c0 16 d6 00 f0 0e d6 00 11 18 d6 00 24 01 37 5c 00 14 00 8c f0 11 d6 00 e6 45 ad 00 00 00 00 00 00 00 00 00 + +---RTC SEND--- +BitStream: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b6 33 d3 5d 00 34 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 be 33 db 5d 00 35 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 33 c3 5d 00 36 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8e 33 cb 5d 00 37 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 96 33 b3 5d 00 38 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9e 33 bb 5d 00 39 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +---Packet--- +26 + +---Packet--- +15 7f 00 00 01 00 fd ff ff + +---RTC SEND--- +BitStream: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5e 32 7b 5d 00 21 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 26 32 63 5d 00 22 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e 32 6b 5d 00 23 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 36 32 53 5d 00 24 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3e 32 5b 5d 00 25 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 32 43 5d 00 26 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +C:\Users\Emily\Downloads\samp-1-master\samp-1-master\testbot\.\Debug\bot.exe (process 24276) exited with code 1. +To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops. +Press any key to close this window . . . \ No newline at end of file diff --git a/notes/2_1.txt b/notes/2_1.txt new file mode 100644 index 0000000..e18a8de --- /dev/null +++ b/notes/2_1.txt @@ -0,0 +1,25 @@ +---RTC SEND--- +BitStream: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 82 52 16 af 6f 10 00 88 c0 c9 ee 77 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 d0 07 00 0a f8 01 00 00 00 00 00 00 fc 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a0 c9 ee 77 9a 52 1e af 5c 11 00 88 80 6e 2a 6f d0 05 2b 6f 00 00 00 00 00 00 00 00 65 69 e6 53 fd fc da 4c a5 20 34 fa 34 59 9a 7f 00 00 00 00 7c 2d 00 00 65 69 e6 53 fd fc da 4c a5 20 34 fa 34 59 9a 7f 92 52 06 af 50 12 00 88 c0 a9 45 71 00 87 48 71 00 00 00 00 00 00 00 00 d2 00 16 5a e5 68 e7 4d bc f4 1c 2d 21 5f e0 fe 00 00 00 00 7c 2d 00 00 d2 00 16 5a e5 68 e7 4d bc f4 1c 2d 21 5f e0 fe aa 52 0e af 56 13 00 88 80 6e 2a 6f 40 04 2b 6f 00 00 00 00 00 00 00 00 f6 89 84 88 de 5d b8 47 85 06 e5 bb c4 0e 81 d1 00 00 00 00 7c 2d 00 00 f6 89 84 88 de 5d b8 47 85 06 e5 bb c4 0e 81 d1 a2 52 36 af 6b 14 00 8c 74 00 73 00 00 00 6f 00 bc 52 34 af 00 17 00 80 4e 00 4f 00 5f 00 44 00 45 00 42 00 55 00 47 00 5f 00 48 00 45 00 41 00 50 00 3d 00 31 00 00 00 60 05 ef 00 00 00 00 00 ba 52 3e af db 15 00 88 90 bd 11 74 40 b7 12 74 00 00 00 00 00 00 00 00 05 4a 00 eb 1a 9b d4 11 91 23 00 50 04 77 59 bc 00 00 00 00 7c 2d 00 00 + +---Packet--- +17 7f 00 00 01 fc f7 00 00 78 38 00 00 + +---RTC--- +ID: xx +BitStream: 87 15 00 00 01 05 53 75 6e 70 79 00 48 28 f3 00 75 16 a7 af 00 10 00 80 01 01 00 00 00 00 00 05 13 00 00 00 00 00 00 00 76 16 aa af 00 11 00 88 e0 0d f2 00 20 1b f2 00 f8 0c f2 00 e8 1a f2 00 73 16 a9 af 00 12 00 8c 80 04 f2 00 b0 62 ad 00 00 00 00 00 00 00 00 00 + +---RTC SEND--- +BitStream: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 27 af ae 00 27 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 27 d7 ae 00 28 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 27 df ae 00 29 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 38 27 c7 ae 00 2a 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 27 cf ae 00 2b 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c8 26 f7 ae 00 2c 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +---Packet--- +26 + +---Packet--- +15 7f 00 00 01 fc f7 ff ff + +---RTC SEND--- +BitStream: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a0 26 5f ae 00 39 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b8 26 47 ae 00 3a 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b0 26 4f ae 00 3b 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 48 26 77 ae 00 3c 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 26 7f ae 00 3d 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 58 26 67 ae 00 3e 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +C:\Users\Emily\Downloads\samp-1-master\samp-1-master\testbot\.\Debug\bot.exe (process 11644) exited with code 1. +To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops. +Press any key to close this window . . . \ No newline at end of file diff --git a/notes/const.md b/notes/const.md new file mode 100644 index 0000000..5b30845 --- /dev/null +++ b/notes/const.md @@ -0,0 +1,2 @@ +UDP_HEADER_SIZE = 28 + diff --git a/notes/notes.md b/notes/notes.md new file mode 100644 index 0000000..71014d7 --- /dev/null +++ b/notes/notes.md @@ -0,0 +1,7 @@ +availableBandwidth -= updateBitStream.GetNumberOfBitsUsed() + UDP_HEADER_SIZE * 8 # -224 + + +GenerateDatagram( &updateBitStream, MTUSize, &reliableDataSent, time, playerId, messageHandlerList ) + +updateBitStream: + diff --git a/notes/packet.md b/notes/packet.md new file mode 100644 index 0000000..4f9a67d --- /dev/null +++ b/notes/packet.md @@ -0,0 +1,21 @@ +|Key|Value| +|---|---| +|---|---| +|Name|ID_OPEN_CONNECTION_REQUEST| +|id|10| +|0|packetID| +|1|0| +|---|---| +|---|---| +|Name|ID_OPEN_CONNECTION_REPLY| +|id|11| +|0|packetID| +|1|0| +|---|---| +|---|---| +|Name|ID_NO_FREE_INCOMING_CONNECTIONS| +|id|1B| +|0|packetID| +|1|0| +|---|---| +|---|---| diff --git a/objects/client.py b/objects/client.py index 45efa6d..0959940 100644 --- a/objects/client.py +++ b/objects/client.py @@ -1,49 +1,78 @@ from importlib import reload import socket -from handlers import serverPingHandler, mainHandler +import logging +import struct + +from network.compression import uncompress + +from handlers import serverQueryHandler, mainHandler + +from helpers.byteFormater import readable_bytes + +logger = logging.getLogger(__name__) class Client: BUFF_SIZE = 65535 HANDLERS = { - b"SAMP": serverPingHandler + b"SAMP": serverQueryHandler.handle } - def __init__(self, server, addr): + def __init__(self, server: "Server", addr: "Address"): self.server = server + + self.ip_uint = struct.unpack(b" %s" % (self.addr, readable_bytes(data))) + queue = mainHandler.handle(self, data) + except Exception as err: + logger.error(err) + finally: + if queue: self.write_to_buffer(queue) - #print("?[{}] -> {} / {}".format(self.addr, data, data.hex())) - def write_to_buffer(self, data): - if type(data) == bytes: + def write_to_buffer(self, data: bytes): + if type(data) == int: self.__writebuffer.append(data) + elif type(data) == list: + for item in data: + self.write_to_buffer(item) else: self.__writebuffer += data - def write_buffer_size(self): + def get_buffer_size(self) -> int: 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) + if self.get_buffer_size() > 0: + #write_chunk = self.__writebuffer.pop(0) + #logger.debug("[%s] <- %s" % (self.addr, write_chunk)) + logger.debug("[%s] <- %s" % (self.addr, readable_bytes(self.__writebuffer))) + self.server.socket.sendto(self.__writebuffer, self.addr) + self.__writebuffer.clear() + + def send_immediate(self, data: bytes): + logger.debug("[%s] <- %s" % (self.addr, readable_bytes(data))) + self.server.socket.sendto(data, self.addr) def restart(): - reload(serverPingHandler) \ No newline at end of file + reload(serverQueryHandler) + reload(mainHandler) + mainHandler.restart() \ No newline at end of file diff --git a/objects/glob.py b/objects/glob.py index 66b2b6e..7269f1b 100644 --- a/objects/glob.py +++ b/objects/glob.py @@ -1,2 +1,47 @@ +import sys +import json +import logging + +from random import randint + +from network.enums import types as TYPE + +# --------------------------------------------------------------------------- +# public config = None -server = None \ No newline at end of file +server = None +challenge_short = None + +# --------------------------------------------------------------------------- + +with open("config.json", "r") as f: + config = json.load(f) + +# fix for logging level +default_logging_fallback = False +if type(config["logging"]["level"]) is not int: + try: + config["logging"]["level"] = getattr(logging, config["logging"]["level"]) + except: + config["logging"]["level"] = logging.INFO + default_logging_fallback = True + +# Setup logging settings +logging_handlers = [logging.StreamHandler(sys.stdout)] +if len(config["logging"]["filename"]): + logging_handlers.append(logging.FileHandler(config["logging"]["filename"])) +del config["logging"]["filename"] +logging.basicConfig(**config["logging"], handlers = logging_handlers) + +logger = logging.getLogger(__name__) + +logger.debug("glob.configured logger") + +if default_logging_fallback: + logger.warning("Invalid logging value in config! Defaulting to logging level INFO.") +logger.info("Logging level: %d" % config["logging"]["level"]) + + +# --------------------------------------------- +challenge_short = randint(0, TYPE.MAX_USHORT) +logger.debug("Client challenge set to: %s" % ("0x" if challenge_short & 0x1000 else "0x0") + hex(challenge_short)[2:]) diff --git a/objects/server.py b/objects/server.py index 26486be..c6b13cd 100644 --- a/objects/server.py +++ b/objects/server.py @@ -1,10 +1,13 @@ import socket import select +import logging from threading import Thread from .client import Client +logger = logging.getLogger(__name__) + class Server(Thread): BUFF_SIZE = 65535 @@ -36,18 +39,19 @@ class Server(Thread): else: try: self.clients[addr] = Client(self, addr) - print("[Server] Accepted connection from {}:{}".format(addr[0], addr[1])) + logger.info("Accepted connection from %s:%s" % (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() + logger.warn("Something went very wrong...") + #exit() + return clients = [x for x in self.clients.values() - if x.write_buffer_size() > 0] + if x.get_buffer_size() > 0] for client in clients: client.write_socket() diff --git a/proxy_data.json b/proxy_data.json new file mode 100644 index 0000000..beea89f --- /dev/null +++ b/proxy_data.json @@ -0,0 +1 @@ +{"id": 14} \ No newline at end of file diff --git a/raknet/bitStream.py b/raknet/bitStream.py new file mode 100644 index 0000000..73543c1 --- /dev/null +++ b/raknet/bitStream.py @@ -0,0 +1,66 @@ +class BitStream: + def __init__(self, data: array = []): + self.bits_used = 0 + self.read_offset = 0 + self.data = data + + def write(self, c_bytes): # ?bytes_to_write + bytes_to_write = len(c_bytes) + if not len(c_bytes): + return + + self.write_bits(c_bytes, bytes_to_write << 3, True) + + def read(self, bytes_to_read: int): + bits_to_read = bytes_to_read << 3 + + if self.read_offset & 7 == 0: + if self.read_offset + bits_to_read > self.bits_used: + return False + + read_offset_bytes = self.read_offset >> 3 + data = self.data[read_offset_bytes:read_offset_bytes + bytes_to_read] + + self.read_offset += bits_to_read + return data + return self.read_bits(bits_to_read) + + def read_bits(self, bits_to_read: int, align_right: bool = False): + if bits_to_read <= 0: + return False + + if self.read_offset + bits_to_read > self.bits_used: + return False + + offset = 0 + bits_read_offset_mod8 = self.read_offset & 7 + + + def write_bits(self, c_bytes, bits_to_write: int, align_right: bool = False): + if not bits_to_write: + return + + offset = 0 + bits_used_mod8 = self.bits_used & 7 + + while bits_to_write: + byte = c_bytes[offset] + + if bits_to_write < 8 and align_right: + byte <<= 8 - bits_to_write + + if bits_used_mod8 == 0: + self.data[self.bits_used >> 3] = byte + else: + self.data[self.bits_used >> 3] |= byte >> bits_used_mod8 + if 8 - bits_used_mod8 < 8 and 8 - bits_used_mod8 < bits_to_write: + self.data[(self.bits_used >> 3) + 1] = byte << (8 - bits_used_mod8) + + if bits_to_write >= 8: + self.bits_used += 8 + else: + self.bits_used += bits_to_write + + bits_to_write -= 8 + + offset += 1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..94d7bf4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +#PyRakLib>=1.0.15b1 \ No newline at end of file