逆向工程 x64/Win64 代码与 x32/Win32 代码有何质的差异?

逆向工程 x64
2021-06-30 02:08:50

许多专业的逆向工程师花费大量时间研究为 Windows 编译的 32 位代码,熟悉程度会提高熟练程度。逆向工程 64 位 Windows 程序与 32 位程序之间的高级区别是什么?

我说的是一直盯着我看的东西,而不是说 API 的行为略有不同。例如,

  • 64 位编译器是否采用了在 32 位上下文中不常见的特定优化?
  • 我会在 64 位程序中看到与 32 位指令集不同或不存在的指令吗?
  • 关于x64vs的工具支持,我有什么特别需要了解的x86吗?
3个回答

x86 和 x86_64 之间最大的区别之一是引入了 RIP 相对寻址。与 32 位 ARM 类似,现在可以(轻松)以与当前 RIP 值的偏移量引用数据。

例如,这里是 x86 程序中 __libc_csu_init() 的前几条指令:

08048420 <__libc_csu_init>:
 8048420:       55                      push   %ebp
 8048421:       57                      push   %edi
 8048422:       31 ff                   xor    %edi,%edi
 8048424:       56                      push   %esi
 8048425:       53                      push   %ebx
 8048426:       e8 f9 fe ff ff          call   8048324 <__x86.get_pc_thunk.bx>
 804842b:       81 c3 79 12 00 00       add    $0x1279,%ebx
 8048431:       83 ec 1c                sub    $0x1c,%esp
 8048434:       8b 6c 24 30             mov    0x30(%esp),%ebp
 8048438:       8d b3 0c ff ff ff       lea    -0xf4(%ebx),%esi

这是在 x86_64 上(注意 0x40050a 和 0x400511):

0000000000400500 <__libc_csu_init>:
  400500:       48 89 6c 24 d8          mov    %rbp,-0x28(%rsp)
  400505:       4c 89 64 24 e0          mov    %r12,-0x20(%rsp)
  40050a:       48 8d 2d 97 01 20 00    lea    0x200197(%rip),%rbp        # 6006a8 <__init_array_end>
  400511:       4c 8d 25 88 01 20 00    lea    0x200188(%rip),%r12        # 6006a0 <__frame_dummy_init_array_entry>
  400518:       48 89 5c 24 d0          mov    %rbx,-0x30(%rsp)
  40051d:       4c 89 6c 24 e8          mov    %r13,-0x18(%rsp)
  400522:       4c 89 74 24 f0          mov    %r14,-0x10(%rsp)
  400527:       4c 89 7c 24 f8          mov    %r15,-0x8(%rsp)

您可以在此处找到有关此约定的更多信息:http : //www.codegurus.be/codegurus/programming/riprelativeaddressing_en.htm

将有所不同的重要事情之一是调用约定 - 在 64 位上,一些参数在寄存器中传递;请参阅http://en.wikipedia.org/wiki/X86_calling_conventions和参考资料

其他明显的东西包括更大的寄存器、更多的 SSE 寄存器和 64 位算术(mov QWORD/movq等)。超出您的预期,事情实际上非常相似。请参阅http://en.wikipedia.org/wiki/X86-64#Architectural_features以了解巨大差异的概述 - 大多数其他新功能对内核空间代码而不是用户空间代码更重要。除了 32 位指令到 64 位指令的逻辑扩展之外,指令集保持相当静态。

关于工具支持,Ollydbg(和 Immunity Debugger)不支持 x64。Windbg 可能是最好的免费替代品。