【发布时间】:2014-01-05 21:41:05
【问题描述】:
我正在尝试挂钩 Windows API 函数 FindWindowA()。我用下面的代码成功地做到了,没有“热补丁”它:我已经覆盖了函数开头的字节。调用 myHook() 并在调用 FindWindowA() 时显示一个消息框。
user32.dll 启用了热补丁,我想在实际函数之前覆盖 NOP,而不是覆盖函数本身。但是,当我将热补丁设置为 TRUE 时,下面的代码将不起作用。当 FindWindowA() 被执行时它什么也不做。
#include <stdio.h>
#include <windows.h>
void myHook()
{
MessageBoxA(NULL, "Hooked", "Hook", MB_ICONINFORMATION);
}
int main(int argc, char *argv[])
{
BOOLEAN hotpatching = FALSE;
LPVOID fwAddress = GetProcAddress(GetModuleHandleA("user32.dll"), "FindWindowA");
LPVOID fwHotpatchingAddress = (LPVOID)((DWORD)fwAddress - 5);
LPVOID myHookAddress = &myHook;
DWORD jmpOffset = (DWORD)&myHook - (DWORD)(!hotpatching ? fwAddress : fwHotpatchingAddress) - 5; // -5 because "JMP offset" = 5 bytes (1 + 4)
printf("fwAddress: %X\n", fwAddress);
printf("fwHotpatchingAddress: %X\n", fwHotpatchingAddress);
printf("myHookAddress: %X\n", myHookAddress);
printf("jmpOffset: %X\n", jmpOffset);
printf("Ready?\n\n");
getchar();
char JMP[1] = {0xE9};
char RETN[1] = {0xC3};
LPVOID offset0 = NULL;
LPVOID offset1 = NULL;
LPVOID offset2 = NULL;
if (!hotpatching)
offset0 = fwAddress;
else
offset0 = fwHotpatchingAddress;
offset1 = (LPVOID)((DWORD)offset0 + 1);
offset2 = (LPVOID)((DWORD)offset1 + 4);
DWORD oldProtect = 0;
VirtualProtect(offset0, 6, PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy(fwAddress, JMP, 1);
memcpy(offset1, &jmpOffset, 4);
memcpy(offset2, RETN, 1);
VirtualProtect(offset0, 6, oldProtect, &oldProtect);
printf("FindWindowA() Patched");
getchar();
FindWindowA(NULL, "Test");
getchar();
return 0;
}
你能告诉我怎么了吗?
谢谢。
【问题讨论】:
-
相当混乱的问题。如果不对函数进行热补丁,则无法对函数进行热补丁。函数入口点之前的 5 个 NOP 不会被执行。它们只是为动态创建的 JMP 指令留出空间。要访问此代码,您必须使用相对跳转覆盖函数入口点处的 2 字节 NOP (
mov edi,edi)。 -
好的,我明白了!我覆盖了 NOP,但它们永远不会被执行,因为它们在实际函数开始之前 (
mov edi, edi)。我必须用跳回 5 个字节的 JMP 指令替换mov edi, edi(或 7 个,因为mov edi, edi是 2 个字节长)。谢谢。
标签: c windows assembly hook hotpatching