From 0a93f152f6adac7110df1ab122b4f9d5bf3b8637 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Wed, 17 Nov 2021 16:18:39 +0000 Subject: [PATCH] Document exploit --- src/component/exploit.cpp | 44 ++++++++++++++++--- src/game/structs.hpp | 91 +++++++++++++++++++++++++++++++++++++++ src/game/symbols.hpp | 3 +- 3 files changed, 131 insertions(+), 7 deletions(-) diff --git a/src/component/exploit.cpp b/src/component/exploit.cpp index ee96def..4c6bec7 100644 --- a/src/component/exploit.cpp +++ b/src/component/exploit.cpp @@ -10,15 +10,46 @@ namespace exploit { game::dvar_t* cl_exploit; - void cl_netchan_transmit_stub(int a1, unsigned char* data, int size) + /* + * void CL_Netchan_Transmit(netchan_t* chan, unsigned char* data, int a3) + * A brief description of data: the first few bytes contain information from clientConnection_t structure + * Offset 0: ServerID Size : 1 + * Offset 1: serverMessageSequence Size: 4 + * Offset 5: serverCommandSequence Size 4 + * One clean way of sending invalid data to the server is to hook the functions that write the info to the packet + * Credit: https://stackoverflow.com/questions/58981714/how-do-i-change-the-value-of-a-single-byte-in-a-uint32-t-variable + */ + + void write_message_sequence(game::msg_t* msg, int data) { - if (cl_exploit->current.enabled) + if (msg->maxsize - msg->cursize < sizeof(int)) { - data[1] = 0xAA; - data[8] = 0x80; + msg->overflowed = TRUE; + return; } - reinterpret_cast(0x4400E0)(a1, data, size); + if (cl_exploit->current.enabled) + data = (data & 0xFFFFFF00) | 0xAAu; + + auto dest = reinterpret_cast(&msg->data[msg->cursize]); + *dest = data; + msg->cursize += sizeof(int); + } + + void write_command_sequence(game::msg_t* msg, int data) + { + if (msg->maxsize - msg->cursize < sizeof(int)) + { + msg->overflowed = TRUE; + return; + } + + if (cl_exploit->current.enabled) + data = (data & 0x00FFFFFF) | (0x80u << 24); + + auto dest = reinterpret_cast(&msg->data[msg->cursize]); + *dest = data; + msg->cursize += sizeof(int); } class component final : public component_interface @@ -31,7 +62,8 @@ namespace exploit add_exploit_commands(); add_key_hooks(); - utils::hook::call(0x420E40, cl_netchan_transmit_stub); + utils::hook::call(0x420B76, write_message_sequence); + utils::hook::call(0x420B86, write_command_sequence); } private: diff --git a/src/game/structs.hpp b/src/game/structs.hpp index 43d9ca1..cf6cc0c 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -26,6 +26,18 @@ namespace game const char** argv[8]; }; + typedef enum + { + ERR_FATAL = 0x0, + ERR_DROP = 0x1, + ERR_SERVERDISCONNECT = 0x2, + ERR_DISCONNECT = 0x3, + ERR_SCRIPT = 0x4, + ERR_SCRIPT_DROP = 0x5, + ERR_LOCALIZATION = 0x6, + ERR_MAPLOADERRORSUMMARY = 0x7 + } errorParm_t; + enum class LocalClientNum_t { LOCAL_CLIENT_0 = 0, @@ -83,6 +95,55 @@ namespace game int lastEntityRef; }; + struct netProfilePacket_t + { + int iTime; + int iSize; + int bFragment; + }; + + struct netProfileStream_t + { + netProfilePacket_t packets[60]; + int iCurrPacket; + int iBytesPerSeconds; + int iLastBPSCalcTime; + int iCountedPackets; + int iCountedFragments; + int iFragmentPercentage; + int iLargestPacket; + int iSmallestPacket; + }; + + struct netProfileInfo_t + { + netProfileStream_t send; + netProfileStream_t recieve; + }; + + struct netchan_t + { + int outgoingSequence; + netsrc_t sock; + int dropped; + int incomingSequence; + netadr_s remoteAddress; + int qport; + int fragmentSequence; + int fragmentLength; + unsigned char* fragmentBuffer; + int fragmentBufferSize; + int unsentFragments; + int unsentFragmentStart; + int unsentLength; + unsigned char* unsentBuffer; + int unsentBufferSize; + netProfileInfo_t prof; + }; + + static_assert(sizeof(netchan_t) == 0x630); + static_assert(sizeof(netProfileInfo_t) == 0x5E0); + struct XZoneInfo { const char* name; @@ -761,4 +822,34 @@ namespace game }; static_assert(sizeof(pml_t) == 140); + + struct clientConnection_t + { + int qport; // 0 + int clientNum; // 4 + int lastPacketSentTime; // 8 + int lastPacketTime; // 12 + netadr_s serverAddress; // 16 + int connectTime; // 40 + int connectPacketCount; // 44 + char serverMessage[256]; // 48 + int challenge; // 304 + int checksumFeed; // 308 + int reliableSequence; // 312 + int reliableAcknowledge; // 316 + char reliableCommands[128][1024]; // 320 + int serverMessageSequence; // 131392 + int serverCommandSequence; // 131396 + int lastExecutedServerCommand; // 131400 + char serverCommands[128][1024]; // 131404 + bool isServerRestarting; // 262476 + char clientDemo[16592]; // 262480 + netchan_t netchan; // 279072 + char netchanOutgoingBuffer[2048]; // 280656 + char netchanIncomingBuffer[65536]; // 282704 + netProfileInfo_t OOBProf; // 348240 + short statPacketsToSend; // 349744 + int statPacketSendTime[10]; // From here it might be wrong + int currentGamestatePacket; + }; } diff --git a/src/game/symbols.hpp b/src/game/symbols.hpp index 7aca8d7..7e8d6d0 100644 --- a/src/game/symbols.hpp +++ b/src/game/symbols.hpp @@ -5,6 +5,7 @@ namespace game { // Functions + WEAK symbol Com_Error{0x4A6660}; WEAK symbol ConcatArgs{0x539060}; WEAK symbol Cbuf_AddText{0x4C1030}; WEAK symbol Cbuf_InsertText{0x429920}; @@ -37,5 +38,5 @@ namespace game // Variables WEAK symbol cmd_args{0x1C96850}; WEAK symbol playerKeys{0xB3A38C}; - WEAK symbol server_remote{0xB3D370}; + WEAK symbol localClientConnection{0xB3D360}; }