【问题标题】:Why is execstack required to execute code on the heap?为什么需要 execstack 在堆上执行代码?
【发布时间】:2018-10-15 12:24:46
【问题描述】:

我编写了下面的代码来测试 shellcode(用于取消链接 /tmp/passwd)在安全类中的分配。

当我使用 gcc -o test -g test.c 编译时,我在跳转到 shellcode 时遇到了段错误。

当我使用 execstack -s test 对二进制文件进行后处理时,我不再遇到段错误并且 shellcode 正确执行,删除了 /tmp/passwd

我正在运行gcc 4.7.2。要求堆栈可执行以使堆可执行似乎是个坏主意,因为后者的合法用例比前者多得多。

这是预期的行为吗?如果有,原因是什么?

#include <stdio.h>                                     
#include <stdlib.h>                                    


char* shellcode;                                       


int main(){                                            
    shellcode = malloc(67);                            
    FILE* code = fopen("shellcode.bin", "rb");      
    fread(shellcode, 1, 67, code);                     

    int (*fp)(void) = (int (*) (void)) shellcode;      
    fp();                                              
}    

这是xxd shellcode.bin的输出:

0000000: eb28 5e89 760c 31c0 8846 0bfe c0fe c0fe  .(^.v.1..F......           
0000010: c0fe c0fe c0fe c0fe c0fe c0fe c0fe c089  ................           
0000020: f3cd 8031 db89 d840 cd80 e8d3 ffff ff2f  ...1...@......./           
0000030: 746d 702f 7061 7373 7764                 tmp/passwd                 

【问题讨论】:

  • @HansPassant,NX 似乎可用于页表条目的粒度。该技术与我的问题有些正交,我的问题是关于将堆栈和堆保护合二为一的基本原理。

标签: c gcc


【解决方案1】:

真正的“意外”行为是设置标志使 heap 和堆栈一样可执行。该标志旨在与生成基于堆栈的 thunk 的可执行文件一起使用(例如,当您获取嵌套函数的地址时的 gcc)并且不应该真正影响堆。但是 Linux 通过全局使所有可读页面可执行来实现这一点。

如果您想要更细粒度的控制,您可以改用mprotect 系统调用来控制每页的可执行权限 -- 添加如下代码:

uintptr_t pagesize = sysconf(_SC_PAGE_SIZE);
#define PAGE_START(P) ((uintptr_t)(P) & ~(pagesize-1))
#define PAGE_END(P)   (((uintptr_t)(P) + pagesize - 1) & ~(pagesize-1))
mprotect((void *)PAGE_START(shellcode), PAGE_END(shellcode+67) - PAGE_START(shellcode),
         PROT_READ|PROT_WRITE|PROT_EXEC);

【讨论】:

【解决方案2】:

这是预期的行为吗?

查看 Linux 内核代码,我认为这个标志的内核内部名称是“读取意味着执行”。所以是的,我认为这是意料之中的。

要求堆栈可执行以使堆可执行似乎是个坏主意,因为后者的合法用例比前者多得多。

为什么需要完整的堆可执行?如果你真的需要动态生成机器码并运行它左右,你可以使用mmap系统调用显式分配可执行内存。

原理是什么?

我认为这个想法是这个标志可以用于期望所有可读的东西也是可执行的遗留程序。这些程序可能会尝试在堆栈上运行东西,也可能会尝试在堆上运行东西,所以这都是允许的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-26
    • 1970-01-01
    • 2017-10-15
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多