2

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

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

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

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

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

4

2 回答 2

1

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

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

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

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

那么 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,则内存被零填充。

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

于 2019-12-12T14:58:39.620 回答
0

看起来PaX /GrSecurity 对我有用:

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

通过创建可执行映射或修改已经存在的可写/可执行映射,可以将代码引入任务的地址空间。第二种方法可以通过根本不允许创建可写/可执行映射来防止。

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

于 2019-12-12T12:07:54.077 回答