gpt4 book ai didi

c++ - 计算热修补/内联函数 Hook 的偏移量

转载 作者:太空狗 更新时间:2023-10-29 21:45:00 26 4
gpt4 key购买 nike

来自 http://lastfrag.com/hotpatching-and-inline-hooking-explained/ ,

Q1) 代码是从高端内存到低端内存还是相反?

Q2)更重要的是,在计算replacement offset时,为什么要减去function preamble?是因为偏移量是从指令的末尾开始的,而不是从头开始的吗?

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中加上原来的destination?

DWORD *relAddrSet = (DWORD *)(currentOpcode + 1);
DWORD_PTR to = (*relAddrSet) + ((DWORD_PTR)functionForHook + opcodeOffset);
*relAddrSet = (DWORD)(to - ((DWORD_PTR)originalFunction + opcodeOffset));

最佳答案

是的,相对地址是指令后的偏移量,这就是为什么你必须减去 5。

但是,在我看来,你应该忘记相对跳转的想法并尝试绝对跳转。
为什么 ?因为它更容易并且与 x86-64 兼容(相对跳转限制在 +/-2GB)。

绝对跳转是 (x64) :

48 b8 ef cd ab 89 67 45 23 01   mov rax, 0x0123456789abcdef
ff e0 jmp rax

对于 x86:

b8 67 45 23 01   mov eax, 0x01234567
ff e0 jmp eax

这是修改后的代码(加载程序现在是 7 个字节而不是 5 个字节):

void HookAPI(wchar_t *Module, char *API, DWORD Function)
{
HMODULE hModule = LoadLibrary(Module);
DWORD OriginalAddress = (DWORD)GetProcAddress(hModule, API);

DWORD OldProtect = 0;
DWORD NewProtect = PAGE_EXECUTE_READWRITE;

VirtualProtect((PVOID)OriginalAddress, 7, NewProtect, &OldProtect);

memcpy(Store, OriginalAddress, 7);

memcpy(OriginalAddress, "\xb8\x00\x00\x00\x00\xff\xe0", 7);
memcpy(OriginalAddress+1, &ReplacementAddress, sizeof(void*));

VirtualProtect((PVOID)OriginalAddress, 7, OldProtect, &NewProtect);

FlushInstructionCache(GetCurrentProcess(), NULL, NULL);

FreeLibrary(hModule);
}

x64 的代码是相同的,但你必须在开头或结尾添加 2 个 nops ( 90 ) 以匹配以下指令的大小,因此加载器是 "\x48\xb8<8-bytes addr>\xff\xe0\x90\x90" (14字节)

关于c++ - 计算热修补/内联函数 Hook 的偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18640028/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com