使所有页面可读/可写/可执行

时间:2016-12-30 23:13:03

标签: elf virtual-memory mprotect

我想向ELF二进制文件中的所有内存页授予完全权限(读,写和执行)。理想情况下,我希望能够在二进制文件或目标文件上进行转换,就像使用objcopy更改符号一样。我还没有找到一个很好的方法来做到这一点。我也可以使用一个解决方案,该解决方案涉及在启动时运行代码,在每个页面上使用标志mprotect调用PROT_READ | PROT_WRITE | PROT_EXEC。我已经简单地试过这个,但是我还没有找到一个很好的方法来了解哪些页面被映射,因此需要mprotect编辑哪些页面。

动态分配的页面不需要具有所有权限,只需要在程序启动时映射的页面。

2 个答案:

答案 0 :(得分:3)

以下脚本在代码中实现了雇用俄语的答案:

  • p_type段的RELRO设置为PT_NULL
  • FlagsLOAD设置为PF_X|PF_W|PF_R

这取决于pyelftools的{​​{1}},可以与python3一起安装。

pip3 install pyelftools

答案 1 :(得分:1)

  

我想向ELF二进制文件中的所有内存页授予完全权限(读,写和执行)。

请注意,某些安全策略(例如selinux中的W^X)会阻止您的二进制文件运行。

  

理想情况下,我希望能够将其作为二进制或目标文件的转换

在二进制文件上运行readelf -Wl。你会看到类似的东西:

$ readelf -Wl /bin/date

Elf file type is EXEC (Executable file)
Entry point 0x4021cf
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000400040 0x0000000000400040 0x0001f8 0x0001f8 R E 0x8
  INTERP         0x000238 0x0000000000400238 0x0000000000400238 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000400000 0x0000000000400000 0x00dde4 0x00dde4 R E 0x200000
  LOAD           0x00de10 0x000000000060de10 0x000000000060de10 0x0004e4 0x0006b0 RW  0x200000
  DYNAMIC        0x00de28 0x000000000060de28 0x000000000060de28 0x0001d0 0x0001d0 RW  0x8
  NOTE           0x000254 0x0000000000400254 0x0000000000400254 0x000044 0x000044 R   0x4
  GNU_EH_FRAME   0x00cb8c 0x000000000040cb8c 0x000000000040cb8c 0x0002f4 0x0002f4 R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x00de10 0x000000000060de10 0x000000000060de10 0x0001f0 0x0001f0 R   0x1

您要做的是将Flags段上的LOAD更改为PF_X|PF_W|PF_R。标志是Elf{32,64}_Phdr表的一部分,表的偏移量存储在e_phoff的{​​{1}}中(存储在每个ELF文件的开头)。

查看Elf{32,64}_Ehdr。解析这里涉及的固定大小的ELF结构并不复杂。

您不太可能找到任何标准工具来为您执行此操作(假设这是一个非常不寻常且不安全的事情),但更改标志的程序在/usr/include/elf.h中写入是微不足道的,{ {1}}或C

P.S。您可能还需要" zap" Python段,可以通过将其Perl更改为RELRO来完成。

  

我还没有找到一个很好的方法来了解哪些页面已映射,因此哪些页面需要p_type

在Linux上,您可以解析PT_NULL以获取该信息。其他操作系统可能提供不同的方法来实现相同的目标。