我需要让一个可执行ELF文件的.text段可写。我需要修改的程序是用C语言编写的,我可以编译它。有什么建议吗?
非常感谢。
非常感谢。
下面的答案中,我将使用以下测试程序:
#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
标志将-N
或(又名--omagic
)传递给链接器,即gcc ... -Wl,--omagic ...
,但这可能会产生其他不良后果(例如禁用共享库)。从man页面中可以看到:
-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在评论中所述,它似乎并没有像说明书上说的那样运行。
让我们看看这些部分是如何标记的:
$ gcc -g -o test test.
$ objdump -h test | fgrep -A1 .text
12 .text 00000192 0000000000400490 0000000000400490 00000490 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
$ 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
的原因。很抱歉没有更多帮助。
mprotect
更改其内存保护。如果您无法更改源代码,则可以尝试使用LD_PRELOAD
来实现。 - abligh--set-section-flag
将代码段设置为可写;这在ELF中是可写的,但我怀疑它实际上并没有做到你需要的。 - abligh