【安全学习之路】Day44

发布时间 2023-10-11 02:17:44作者: Corax0o0

距离上次《逆向工程核心原理》隔得远了点,并不是没继续看下去,一直没什么时间写博客,读得一些章节没什么营养的我就跳过了,现在从x64处理器开始。

x64处理器

64位

64位系统当中的内存地址变为64位,使用64位大小的指针。如寄存器等基本单位也变成了64位的。

内存

虚拟内存的实际大小实际上是16TB,内核和用户空间各占8个TB。

其实2^64=16EB,这个是理论上支持16EB的内存寻址,但是如果调的这么大的话,会浪费大量资源在内存管理上面。

通用寄存器

x64以R开头,x86以E开头

CALL/JMP

相同在于都是使用FF15XXXXXXXX,不过在x64里面解析方法不同。

也可以看到本来在x86里面是4个字节,在x64当中变成了8个字节。然后x86FF15后面的8个字节应该是绝对地址VA。这样的话指令长度就增长了,为了防止增加指令长度,在后面仍然跟着4个字节的地址,只不过变成了相对地址,也就是RVA。可以看到有个FF15FA3F0000,也就是这个相对地址就是3FFA,再加上本来的字节数(6个字节)

有个值得琢磨的事情,就是这个6是啥东西。

问了问GPT,他告诉我这个加上6其实是因为,这个3FFA也就是相对地址,实际上从CALL的下一条指令开始到目标地址的偏移,所以是现在这个CALL的实际地址加上6,再加上RVA。

同时

  • 如果RelativeOffset是有符号整数,则目标地址 = CurrentAddress + 5 + RelativeOffset(5是CALL指令的长度)。
  • 如果RelativeOffset是无符号整数,则目标地址 = CurrentAddress + 6 + RelativeOffset(6是CALL指令的长度)。

看到目标地址的内容了,75CE1E12,所以上面那个CALL被解析为CALL 00000000‘75CE1E12

函数调用约定

64位当中把32位的多种传递规则统一称为一种变形的fastcall。这个fastcall中可以把最多函数的四个参数存储到寄存器当中传递

也就是第一个永远存在RCX或XMM0当中。

如果超过了4个,则与栈并用,也就是第五个参数存入栈来传递,此外函数返回时传递参数过程中所用的栈由调用者清理。需要注意的是虽然多的参数会用栈来传递,但是前面这四个参数还是会预留空间。

栈 栈帧

通过MOV指令操作寄存器与预定的栈来传递,使用VC++的程序代码中几乎看不到push/pop指令。