bool CriticalHitManager::CreateCriticalDetour() { if (!g_pGameConf->GetMemSig("CalcCritical", &critical_address) || !critical_address) { g_pSM->LogError(myself, "Could not locate CalcCritical - Disabling Critical Hit forward"); return false; } if (!g_pGameConf->GetOffset("CalcCriticalBackup", (int *)&(critical_restore.bytes))) { g_pSM->LogError(myself, "Could not locate CalcCriticalBackup - Disabling Critical Hit forward"); return false; } /* First, save restore bits */ for (size_t i=0; i<critical_restore.bytes; i++) { critical_restore.patch[i] = ((unsigned char *)critical_address)[i]; } critical_callback = spengine->ExecAlloc(100); JitWriter wr; JitWriter *jit = ≀ wr.outbase = (jitcode_t)critical_callback; wr.outptr = wr.outbase; /* Function we are detouring into is * * void CriticalDetour(CTFWeaponBase(void *) *pWeapon) * * push pWeapon [ecx] */ #if defined PLATFORM_WINDOWS IA32_Push_Reg(jit, REG_ECX); #elif defined PLATFORM_LINUX IA32_Push_Rm_Disp8_ESP(jit, 4); #endif jitoffs_t call = IA32_Call_Imm32(jit, 0); IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour); #if defined PLATFORM_LINUX IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4 #elif defined PLATFORM_WINDOWS IA32_Pop_Reg(jit, REG_ECX); #endif //If TempDetour returns non-zero we want to load something into eax and return this value //IA32_Test_Rm_Reg(jit, eax, eax, something); jit->write_ubyte(0x85); jit->write_ubyte(0xC0); //JNZ critical_callback+50 jit->write_ubyte(0x75); jit->write_ubyte(50-((jit->outptr+1)-jit->outbase)); /* Patch old bytes in */ for (size_t i=0; i<critical_restore.bytes; i++) { jit->write_ubyte(critical_restore.patch[i]); } /* Return to the original function */ call = IA32_Jump_Imm32(jit, 0); IA32_Write_Jump32_Abs(jit, call, (unsigned char *)critical_address + critical_restore.bytes); wr.outbase = (jitcode_t)critical_callback+50; wr.outptr = wr.outbase; //copy g_returnvalue into eax jit->write_ubyte(0xA1); jit->write_uint32((jit_uint32_t)&g_returnvalue); IA32_Return(jit); return true; }
bool CriticalHitManager::CreateCriticalMeleeDetour() { if (!g_pGameConf->GetMemSig("CalcCriticalMelee", &melee_address) || !melee_address) { g_pSM->LogError(myself, "Could not locate CalcCriticalMelee - Disabling Critical Hit forward"); return false; } if (!g_pGameConf->GetOffset("CalcCriticalMeleeBackup", (int *)&(melee_restore.bytes))) { g_pSM->LogError(myself, "Could not locate CalcCriticalMeleeBackup - Disabling Critical Hit forward"); return false; } /* First, save restore bits */ for (size_t i=0; i<melee_restore.bytes; i++) { melee_restore.patch[i] = ((unsigned char *)melee_address)[i]; } melee_callback = spengine->ExecAlloc(100); JitWriter wr; JitWriter *jit = ≀ wr.outbase = (jitcode_t)melee_callback; wr.outptr = wr.outbase; /* Function we are detouring into is * * void CriticalDetour(CTFWeaponBase(void *) *pWeapon) * * push pWeapon [ecx] */ #if defined PLATFORM_WINDOWS IA32_Push_Reg(jit, REG_ECX); #elif defined PLATFORM_LINUX IA32_Push_Rm_Disp8_ESP(jit, 4); #endif jitoffs_t call = IA32_Call_Imm32(jit, 0); IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour); #if defined PLATFORM_LINUX IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4 #elif defined PLATFORM_WINDOWS IA32_Pop_Reg(jit, REG_ECX); #endif //If TempDetour returns non-zero we want to load something into eax and return this value //IA32_Test_Rm_Reg(jit, eax, eax, something); jit->write_ubyte(0x85); jit->write_ubyte(0xC0); //JNZ critical_callback+50 jit->write_ubyte(0x75); jit->write_ubyte(50-((jit->outptr+1)-jit->outbase)); int callbyte = -1; /* The callbyte should return the nth byte (starting from 1) in the backup bytes - Should be an 0xE8 (call) */ g_pGameConf->GetOffset("CalcCriticalMeleeCallByte", &callbyte); callbyte--; void *function = NULL; if (callbyte > -1) { /* Check if the 'callbyte' is actually a call */ if (melee_restore.patch[callbyte] != 0xE8) { g_pSM->LogError(myself, "Invalid callbyte - Melee detour may work incorrectly"); } else { /* Find the absolute address of the function it calls */ void *offsetaddr = (void *)((unsigned char *)melee_address + callbyte + 1); int offset = (int)*(unsigned char *)offsetaddr; function = (unsigned char *)offsetaddr + offset + 4; } } /* Patch old bytes in */ for (size_t i=0; i<melee_restore.bytes; i++) { if ((int)i != callbyte) { jit->write_ubyte(melee_restore.patch[i]); continue; } /* Write in the adjusted call instead */ jitoffs_t call = IA32_Call_Imm32(jit, 0); IA32_Write_Jump32_Abs(jit, call, function); i += 4; } /* Return to the original function */ call = IA32_Jump_Imm32(jit, 0); IA32_Write_Jump32_Abs(jit, call, (unsigned char *)melee_address + melee_restore.bytes); wr.outbase = (jitcode_t)melee_callback+50; wr.outptr = wr.outbase; //copy g_returnvalue into eax jit->write_ubyte(0xA1); jit->write_uint32((jit_uint32_t)&g_returnvalue); IA32_Return(jit); return true; }