Ini adalah Ubuntu 9.04, 2.6.28-11-server, 32bit x86
$ cat test.c
main() { int *dt = (int *)0x08049f18; *dt = 1; }
$ readelf -S ./test
...
[18] .dtors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4
...
$ ./test
Segmentation fault
$
Untuk yang belum tahu: gcc membuat segmen destruktor .dtors
,, di dalam executable elf, yang dipanggil setelah main()
keluar. Tabel ini telah lama dapat ditulisi, dan sepertinya harus dalam kasus saya (lihat readelf
output). Tetapi mencoba menulis ke tabel menyebabkan segfault.
Saya menyadari telah ada gerakan menuju readonly. Dtp, plt, dapatkan akhir-akhir ini, tetapi apa yang saya tidak mengerti adalah ketidakcocokan antara readelf
dan segfault.
memory
gcc
segmentation-fault
Fixee
sumber
sumber
Jawaban:
Bagian-bagian itu ditandai GNU_RELRO (relokasi hanya baca), yang berarti bahwa segera setelah loader dinamis telah diperbaiki (pada waktu buka, tidak ada relokasi malas di sana) semua relokasi, itu menandai bagian-bagian itu hanya-baca. Perhatikan bahwa sebagian besar
.got.plt
ada di halaman lain, jadi tidak mendapatkan perawatan.Anda dapat melihat skrip tautan dengan
ld --verbose
, jika Anda mencari RELRO Anda akan menemukan sesuatu yang mirip dengan:yang berarti bahwa bagian-bagian RELRO mengakhiri 12 byte menjadi
.got.plt
(pointer ke fungsi linker dinamis sudah diselesaikan, sehingga dapat ditandai hanya-baca).Proyek Gentoo yang diperkeras memiliki beberapa dokumentasi tentang RELRO di http://www.gentoo.at/proj/en/hardened/hardened-toolchain.xml#RELRO .
sumber
Saya bisa tahu mengapa itu gagal, meskipun saya sebenarnya tidak tahu bagian mana dari sistem yang bertanggung jawab. Sementara
.dtors
ditandai dapat ditulis dalam biner, sepertinya (bersama dengan.ctors
, GOT, dan beberapa hal lainnya) sedang dipetakan ke halaman terpisah, tidak dapat ditulis dalam memori. Di sistem saya,.dtors
dimasukkan ke0x8049f14
:Jika saya menjalankan executable dan memeriksa
/proc/PID/maps
, saya melihat:.data
Saya.bss
masih dapat ditulis di halaman mereka sendiri, tetapi yang lain di0x8049000-0x804a000
tidak. Saya berasumsi ini adalah fitur keamanan di kernel (seperti yang Anda katakan, "telah ada gerakan menuju readonly .dtors, plt, dapatkan belakangan ini"), tetapi saya tidak tahu secara spesifik apa namanya (OpenBSD memiliki sesuatu yang sangat mirip disebut W ^ X ; Linux memiliki PaX , tetapi tidak dibangun di sebagian besar kernel)Anda dapat menyiasatinya
mprotect
, yang memungkinkan Anda mengubah atribut di-memori dari sebuah halaman:Dengan itu, program pengujian saya tidak macet, tetapi jika saya mencoba menimpa akhir sentinel dari
.dtors
(0x8049f18
) dengan alamat fungsi lain, fungsi itu masih tidak dijalankan; bagian yang saya tidak tahu.Semoga orang lain tahu apa yang bertanggung jawab untuk membuat halaman dibaca hanya, dan mengapa memodifikasi
.dtors
tampaknya tidak melakukan apa pun pada sistem sayasumber
mprotect
tidak dapat membuat halaman yang dapat dieksekusi dapat ditulis atau membuat halaman yang dapat dieksekusi yang dapat ditulisi sebelumnya kecuali jika fitur itu dinonaktifkanpaxctl -m
.