加密与解密x64逆向——寄存器和函数调用
64位软件逆向技术
寄存器
本节讨论的x64是AMD和INTEL64的合成,是指与现有x86兼容的64位CPU。在64位系统中,内存地址为64位。
x64系统通用寄存器的名称,第一个字母从E改为R“RAX”,大小扩展到64位,数量增加8个,扩充了8个128位XMM寄存器。
函数
1.栈平衡
RSP用来保存当前的栈顶指针,每8个字节的栈空间来保存一个数据。
栈中存储的数据主要包括局部变量,函数参数,函数返回地址等。每调用一个函数,函数都要申请相应的栈空间。当函数调用完成时需要对刚才申请的栈空间进行释放,这就是栈平衡。
如果不进行栈平衡,栈内存很快就会被消耗光。
2.启动函数
前面有讲,不再重复。详细见文章:x64逆向——MT、MT在release和debug下的四种模式寻找main入口 细节很多,容易被坑!
3.调用约定
与之前不同,x64程序只有一种寄存器快速调用约定。前四个参数使用寄存器传递,如果参数超过四个,多于的参数放在栈里,入栈顺序从右到左,由函数调用方平衡栈空间。
前四个参数虽然使用了寄存器来传递,但还是在栈中为4个参数预留了空间。为方便叙述,这里称之为预留栈空间。在x64中如果像之前那样前四个用寄存器传递那么在函数中相当于少了四个寄存器。当函数功能比较复杂可能导致寄存器不够用,为了避免这个问题,就可以使用预留栈空间。
4.参数传递
参数小于四个时,通过寄存器传递。
4个以上参数传递,后面的通过栈传递。
参数为结构体,且大小不超过8字节,这时应该直接把整个结构体的内容放在寄存器当中,通过访问寄存器的高32位和低32位来访问结构体成员。
大于8字节时
可以见得大于8个字节时,传递参数时会把结构内容复制到栈空间,再把结构体地址当做函数的参数来进行传递(引用传递),
thiscall传递,是C++类的成员函数调用约定。
由此可知类的成员函数调用,参数传递方式与普通函数没很大的区别,唯一的区别是成员函数调用会隐含地传递一个this指针参数。
5.函数返回值
在64位环境中,使用RAX寄存器来保存函数返回值。返回值类型由浮点类型使用MMX0寄存器返回。RAX寄存器可以保存8字节数据。当返回值大于8字节,可以将栈空间的地址作为参数间接访问达到目的。