我们可以添加并使用 return 地址堆栈寄存器来防止堆栈溢出攻击吗?
Could we add and use a return address stack register to prevent stack overflow attack?
来自 this question,将 return 地址压入特定的堆栈寄存器会不会更安全,这样我们就无法利用堆栈溢出?
- 调用者将 return 地址(按
call
)推送到 return address stack register
。
- 调用方推送参数。
- 被叫方推当地人。
- 被调用方正在进行一些工作。
- 被调用者清理堆栈。
ret
将 return address stack register
的值弹出到 RIP
/EIP
.
在大多数情况下,在寄存器中而不是在堆栈中传递 return 地址没有帮助。
大多数 RISC ISA 已经使用 link 寄存器执行此操作,它们的 call
等价物是跳转和 link(MIPS jal
)或 ARM bl
).如果被调用者想调用子函数,则被调用者必须自己将 return 地址保存在堆栈中,因为 jal
会破坏 link 寄存器。 (所以他们最终 return 通过将 return 地址加载到寄存器并使用跳转到寄存器指令。)
这与 x86 所做的没有根本区别,其中 ret
基本上是直接 pop rip
。唯一的区别是叶函数,其中 return 地址永远不会进入内存,除非被调用者 spills/reloads 它获得一个额外的临时寄存器。
来自 this question,将 return 地址压入特定的堆栈寄存器会不会更安全,这样我们就无法利用堆栈溢出?
- 调用者将 return 地址(按
call
)推送到return address stack register
。 - 调用方推送参数。
- 被叫方推当地人。
- 被调用方正在进行一些工作。
- 被调用者清理堆栈。
ret
将return address stack register
的值弹出到RIP
/EIP
.
在大多数情况下,在寄存器中而不是在堆栈中传递 return 地址没有帮助。
大多数 RISC ISA 已经使用 link 寄存器执行此操作,它们的 call
等价物是跳转和 link(MIPS jal
)或 ARM bl
).如果被调用者想调用子函数,则被调用者必须自己将 return 地址保存在堆栈中,因为 jal
会破坏 link 寄存器。 (所以他们最终 return 通过将 return 地址加载到寄存器并使用跳转到寄存器指令。)
这与 x86 所做的没有根本区别,其中 ret
基本上是直接 pop rip
。唯一的区别是叶函数,其中 return 地址永远不会进入内存,除非被调用者 spills/reloads 它获得一个额外的临时寄存器。