ChatGPT解决这个技术问题 Extra ChatGPT

项目中包含程序集文件时,来自 mmap 的意外 exec 权限

我正用这个把头撞到墙上。

在我的项目中,当我使用 mmap 分配内存时,映射 (/proc/self/maps) 显示它是一个可读和可执行的区域尽管我只请求了可读内存。

在查看 strace (看起来不错)和其他调试之后,我能够确定唯一似乎可以避免这个奇怪问题的东西:从项目中删除程序集文件并只留下纯 C。(什么?!)

所以这是我奇怪的例子,我正在使用 Ubunbtu 19.04 和默认 gcc。

如果您使用 ASM 文件(为空)编译目标可执行文件,则 mmap 返回一个可读且可执行的区域,如果您不使用该文件进行构建,则它的行为正确。请参阅我在示例中嵌入的 /proc/self/maps 的输出。

例子.c

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

int main()
{
    void* p;
    p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);

    {
        FILE *f;
        char line[512], s_search[17];
        snprintf(s_search,16,"%lx",(long)p);
        f = fopen("/proc/self/maps","r");
        while (fgets(line,512,f))
        {
            if (strstr(line,s_search)) fputs(line,stderr);
        }

        fclose(f);
    }

    return 0;
}

example.s:是一个空文件!

输出

包含 ASM 的版本

VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0 

不包含 ASM 的版本

VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 r--p 00000000 00:00 0 
这很奇怪。
我设法仅使用 GCC(没有 CMake)来重现此问题,因此我编辑了问题以使示例更加简洁。
您可能是对的,他的部分答案必须围绕 READ_IMPLIES_EXEC 角色
使用 -Wa,--noexecstack 组装您的源文件。

P
Peter Cordes

Linux 有一个名为 READ_IMPLIES_EXECexecution domain,它会导致分配有 PROT_READ 的所有页面也被赋予 PROT_EXEC。旧版 Linux 内核 used to use this 用于使用 gcc -z execstack 等效项的可执行文件。该程序将向您显示是否已为自己启用:

#include <stdio.h>
#include <sys/personality.h>

int main(void) {
    printf("Read-implies-exec is %s\n", personality(0xffffffff) & READ_IMPLIES_EXEC ? "true" : "false");
    return 0;
}

如果您将它与一个空的 .s 文件一起编译,您会看到它已启用,但如果没有它,它将被禁用。此 comes from the ELF meta-information in your binary 的初始值。做readelf -Wl example。当您在没有空 .s 文件的情况下进行编译时,您会看到这一行:

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10

但是当你用它编译时这个:

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10

注意 RWE 而不仅仅是 RW。这样做的原因是链接器假定您的程序集文件需要 read-implies-exec,除非它被明确告知它们不需要,并且如果您的程序的任何部分需要 read-implies-exec,那么它会为您的整个程序启用. GCC 编译的汇编文件告诉它它不需要这个,用这一行(如果你用 -S 编译你会看到这个):

    .section        .note.GNU-stack,"",@progbits

默认部分权限不包括 exec。有关“标志”和@attributes 的含义,请参见 .section documentation 的 ELF 部分。

(如果您的 .s 依赖于 .text 因为文件顶部的默认部分,请不要忘记在该 .section 指令之后切换到另一个部分,如 .text.data。)

将该行放入 example.s(以及项目中的所有其他 .s 文件)。该 .note.GNU-stack 部分的存在将用于告诉链接器此目标文件不依赖于可执行堆栈,因此链接器将在 GNU_STACK 元数据上使用 RW 而不是 RWE,并且您的程序然后将按预期工作。

for NASM 类似,带有正确标志的 section 指令指定不可执行的堆栈。

5.4 和 5.8 之间的现代 Linux 内核改变了 ELF 程序加载器的行为。对于 x86-64,没有任何东西打开 READ_IMPLIES_EXEC。最多(通过 ld 添加的 RWE GNU_STACK),您将获得可执行的堆栈本身,而不是每个可读页面。 (This answer 涵盖了 5.8 中的最后一个更改,但在此之前肯定有其他更改,因为该问题显示在 x86-64 Linux 5.4 上成功执行了 .data 中的代码)

exec-all (READ_IMPLIES_EXEC) 仅适用于链接器根本没有添加 GNU_STACK 标头条目的旧版 32 位可执行文件。但如此处所示,即使输入 .o 文件缺少注释,现代 ld 总是使用一种设置或另一种设置添加它。

您仍应使用此 .note 部分来表示正常程序中的不可执行堆栈。但是,如果您希望在 .data 中测试自修改代码或遵循 testing shellcode 的一些旧教程,那么这不是现代内核的选项。


废话,这是一个奇怪的默认值。我猜这个工具链在 noexec 之前就已经存在了,并且将 noexec 设置为默认值可能会破坏一些东西。现在我很好奇 NASM / YASM 等其他汇编程序是如何创建 .o 文件的!但无论如何,我想这就是 gcc -zexecstack 使用的机制,以及为什么它不仅使堆栈而且使所有内容都可执行。
@Peter - 这就是为什么像 Botan、Crypto++ 和 OpenSSL 这样使用汇编程序的项目添加 -Wa,--noexecstack。我认为这是一个非常讨厌的锋利边缘。 nx 堆栈的静默丢失应该是一个安全漏洞。 Binutil 的人应该修复它。
@jww 确实是安全问题,奇怪之前没人举报
+1,但如果解释第 .note.GNU-stack,"",@progbits 行的含义/逻辑,这个答案会更好 - 现在它是不透明的,相当于“这个神奇的字符串导致这种效果”,但字符串显然看起来像某种语义。
这似乎已被最近的 Linux 内核更改修复:没有 .note.GNU-stack 部分的默认设置是 exec-none,而不是 exec-all Linux default behavior against `.data` section,甚至 gcc -zexecstack (RWX) 也只是真正的 exec -stack,而不是 exec-all。
R
R.. GitHub STOP HELPING ICE

作为使用特定于 GNU 的部分指令变体修改汇编文件的替代方法,您可以将 -Wa,--noexecstack 添加到命令行以构建汇编文件。例如,看看我在 musl 的 configure 中是如何做到的:

https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a

我相信至少某些带有集成汇编器的 clang 版本可能要求它作为 --noexecstack 传递(没有 -Wa),因此您的配置脚本可能应该检查两者并查看哪个被接受。

您也可以在链接时(在 LDFLAGS 中)使用 -Wl,-z,noexecstack 来获得相同的结果。这样做的缺点是,如果您的项目生成供其他软件使用的静态 (.a) 库文件,这将无济于事,因为当它被其他程序使用时,您无法控制链接时间选项。


嗯...在阅读这篇文章之前,我不知道您是 Rich Felker。为什么你的显示名称不是 dalias?

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅