From 8ae003046c8599c7ca81bf7f61368fefd120298c Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Thu, 26 Feb 2009 12:42:13 +1300 Subject: [PATCH 1/2] Updated CDetour code in TF2 extension to prevent crashes with spies. Updated windows sig. --- extensions/tf2/CDetour/detourhelpers.h | 6 +- extensions/tf2/CDetour/detours.cpp | 244 ++++--------------------- extensions/tf2/CDetour/detours.h | 221 +++++++++++++--------- extensions/tf2/asm/asm.c | 92 ++++++++++ extensions/tf2/asm/asm.h | 2 + extensions/tf2/criticals.cpp | 84 ++++----- extensions/tf2/criticals.h | 2 - extensions/tf2/extension.cpp | 2 +- gamedata/sm-tf2.games.txt | 14 +- 9 files changed, 312 insertions(+), 355 deletions(-) diff --git a/extensions/tf2/CDetour/detourhelpers.h b/extensions/tf2/CDetour/detourhelpers.h index aea6faa0..b1710747 100644 --- a/extensions/tf2/CDetour/detourhelpers.h +++ b/extensions/tf2/CDetour/detourhelpers.h @@ -26,13 +26,13 @@ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * or . * - * Version: $Id$ + * Version: $Id: detourhelpers.h 248 2008-08-27 00:56:22Z pred $ */ #ifndef _INCLUDE_SOURCEMOD_DETOURHELPERS_H_ #define _INCLUDE_SOURCEMOD_DETOURHELPERS_H_ -#if defined PLATFORM_POSIX +#if defined PLATFORM_LINUX #include #define PAGE_SIZE 4096 #define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1)) @@ -52,7 +52,7 @@ struct patch_t inline void ProtectMemory(void *addr, int length, int prot) { -#if defined PLATFORM_POSIX +#if defined PLATFORM_LINUX void *addr2 = (void *)ALIGN(addr); mprotect(addr2, sysconf(_SC_PAGESIZE), prot); #elif defined PLATFORM_WINDOWS diff --git a/extensions/tf2/CDetour/detours.cpp b/extensions/tf2/CDetour/detours.cpp index 879db4fa..71aba447 100644 --- a/extensions/tf2/CDetour/detours.cpp +++ b/extensions/tf2/CDetour/detours.cpp @@ -26,7 +26,7 @@ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * or . * -* Version: $Id$ +* Version: $Id: detours.cpp 248 2008-08-27 00:56:22Z pred $ */ #include "detours.h" @@ -34,7 +34,6 @@ ISourcePawnEngine *CDetourManager::spengine = NULL; IGameConfig *CDetourManager::gameconf = NULL; -int CDetourManager::returnValue = 0; void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) { @@ -42,9 +41,9 @@ void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) CDetourManager::gameconf = gameconf; } -CDetour *CDetourManager::CreateDetour(void *callbackfunction, size_t paramsize, const char *signame) +CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame) { - CDetour *detour = new CDetour(callbackfunction, paramsize, signame); + CDetour *detour = new CDetour(callbackfunction, trampoline, signame); if (detour) { if (!detour->Init(spengine, gameconf)) @@ -59,50 +58,17 @@ CDetour *CDetourManager::CreateDetour(void *callbackfunction, size_t paramsize, return NULL; } -void CDetourManager::DeleteDetour(CDetour *detour) -{ - delete detour; -} - -CBlocker * CDetourManager::CreateFunctionBlock( const char *signame, bool isVoid ) -{ - CBlocker *block = new CBlocker(signame, isVoid); - - if (block) - { - if (!block->Init(spengine, gameconf)) - { - delete block; - return NULL; - } - - return block; - } - - return NULL; -} - -void CDetourManager::DeleteFunctionBlock(CBlocker *block) -{ - delete block; -} - -CDetour::CDetour(void *callbackfunction, size_t paramsize, const char *signame) +CDetour::CDetour(void *callbackfunction, void **trampoline, const char *signame) { enabled = false; detoured = false; detour_address = NULL; - detour_callback = NULL; + detour_trampoline = NULL; this->signame = signame; - this->callbackfunction = callbackfunction; + this->detour_callback = callbackfunction; spengine = NULL; gameconf = NULL; - this->paramsize = paramsize; -} - -CDetour::~CDetour() -{ - DeleteDetour(); + this->trampoline = trampoline; } bool CDetour::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) @@ -121,6 +87,12 @@ bool CDetour::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) return enabled; } +void CDetour::Destroy() +{ + DeleteDetour(); + delete this; +} + bool CDetour::IsEnabled() { return enabled; @@ -148,7 +120,6 @@ bool CDetour::CreateDetour() detour_restore.patch[i] = ((unsigned char *)detour_address)[i]; } - //detour_callback = spengine->ExecAlloc(100); JitWriter wr; JitWriter *jit = ≀ jit_uint32_t CodeSize = 0; @@ -158,47 +129,6 @@ bool CDetour::CreateDetour() jit_rewind: - /* Push all our params onto the stack */ - for (size_t i=0; iAllocatePageMemory(CodeSize); spengine->SetReadWrite(wr.outbase); wr.outptr = wr.outbase; - detour_callback = wr.outbase; + detour_trampoline = wr.outbase; goto jit_rewind; } spengine->SetReadExecute(wr.outbase); + *trampoline = detour_trampoline; + return true; } +void CDetour::DeleteDetour() +{ + if (detoured) + { + DisableDetour(); + } + + if (detour_trampoline) + { + /* Free the allocated trampoline memory */ + spengine->FreePageMemory(detour_trampoline); + detour_trampoline = NULL; + } +} + void CDetour::EnableDetour() { if (!detoured) @@ -241,132 +181,12 @@ void CDetour::EnableDetour() } } -void CDetour::DeleteDetour() -{ - if (detoured) - { - DisableDetour(); - } - - if (detour_callback) - { - /* Free the gate */ - spengine->FreePageMemory(detour_callback); - detour_callback = NULL; - } -} - void CDetour::DisableDetour() { if (detoured) { /* Remove the patch */ - /* This may screw up */ ApplyPatch(detour_address, 0, &detour_restore, NULL); detoured = false; } } - -CBlocker::CBlocker( const char *signame, bool isVoid ) -{ - this->isVoid = isVoid; - isEnabled = false; - isValid = false; - - spengine = NULL; - gameconf = NULL; - block_address = NULL; - block_sig = signame; - - if (isVoid) - { - /* Void functions we only patch in a 'ret' (1 byte) */ - block_restore.bytes = 1; - } - else - { - /* Normal functions need an mov eax, value */ - block_restore.bytes = 6; - } -} - -void CBlocker::EnableBlock( int returnValue ) -{ - if (!isValid || isEnabled) - { - return; - } - - /* First, save restore bits */ - for (size_t i=0; ispengine = spengine; - this->gameconf = gameconf; - - if (!gameconf->GetMemSig(block_sig, &block_address)) - { - g_pSM->LogError(myself, "Could not locate %s - Disabling blocker", block_sig); - isValid = false; - return false; - } - - if (!block_address) - { - g_pSM->LogError(myself, "Sigscan for %s failed - Disabling blocker", block_sig); - isValid = false; - return false; - } - - isValid = true; - - return true; -} diff --git a/extensions/tf2/CDetour/detours.h b/extensions/tf2/CDetour/detours.h index a4b9c1a2..e43b3ce0 100644 --- a/extensions/tf2/CDetour/detours.h +++ b/extensions/tf2/CDetour/detours.h @@ -26,7 +26,7 @@ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * or . * -* Version: $Id$ +* Version: $Id: detours.h 257 2008-09-23 03:12:13Z pred $ */ #ifndef _INCLUDE_SOURCEMOD_DETOURS_H_ @@ -40,9 +40,103 @@ /** * CDetours class for SourceMod Extensions by pRED* * detourhelpers.h entirely stolen from CSS:DM and were written by BAILOPAN (I assume). - * asm.h/c from devmaster.net (thanks cybermind) + * asm.h/c from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -fPIC thunks correctly + * Concept by Nephyrin Zey (http://www.doublezen.net/) and Windows Detour Library (http://research.microsoft.com/sn/detours/) + * Member function pointer ideas by Don Clugston (http://www.codeproject.com/cpp/FastDelegate.asp) */ +#define DETOUR_MEMBER_CALL(name) (this->*name##_Actual) +#define DETOUR_STATIC_CALL(name) (name##_Actual) + +#define DETOUR_DECL_STATIC0(name, ret) \ +ret (*name##_Actual)(void) = NULL; \ +ret name(void) + +#define DETOUR_DECL_STATIC1(name, ret, p1type, p1name) \ +ret (*name##_Actual)(p1type) = NULL; \ +ret name(p1type p1name) + +#define DETOUR_DECL_STATIC4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ +ret (*name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ +ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) + +#define DETOUR_DECL_MEMBER0(name, ret) \ +class name##Class \ +{ \ +public: \ + ret name(); \ + static ret (name##Class::* name##_Actual)(void); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(void) = NULL; \ +ret name##Class::name() + +#define DETOUR_DECL_MEMBER1(name, ret, p1type, p1name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name); \ + static ret (name##Class::* name##_Actual)(p1type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type) = NULL; \ +ret name##Class::name(p1type p1name) + +#define DETOUR_DECL_MEMBER2(name, ret, p1type, p1name, p2type, p2name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name) + +#define DETOUR_DECL_MEMBER3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name, p3type p3name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type, p3type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name, p3type p3name) + +#define DETOUR_DECL_MEMBER4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) + + +#define GET_MEMBER_CALLBACK(name) (void *)GetCodeAddress(&name##Class::name) +#define GET_MEMBER_TRAMPOLINE(name) (void **)(&name##Class::name##_Actual) + +#define GET_STATIC_CALLBACK(name) (void *)&name +#define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual + +#define DETOUR_CREATE_MEMBER(name, gamedata) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata); +#define DETOUR_CREATE_STATIC(name, gamedata) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata); + + +class GenericClass {}; +typedef void (GenericClass::*VoidFunc)(); + +inline void *GetCodeAddr(VoidFunc mfp) +{ + return *(void **)&mfp; +} + +/** + * Converts a member function pointer to a void pointer. + * This relies on the assumption that the code address lies at mfp+0 + * This is the case for both g++ and later MSVC versions on non virtual functions but may be different for other compilers + * Based on research by Don Clugston : http://www.codeproject.com/cpp/FastDelegate.asp + */ +#define GetCodeAddress(mfp) GetCodeAddr(reinterpret_cast(mfp)) + class CDetourManager; class CDetour @@ -57,11 +151,12 @@ public: void EnableDetour(); void DisableDetour(); + void Destroy(); + friend class CDetourManager; protected: - CDetour(void *callbackfunction, size_t paramsize, const char *signame); - ~CDetour(); + CDetour(void *callbackfunction, void **trampoline, const char *signame); bool Init(ISourcePawnEngine *spengine, IGameConfig *gameconf); private: @@ -74,42 +169,16 @@ private: bool detoured; patch_t detour_restore; + /* Address of the detoured function */ void *detour_address; + /* Address of the allocated trampoline function */ + void *detour_trampoline; + /* Address of the callback handler */ void *detour_callback; - + /* The function pointer used to call our trampoline */ + void **trampoline; + const char *signame; - - void *callbackfunction; - - size_t paramsize; - - ISourcePawnEngine *spengine; - IGameConfig *gameconf; -}; - -class CBlocker -{ -public: - void EnableBlock(int returnValue = 0); - void DisableBlock(); - - friend class CDetourManager; - -protected: - CBlocker(const char *signame, bool isVoid); - ~CBlocker(); - - bool Init(ISourcePawnEngine *spengine, IGameConfig *gameconf); - -private: - bool isValid; - bool isEnabled; - bool isVoid; - patch_t block_restore; - void *block_address; - - const char *block_sig; - ISourcePawnEngine *spengine; IGameConfig *gameconf; }; @@ -118,25 +187,13 @@ class CDetourManager { public: - /** - * Return Types for Detours - */ - enum DetourReturn - { - DetourReturn_Ignored = 0, /** Ignore our result and let the original function run */ - DetourReturn_Override = 1, /** Block the original function from running and use our return value */ - }; - static void Init(ISourcePawnEngine *spengine, IGameConfig *gameconf); /** * Creates a new detour - * @param callbackfunction Void pointer to your detour callback function. This should be a static function. - * It should have pointer to the thisptr as the first param and then the same params - * as the original function. Use void * for unknown types. - * @param paramsize This is usually the number of params the function has (not including thisptr). If the function - * passes complex types by value you need to add the sizeof() the type (aligned to 4 bytes). - * Ie: passing something of size 8 would count as 2 in the param count. + * + * @param callbackfunction Void pointer to your detour callback function. + * @param trampoline Address of the trampoline pointer * @param signame Section name containing a signature to fetch from the gamedata file. * @return A new CDetour pointer to control your detour. * @@ -144,37 +201,34 @@ public: * * CBaseServer::ConnectClient(netadr_s &, int, int, int, char const*, char const*, char const*, int) * - * Callback: - * DetourReturn ConnectClientDetour(void *CBaseServer, void *netaddr_s, int something, int something2, int something3, char const* name, char const* pass, const char* steamcert, int len); + * Define a new class with the required function and a member function pointer to the same type: + * + * class CBaseServerDetour + * { + * public: + * bool ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int); + * static bool (CBaseServerDetour::* ConnectClient_Actual)(void *netaddr_s, int, int, int, char const*, char const*, char const*, int); + * } + * + * void *callbackfunc = GetCodeAddress(&CBaseServerDetour::ConnectClient); + * void **trampoline = (void **)(&CBaseServerDetour::ConnectClient_Actual); * * Creation: - * CDetourManager::CreateDetour((void *)&ConnectClientDetour, 8, "ConnectClient"); - */ - static CDetour *CreateDetour(void *callbackfunction, size_t paramsize, const char *signame); - - /** - * Deletes a detour - */ - static void DeleteDetour(CDetour *detour); - - /** - * Creates a function blocker. This is slightly faster than a detour because it avoids a call. + * CDetourManager::CreateDetour(callbackfunc, trampoline, "ConnectClient"); * - * @param signame Section name containing a signature to fetch from the gamedata file. - * @param isVoid Specifies if the function can return void. + * Usage: + * + * CBaseServerDetour::ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int) + * { + * //pre hook code + * bool result = (this->*ConnectClient_Actual)(netaddr_s, rest of params); + * //post hook code + * return result; + * } + * + * Note we changed the netadr_s reference into a void* to avoid needing to define the type */ - static CBlocker *CreateFunctionBlock(const char *signame, bool isVoid); - - /** - * Delete a function blocker. - */ - static void DeleteFunctionBlock(CBlocker *block); - - - /** - * Global DetourReturn value to use for the current hook - */ - static int returnValue; + static CDetour *CreateDetour(void *callbackfunction, void **trampoline, const char *signame); friend class CBlocker; friend class CDetour; @@ -184,13 +238,4 @@ private: static IGameConfig *gameconf; }; -typedef bool DetourReturn; - -#define DETOUR_RESULT_IGNORED false -#define DETOUR_RESULT_OVERRIDE true - -#define SET_DETOUR_RETURN_VALUE(value) CDetourManager::returnValue=(int)value -#define RETURN_DETOUR(result) return result -#define RETURN_DETOUR_VALUE(result,value) do { SET_DETOUR_RETURN_VALUE(value); return (result); } while(0) - #endif // _INCLUDE_SOURCEMOD_DETOURS_H_ diff --git a/extensions/tf2/asm/asm.c b/extensions/tf2/asm/asm.c index ce3a7dff..b984fefe 100644 --- a/extensions/tf2/asm/asm.c +++ b/extensions/tf2/asm/asm.c @@ -1,5 +1,91 @@ #include "asm.h" +#ifndef WIN32 +#define _GNU_SOURCE +#include +#include + +#define REG_EAX 0 +#define REG_ECX 1 +#define REG_EDX 2 +#define REG_EBX 3 + +#define IA32_MOV_REG_IMM 0xB8 // encoding is +r +#endif + +extern void Msg( const char *, ... ); + +/** +* Checks if a call to a fpic thunk has just been written into dest. +* If found replaces it with a direct mov that sets the required register to the value of pc. +* +* @param dest Destination buffer where a call opcode + addr (5 bytes) has just been written. +* @param pc The program counter value that needs to be set (usually the next address from the source). +* @noreturn +*/ +void check_thunks(unsigned char *dest, unsigned char *pc) +{ +#if defined WIN32 + return; +#else + /* Step write address back 4 to the start of the function address */ + unsigned char *writeaddr = dest - 4; + unsigned char *calloffset = *(unsigned char **)writeaddr; + unsigned char *calladdr = (unsigned char *)(dest + (unsigned int)calloffset); + + /* Lookup name of function being called */ + if ((*calladdr == 0x8B) && (*(calladdr+2) == 0x24) && (*(calladdr+3) == 0xC3)) + { + //a thunk maybe? + char movByte = IA32_MOV_REG_IMM; + + /* Calculate the correct mov opcode */ + switch (*(calladdr+1)) + { + case 0x04: + { + movByte += REG_EAX; + break; + } + case 0x1C: + { + movByte += REG_EBX; + break; + } + case 0x0C: + { + movByte += REG_ECX; + break; + } + case 0x14: + { + movByte += REG_EDX; + break; + } + default: + { + Msg("Unknown thunk: %c\n", *(calladdr+1)); + break; + } + } + + /* Move our write address back one to where the call opcode was */ + writeaddr--; + + + /* Write our mov */ + *writeaddr = movByte; + writeaddr++; + + /* Write the value - The provided program counter value */ + *(void **)writeaddr = (void *)pc; + writeaddr += 4; + } + + return; +#endif +} + //if dest is NULL, returns minimum number of bytes needed to be copied //if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs //http://www.devmaster.net/forums/showthread.php?t=2311 @@ -195,9 +281,15 @@ int copy_bytes(unsigned char *func, unsigned char* dest, int required_len) { //Fix CALL/JMP offset if ((opcode & 0xFE) == 0xE8) { if (operandSize == 4) + { *(long*)dest = ((func + *(long*)func) - dest); + + //pRED* edit. func is the current address of the call address, +4 is the next instruction, so the value of $pc + check_thunks(dest+4, func+4); + } else *(short*)dest = ((func + *(short*)func) - dest); + } else { if (operandSize == 4) *(unsigned long*)dest = *(unsigned long*)func; diff --git a/extensions/tf2/asm/asm.h b/extensions/tf2/asm/asm.h index 23b774ed..60862323 100644 --- a/extensions/tf2/asm/asm.h +++ b/extensions/tf2/asm/asm.h @@ -17,6 +17,8 @@ extern "C" { #endif +void check_thunks(unsigned char *dest, unsigned char *pc); + //if dest is NULL, returns minimum number of bytes needed to be copied //if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs //http://www.devmaster.net/forums/showthread.php?t=2311 diff --git a/extensions/tf2/criticals.cpp b/extensions/tf2/criticals.cpp index 30006072..81312f08 100644 --- a/extensions/tf2/criticals.cpp +++ b/extensions/tf2/criticals.cpp @@ -39,40 +39,6 @@ CDetour *calcIsAttackCriticalKnifeDetour = NULL; IForward *g_critForward = NULL; -void InitialiseDetours() -{ - calcIsAttackCriticalDetour = CDetourManager::CreateDetour((void *)&TempDetour, 0, "CalcCritical"); - calcIsAttackCriticalMeleeDetour = CDetourManager::CreateDetour((void *)&TempDetour, 0, "CalcCriticalMelee"); - calcIsAttackCriticalKnifeDetour = CDetourManager::CreateDetour((void *)&TempDetour, 0, "CalcCriticalKnife"); - - bool HookCreated = false; - - if (calcIsAttackCriticalDetour != NULL) - { - calcIsAttackCriticalDetour->EnableDetour(); - HookCreated = true; - } - - if (calcIsAttackCriticalMeleeDetour != NULL) - { - calcIsAttackCriticalMeleeDetour->EnableDetour(); - HookCreated = true; - } - - if (calcIsAttackCriticalKnifeDetour != NULL) - { - calcIsAttackCriticalKnifeDetour->EnableDetour(); - HookCreated = true; - } - - if (!HookCreated) - { - g_pSM->LogError(myself, "No critical hit forwards could be initialized - Disabled critical hit hooks"); - return; - } - -} - int CheckBaseHandle(CBaseHandle &hndl) { if (!hndl.IsValid()) @@ -106,9 +72,9 @@ int CheckBaseHandle(CBaseHandle &hndl) return index; } -DetourReturn TempDetour(void *pWeapon) +DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelper, bool) { - edict_t *pEdict = gameents->BaseEntityToEdict((CBaseEntity *)pWeapon); + edict_t *pEdict = gameents->BaseEntityToEdict((CBaseEntity *)this); if (!pEdict) { @@ -132,7 +98,7 @@ DetourReturn TempDetour(void *pWeapon) int returnValue=0; - CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pWeapon + info.actual_offset); + CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)this + info.actual_offset); int index = CheckBaseHandle(hndl); g_critForward->PushCell(index); //Client index @@ -146,18 +112,52 @@ DetourReturn TempDetour(void *pWeapon) if (result) { - RETURN_DETOUR_VALUE(DETOUR_RESULT_OVERRIDE, returnValue); + return !!returnValue; } else { - RETURN_DETOUR_VALUE(DETOUR_RESULT_IGNORED, returnValue); + return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelper)(); } } +void InitialiseDetours() +{ + calcIsAttackCriticalDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelper, "CalcCritical"); + calcIsAttackCriticalMeleeDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelper, "CalcCriticalMelee"); + calcIsAttackCriticalKnifeDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelper, "CalcCriticalKnife"); + + bool HookCreated = false; + + if (calcIsAttackCriticalDetour != NULL) + { + calcIsAttackCriticalDetour->EnableDetour(); + HookCreated = true; + } + + if (calcIsAttackCriticalMeleeDetour != NULL) + { + calcIsAttackCriticalMeleeDetour->EnableDetour(); + HookCreated = true; + } + + if (calcIsAttackCriticalKnifeDetour != NULL) + { + calcIsAttackCriticalKnifeDetour->EnableDetour(); + HookCreated = true; + } + + if (!HookCreated) + { + g_pSM->LogError(myself, "No critical hit forwards could be initialized - Disabled critical hit hooks"); + return; + } + +} + void RemoveDetours() { - CDetourManager::DeleteDetour(calcIsAttackCriticalDetour); - CDetourManager::DeleteDetour(calcIsAttackCriticalMeleeDetour); - CDetourManager::DeleteDetour(calcIsAttackCriticalKnifeDetour); + calcIsAttackCriticalDetour->Destroy(); + calcIsAttackCriticalMeleeDetour->Destroy(); + calcIsAttackCriticalKnifeDetour->Destroy(); } diff --git a/extensions/tf2/criticals.h b/extensions/tf2/criticals.h index 199090c9..7c0410a3 100644 --- a/extensions/tf2/criticals.h +++ b/extensions/tf2/criticals.h @@ -40,8 +40,6 @@ void InitialiseDetours(); void RemoveDetours(); -bool TempDetour(void *pWeapon); - extern IForward *g_critForward; extern IServerGameEnts *gameents; diff --git a/extensions/tf2/extension.cpp b/extensions/tf2/extension.cpp index 0971c479..71cdc5a0 100644 --- a/extensions/tf2/extension.cpp +++ b/extensions/tf2/extension.cpp @@ -90,7 +90,7 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late) char conf_error[255] = ""; if (!gameconfs->LoadGameConfigFile("sm-tf2.games", &g_pGameConf, conf_error, sizeof(conf_error))) { - if (conf_error) + if (conf_error[0]) { UTIL_Format(error, maxlength, "Could not read sm-tf2.games.txt: %s", conf_error); } diff --git a/gamedata/sm-tf2.games.txt b/gamedata/sm-tf2.games.txt index 32c559fa..fcd0bacb 100644 --- a/gamedata/sm-tf2.games.txt +++ b/gamedata/sm-tf2.games.txt @@ -6,39 +6,39 @@ { "Burn" { - "library" "server" + "library" "server" "windows" "\x56\x8B\xF1\x8B\x8E\x2A\x2A\x00\x00\x8B\x01\x8B\x90\x2A\x2A\x00\x00\xFF\xD2\x84\xC0" "linux" "@_ZN15CTFPlayerShared4BurnEP9CTFPlayerP13CTFWeaponBase" } "RemoveDisguise" { - "library" "server" + "library" "server" "windows" "\x51\x56\x8B\xF1\x8B\x46\x2A\x57\x8D\x7E\x2A\x8D\x4C\x24\x08\x83\xE0\xF7" "linux" "@_ZN15CTFPlayerShared14RemoveDisguiseEv" } "Disguise" { - "library" "server" + "library" "server" "windows" "\x56\x8B\xF1\x8B\x8E\x2A\x2A\x00\x00\xE8\x2A\x2A\x2A\x2A\x8B\x8E\x2A\x2A\x00\x00\x8B\x89\x2A\x2A\x00\x00" "linux" "@_ZN15CTFPlayerShared8DisguiseEii" } "CalcCritical" { - "library" "server" + "library" "server" "linux" "@_ZN13CTFWeaponBase26CalcIsAttackCriticalHelperEv" "windows" "\x83\xEC\x08\x53\x56\x6A\x00" } "CalcCriticalMelee" { - "library" "server" + "library" "server" "linux" "@_ZN18CTFWeaponBaseMelee26CalcIsAttackCriticalHelperEv" "windows" "\x83\xEC\x08\x53\x57\x8B\xF9\xE8\x2A\x2A\x2A\x2A\x8B\xD8" } "CalcCriticalKnife" { - "library" "server" + "library" "server" "linux" "@_ZN8CTFKnife26CalcIsAttackCriticalHelperEv" - "windows" "\x33\xC0\x83\xB9\x30\x13\x00\x00\x01\x0F\x94\xC0\xC3" + "windows" "\x8B\x81\xF0\x13\x00\x00\x83\xF8\xFF\x74\x29\x8B\x15" } } From 8541040bb98ad36e91b67aa4a251be93958b650a Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Thu, 26 Feb 2009 12:42:59 +1300 Subject: [PATCH 2/2] Fixed CommitSuicide offset. --- gamedata/sdktools.games.ep2.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gamedata/sdktools.games.ep2.txt b/gamedata/sdktools.games.ep2.txt index fb7d7993..6e4f28b5 100644 --- a/gamedata/sdktools.games.ep2.txt +++ b/gamedata/sdktools.games.ep2.txt @@ -318,8 +318,8 @@ } "CommitSuicide" { - "windows" "388" - "linux" "388" + "windows" "390" + "linux" "390" } "GetVelocity" {