![Linux 进程的页表中是否有一个特殊位来停止指令在堆栈中运行,从而阻止溢出攻击?](https://linux22.com/image/11748/Linux%20%E8%BF%9B%E7%A8%8B%E7%9A%84%E9%A1%B5%E8%A1%A8%E4%B8%AD%E6%98%AF%E5%90%A6%E6%9C%89%E4%B8%80%E4%B8%AA%E7%89%B9%E6%AE%8A%E4%BD%8D%E6%9D%A5%E5%81%9C%E6%AD%A2%E6%8C%87%E4%BB%A4%E5%9C%A8%E5%A0%86%E6%A0%88%E4%B8%AD%E8%BF%90%E8%A1%8C%EF%BC%8C%E4%BB%8E%E8%80%8C%E9%98%BB%E6%AD%A2%E6%BA%A2%E5%87%BA%E6%94%BB%E5%87%BB%EF%BC%9F.png)
所以视频中的那个人:
https://www.youtube.com/watch?v=1S0aBV-Waeo
溢出堆栈,篡改返回地址,将其指向堆栈,并使用 NOP 指令将可执行代码复制到堆栈中
但我认为所有现代 Linux 系统(包括 debian 系统)都可以使用页表中的 NX(不可执行)类型的位并使用像这样的停止指令在堆栈中工作来防御这种情况?或者我错过了什么?
答案1
不可执行页面(NX 位)是一项硬件功能。它允许操作系统标记哪些页面可以被执行。如果程序尝试在不可执行的内存页中执行代码,处理器就会出错。
此外,堆栈是否可执行还取决于编译器选项(以及生成的二进制文件)。现代 Linux 发行版为用户空间二进制文件启用了许多强化技术,例如不可执行堆栈、堆栈金丝雀、地址空间布局随机化。例如Ubuntu 用户空间强化。
这是可能的使用可执行堆栈编译二进制文件,而不使用堆栈金丝雀,以使堆栈溢出成为可能,就像视频示例中所做的那样(无法看到编译的程序/使用了哪些选项,但默认情况下,gcc 不应为此类启用可执行堆栈简单的程序)。
此外,还可以配置 SELinux(和其他 Linux 安全模块)来防止系统运行需要可执行+可写内存(堆或堆栈)的二进制文件。
答案2
NX 位仅在 x86_64 架构中引入,在 32 位 Intel/AMD 处理器中不存在。当然,现在几乎每个人都在运行 64 位 PC,但似乎没有人通知那些仍然坚持在旧 386 世界的背景下解释事物的博主和视频博主。