Engine: fix stack smash in client side UserMessage processor

Unclamped CBitRead::ReadBits() call on stack buffer of MAX_USER_MSG_DATA bytes. Function has been rebuilt with additional clamping to mitigate the problem.
This commit is contained in:
Kawe Mazidjatari 2024-05-07 14:44:12 +02:00
parent 56011c5d50
commit 5b0303357f
3 changed files with 42 additions and 0 deletions

View File

@ -47,6 +47,12 @@ public:
const static int index = 28;
return CallVFunc<CUserCmd*>(index, this, sequenceNumber); /*48 83 EC 28 48 8B 05 ? ? ? ? 48 8D 0D ? ? ? ? 44 8B C2*/
}
bool DispatchUserMessage(int msgType, bf_read* msgData)
{
const static int index = 59;
return CallVFunc<bool>(index, this, msgType, msgData);
}
};
/* ==== CHLCLIENT ======================================================================================================================================================= */

View File

@ -9,6 +9,7 @@
//
/////////////////////////////////////////////////////////////////////////////////
#include "core/stdafx.h"
#include "mathlib/bitvec.h"
#include "tier0/frametask.h"
#include "engine/common.h"
#include "engine/host.h"
@ -307,6 +308,36 @@ bool CClientState::_ProcessCreateStringTable(CClientState* thisptr, SVC_CreateSt
return (endbit - startbit) == msg->m_nLength;
}
//------------------------------------------------------------------------------
// Purpose: processes user message data
// Input : *thisptr -
// *msg -
// Output : true on success, false otherwise
//------------------------------------------------------------------------------
bool CClientState::_ProcessUserMessage(CClientState* thisptr, SVC_UserMessage* msg)
{
CClientState* const cl = thisptr->GetShiftedBasePointer();
if (!cl->IsConnected())
return false;
// buffer for incoming user message
ALIGN4 byte userdata[MAX_USER_MSG_DATA] ALIGN4_POST = { 0 };
bf_read userMsg("UserMessage(read)", userdata, sizeof(userdata));
int bitsRead = msg->m_DataIn.ReadBitsClamped(userdata, msg->m_nLength);
userMsg.StartReading(userdata, Bits2Bytes(bitsRead));
// dispatch message to client.dll
if (!g_pHLClient->DispatchUserMessage(msg->m_nMsgType, &userMsg))
{
Warning(eDLL_T::CLIENT, "Couldn't dispatch user message (%i)\n", msg->m_nMsgType);
return false;
}
return true;
}
static ConVar cl_onlineAuthEnable("cl_onlineAuthEnable", "1", FCVAR_RELEASE, "Enables the client-side online authentication system");
static ConVar cl_onlineAuthToken("cl_onlineAuthToken", "", FCVAR_HIDDEN | FCVAR_USERINFO | FCVAR_DONTRECORD | FCVAR_SERVER_CANNOT_QUERY | FCVAR_PLATFORM_SYSTEM, "The client's online authentication token");
@ -402,6 +433,7 @@ void VClientState::Detour(const bool bAttach) const
DetourSetup(&CClientState__ProcessStringCmd, &CClientState::_ProcessStringCmd, bAttach);
DetourSetup(&CClientState__ProcessServerTick, &CClientState::VProcessServerTick, bAttach);
DetourSetup(&CClientState__ProcessCreateStringTable, &CClientState::_ProcessCreateStringTable, bAttach);
DetourSetup(&CClientState__ProcessUserMessage, &CClientState::_ProcessUserMessage, bAttach);
DetourSetup(&CClientState__Connect, &CClientState::VConnect, bAttach);
}

View File

@ -40,6 +40,7 @@ public: // Hook statics.
static bool _ProcessStringCmd(CClientState* thisptr, NET_StringCmd* msg);
static bool VProcessServerTick(CClientState* thisptr, SVC_ServerTick* msg);
static bool _ProcessCreateStringTable(CClientState* thisptr, SVC_CreateStringTable* msg);
static bool _ProcessUserMessage(CClientState* thisptr, SVC_UserMessage* msg);
static void VConnect(CClientState* thisptr, connectparams_t* connectParams);
@ -228,6 +229,7 @@ inline bool(*CClientState__HookClientStringTable)(CClientState* thisptr, const c
inline bool(*CClientState__ProcessStringCmd)(CClientState* thisptr, NET_StringCmd* msg);
inline bool(*CClientState__ProcessServerTick)(CClientState* thisptr, SVC_ServerTick* msg);
inline bool(*CClientState__ProcessCreateStringTable)(CClientState* thisptr, SVC_CreateStringTable* msg);
inline bool(*CClientState__ProcessUserMessage)(CClientState* thisptr, SVC_UserMessage* msg);
///////////////////////////////////////////////////////////////////////////////
class VClientState : public IDetour
@ -242,6 +244,7 @@ class VClientState : public IDetour
LogFunAdr("CClientState::ProcessStringCmd", CClientState__ProcessStringCmd);
LogFunAdr("CClientState::ProcessServerTick", CClientState__ProcessServerTick);
LogFunAdr("CClientState::ProcessCreateStringTable", CClientState__ProcessCreateStringTable);
LogFunAdr("CClientState::ProcessUserMessage", CClientState__ProcessUserMessage);
LogVarAdr("g_ClientState", g_pClientState);
LogVarAdr("g_ClientState_Shifted", g_pClientState_Shifted);
}
@ -255,6 +258,7 @@ class VClientState : public IDetour
g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 80 B9 ?? ?? ?? ?? ?? 48 8B DA").GetPtr(CClientState__ProcessStringCmd);
g_GameDll.FindPatternSIMD("40 57 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B F9 7C 66").GetPtr(CClientState__ProcessServerTick);
g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 53 56 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ??").GetPtr(CClientState__ProcessCreateStringTable);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ??").GetPtr(CClientState__ProcessUserMessage);
}
virtual void GetVar(void) const
{