【问题标题】:c++ mprotect for read, write and executec++ mprotect 用于读取、写入和执行
【发布时间】:2020-04-05 18:54:15
【问题描述】:

作为我正在进行的项目的一部分,我想分配一些内存,将操作码写入该内存,然后call 它。届时,代码将跳转到我分配的内存中,运行操作码并使用操作码ret 返回到之前的位置。

我的代码在 Linux 上运行,不需要支持 Windows。

我尝试将 mprotect 与标志 PROT_READ | PROT_WRITE | PROT_EXEC 一起使用,但出现“权限被拒绝”错误。 我需要此内存的写入和执行权限。

我怎样才能实现我正在尝试的目标?为什么我会收到“权限被拒绝”?

分配的内存是使用aligned_alloc 分配的,因此它将对齐到 4KB(页面大小)。

【问题讨论】:

    标签: c++ permissions mprotect


    【解决方案1】:

    我找到了一个解决方案,很高兴了解发生了什么。希望你会喜欢。

    当你测试它时,你可以看到如果你分配一个“大”的内存块,比如1MB 然后mprotect 管理添加执行权限。使用二分搜索,您可以发现最佳位置在128KB。 Glibc 的 malloc 以一种有趣的方式工作,您应该阅读一下,但很快,它会提前分配内存并在您需要时给您一些内存。如果它用完了内存,它会分配更多等等。但是在某些大小下,它不会从它自己的池中为您提供内存。你要求一个足够大的缓冲区让他专门为你分配一个。此阈值为 128KB,由源代码中的DEFAULT_MMAP_THRESHOLD 定义。

    默认内存由 glibc.o 分配,它位于不同的内存段中,并在运行时加载。因此,您的库无权更改该内存保护并添加PERM_EXEC。但是,当您请求大内存并 malloc 为您分配新内存时,您的 LIBRARY 拥有此内存,因此您可以根据需要更改它的权限。

    更多细节以及如何解决小内存量的问题:

    那么 GCC 是如何为你分配内存的呢?使用mmap - http://man7.org/linux/man-pages/man2/mmap.2.html

       #include <sys/mman.h>
       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
       int munmap(void *addr, size_t length);
    

    mmap 在新的内存段中分配内存。 If addr is NULL, then the kernel chooses the (page-aligned) address at which to create the mapping。因此,我们可以使用此函数分配内存。 length 必须是页面大小 (4096) 的乘积,这对于少量内存来说是非常浪费的。如果fd-1,那么内存将被零填充。

    使用这种方法,我们可以根据需要分配具有保护的内存,在这种情况下,具有执行权限。

    【讨论】:

      【解决方案2】:

      看起来PaX/GrSecurity 对我有用:

      PaX 项目的目标是研究各种防御机制 反对利用给攻击者任意的软件错误 对受攻击任务的地址空间的读/写访问。此类错误 包含各种形式的缓冲区溢出错误(无论是堆栈 或基于堆),用户提供的格式字符串错误等。

      将代码引入任务的地址空间可以通过以下任一方式进行 创建可执行映射或修改已存在的映射 可写/可执行映射。第二种方法可以通过不允许 完全创建可写/可执行映射。

      尝试使用paxctl 实用程序来禁用程序二进制文件的内存保护机制。

      【讨论】:

        猜你喜欢
        • 2015-07-26
        • 1970-01-01
        • 1970-01-01
        • 2018-05-08
        • 2017-07-22
        • 1970-01-01
        • 2012-02-21
        • 1970-01-01
        • 2019-05-31
        相关资源
        最近更新 更多