我可以执行驻留在数据段(ELF二进制)中的代码吗? [英] Can i execute code that resides in data segment (ELF binary)?

查看:142
本文介绍了我可以执行驻留在数据段(ELF二进制)中的代码吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

现在的难题是,每当我编译执行时,我都会收到一个分段错误
可执行代码不存储输入/输出(它只是一堆 NOP )。

我使用GDB确保该过程正常运行:将返回地址更改为字符串的地址,但返回永远不会发生。

我所知道的就是将可执行代码映射到虚拟内存中的页面标记为 RW .data & .bss 段),所以除非将代码注入到内存的可执行区域(标记为 RE )。这是我关于这个主题的理论,我邀请您提供更多详细信息。

In the way to understanding binaries (Virtual memory layout, execution...etc), I've written a C code that declares a global string which contains bytes of an executable code, then i overwrote the return address from the main() function to that executable code using a simple trick by declaring a pointer (PTR) in main() which is a local area of memory reserved on the stack 2 WORDS far away from the return address from the main(), so all i do is assigning the address of the return address to that pointer (PTR=(int*)&PTR+2) and then overwrite the content of that address with the address of the executable code (the static string).

Now the dilemma is that, whenever i compile and i execute, i receive a segmentation fault. The executable code does no memory input/output (its just a bunch of NOPs).

Using GDB i made sure that the process works perfectly: the return address is changed to be the string's address but the return never happens.

All i know is that the executable code is mapped to pages in virtual memory thar are marked RW (.data & .bss segments) so maybe there's no way to do such a code execution unless code is injected in an executable area of memory (Pages that are marked RE). That's my theory about the subject, i invite you to give more details.

char code[]="\x90\x90\x90\x90\x90\x90\x90\x90"; //a static string contains executable code

int main()
{
int *return_address; //Pointer to the return address - uninitialized
return_address = (int *)&return_address + 2; //Initializing the return address - according to stack layout
(*return_address) = (int)code; //Overwriting the return address with the code's address
}


覆盖返回地址

推荐答案


我收到分段错误。

i receive a segmentation fault.

这是防止执行数据的硬件控制(<一个href = https://en.wikipedia.org/wiki/Executable_space_protection#Linux rel = nofollow noreferrer> https://en.wikipedia.org/wiki/Executable_space_protection#Linux )-您可以如果页表中没有设置 x(执行)位,则不只是跳转到数据页。 / proc / $ pid / maps / / proc / $ pid / smaps 文件中列出了所有位的内存映射对于可写代码,为 rwx,对于未执行的数据为 rw-,对于只读数据,为 r--,对于普通代码为 r-x。

It is hardware control of data execution prevention (https://en.wikipedia.org/wiki/Executable_space_protection#Linux) - you can't just jump to data page if it has no 'x' (execute) bit set in page tables. Memory mappings with all bits are listed in /proc/$pid/maps / /proc/$pid/smaps files as 'rwx' for writable code, 'rw-' for data without execution, 'r--' for readonly data, 'r-x' for normal code.

如果要执行数据,应使用 PROT_EXEC调用 mprotect syscall 标记在您要成为代码的数据部分。

If you want to execute data, you should call mprotect syscall with PROT_EXEC flag on the section of your data which wants to be code.

在x86世界中,它已完全实现为奔腾4(Prescott)和更高版本(Core,Core2,Core i *,内核m)/ Athlon 64 / Opteron和更高版本中具有NX位 / XD位功能。如果OS在32位模式下工作,则必须打开PAE才能在页表中包含此位。在x86_64模式(64位)下,始终支持NX / XD位。

In x86 world this was fully implemented as "NX bit" / "XD bit" feature in Pentium 4 (Prescott) and newer (Core, Core2, Core i*, core m) / in Athlon 64 / Opteron and newer. If OS works in 32-bit mode, it must turn on PAE to have this bit in page table. In x86_64 mode (64-bit) there is always NX/XD bit supported.

第一个支持版本是在2004年左右添加到linux的: http://linuxgazette.net/107/pramode.html

First variants of support were added to linux around 2004: http://linuxgazette.net/107/pramode.html

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

In 2007 you may have outdated hardware, old kernel or 32-bit mode kernel without PAE.

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

Info about NX/XD bits: https://en.wikipedia.org/wiki/NX_bit

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

Sometimes 'rwx' mode may be prohibited, check https://en.wikipedia.org/wiki/W^X.

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

For pre-NX systems there were solutions based on segment registers of x86 to partially disable part of memory space from executing.


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

can i execute the program above without having an segmentation fault ?

您可以:


  • 使用 mprotect 使数据页可执行> PROT_READ | PROT_EXEC

  • 将elf文件的数据段标记为可执行文件(需要深入破解 ld 脚本-默认为 ld --verbose

  • 制作所有包含的页面。数据和堆可执行文件(不仅仅是堆栈)

    ,带有ld或gcc -z execstack

  • 将shellcode移动到elf文件的文本数据

  • 尝试禁用内核中的nx / xd位(硬;

  • 使用未启用PAE选项(构建时间选项)的32位操作系统(内核)。

  • 使用不具有NX的较旧cpu / XD

  • make the data page executable by calling mprotect on it with PROT_READ|PROT_EXEC
  • make the data segment of elf file marked as executable (need to hack deeply inside ld scripts - default is in ld --verbose)
  • make all pages including .data and the heap executable (not just the stack)
    with ld or gcc -z execstack
  • move shellcode to text data of elf file
  • try to disable nx/xd bit in kernel (hard; recompilation may be needed)
  • use 32-bit OS (kernel) without PAE option enabled (build time option).
  • use older cpu without NX/XD

这篇关于我可以执行驻留在数据段(ELF二进制)中的代码吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆