【问题标题】:Make text segment writable, ELF [duplicate]使文本段可写,ELF [重复]
【发布时间】:2015-02-19 06:55:31
【问题描述】:

我需要使可执行 ELF 的 .text 段可写。 我需要修改的程序是用C编写的,我可以编译它。有任何想法吗?

非常感谢。

【问题讨论】:

  • 不够清楚。 .text 通常是代码。它把你的软件/固件放在哪里?
  • 也许它是重复的,但在另一个问题中,他们分享了不起作用的解决方案。
  • 是的,我需要在运行时修改代码,所以文本段必须是可写的..
  • 我不知道为什么这会吸引密切的选票。 OP 非常清楚他要做什么 - 编译和链接 C 程序,以便生成的 ELF 二进制文件具有可写的文本部分。也许他想编写自修改代码。但谁在乎为什么,这是一个合理的问题。

标签: c gcc text ld elf


【解决方案1】:

对于下面的答案,我将使用这个测试程序:

#include <stdio.h>
#include <stdlib.h>

int
main (int argc, char **argv)
{
  printf ("Hello world\n");
  void *m = main;
  *((char *) m) = 0;
  exit (0);
}

编译:

$ gcc -g -o test test.c

如预期:

$ gdb test
...
(gdb) run
Starting program: /home/amb/so/test
Hello world

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a2 in main (argc=1, argv=0x7fffffffe628) at test.c:9
9       *((char *)m) = 0;
(gdb)

这里明显的路线是使用-Wl 标志到gcc-N 或(又名--omagic)传递给链接器,即gcc ... -Wl,--omagic ...,尽管这可能会产生其他不良结果(例如禁用共享库)。从手册页:

   -N
   --omagic
       Set the text and data sections to be readable and writable.  Also, do not page-align the
       data segment, and disable linking against shared libraries.  If the output format
       supports Unix style magic numbers, mark the output as "OMAGIC". Note: Although a
       writable text section is allowed for PE-COFF targets, it does not conform to the format
       specification published by Microsoft.

让我们试一试:

$ gcc --static -g -Wl,--omagic -o test test.c
$ ./test
Hello world
$

这很好用,但是您失去了对动态库的支持。

要保持动态库支持,并保留可写文本段,您应该能够使用:

objcopy --writable-text ...

来自手册页:

   --writable-text
       Mark the output text as writable.  This option isn't meaningful for all object file
       formats.

这应该可以,但不会,objdump 会验证。因此,这是一个比--writable-text 更进一步的解决方案,正如 OP 在 cmets 中所说的那样,它似乎并没有像 tin^Wmanpage 上所说的那样做。

让我们看看这些部分是如何标记的:

$ gcc -g -o test test.
$ objdump -h test | fgrep -A1 .text
  12 .text         00000192  0000000000400490  0000000000400490  00000490  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE

现在让我们摆脱 READONLY 标志:

$ objcopy --set-section-flags .text=contents,alloc,load,code test test1
$ objdump -h test1 | fgrep -A1 .text
 12 .text         00000192  0000000000400490  0000000000400490  00000490  2**4
                  CONTENTS, ALLOC, LOAD, CODE

现在READONLY 已按要求离开了。

但是:

 $ gdb test1
 ...
(gdb) run
Starting program: /home/amb/so/test1
Hello world

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a2 in main (argc=1, argv=0x7fffffffe628) at test.c:9
9       *((char *)m) = 0;
(gdb)

我怀疑这里的问题是 ELF 部分名称以外的其他内容在实际加载时使该部分成为只读。这可能就是人们建议您使用mprotect 的原因。很抱歉没有得到更多帮助。

【讨论】:

  • 首先感谢您的回答。但是 objcopy 不起作用,我的 gcc 无法识别 -XN 选项。
  • @Cronovirus - 好吧,可靠的方法(显然在链接时不可用)是使用mprotect 更改其内存保护。如果您无法更改源,则可以使用LD_PRELOAD 来实现。
  • 谢谢,我知道 mprotect,但我首先在寻找静态解决方案..
  • @Cronovirus 这是我所知道的仅有的两种静态方法。你可以试试gcc ... -Wl,--omagic
  • 没办法.. 我想我将不得不编写一个精灵解析器来修改 .text 段的标志
猜你喜欢
  • 2018-12-12
  • 2012-06-07
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 2018-10-22
相关资源
最近更新 更多