From c64a0d148f5fcfe7fee50dcc6414348143898ab6 Mon Sep 17 00:00:00 2001 From: KittenPopo Date: Wed, 22 Jun 2022 04:32:51 -0700 Subject: ExploitFixes: Fix respawn exploit and block other Portal 2 commands (#204) * Implement SpecialClientCommand hook (fix respawn exploit, etc.) This replaces the old function_containing_emit_hook (who made it??? why is it so messy??? why is it in snake case???) * Remove extra indents * Blacklist additional commands * Clarify (supposed) purpose of blocked commands --- NorthstarDedicatedTest/ExploitFixes.cpp | 54 ++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'NorthstarDedicatedTest/ExploitFixes.cpp') diff --git a/NorthstarDedicatedTest/ExploitFixes.cpp b/NorthstarDedicatedTest/ExploitFixes.cpp index 84ccc997..19b323c8 100644 --- a/NorthstarDedicatedTest/ExploitFixes.cpp +++ b/NorthstarDedicatedTest/ExploitFixes.cpp @@ -5,9 +5,6 @@ #include "NSMem.h" #include "cvar.h" -typedef char(__fastcall* function_containing_emit_t)(uint64_t a1, uint64_t a2); -function_containing_emit_t function_containing_emit; -ConVar* sv_cheats; ConVar* ns_exploitfixes_log; #define SHOULD_LOG (ns_exploitfixes_log->m_Value.m_nValue > 0) #define BLOCKED_INFO(s) \ @@ -489,16 +486,49 @@ void DoBytePatches() } } -char function_containing_emit_hook(uint64_t unknown_value, uint64_t command_ptr) +KHOOK( + SpecialClientCommand, + ("server.dll", "48 89 5C 24 ? 48 89 74 24 ? 55 57 41 56 48 8D 6C 24 ? 48 81 EC ? ? ? ? 83 3A 00"), + bool, + __fastcall, + (void* player, CCommand* command)) { - char* command_string = *(char**)(command_ptr + 1040); // From decompile - if (!sv_cheats->m_Value.m_nValue && !_strnicmp(command_string, "emit", 5)) + static ConVar* sv_cheats = g_pCVar->FindVar("sv_cheats"); + + if (sv_cheats->GetBool()) + return oSpecialClientCommand(player, command); // Don't block anything if sv_cheats is on + + // These are mostly from Portal 2 (sigh) + constexpr const char* blockedCommands[] = { + "emit", // Sound-playing exploit (likely for Portal 2 coop devs testing splitscreen sound or something) + + // These both execute a command for every single entity for some reason, nice one valve + "pre_go_to_hub", + "pre_go_to_calibration", + + "end_movie", // Calls "__MovieFinished" script function, not sure exactly what this does but it certainly isn't needed + "load_recent_checkpoint" // This is the instant-respawn exploit, literally just calls RespawnPlayer() + }; + + if (command->ArgC() > 0) { - spdlog::info("Blocking command \"emit\" because sv_cheats was 0"); - return 1; + std::string cmdStr = command->Arg(0); + for (char& c : cmdStr) + c = tolower(c); + + for (const char* blockedCommand : blockedCommands) + { + if (cmdStr.find(blockedCommand) != std::string::npos) + { + // Block this command + spdlog::warn("Blocked exploititive client command \"{}\".", cmdStr); + return true; + } + } } - return function_containing_emit(unknown_value, command_ptr); + + return oSpecialClientCommand(player, command); } void ExploitFixes::LoadCallback(HMODULE baseAddress) @@ -525,9 +555,5 @@ void ExploitFixes::LoadCallback(HMODULE baseAddress) new ConVar("ns_exploitfixes_log", "1", FCVAR_GAMEDLL, "Whether to log whenever ExploitFixes.cpp blocks/corrects something"); HookEnabler hook; - - sv_cheats = g_pCVar->FindVar("sv_cheats"); - ENABLER_CREATEHOOK( - hook, (char*)baseAddress + 0x5889A0, &function_containing_emit_hook, reinterpret_cast(&function_containing_emit)); ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x2a8a50, &GetEntByIndexHook, reinterpret_cast(&GetEntByIndex)); -} +} \ No newline at end of file -- cgit v1.2.3