From 4a16290a48e65d9cb30c7aef6c405043d7c5d182 Mon Sep 17 00:00:00 2001 From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> Date: Mon, 10 Jan 2022 02:45:34 +0000 Subject: prevent FCVAR_GAMEDLL concommands without FCVAR_CLIENTCMD_CAN_EXECUTE from being called by non-local clients --- NorthstarDedicatedTest/gameutils.cpp | 5 +++++ NorthstarDedicatedTest/gameutils.h | 13 +++++++++++++ NorthstarDedicatedTest/serverauthentication.cpp | 26 +++++++++++++++++++++++++ 3 files changed, 44 insertions(+) (limited to 'NorthstarDedicatedTest') diff --git a/NorthstarDedicatedTest/gameutils.cpp b/NorthstarDedicatedTest/gameutils.cpp index 59f85194..b5a13928 100644 --- a/NorthstarDedicatedTest/gameutils.cpp +++ b/NorthstarDedicatedTest/gameutils.cpp @@ -18,6 +18,7 @@ CHostState* g_pHostState; // cengine stuff CEngine* g_pEngine; +server_state_t* sv_m_State; // network stuff ConVar* Cvar_hostport; @@ -46,6 +47,7 @@ ErrorType Error; CommandLineType CommandLine; Plat_FloatTimeType Plat_FloatTime; ThreadInServerFrameThreadType ThreadInServerFrameThread; +GetBaseLocalClientType GetBaseLocalClient; void InitialiseEngineGameUtilFunctions(HMODULE baseAddress) { @@ -55,6 +57,7 @@ void InitialiseEngineGameUtilFunctions(HMODULE baseAddress) g_pHostState = (CHostState*)((char*)baseAddress + 0x7CF180); g_pEngine = *(CEngine**)((char*)baseAddress + 0x7D70C8); + sv_m_State = (server_state_t*)((char*)baseAddress + 0x12A53D48); Cvar_hostport = (ConVar*)((char*)baseAddress + 0x13FA6070); @@ -68,6 +71,8 @@ void InitialiseEngineGameUtilFunctions(HMODULE baseAddress) Cvar_match_defaultMap = (ConVar*)((char*)baseAddress + 0x8AB530); Cvar_communities_hostname = (ConVar*)((char*)baseAddress + 0x13157E50); + + GetBaseLocalClient = (GetBaseLocalClientType)((char*)baseAddress + 0x78200); } void InitialiseServerGameUtilFunctions(HMODULE baseAddress) diff --git a/NorthstarDedicatedTest/gameutils.h b/NorthstarDedicatedTest/gameutils.h index ff6a0fbf..aaa1dfb9 100644 --- a/NorthstarDedicatedTest/gameutils.h +++ b/NorthstarDedicatedTest/gameutils.h @@ -193,6 +193,16 @@ public: extern CEngine* g_pEngine; +enum server_state_t +{ + ss_dead = 0, // Dead + ss_loading, // Spawning + ss_active, // Running + ss_paused, // Running, but paused +}; + +extern server_state_t* sv_m_State; + // network stuff extern ConVar* Cvar_hostport; @@ -237,6 +247,9 @@ extern Plat_FloatTimeType Plat_FloatTime; typedef bool(*ThreadInServerFrameThreadType)(); extern ThreadInServerFrameThreadType ThreadInServerFrameThread; +typedef void*(*GetBaseLocalClientType)(); +extern GetBaseLocalClientType GetBaseLocalClient; + void InitialiseEngineGameUtilFunctions(HMODULE baseAddress); void InitialiseServerGameUtilFunctions(HMODULE baseAddress); void InitialiseTier0GameUtilFunctions(HMODULE baseAddress); \ No newline at end of file diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp index 4e3446c2..7253f31b 100644 --- a/NorthstarDedicatedTest/serverauthentication.cpp +++ b/NorthstarDedicatedTest/serverauthentication.cpp @@ -7,6 +7,8 @@ #include "gameutils.h" #include "bansystem.h" #include "miscserverscript.h" +#include "concommand.h" +#include "dedicated.h" #include #include #include @@ -41,6 +43,8 @@ ProcessConnectionlessPacketType ProcessConnectionlessPacket; typedef void(*CServerGameDLL__OnRecievedSayTextMessageType)(void* self, unsigned int senderClientIndex, const char* message, char unknown); CServerGameDLL__OnRecievedSayTextMessageType CServerGameDLL__OnRecievedSayTextMessage; +typedef void(*ConCommand__DispatchType)(ConCommand* command, const CCommand& args, void* a3); +ConCommand__DispatchType ConCommand__Dispatch; // global vars ServerAuthenticationManager* g_ServerAuthenticationManager; @@ -310,8 +314,13 @@ void CBaseClient__DisconnectHook(void* self, uint32_t unknownButAlways1, const c } // maybe this should be done outside of auth code, but effort to refactor rn and it sorta fits +// hack: store the client that's executing the current stringcmd for pCommand->Dispatch() hook later +void* pExecutingGameClient; + char CGameClient__ExecuteStringCommandHook(void* self, uint32_t unknown, const char* pCommandString) { + pExecutingGameClient = self; + if (CVar_sv_quota_stringcmdspersecond->m_nValue != -1) { // note: this isn't super perfect, legit clients can trigger it in lobby, mostly good enough tho imo @@ -336,6 +345,22 @@ char CGameClient__ExecuteStringCommandHook(void* self, uint32_t unknown, const c return CGameClient__ExecuteStringCommand(self, unknown, pCommandString); } +void ConCommand__DispatchHook(ConCommand* command, const CCommand& args, void* a3) +{ + // patch to ensure FCVAR_GAMEDLL concommands without FCVAR_CLIENTCMD_CAN_EXECUTE can't be executed by remote clients + if (*sv_m_State == server_state_t::ss_active && command->GetFlags() & FCVAR_GAMEDLL && !(command->GetFlags() & FCVAR_CLIENTCMD_CAN_EXECUTE)) + { + if (IsDedicated()) + return; + + // hack because don't currently have a way to check GetBaseLocalClient().m_nPlayerSlot + if (strcmp((char*)pExecutingGameClient + 0xF500, g_LocalPlayerUserID)) + return; + } + + ConCommand__Dispatch(command, args, a3); +} + char __fastcall CNetChan___ProcessMessagesHook(void* self, void* buf) { double startTime = Plat_FloatTime(); @@ -478,6 +503,7 @@ void InitialiseServerAuthentication(HMODULE baseAddress) ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x2140A0, &CNetChan___ProcessMessagesHook, reinterpret_cast(&CNetChan___ProcessMessages)); ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x104FB0, &CBaseClient__SendServerInfoHook, reinterpret_cast(&CBaseClient__SendServerInfo)); ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x117800, &ProcessConnectionlessPacketHook, reinterpret_cast(&ProcessConnectionlessPacket)); + ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x417440, &ConCommand__DispatchHook, reinterpret_cast(&ConCommand__Dispatch)); // patch to disable kicking based on incorrect serverfilter in connectclient, since we repurpose it for use as an auth token { -- cgit v1.2.3