linux - linux栈区为什么有可执行保护?

标签 linux stack virtual-memory

在研究 Linux 内核时,我刚刚发现,默认情况下,可执行文件有一个“可执行”堆栈区域。我自然认为唯一(必要的)可执行区域是文本部分。有没有与此相关的历史原因,或任何实际用法?

最佳答案

在某些情况下,可执行堆栈是必需的,例如嵌套函数的 GCC trampoline。

蹦床是在获取嵌套函数的地址时在运行时创建的一小段代码。它通常驻留在栈上,在包含函数的栈帧中。这些宏告诉 GCC 如何生成代码来分配和初始化蹦床。

在大多数发行版中,由于攻击风险和使用堆栈来执行 shellcode,此功能被禁用,尽管您可以使用 -z execstack 编译代码以启用它。也可以使用名为 execstack 的程序在编译程序后启用或禁用此功能。为了清楚这一点,我编写了一个简单的程序来执行 exit 系统调用,退出代码为 32。如果启用此功能,代码将正常工作,否则会出现段错误。

#include <stdlib.h>
#include <unistd.h>

char shellCode[] =  "\xb8\x01\x00\x00\x00" //          mov    $0x1,%eax
                    "\xbb\x20\x00\x00\x00" //          mov    $0x20,%ebx
                    "\xcd\x80";            //          int $0x80

int main(){
    int *ret;
    ret = (int*) &ret + 2;
    *ret = (int) shellCode;
    return 5;
}

在这段代码中,ret 指向它的地址加 2。正如我们所知,在 IA32 系统中指针大小为 4 字节,并且在每个函数的开头都有一个 push ebp 编译后。因此,为了到达 main 的返回地址,我们需要添加 2*stack_chunk_size 并在编译时将每个 block 设置为 4 字节,这非常有效。

像这样编译代码进行测试:

gcc -mpreferred-stack-boundary=2 -z execstack -o testShellCode testShellCode.c

-mpreferred-stack-boundary=2 是以 4 字节 block 对齐堆栈,-z execstack 是使用可执行堆栈进行编译。

这个简单的代码可以让我们深入了解为什么会有可执行堆栈保护这样的东西。

查找以下链接以获取有关嵌套函数和 execstack 命令的更多信息:

Trampolines

execstack

关于linux - linux栈区为什么有可执行保护?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32740003/

相关文章:

memory-management - 什么数据结构使用 1GB Linux 内核空间中的 128MB?

linux - 为什么 time.h 中的 time() 没有对 sys_time 的系统调用?

python - 在 OpenCV 中保存视频(Linux、Python)

java - 我该怎么做才能获取堆栈的元素并将它们添加到单个链表中?

c - 如何保护解释器的 native 调用堆栈免受垃圾收集?

architecture - 计算页面大小和段大小

c++ - 如何检查显示器是否已插入? (Linux)

linux - 不想按 Ctrl +D 来结束文件。任何替代方案

recursion - 堆栈递归程序问题

iPhone 应用程序在启动时使用 60MB 虚拟内存