许多专业的逆向工程师花费大量时间研究为 Windows 编译的 32 位代码,熟悉程度会提高熟练程度。逆向工程 64 位 Windows 程序与 32 位程序之间的高级区别是什么?
我说的是一直盯着我看的东西,而不是说 API 的行为略有不同。例如,
- 64 位编译器是否采用了在 32 位上下文中不常见的特定优化?
- 我会在 64 位程序中看到与 32 位指令集不同或不存在的指令吗?
- 关于
x64
vs的工具支持,我有什么特别需要了解的x86
吗?
许多专业的逆向工程师花费大量时间研究为 Windows 编译的 32 位代码,熟悉程度会提高熟练程度。逆向工程 64 位 Windows 程序与 32 位程序之间的高级区别是什么?
我说的是一直盯着我看的东西,而不是说 API 的行为略有不同。例如,
x64
vs的工具支持,我有什么特别需要了解的x86
吗?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 可能是最好的免费替代品。