64位软件逆向技术
寄存器
64位通用寄存器的名称第一个字母从'E'改为'R',大小扩展到64位,数量增加了8个(R8~R15),扩充了8个128位的XMM寄存器。
函数
- 函数调用约定
- x86应用程序的函数调用有stdcall、__cdecl、Fastcall等方式,但x64应用程序就只有一种寄存器快速调用约定。
- 前四个用寄存器传递,超过四个多余的参数就放在栈里,入栈顺序从右到左。
- 前四个参数存放的寄存器是固定的,分别是RCX、RDX、R8、R9.
- 任何大于8字节或者不是1字节、2字节、4字节、8字节的参数必须由引用来传递(地址传递)
- 所有浮点参数的传递都是使用XMM寄存器完成的。(在XMM0、XMM1、XMM2、XMM3)
函数的四个参数虽然使用寄存器来传递,但是栈仍然为这4个参数预留了空间(32字节)。
且函数执行体内一般将参数值填充进预留栈空间内并进行数据填充。
参数使用的栈空间由函数调用者负责平衡。
64位环境下,使用RAX寄存器来保存函数返回值。(返回值类型由浮点类型使用MMX0寄存器返回)。
结构体
-
参数不超过八字节
传递结构体参数时,直接将结构体内容放在寄存器里。通过访问寄存器高位和低位分别访问结构体成员。 -
参数超过八字节
传递参数时,会先将结构内容复制到栈空间中,再把结构体地址当成函数的参数来传递(引用传递)。在函数内部通过“结构体地址+偏移”的方式访问结构体内容。
数据结构
-
局部变量
预留栈空间在低地址,局部变量空间在高地址。 -
全局变量
先定义的在低地址,后定义的在高地址。 -
数组
数组从低地址到高地址进行顺序排列的。
数组占用大小 :sizeof(类型) * 个数
寻址公式:数组元素的地址 = 数组首地址 + sizeof(数组类型) * 下标
多维数组也可以看成一个一维数组。
二维寻址公式:数组元素地址 = 数组首地址 + sizeof(一维数组类型)*下标1+sizeof(数组类型)*下标2
访问二维数组特征:
[数组首地址 + n]
[数组收地址 + 寄存器 * n]
网友评论