为了防范栈溢出攻击,现代处理器架构(如Arm架构)具有执行权限。在Armv8-A中,主要的控制是在MMU地址转换表(translation tables)中的执行权限位。
UXN User (EL0) Execute-never
PXN Privileged Execute-never
设置其中一个位将页面标记为不可执行。这意味着任何尝试跳转到该页面内地址的操作都会触发异常,以权限错误的形式。有单独的特权位和非特权位。这是因为应用代码需要在用户空间(EL0)中可执行,但不应以内核权限(EL1/EL2)执行。另一种攻击形式涉及滥用系统调用,试图使特权代码调用来自用户内存的代码。
下图显示了在操作系统(OS)下运行的应用程序的简化但典型的虚拟地址空间,具有预期的执行权限:
总的来说,这些控制可以有效防范我们描述的各种攻击。翻译表属性和写入控制可以阻止恶意代码写入的任何位置执行,正如您在以下图表中所见:
栈保护为编译器的保护机制,当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。
Stack Canaries (取名自地下煤矿的金丝雀,因为它能比矿工更早地发现煤气泄露,有预警的作用)
有几种针对内存安全的软件缓解技术,如ASan和HWSAN。然而,这些技术在性能和电池寿命方面都需要很多成本,因此不适合广泛部署。内存标记扩展(MTE)解决了这些挑战,带来了一个高性能和可扩展的硬件解决方案,减少了使用不安全语言编写的代码中可能存在的内存安全违规的利用。