【问题标题】:What is the difference between the ret instruction in x86 and x64?x86 和 x64 中的 ret 指令有什么区别?
【发布时间】:2020-06-13 18:59:44
【问题描述】:

我最近尝试在 x64 上进行堆栈溢出练习。在 x86 上执行此操作时,我希望垃圾覆盖地址(例如“AAAA”)如下所示:

  1. 我提供的数据溢出缓冲区,覆盖了返回地址
  2. ret 时,(被覆盖的)返回地址将(有效)弹出到 EIP 寄存器中
  3. 发现地址无效,引发段错误

在 x64 中,这似乎有所不同(除了上述步骤中 EIP 与 RIP 的互换)。当提供“AAAAAAA”的垃圾地址时,处理器似乎会在弹出地址之前进行一些有效性检查。通过观察,似乎要求地址的两个最高有效字节在加载之前为空。否则,会发生段错误。我相信这是由于在 x64 中使用了 48 位寻址,但我的印象是,以 0xFFFF 开头的地址也是有效的,但这也会产生段错误。

这是对差异的准确描述吗?为什么这个检查是在数据加载到 RIP 寄存器之前执行的,而另一个有效性检查是在之后执行的?这些说明之间还有其他区别吗?

编辑:为了澄清我的观察,我注意到当提供一个 8 字节的返回地址时,RIP 仍然指向 ret 指令的地址,并且 RSP 仍然指向在 segfault 上被覆盖的返回地址。当提供一个 6 字节的返回地址时,当观察到 segfault 时,被覆盖的地址已经被弹出到 RIP 中。

【问题讨论】:

  • 检查提前完成,因为rip 寄存器可能甚至没有硬件中的位,因此无法加载。是的,地址范围的顶部也应该是规范的,但您必须使用符号扩展。因此,例如 0xffff800000000000 是规范的,将被加载到 rip 中,之后只会出错:) 0xffff4141414141414141 不是规范的。
  • 0xffff 开头的地址仅在内核模式afaik 中有效。
  • @fuz:它们不会自动无效(非规范),它们仅受正常页表机制的保护。 (例如,内核在 PTE 中设置 U/S 位,以便大多数/所有这些虚拟页面都是主管专用的)。例如,Linux 将ffffffffff600000-ffffffffff601000 范围映射到用户空间进程作为[vsyscall] 页面。 (cat /proc/self/maps)。
  • @Vortix:你到底声称发生了什么?那个RSP没有更新还是什么?您如何区分从导致段错误的无效页面获取代码与尝试将非规范地址加载到 RIP 中? ret 手册的操作部分因retf(远)的混乱而变得复杂,但 IA-32E-MODE-RETURN-TO-SAME-PRIVILEGE-LEVEL: 包括 IF the return instruction pointer is not within canonical address space THEN #GP(0); FI;。而不是#PF,而是GP或无效页面错误都让内核传递SIGSEGV
  • 你应该edit你的问题说得更清楚。有趣的是,RSP 在故障之前没有得到更新。因此,错误不是从非规范地址提取代​​码,而是 ret 指令尝试将 RIP 设置为非规范地址。这使得整个 RET 指令出错,这意味着它的任何效果都不可见。

标签: assembly x86 return x86-64


【解决方案1】:

有趣的是,RSP 在故障之前没有得到更新。因此,错误不是从非规范地址提取代​​码,而是 ret 指令尝试将 RIP 设置为非规范地址。

这会使整个 RET 指令出错,这意味着它的任何效果都不可见。 (因为Intel's manual 没有定义任何部分进度/更新的东西,即使ret 的错误行为也是如此。)

不幸的是,英特尔手册中ret 的操作部分是一个条件句的老鼠巢,因为它们使用一个块来记录远近,以及模式和操作数大小的每种组合。 64 位模式下的普通ret 是“IA-32e 模式”,操作数大小=64,和“near”(不将 CS 更改为不同的代码段,只是更改 RIP)。

在这种情况下,x86-64 正常的ret 基本上是pop rip
32位模式正常ret基本就是pop eip
不多也不少。 RIP = *RSP++.

另见


请注意,规范范围的上半部分从 0xffff800000000000 开始:48 位 符号扩展 到 64。0xffff7f0000000000 不是规范的。高 16 位必须匹配第 48 位。

一般来说,x86-64 似乎被设计成 RIP 可以真正只有虚拟地址宽度一样宽,48 或 57 位,从不需要保存非规范地址。任何将 RIP 设置为非规范值的尝试都会在尝试时出错,而不是稍后在代码获取时出错。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 2016-10-28
    • 2019-02-25
    • 2016-12-13
    相关资源
    最近更新 更多