我正在编写一个全局钩子来纠正在Matrox TripleHead2Go平台上的三头监视器窗口定位,这对于32位程序来说非常好用,但现在我需要构建64位版本我需要一些帮助来翻译我的我在每个窗口类上安装的wndproc thunk的x86操作码。
thunk为wndproc调用添加了一个额外的参数,这是原始的wndproc地址,因此我的wndproc处理程序可以在最后调用它。
#ifdef _WIN64
//TODO: figure out the WIN64 instructions
#else
const unsigned char PatchTemplate[] =
{
0x90, // nop, will become int3 if debug = true
0x58, // pop eax (get the return address)
0x68, 0x00, 0x00, 0x00, 0x00, // push imm32, original wndproc address
0x50, // push eax (restore the return address)
0x68, 0x00, 0x00, 0x00, 0x00, // push imm32, our wndproc address
0xC3 // retn
};
#define PATCH_ORIG_OFFSET 3
#define PATCH_NEW_OFFSET 9
#endif
答案 0 :(得分:4)
在64位模式下,前4个参数在寄存器rcx
,rdx
,r8
和r9
中传递。然而,无论如何都为它们分配了堆栈空间。
我们需要知道您传递了多少个参数,以便可以将额外的参数放在适当的位置。如果它是标准的wndproc,它已经有4个参数。你的32位代码在开头插入新的参数,所以我假设你的C原型,我们也必须在64位模式下做同样的事情,在那里更容易在最后添加新的参数。 / p>
此外,堆栈必须保持16字节对齐,并且调用约定要求调用者释放参数(在64位模式下不再有stdcall)。当然,来电者不知道额外的参数,所以不能正确地恢复堆栈,所以我们必须自己做。
代码可能如下所示:
00000000 90 nop ; nop, will become int3 if debug = true
00000001 4883EC28 sub rsp, 40 ; allocate space for arguments
00000005 4C894C2420 mov [rsp + 32], r9 ; spill 4th arg to stack
0000000A 4D89C1 mov r9, r8 ; move 3rd arg
0000000D 4989D0 mov r8, rdx ; move 2nd arg
00000010 4889CA mov rdx, rcx ; move 1st arg
00000013 48B988776655443322- mov rcx, 0x1122334455667788 ; old wndproc
0000001C 11
0000001D 48B888776655443322- mov rax, 0x1122334455667788 ; new wndproc
00000026 11
00000027 FFD0 call rax ; call new wndproc
00000029 4883C428 add rsp, 40 ; restore stack
0000002D C3 ret
更新:这应该是将旧wndproc作为第五个参数附加的版本:
00000000 90 nop ; nop, will become int3 if debug = true
00000001 4883EC28 sub rsp, 40 ; allocate space for arguments
00000005 48B888776655443322- mov rax, 0x1122334455667788 ; old wndproc
0000000E 11
0000000F 4889442420 mov [rsp + 32], rax ; add as 5th argument
00000014 48B888776655443322- mov rax, 0x1122334455667788 ; new wndproc
0000001D 11
0000001E FFD0 call rax ; call new wndproc
00000020 4883C428 add rsp, 40 ; restore stack
00000024 C3 ret