http://lastfrag.com/hotpatching-and-inline-hooking-explained/から、
Q1) コードは上位メモリから下位メモリへ、またはその逆に進みますか?
Q2) さらに重要なことは、置換オフセットの計算中に、関数プリアンブルを差し引かなければならないのはなぜですか? オフセットが命令の先頭ではなく末尾から始まるためですか?
DWORD ReplacementAddressOffset = ReplacementAddress - OriginalAddress - 5;
完全なコード:
void HookAPI(wchar_t *Module, char *API, DWORD Function)
{
HMODULE hModule = LoadLibrary(Module);
DWORD OriginalAddress = (DWORD)GetProcAddress(hModule, API);
DWORD ReplacementAddress = (DWORD)Function;
DWORD ReplacementAddressOffset = ReplacementAddress - OriginalAddress - 5;
LPBYTE pOriginalAddress = (LPBYTE)OriginalAddress;
LPBYTE pReplacementAddressOffset = (LPBYTE)(&ReplacementAddressOffset);
DWORD OldProtect = 0;
DWORD NewProtect = PAGE_EXECUTE_READWRITE;
VirtualProtect((PVOID)OriginalAddress, 5, NewProtect, &OldProtect);
for (int i = 0; i < 5; i++)
Store[i] = pOriginalAddress[i];
pOriginalAddress[0] = (BYTE)0xE9;
for (int i = 0; i < 4; i++)
pOriginalAddress[i + 1] = pReplacementAddressOffset[i];
VirtualProtect((PVOID)OriginalAddress, 5, OldProtect, &NewProtect);
FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
FreeLibrary(hModule);
}
Q3) このコードでは、jmp 命令の相対アドレスが置き換えられています。relAddrSet は元の宛先へのポインターです。to は、新しい宛先へのポインターです。to アドレスの計算がわかりません。元の宛先を functionForHook + opcodeOffset に追加する必要があるのはなぜですか?
DWORD *relAddrSet = (DWORD *)(currentOpcode + 1);
DWORD_PTR to = (*relAddrSet) + ((DWORD_PTR)functionForHook + opcodeOffset);
*relAddrSet = (DWORD)(to - ((DWORD_PTR)originalFunction + opcodeOffset));