security - 使用单独的寄存器来存储返回地址?

标签 security assembly hardware exploit

我正在阅读有关漏洞利用的工作原理,似乎很多漏洞都是通过覆盖堆栈上的返回地址来操作的。已经付出了很多努力来使这变得更加困难(堆栈金丝雀、ASLR、DEP 等),但在我看来,硬件生产商添加寄存器会更容易,只能通过调用和 ret 指令访问,那将保存返回地址。这样,根据定义,返回地址不能被缓冲区溢出覆盖。因为 call 和 ret 仍然存在并且仍然像今天的 CPU 一样运行(唯一的区别是它们存储返回地址的位置),在我看来,兼容性不会有太多问题。而且由于您使用寄存器而不是 RAM 来访问地址,因此性能影响可能是积极的(尽管微不足道)。

出于安全目的,英特尔显然有空间分配更多寄存器,因为尽管需要两个额外的寄存器,但仍在实现 MPX。那么他们为什么不添加一个特殊的寄存器来存储返回地址呢?

最佳答案

这已经有点存在了。我知道三种架构和一种具有以下功能的语言:

  • SPARC 有一个叫做 register windows 的东西基本上CPU保存和恢复寄存器一个函数调用/返回。按照惯例,返回地址存储在寄存器 o7 中。在函数调用上,然后旋转到 i7当被调用者建立他的堆栈帧时。当被调用者调用另一个函数时,这个地址被旋转到内部寄存器堆栈中,危险代码无法触及。
  • Knuth 的 MMIX 具有类似的设计,但返回地址直接存储在函数调用时几乎无法访问的寄存器堆栈中,因此几乎是您想要的。
  • ARM 和 ARM64 只有一个链接寄存器。在函数调用时,返回地址存储在链接寄存器中,函数返回只是间接跳转到链接寄存器中的地址。这并不能真正满足您的要求,因为链接寄存器的内容必须以嵌套函数调用的形式存储在堆栈中,从而在除叶函数(即不调用其他函数的函数)之外的任何其他方面都破坏了其额外的安全性。
  • Forth 编程语言设计了一个用于值的堆栈和一个用于返回地址的单独堆栈。两个堆栈都可以由程序自由操作,但在操作返回堆栈时需要小心。在实践中,这是通过使用体系结构的寄存器之一用于返回堆栈和一个用于数据堆栈来实现的。这也解决了你提到的问题,但是一个足够聪明的程序员仍然可以通过允许错误的输入粉碎返回堆栈来搞砸。
  • 关于security - 使用单独的寄存器来存储返回地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45315482/

    相关文章:

    linux - 谁能具体解释一下磁盘第一个扇区剩下的2个字节?

    algorithm - 有没有办法在硬件上并行化霍夫曼编码实现?

    node.js - 如何保护基于 Node JS(在 Ubuntu 上运行)和 MongoDB 构建的网站/服务器?

    javascript - 跨域拆分请求——阻止过度的安全性

    assembly - 数据缓存和指令缓存是什么意思?

    assembly - 在 NASM 中声明常量绝对 64 位地址

    assembly - 我如何以二进制/十进制打印寄存器 ds 的内容..?

    iphone - iOS 真的可以支持 AES 256 吗?

    java - 如何在 Android 应用程序关闭或失去焦点时调用方法?

    vhdl - modelsim 说 : "near " )": (vcom-1576) expecting IDENTIFIER." while compiling