跳转至

钩住近调用

遵循清单 8-2 中相同的内存保护规则,你可以像这样钩住近调用(打开 CallHookExample.cpp 跟着做):

DWORD callHook(DWORD hookAt, DWORD newFunc)
{
    DWORD newOffset = newFunc - hookAt - 5;
    auto oldProtection =
        protectMemory<DWORD>(hookAt + 1, 
PAGE_EXECUTE_READWRITE);
hookAt + 1);
    writeMemory<DWORD>(hookAt + 1, newOffset);
    protectMemory<DWORD>(hookAt + 1, 
oldProtection);
  return originalOffset + hookAt + 5;
}

这个函数把要钩的 CALL 地址(hookAt)和要重定向到的地址(newFunc)作为参数,并用它们计算调用 newFunc 中代码所需的偏移量。应用正确的内存保护后,callHook() 函数把新偏移量写入 hookAt + 1①处的内存,重新应用旧内存保护,计算原始调用的地址②,并把该值返回给调用者。

以下是你可能在游戏破解中实际使用这种函数的方式:

DWORD origFunc = callHook(0xDEADBEEF, 
(DWORD)&someNewFunction);

这钩住了 0xDEADBEEF 处对 0x0BADF00D 的近调用,把它重定向到 someNewFunction 的地址,也就是你的破解要执行的代码。调用后,origFunc 值将持有 0x0BADF00D。