#include "detours.h" #include ISourcePawnEngine *CDetourManager::spengine = NULL; IGameConfig *CDetourManager::gameconf = NULL; int CDetourManager::returnValue = 0; void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) { CDetourManager::spengine = spengine; CDetourManager::gameconf = gameconf; } CDetour *CDetourManager::CreateDetour(void *callbackfunction, size_t paramsize, const char *signame) { CDetour *detour = new CDetour(callbackfunction, paramsize, signame); if (detour) { if (!detour->Init(spengine, gameconf)) { delete detour; return NULL; } return detour; } 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) { enabled = false; detoured = false; detour_address = NULL; detour_callback = NULL; this->signame = signame; this->callbackfunction = callbackfunction; spengine = NULL; gameconf = NULL; this->paramsize = paramsize; } CDetour::~CDetour() { DeleteDetour(); } bool CDetour::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) { this->spengine = spengine; this->gameconf = gameconf; if (!CreateDetour()) { enabled = false; return enabled; } enabled = true; return enabled; } bool CDetour::IsEnabled() { return enabled; } bool CDetour::CreateDetour() { if (!gameconf->GetMemSig(signame, &detour_address)) { g_pSM->LogError(myself, "Could not locate %s - Disabling detour", signame); return false; } if (!detour_address) { g_pSM->LogError(myself, "Sigscan for %s failed - Disabling detour", signame); return false; } detour_restore.bytes = copy_bytes((unsigned char *)detour_address, NULL, OP_JMP_SIZE); /* First, save restore bits */ for (size_t i=0; iExecAlloc(100); JitWriter wr; JitWriter *jit = ≀ jit_uint32_t CodeSize = 0; wr.outbase = NULL; wr.outptr = NULL; 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; goto jit_rewind; } spengine->SetReadExecute(wr.outbase); return true; } void CDetour::EnableDetour() { if (!detoured) { DoGatePatch((unsigned char *)detour_address, &detour_callback); detoured = true; } } void CDetour::DeleteDetour() { if (detoured) { DisableDetour(); } if (detour_callback) { /* Free the gate */ spengine->ExecFree(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; }