2022-04-27 16:29:14 +02:00
|
|
|
//===============================================================================//
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
// $NoKeywords: $
|
|
|
|
//
|
|
|
|
//===============================================================================//
|
|
|
|
// netmessages.cpp: implementation of the CNetMessage types.
|
|
|
|
//
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "core/stdafx.h"
|
2023-04-15 02:13:29 +02:00
|
|
|
#include "tier1/cvar.h"
|
2022-08-15 02:59:41 +02:00
|
|
|
#include "engine/net.h"
|
2022-04-27 16:29:14 +02:00
|
|
|
#include "common/netmessages.h"
|
2023-06-12 02:02:29 +02:00
|
|
|
#include "game/shared/usermessages.h"
|
2022-04-27 16:29:14 +02:00
|
|
|
|
2023-04-15 02:13:29 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// re-implementation of 'SVC_Print::Process'
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2022-08-15 14:44:54 +02:00
|
|
|
bool SVC_Print::ProcessImpl()
|
2022-04-27 16:29:14 +02:00
|
|
|
{
|
2022-04-27 18:42:49 +02:00
|
|
|
if (this->m_szText)
|
2022-04-27 16:29:14 +02:00
|
|
|
{
|
2023-04-09 22:22:06 +02:00
|
|
|
Assert(m_szText == m_szTextBuffer); // Should always point to 'm_szTextBuffer'.
|
|
|
|
|
|
|
|
size_t len = strnlen_s(m_szText, sizeof(m_szTextBuffer));
|
|
|
|
Assert(len < sizeof(m_szTextBuffer));
|
|
|
|
|
|
|
|
if (len < sizeof(m_szTextBuffer))
|
|
|
|
{
|
2023-08-21 19:12:29 +02:00
|
|
|
Msg(eDLL_T::SERVER, m_szText[len-1] == '\n' ? "%s" : "%s\n", m_szText);
|
2023-04-09 22:22:06 +02:00
|
|
|
}
|
2022-04-27 16:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true; // Original just return true also.
|
|
|
|
}
|
|
|
|
|
2023-04-15 02:13:29 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// re-implementation of 'SVC_UserMessage::Process'
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2022-08-15 14:44:54 +02:00
|
|
|
bool SVC_UserMessage::ProcessImpl()
|
2022-04-30 03:00:24 +02:00
|
|
|
{
|
2023-06-12 02:02:29 +02:00
|
|
|
if (m_nMsgType == UserMessages_t::TextMsg)
|
2022-04-30 03:00:24 +02:00
|
|
|
{
|
2023-06-12 02:02:29 +02:00
|
|
|
bf_read buf = m_DataIn;
|
|
|
|
byte type = byte(buf.ReadByte());
|
2023-04-09 22:22:06 +02:00
|
|
|
|
2023-06-12 02:02:29 +02:00
|
|
|
if (type == HUD_PRINTCONSOLE ||
|
|
|
|
type == HUD_PRINTCENTER)
|
2022-04-30 03:00:24 +02:00
|
|
|
{
|
2023-06-12 02:02:29 +02:00
|
|
|
char text[MAX_USER_MSG_DATA];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
buf.ReadString(text, sizeof(text), false, &len);
|
|
|
|
Assert(len < sizeof(text));
|
|
|
|
|
|
|
|
if (len && len < sizeof(text))
|
|
|
|
{
|
2023-08-21 19:12:29 +02:00
|
|
|
Msg(eDLL_T::SERVER, text[len - 1] == '\n' ? "%s" : "%s\n", text);
|
2023-06-12 02:02:29 +02:00
|
|
|
}
|
2022-04-30 03:00:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SVC_UserMessage_Process(this); // Need to return original.
|
|
|
|
}
|
|
|
|
|
2023-07-07 09:14:39 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2023-07-08 03:07:19 +02:00
|
|
|
// Below functions are hooked as playlist overrides can be abused from the client.
|
|
|
|
// The client could basically manage the server's playlists. Only allow read/write
|
|
|
|
// when cheats are enabled.
|
2023-07-07 09:14:39 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CLC_SetPlaylistVarOverride::ReadFromBufferImpl(CLC_SetPlaylistVarOverride* thisptr, bf_read* buffer)
|
|
|
|
{
|
|
|
|
// Abusable netmsg; only allow if cheats are enabled.
|
|
|
|
if (!sv_cheats->GetBool())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CLC_SetPlaylistVarOverride_ReadFromBuffer(thisptr, buffer);
|
|
|
|
}
|
|
|
|
bool CLC_SetPlaylistVarOverride::WriteToBufferImpl(CLC_SetPlaylistVarOverride* thisptr, bf_write* buffer)
|
|
|
|
{
|
|
|
|
// Abusable netmsg; only allow if cheats are enabled.
|
|
|
|
if (!sv_cheats->GetBool())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CLC_SetPlaylistVarOverride_WriteToBuffer(thisptr, buffer);
|
|
|
|
}
|
|
|
|
|
2024-02-24 02:15:09 +01:00
|
|
|
static ConVar enable_CmdKeyValues("enable_CmdKeyValues", "0", FCVAR_DEVELOPMENTONLY, "Toggle CmdKeyValues transmit and receive.");
|
2023-07-07 09:14:39 +02:00
|
|
|
|
2023-04-15 02:13:29 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// below functions are hooked as 'CmdKeyValues' isn't really used in this game, but
|
|
|
|
// still exploitable on the server. the 'OnPlayerAward' command calls the function
|
|
|
|
// 'UTIL_SendClientCommandKVToPlayer' which forwards the keyvalues to all connected clients.
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool Base_CmdKeyValues::ReadFromBufferImpl(Base_CmdKeyValues* thisptr, bf_read* buffer)
|
|
|
|
{
|
2024-02-24 02:15:09 +01:00
|
|
|
// Abusable netmsg; only allow if explicitly enabled by the client.
|
|
|
|
if (!enable_CmdKeyValues.GetBool())
|
2023-04-15 02:13:29 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Base_CmdKeyValues_ReadFromBuffer(thisptr, buffer);
|
|
|
|
}
|
|
|
|
bool Base_CmdKeyValues::WriteToBufferImpl(Base_CmdKeyValues* thisptr, bf_write* buffer)
|
|
|
|
{
|
2024-02-24 02:15:09 +01:00
|
|
|
// Abusable netmsg; only allow if explicitly enabled by the client.
|
|
|
|
if (!enable_CmdKeyValues.GetBool())
|
2023-04-15 02:13:29 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Base_CmdKeyValues_WriteToBuffer(thisptr, buffer);
|
|
|
|
}
|
|
|
|
|
2023-05-30 23:01:46 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// determine whether or not the message should be copied into the replay buffer,
|
|
|
|
// regardless of the 'CNetMessage::m_Group' type.
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2023-05-31 22:07:54 +02:00
|
|
|
bool ShouldReplayMessage(const CNetMessage* msg)
|
2023-05-30 23:01:46 +02:00
|
|
|
{
|
|
|
|
switch (msg->GetType())
|
|
|
|
{
|
|
|
|
// String commands can be abused in a way they get executed
|
|
|
|
// on the client that is watching a replay. This happens as
|
|
|
|
// the server copies the message into the replay buffer from
|
|
|
|
// the client that initially submitted it. Its group type is
|
|
|
|
// 'None', so call this to determine whether or not to set
|
|
|
|
// the group type to 'NoReplay'. This exploit has been used
|
|
|
|
// to connect clients to an arbitrary server during replay.
|
|
|
|
case NetMessageType::net_StringCmd:
|
|
|
|
// Print and user messages sometimes make their way to the
|
|
|
|
// client that is watching a replay, while it should only
|
|
|
|
// be broadcasted to the target client. This happens for the
|
|
|
|
// same reason as the 'net_StringCmd' above.
|
|
|
|
case NetMessageType::svc_Print:
|
2023-06-12 02:02:29 +02:00
|
|
|
{
|
2023-05-30 23:01:46 +02:00
|
|
|
return false;
|
2023-06-12 02:02:29 +02:00
|
|
|
}
|
|
|
|
case NetMessageType::svc_UserMessage:
|
|
|
|
{
|
|
|
|
SVC_UserMessage* userMsg = (SVC_UserMessage*)msg;
|
|
|
|
|
|
|
|
// Just don't replay console prints.
|
|
|
|
if (userMsg->m_nMsgType == UserMessages_t::TextMsg)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2023-05-30 23:01:46 +02:00
|
|
|
default:
|
2023-06-12 02:02:29 +02:00
|
|
|
{
|
2023-05-30 23:01:46 +02:00
|
|
|
return true;
|
|
|
|
}
|
2023-06-12 02:02:29 +02:00
|
|
|
}
|
2023-05-30 23:01:46 +02:00
|
|
|
}
|
|
|
|
|
2023-11-26 13:21:20 +01:00
|
|
|
void V_NetMessages::Detour(const bool bAttach) const
|
2022-04-27 16:29:14 +02:00
|
|
|
{
|
2023-11-26 13:21:20 +01:00
|
|
|
if (bAttach)
|
|
|
|
{
|
|
|
|
auto hk_SVCPrint_Process = &SVC_Print::ProcessImpl;
|
|
|
|
auto hk_SVCUserMessage_Process = &SVC_UserMessage::ProcessImpl;
|
|
|
|
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pSVC_Print_VFTable, (LPVOID&)hk_SVCPrint_Process, NetMessageVtbl::Process, (LPVOID*)&SVC_Print_Process);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pSVC_UserMessage_VFTable, (LPVOID&)hk_SVCUserMessage_Process, NetMessageVtbl::Process, (LPVOID*)&SVC_UserMessage_Process);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID*)&Base_CmdKeyValues::ReadFromBufferImpl, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&Base_CmdKeyValues_ReadFromBuffer);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID*)&Base_CmdKeyValues::WriteToBufferImpl, NetMessageVtbl::WriteToBuffer, (LPVOID*)&Base_CmdKeyValues_WriteToBuffer);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID*)&CLC_SetPlaylistVarOverride::ReadFromBufferImpl, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&CLC_SetPlaylistVarOverride_ReadFromBuffer);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID*)&CLC_SetPlaylistVarOverride::WriteToBufferImpl, NetMessageVtbl::WriteToBuffer, (LPVOID*)&CLC_SetPlaylistVarOverride_WriteToBuffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
void* hkRestore = nullptr;
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pSVC_Print_VFTable, (LPVOID)SVC_Print_Process, NetMessageVtbl::Process, (LPVOID*)&hkRestore);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pSVC_UserMessage_VFTable, (LPVOID)SVC_UserMessage_Process, NetMessageVtbl::Process, (LPVOID*)&hkRestore);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID)Base_CmdKeyValues_ReadFromBuffer, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&hkRestore);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID)Base_CmdKeyValues_WriteToBuffer, NetMessageVtbl::WriteToBuffer, (LPVOID*)&hkRestore);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID)CLC_SetPlaylistVarOverride_ReadFromBuffer, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&hkRestore);
|
|
|
|
CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID)CLC_SetPlaylistVarOverride_WriteToBuffer, NetMessageVtbl::WriteToBuffer, (LPVOID*)&hkRestore);
|
|
|
|
}
|
2023-07-07 09:14:39 +02:00
|
|
|
}
|