我可以执行驻留在数据段(ELF二进制)中的代码吗?

时间:2016-06-30 03:36:18

标签: c memory segmentation-fault elf shellcode

在理解二进制文件(虚拟内存布局,执行等)的过程中,我编写了一个C代码,声明了一个包含可执行代码字节的全局字符串,然后我覆盖了返回通过在main()中声明指针(PTR)使用简单技巧从main()函数到该可执行代码的地址,该指针是在堆栈2上保留的本地内存区域。来自main()的返回地址,所以我所做的就是将返回地址的地址分配给该指针(PTR=(int*)&PTR+2),然后用可执行代码的地址(静态字符串)覆盖该地址的内容)。

现在的困境是,每当我编译并执行时,我都会收到分段错误。 可执行代码没有内存input/output(它只是一堆NOPs)。

使用GDB我确保过程完美地工作:返回地址被更改为字符串的地址但返回从未发生。

我所知道的是可执行文件代码映射到虚拟内存中的页面thar标记为RW.data& .bss段)所以除非代码注入{{{}},否则可能无法执行此类代码执行1}}内存区域(标记为executable的页面)。这是我关于这个主题的理论,我邀请你提供更多细节。

RE

1 个答案:

答案 0 :(得分:2)

  

我收到分段错误。

它是数据执行预防的硬件控制(https://en.wikipedia.org/wiki/Executable_space_protection#Linux) - 如果没有' x'那么你就不能跳转到数据页面。 (执行)在页表中设置的位。所有位的内存映射在/proc/$pid/maps / /proc/$pid/smaps文件中列为' rwx'对于可写代码,' rw - '对于没有执行的数据,' r - '对于只读数据,' r-x'对于普通代码。

如果要执行数据,则应在要成为代码的数据部分调用带有mprotect标记的PROT_EXEC系统调用。

在x86世界中,这完全实现为奔腾4(Prescott)中的"NX bit" / "XD bit" feature和更新(Core,Core2,Core i *,核心m)/ Athlon 64 / Opteron及更新版本。如果OS在32位模式下工作,则必须打开PAE才能在页表中使用该位。在x86_64模式(64位)中,始终支持NX / XD位。

2004年左右,Linux的第一个支持变种被添加到http://linuxgazette.net/107/pramode.html

2007年,您可能已经过时了没有PAE的硬件,旧内核或32位模式内核。

有关NX / XD位的信息:https://en.wikipedia.org/wiki/NX_bit

有时' rwx'模式可能被禁止,请检查https://en.wikipedia.org/wiki/W^X

对于pre-NX系统,存在基于x86的段寄存器的解决方案,以部分禁用部分内存空间执行。

  

我可以执行上面的程序而不会出现分段错误吗?

你可以:

  • 使用mprotect
  • 调用PROT_READ|PROT_EXEC,使数据页可执行
  • 将elf文件的数据段标记为可执行文件(需要深入查看ld个脚本 - 默认位于ld --verbose
  • 将shellcode移动到堆栈,并使用execstack
  • 使堆栈可执行
  • 将shellcode移动到elf文件的文本数据
  • 尝试禁用内核中的nx / xd位(很难;可能需要重新编译)
  • 使用未启用PAE选项的32位操作系统(内核)(构建时选项)。
  • 使用没有NX / XD的旧cpu