所以视频中的那个人:
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 世界的背景下解释事物的博主和视频博主。