使文本段可写,ELF

时间:2014-12-20 14:44:43

标签: c gcc text ld elf

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

非常感谢。

1 个答案:

答案 0 :(得分:9)

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

#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在评论中所说的那样,似乎没有按照它在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的原因。很抱歉没有得到更多的帮助。