.dtors terlihat dapat ditulis, tetapi mencoba untuk menulis segfault

9

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 readelfoutput). 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 readelfdan segfault.

Fixee
sumber
Pertanyaan sebenarnya adalah mengapa Anda ingin bisa ditulis?
alex
1
Saya mengajar kelas keamanan yang melibatkan melanggar serangkaian program rentan, tetapi satu latihan melibatkan menulis ke .docs ke exec shellcode. Tidak lagi berfungsi dan saya mencoba melacak masalahnya.
Fixee
Ketidakcocokan karena mungkin ada beberapa relokasi data (yang perlu diperbaiki sebelum menandai read-only, dan tidak bisa malas, jadi akan tetap konstan setelah diperbaiki) di sana.
ninjalj

Jawaban:

5

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

.got            : { *(.got) }
. = DATA_SEGMENT_RELRO_END (12, .);
.got.plt        : { *(.got.plt) }

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 .

ninjalj
sumber
5

Saya bisa tahu mengapa itu gagal, meskipun saya sebenarnya tidak tahu bagian mana dari sistem yang bertanggung jawab. Sementara .dtorsditandai 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, .dtorsdimasukkan ke 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

Jika saya menjalankan executable dan memeriksa /proc/PID/maps, saya melihat:

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

.dataSaya .bssmasih dapat ditulis di halaman mereka sendiri, tetapi yang lain di 0x8049000-0x804a000tidak. 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:

mprotect((void*)0x8049000, 4096, PROT_WRITE);

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 .dtorstampaknya tidak melakukan apa pun pada sistem saya

Michael Mrozek
sumber
3
Jika OP Linux dengan PaX mprotecttidak dapat membuat halaman yang dapat dieksekusi dapat ditulis atau membuat halaman yang dapat dieksekusi yang dapat ditulisi sebelumnya kecuali jika fitur itu dinonaktifkan paxctl -m.
stribika
@stribika Ah, baik untuk tahu
Michael Mrozek