将x86操作码转换为64位版本

时间:2014-06-11 06:18:10

标签: assembly x86 32bit-64bit x86-64

我正在编写一个全局钩子来纠正在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

1 个答案:

答案 0 :(得分:4)

在64位模式下,前4个参数在寄存器rcxrdxr8r9中传递。然而,无论如何都为它们分配了堆栈空间。

我们需要知道您传递了多少个参数,以便可以将额外的参数放在适当的位置。如果它是标准的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