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

问题描述 投票:0回答:1

我正在编写一个全局钩子来纠正 Matrox TripleHead2Go 等平台上的三头监视器窗口定位,到目前为止,它对于 32 位程序运行良好,但现在我需要构建 64 位版本,我需要一些帮助将我的 x86 操作码转换为我在每个窗口类上安装的 wndproc thunk。

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
assembly x86 32bit-64bit x86-64
1个回答
4
投票

在 64 位模式下,前 4 个参数在寄存器

rcx
rdx
r8
r9
中传递。尽管如此,堆栈空间还是为它们分配的。

我们需要知道您传递了多少个参数,以便将额外的参数放在正确的位置。如果它是一个标准的 wndproc,它已经有 4 个参数。你的 32 位代码在开头插入新参数,所以我假设这是你的 C 原型,我们也必须在 64 位模式下执行相同的操作,这样在末尾附加新参数会更容易。

此外,堆栈必须保持 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
© www.soinside.com 2019 - 2024. All rights reserved.