From 0377715cdc5f2a94e654c282fdfb47ba6b3ea64d Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 26 Apr 2007 19:18:55 +0000 Subject: [PATCH] added CS hook to catch internal bot commands and rebuy commands for players --- dlls/cstrike/cstrike/CstrikeHacks.cpp | 157 ++++++++++++++++++++++ dlls/cstrike/cstrike/cstrike.cpp | 11 ++ dlls/cstrike/cstrike/cstrike.h | 20 ++- dlls/cstrike/cstrike/msvc7/cstrike.vcproj | 3 + dlls/cstrike/cstrike/sdk/moduleconfig.h | 4 +- 5 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 dlls/cstrike/cstrike/CstrikeHacks.cpp diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp new file mode 100644 index 00000000..94418390 --- /dev/null +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -0,0 +1,157 @@ +#include "cstrike.h" +#include + +#ifdef __linux__ +#include +#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC +#endif + +/* Utils */ +unsigned char *UTIL_CodeAlloc(size_t size); +void UTIL_CodeFree(unsigned char *addr); +void UTIL_MemProtect(void *addr, int length, int prot); + +/* Detours */ +void CtrlDetour_ClientCommand(bool set); +void Detour_ClientCommand(edict_t *pEdict, int retVal); + +int g_CSCliCmdFwd = -1; +int *g_UseBotArgs = NULL; +const char **g_BotArgs = NULL; + +/* Called on startup */ +void InitializeHacks() +{ + CtrlDetour_ClientCommand(true); +} + +void OnPluginsLoaded() +{ + g_CSCliCmdFwd = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE); +} + +void ShutdownHacks() +{ + CtrlDetour_ClientCommand(false); +} + +void CtrlDetour_ClientCommand(bool set) +{ +#if defined AMD64 +#error UNSUPPORTED +#endif + static unsigned char DetourOps[] = + { + '\x50', /* push eax ; just for safety */ + '\x68', '\x00', '\x00', '\x00', '\x00', /* push 0 ; space to store override rule */ + '\xff', '\x74', '\x24', '\x04', /* push [esp+4] ; push the edict pointer */ + '\xe8', '\x00', '\x00', '\x00', '\x00', /* call ; call our function */ + '\x58', /* pop eax ; remove 3rd push */ + '\x58', /* pop eax ; remove 2nd push */ + '\x85', '\xc0', /* test eax, eax ; do != 0 test now, flags will be saved */ + '\x58', /* pop eax ; remove 1st push */ + '\x74', '\x01', /* je ; if == 0, jump to where old func is saved */ + '\xc3' /* ret ; return otherwise */ + }; + static unsigned char DetourJmp = '\xE9'; + + const unsigned int DetourBytes = 23; + const unsigned int DetourCallPos = 11; + const unsigned int DetourJmpPos = DetourBytes + CS_DETOURCOPYBYTES_CLIENTCOMMAND; + const unsigned int DetourJmpBytes = 5; + static unsigned char *FullDetour = NULL; + + void *target = MDLL_ClientCommand; + unsigned char *paddr; + + if (!g_UseBotArgs) + { +#if defined __linux__ +#else + /* Find the bot args addresses */ + paddr = (unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS; + g_UseBotArgs = *(int **)paddr; + paddr = (unsigned char *)target + CS_CLICMD_OFFS_BOTARGS; + g_BotArgs = (const char **)*(const char **)paddr; +#endif + } + + if (set) + { + assert(FullDetour == NULL); + FullDetour = UTIL_CodeAlloc(DetourBytes + CS_DETOURCOPYBYTES_CLIENTCOMMAND + DetourJmpBytes); + + /* Copy the main trampoline function */ + memcpy(FullDetour, DetourOps, DetourBytes); + + /* Copy our detour call into the trampoline */ + paddr = &FullDetour[DetourCallPos]; + *(unsigned long *)paddr = (unsigned long)Detour_ClientCommand - (unsigned long)(paddr + 4); + + /* Copy original bytes onto the end of the function */ + memcpy(&FullDetour[DetourBytes], target, CS_DETOURCOPYBYTES_CLIENTCOMMAND); + + /* Patch and copy the final jmp */ + paddr = &FullDetour[DetourJmpPos]; + *paddr++ = DetourJmp; + *(unsigned long *)paddr = ((unsigned long)target + CS_DETOURCOPYBYTES_CLIENTCOMMAND) + - (unsigned long)(paddr + 4); + + /* Now overwrite the target function with our trampoline */ + UTIL_MemProtect(target, CS_DETOURCOPYBYTES_CLIENTCOMMAND + 10, PAGE_EXECUTE_READWRITE); + paddr = (unsigned char *)target; + *paddr++ = DetourJmp; + *(unsigned long *)paddr = (unsigned long)FullDetour - (unsigned long)(paddr + 4); + } else { + assert(FullDetour != NULL); + + /* Copy back the original function bytes */ + memcpy(target, &FullDetour[DetourBytes], CS_DETOURCOPYBYTES_CLIENTCOMMAND); + + /* Free memory used */ + UTIL_CodeFree(FullDetour); + FullDetour = NULL; + } +} + +void Detour_ClientCommand(edict_t *pEdict, int retVal) +{ + if (*g_UseBotArgs) + { + int client = ENTINDEX(pEdict); + const char *args = *g_BotArgs; + retVal = MF_ExecuteForward(g_CSCliCmdFwd, (cell)client, args); + } +} + +unsigned char *UTIL_CodeAlloc(size_t size) +{ +#if defined WIN32 + return (unsigned char *)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + unsigned char *addr = (unsigned char *)memalign(sysconf(_SC_PAGESIZE), size); + mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC); + return addr; +#endif +} + +void UTIL_CodeFree(unsigned char *addr) +{ +#if defined WIN32 + VirtualFree(addr, 0, MEM_RELEASE); +#else + free(addr); +#endif +} + +void UTIL_MemProtect(void *addr, int length, int prot) +{ +#ifdef __linux__ +#define ALIGN(ar) ((long)ar & ~(sysconf(_SC_PAGESIZE)-1)) + void *addr2 = (void *)ALIGN(addr); + mprotect(addr2, sysconf(_SC_PAGESIZE), prot); +#else + DWORD old_prot; + VirtualProtect(addr, length, prot, &old_prot); +#endif +} diff --git a/dlls/cstrike/cstrike/cstrike.cpp b/dlls/cstrike/cstrike/cstrike.cpp index 72992f4d..ce1b50f2 100755 --- a/dlls/cstrike/cstrike/cstrike.cpp +++ b/dlls/cstrike/cstrike/cstrike.cpp @@ -33,6 +33,11 @@ * version. */ +CCstrikePlayer g_players[33]; +int g_zooming[33] = {0}; +bool g_precachedknife = false; +bool g_noknives = false; + // Utils first bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer) { @@ -1836,4 +1841,10 @@ void PlayerPreThink(edict_t *pPlayer) void OnAmxxAttach() { MF_AddNatives(cstrike_Exports); + InitializeHacks(); +} + +void OnAmxxDetach() +{ + ShutdownHacks(); } diff --git a/dlls/cstrike/cstrike/cstrike.h b/dlls/cstrike/cstrike/cstrike.h index a1f75397..a051e71c 100755 --- a/dlls/cstrike/cstrike/cstrike.h +++ b/dlls/cstrike/cstrike/cstrike.h @@ -152,6 +152,15 @@ #define OFFSET_HOSTAGEID 516 + EXTRAOFFSET // +29 #endif +#if defined __linux__ +#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 9 +#else +#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 +#define CS_CLICMD_OFFS_USEBOTARGS 2 +#define CS_CLICMD_OFFS_BOTARGS 22 +#endif + + // Ids of weapons in CS #define CSW_P228 1 //#define CSW_SHIELD 2 @@ -280,12 +289,15 @@ enum }; // cstrike-specific defines above -CCstrikePlayer g_players[33]; -int g_zooming[33] = {0}; -bool g_precachedknife = false; -bool g_noknives = false; +extern CCstrikePlayer g_players[33]; +extern int g_zooming[33]; +extern bool g_precachedknife; +extern bool g_noknives; // Globals above +void InitializeHacks(); +void ShutdownHacks(); + #define CHECK_ENTITY(x) \ if (x < 0 || x > gpGlobals->maxEntities) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \ diff --git a/dlls/cstrike/cstrike/msvc7/cstrike.vcproj b/dlls/cstrike/cstrike/msvc7/cstrike.vcproj index 4c33e01a..52159e0c 100755 --- a/dlls/cstrike/cstrike/msvc7/cstrike.vcproj +++ b/dlls/cstrike/cstrike/msvc7/cstrike.vcproj @@ -151,6 +151,9 @@ + + diff --git a/dlls/cstrike/cstrike/sdk/moduleconfig.h b/dlls/cstrike/cstrike/sdk/moduleconfig.h index 172df546..0f6a2a86 100755 --- a/dlls/cstrike/cstrike/sdk/moduleconfig.h +++ b/dlls/cstrike/cstrike/sdk/moduleconfig.h @@ -52,12 +52,12 @@ #define FN_AMXX_ATTACH OnAmxxAttach /** AMXX Detach (unload) */ -//#define FN_AMXX_DETACH OnAmxxDetach +#define FN_AMXX_DETACH OnAmxxDetach /** All plugins loaded * Do forward functions init here (MF_RegisterForward) */ -//#define FN_AMXX_PLUGINSLOADED OnPluginsLoaded +#define FN_AMXX_PLUGINSLOADED OnPluginsLoaded /** All plugins are about to be unloaded */ //#define FN_AMXX_PLUGINSUNLOADING OnPluginsUnloading