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 to prevent crashes", signame); return false; } detour_restore.bytes = copy_bytes((unsigned char *)detour_address, NULL, OP_JMP_SIZE+1); /* First, save restore bits */ for (size_t i=0; i<detour_restore.bytes; i++) { detour_restore.patch[i] = ((unsigned char *)detour_address)[i]; } JitWriter wr; JitWriter *jit = ≀ jit_uint32_t CodeSize = 0; wr.outbase = NULL; wr.outptr = NULL; jit_rewind: /* Patch old bytes in */ if (wr.outbase != NULL) { copy_bytes((unsigned char *)detour_address, (unsigned char*)wr.outptr, detour_restore.bytes); } wr.outptr += detour_restore.bytes; /* Return to the original function */ jitoffs_t call = IA32_Jump_Imm32(jit, 0); IA32_Write_Jump32_Abs(jit, call, (unsigned char *)detour_address + detour_restore.bytes); if (wr.outbase == NULL) { CodeSize = wr.get_outputpos(); wr.outbase = (jitcode_t)spengine->AllocatePageMemory(CodeSize); spengine->SetReadWrite(wr.outbase); wr.outptr = wr.outbase; detour_trampoline = wr.outbase; goto jit_rewind; } spengine->SetReadExecute(wr.outbase); *trampoline = detour_trampoline; return true; }
// this was pretty much copied verbatim from pRED's CBaseServer code. Too much I didn't // understand in this area .... yet bool CDetour::StartDetour() { if (!DetourAddress) { Msg ("Detour for %s failed - no valid pointer was provided.\n", FunctionDetoured); return false; } orig_bytes.size_stored = copy_bytes((mem_t *)DetourAddress, NULL, OP_JMP_SIZE+1); for ( size_t i=0; i < orig_bytes.size_stored; i++ ) orig_bytes.bytes_from_memory[i] = ((mem_t *)DetourAddress)[i]; JitWriter wr; JitWriter *jit = ≀ jit_uint32_t CodeSize = 0; wr.outbase = NULL; wr.outptr = NULL; jit_rewind: /* Patch old bytes in */ if (wr.outbase != NULL) copy_bytes((mem_t *)DetourAddress, (mem_t *)wr.outptr, orig_bytes.size_stored); wr.outptr += orig_bytes.size_stored; /* Return to the original function */ jitoffs_t call = IA32_Jump_Imm32(jit, 0); IA32_Write_Jump32_Abs(jit, call, (mem_t *)DetourAddress + orig_bytes.size_stored); if (wr.outbase == NULL) { CodeSize = wr.get_outputpos(); wr.outbase = (jitcode_t)KE_AllocCode(g_pCodeCache, CodeSize); wr.outptr = wr.outbase; TrampolineAddress = wr.outbase; goto jit_rewind; } *TrampolineFunc = TrampolineAddress; return true; }