2014-12-20 38 views
5

Potrzebuję wykonać segment .text pliku wykonywalnego ELF z możliwością zapisu. Program, który muszę zmodyfikować, jest napisany w języku C i mogę go skompilować. Jakieś pomysły?Utwórz segment tekstowy zapisywalny, ELF

Wielkie dzięki.

+0

Niewystarczająco jasne. .text usuaally to kod. Gdzie znajduje się twoje oprogramowanie/oprogramowanie sprzętowe? – LPs

+0

Może to duplikat, ale w drugim pytaniu dzielili się rozwiązaniami, które nie działają. – Cronovirus

+1

Tak, muszę zmodyfikować kod w czasie wykonywania, więc segment tekstowy musi być zapisywalny. – Cronovirus

Odpowiedz

8

Na poniższym odpowiedź, mam zamiar używać tego programu testowego:

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

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

skompilować z:

$ gcc -g -o test test.c 

Zgodnie z oczekiwaniami:

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

oczywistym trasy tutaj należy użyć flagi -Wl do gcc, aby przekazać -N lub (aka --omagic) do łącznika, tj. gcc ... -Wl,--omagic ..., chociaż może to mieć inne niepożądane wyniki (np. wyłączanie bibliotek współdzielonych). Od strony 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. 

Dajmy że Go:

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

który działa dobrze, ale straciłeś dynamiczne wsparcie biblioteki.

Aby utrzymać dynamiczne wsparcie biblioteki i zachować segment tekstu zapisu, powinien mieć możliwość korzystania z:

objcopy --writable-text ... 

Od strony man:

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

To powinno działać, ale nie robi 't, jako objdump zweryfikuje. Oto rozwiązanie, które jest nieco inne niż --writable-text, które, jak OP stwierdził w komentarzach, nie wydaje się robić tego, co napisano na blaszce^Wmanpage.

Zobaczmy jak sekcje są zaznaczone:

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

Teraz pozbyć się tego READONLY flagi:

$ 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 

i teraz READONLY upadł, zgodnie z wnioskiem.

Ale:

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

Podejrzewam, że problem jest to, że jeszcze coś innego niż nazwa sekcji ELF robi sekcję tylko do odczytu, gdy faktycznie załadowane. Zapewne dlatego ludzie sugerują, że używasz mprotect. Przepraszam, że nie pomogłem.

+0

Dzięki za odpowiedź w pierwszej kolejności. Ale objcopy nie działa, a opcja -XN nie jest rozpoznawana przez mój gcc. – Cronovirus

+0

@Cronovirus - cóż, niezawodną metodą (niedostępną oczywiście w czasie połączenia) byłoby zmiana ochrony pamięci za pomocą 'mprotect'. Jeśli nie możesz zmienić źródła, być może użyj 'LD_PRELOAD', aby to osiągnąć. – abligh

+0

Dzięki, znam mprotect, ale najpierw szukałem statycznego rozwiązania. – Cronovirus