Я можу сказати, чому це не вдається, хоча я насправді не знаю, яка частина системи відповідає. Незважаючи .dtors
на те, що в двійковому коді позначено для запису, він виглядає так, що він (разом із .ctors
GOT та кількома іншими речами) відображається в окрему незаписану сторінку в пам'яті. У моїй системі .dtors
ставлять на 0x8049f14
:
$ readelf -S test
[17] .ctors PROGBITS 08049f0c 000f0c 000008 00 WA 0 0 4
[18] .dtors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4
[19] .jcr PROGBITS 08049f1c 000f1c 000004 00 WA 0 0 4
[20] .dynamic DYNAMIC 08049f20 000f20 0000d0 08 WA 6 0 4
[21] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4
[22] .got.plt PROGBITS 08049ff4 000ff4 00001c 04 WA 0 0 4
[23] .data PROGBITS 0804a010 001010 000008 00 WA 0 0 4
[24] .bss NOBITS 0804a018 001018 000008 00 WA 0 0 4
Якщо я запускаю виконуваний файл і перевіряю /proc/PID/maps
, я бачу:
08048000-08049000 r-xp 00000000 08:02 163678 /tmp/test
08049000-0804a000 r--p 00000000 08:02 163678 /tmp/test
0804a000-0804b000 rw-p 00001000 08:02 163678 /tmp/test
.data
/ .bss
досі пишуть на своїй власній сторінці, але інші в 0x8049000-0x804a000
ні. Я припускаю, що це захисна функція в ядрі (як ви вже сказали, "останнім часом відбувся рух до readonly. W ^ X ; Linux має PaX , але не вбудований у більшість ядер)
Ви можете обійти його за допомогою mprotect
, що дозволяє змінювати атрибути пам'яті сторінки:
mprotect((void*)0x8049000, 4096, PROT_WRITE);
З цим моя тестова програма не виходить з ладу, але якщо я спробую замінити кінцевий дозор .dtors
( 0x8049f18
) адресою іншої функції, ця функція все ще не виконується; цю частину я не можу зрозуміти.
Сподіваємось, хтось інший знає, що відповідає за те, щоб перетворити сторінку наново, і чому зміна .dtors
, здається, не робить нічого в моїй системі