11

I need to make .text segment of an executable ELF writable. The program i need to modify is written in C and i can compile it. Any ideas?

Thanks A lot.

Cronovirus
  • 187
  • 1
  • 9
  • Not clear enough. .text usuaally is code. Where is it placed your software/firmware? – LPs Dec 20 '14 at 14:47
  • Maybe it is a duplicate, but in the other question they shared solutions that doesn't work. – Cronovirus Dec 20 '14 at 15:04
  • 1
    Yes i need to modify code at run time, so the text segment has to be writable.. – Cronovirus Dec 20 '14 at 15:05
  • 3
    I'm not sure why this is attracting close votes. The OP's been perfectly clear what he's trying to do - compile and link a C program such that the resultant ELF binary has a writeable text section. Perhaps he wants to write self-modifying code. But who cares why, it's a reasonable question. – abligh Dec 20 '14 at 15:18

1 Answers1

13

For the answer below, I'm going to use this test program:

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

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

Compile with:

$ gcc -g -o test test.c

As expected:

$ 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)

The obvious route here is to use the -Wl flag to gcc to pass -N or (aka --omagic) to the linker, i.e. gcc ... -Wl,--omagic ..., though this may have other undesirable results (e.g. disabling shared libraries). From the man page:

   -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.

Let's give that a go:

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

That works fine, but you've lost dynamic library support.

To keep dynamic library support, and retain a writable text segment, you should be able to use:

objcopy --writable-text ...

From the man page:

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

This ought to work, but doesn't, as objdump will verify. So here's a solution that gets a bit further than --writable-text which as OP has stated in the comments does not appear to do what it says on the tin^Wmanpage.

Let's see how the sections are marked:

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

Now let's get rid of that READONLY flag:

$ 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

and now READONLY has gone, as requested.

But:

 $ 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)

I suspect the issue here is that something else other than the ELF section name is making the section read-only when actually loaded. Which is probably why people are suggesting you use mprotect. Sorry not to have been more help.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • Thanks for your answer first. But objcopy doesn't work and the option -XN isn't recognized by my gcc.. – Cronovirus Dec 20 '14 at 15:01
  • @Cronovirus - well, the reliable method (not available at link time obviously) would be to change its memory protection with `mprotect`. If you can't change the source, perhaps use `LD_PRELOAD` to achieve that. – abligh Dec 20 '14 at 15:03
  • Thanks, i know mprotect, but i was looking for a static solution first.. – Cronovirus Dec 20 '14 at 15:11
  • @Cronovirus those are the only two static methods I know. You might try with `gcc ... -Wl,--omagic`. – abligh Dec 20 '14 at 15:16
  • no way.. I think i will have to write an elf parser that modify the flag of the .text segment – Cronovirus Dec 20 '14 at 15:25
  • @Cronovirus - I've updated the answer to show how to use `--set-section-flag` to set the code segment to be writable; that works in so much as it's writable in the ELF, but I suspect doesn't actually do what you need. – abligh Dec 20 '14 at 16:27
  • Perhaps you could try with `mprotect()` and the [following magic symbols](http://stackoverflow.com/a/7373301/2809095)? – Iwillnotexist Idonotexist Dec 20 '14 at 16:29
  • @ abligh --set-section-flags and seems that it works: readelf shows that text is writable. Thanks so much! – Cronovirus Dec 20 '14 at 16:34
  • 1
    Real solution: Open the binary with hexedit and look at the value at file offset 0x1C (often 0x34), then traverse through the 0x20 byte structures (a size listed at file offset 0x2a) until you find the one which you identified in the previous dump as containing the .text section. The second to last long value will be 00000005 (05 00 00 00) and needs to have write added which will become thereby 00000007 (07 00 00 00). Now it will work as expected without any limitations such as shared library issues with -Wl,--omagic. A bit technical, but takes a few seconds to do. – Gregory Morse Jul 09 '17 at 04:58
  • @abligh ... really great help and kinowledge your answer ... though experimenting in android user space i am still getting seg fault when i write to non readonly text section .. sigh .. – sol Feb 07 '23 at 18:05
  • @GregoryMorse . .. going to try your ELF magic next ... – sol Feb 07 '23 at 18:06
  • @GregoryMorse ... it works, thankyou . very cool ... b good to find some way to do this at compile / assemble time without omagic etc ... or how to make objcopy do it correctly ... or some linker option ... looking – sol Feb 07 '23 at 18:55