一、前言
前面一章节主要介绍了逆向方面的基础知识点,并且介绍的都是32位的逆向。
但如今的程序大部分都已经过渡到了64位,所以只学习32位肯定是不够的。
而本章要介绍的便是64位逆向基础内容,当然,这是在前文基础之上的,已经讲解过的知识点不会再重复赘述。
二、寄存器
首先一个不同之处就是寄存器的不同,64位程序的寄存器与32位程序的寄存器相差很大。
前面我们一直看到过:EAX
、EBX
等寄存器的名字,前面的E
实际上就是扩展的意思(extend
),在16位上,就是AX
、BX
等寄存器名字,因为扩展到了32位,所以前面添加了一个E
。
而64位则是将这个E
改为了R
,并将其大小扩展到了64位,此时寄存器的名字就为RAX
、RBX
等等
并且数量还增加了8个(R8-R15
),并且还扩展了8个128位的XMM寄存器。
64位程序中,XMM寄存器经常被用来优化代码。
而64位程序是可以与32位寄存器兼容的:
- RAX:占64位
- EAX:使用RAX的低32位
- AX:使用EAX的低32位
- AL、AH:分别为AX的低8位与高八位
这就是一个寄存器的分布情况,就目前来说,我们一般用到的只有RAX
与EAX
了。
比如当你使用x64的64位调试器时,就可以从右边的寄存器窗口看到所有可用的寄存器,非常之多:
三、函数
对于函数的内容,上一章节已经介绍的非常详细了,所以这里只介绍一些存在的不同之处。
首先是传递参数问题。
注意:此时要将vs项目更改为x64模式,并在属性中关闭优化,具体步骤不再赘述。
由于64位程序的寄存器比32位要多很多,而寄存器的速度又比内存快,所以此时,它只有一种约定:寄存器快速调用约定:
此时我给函数传递了5个参数,但可以看到,前面4个参数都直接使用的寄存器来传递:ecx
、edx
、r8d
、r9d
,只有第五个参数才使用的栈来传递。
传递方向仍然是从右向左,所以最下面的ecx是第一个参数。
之所以这里使用的ecx
而不是rcx
,是由于我们这里是int
类型,只占32位,所以只需要rcx寄存器低32位就能存放了,如果为64位的long long
,就是rcx
了。