我最近一直试图将MessageBox挂钩作为学习课程的一部分,在此期间我开发了一个钩子回调,它是:
int WINAPI MessageBoxCallback(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
DWORD dwAddr = (DWORD)GetProcAddress(GetModuleHandle("User32.dll"), "MessageBoxA"); //Grab address of MessageBoxA
__asm
{
add dwAddr, 0x5 //Before we continue on-wards we add 5 bytes to the current address to avoid the infinite loop
jmp dwAddr //Then finally jump to (MessageBoxA + 0x5)
}
}
考虑到这一点非常简单,因为我们只是跳回到MessageBoxA + 0x5,所以我相信它本身没有错误,事实上我甚至检查过我是否忘记了丢失的字节但序言是回调是:
mov edi,edi
推送ebp
mov ebp esp
那就是说,我确信我没有任何错误回报字节。如果是这样,它会崩溃程序然后显示一个消息框,然后在放置钩子后崩溃。
我已经进一步检查了钩子是否放置得正确并且它看起来很完美我已经完成了所有的断点和调试但它失败了。
答案 0 :(得分:1)
MessageBoxA(),取决于Windows版本,不创建堆栈帧。所以它的结局并没有恢复ESP寄存器。但是你的函数需要存储dwAddr
局部变量。因此堆栈指针不会被恢复,MessageBoxA()中的RET指令会弹出错误的返回地址。 KABOOM。
你必须修补__declspec(裸体)才能获得功能的序幕以匹配MessageBoxA的结局。这适用于我的机器:
__declspec(naked)
int WINAPI MessageBoxCallback(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
__asm {
push ebp
}
static DWORD dwAddr = (DWORD)GetProcAddress(GetModuleHandle("User32.dll"), "MessageBoxA"); //Grab address of MessageBoxA
__asm
{
add dwAddr, 0x5
jmp dwAddr
}
}