.dtors ดูเขียนได้ แต่พยายามเขียน segfault


9

นี่คือ 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
$

สำหรับมือใหม่: gcc สร้างเซ็กเมนต์ destructor .dtors, ใน elf executable, ซึ่งถูกเรียกใช้หลังจากmain()ออก ตารางนี้สามารถเขียนได้นานและดูเหมือนว่ามันควรจะเป็นในกรณีของฉัน (ดูreadelfผลลัพธ์) แต่การพยายามเขียนลงในตารางทำให้เกิด segfault

ฉันรู้ว่ามีการเคลื่อนไหวไปยัง. doc, plt, ได้รับเมื่อเร็ว ๆ นี้ แต่สิ่งที่ฉันไม่เข้าใจคือความไม่ตรงกันระหว่างreadelfและ segfault


คำถามจริงคือทำไมคุณต้องการให้เขียนได้?
alex

1
ฉันกำลังสอนคลาสความปลอดภัยที่เกี่ยวข้องกับการทำลายชุดโปรแกรมที่มีช่องโหว่ ไม่ทำงานอีกต่อไปและฉันพยายามติดตามปัญหา
Fixee

ไม่ตรงกันเนื่องจากอาจมีการย้ายข้อมูลบางอย่าง (ซึ่งจำเป็นต้องแก้ไขก่อนที่จะทำเครื่องหมายอ่านอย่างเดียวและไม่สามารถขี้เกียจได้ดังนั้นจะมีค่าคงที่เมื่อทำการแก้ไข)
ninjalj

คำตอบ:


5

ส่วนเหล่านั้นถูกทำเครื่องหมายว่า GNU_RELRO (ย้ายแบบอ่านอย่างเดียว) ซึ่งหมายความว่าทันทีที่ตัวโหลดไดนามิกได้รับการแก้ไข (ณ เวลาโหลดไม่มีการย้ายตำแหน่งแบบขี้เกียจที่นั่น) การเปลี่ยนตำแหน่งทั้งหมดนั้นเป็นการทำเครื่องหมายส่วนที่อ่านได้อย่างเดียว โปรดทราบว่าส่วนใหญ่.got.pltอยู่ในหน้าอื่นจึงไม่ได้รับการรักษา

คุณสามารถดูสคริปต์ตัวเชื่อมโยงld --verboseได้หากคุณค้นหา RELRO คุณจะพบสิ่งที่คล้ายกับ:

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

ซึ่งหมายความว่าส่วน RELRO สิ้นสุด 12 ไบต์ลงไป.got.plt(ฟังก์ชั่นตัวชี้ไปยังตัวเชื่อมโยงแบบไดนามิกได้รับการแก้ไขแล้วดังนั้นสามารถทำเครื่องหมายอ่านอย่างเดียว)

โครงการ Gentoo แข็งมีเอกสารบางอย่างเกี่ยวกับ RELRO ที่http://www.gentoo.at/proj/en/hardened/hardened-toolchain.xml#RELRO


5

ฉันสามารถบอกได้ว่าทำไมมันถึงล้มเหลวถึงแม้ว่าฉันไม่รู้จริง ๆ ว่าส่วนใดของระบบที่รับผิดชอบ ในขณะที่.dtorsถูกทำเครื่องหมายว่าสามารถเขียนได้ในไบนารีดูเหมือนว่า (พร้อมกับ.ctorsGOT และอีกสองสามอย่าง) กำลังถูกแมปไปยังหน้าแยกต่างหากที่ไม่สามารถเขียนได้ในหน่วยความจำ ในระบบของฉัน.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นั้นไม่ได้ ฉันคิดว่านี่เป็นคุณลักษณะด้านความปลอดภัยในเคอร์เนล (อย่างที่คุณพูดว่า "มีการเคลื่อนไหวไปสู่. docers, plt, ได้เมื่อเร็ว ๆ นี้") แต่ฉันไม่รู้ว่ามันเรียกว่าอะไรโดยเฉพาะ (OpenBSD มีบางสิ่งที่คล้ายกันมากW ^ X ; Linux มีPaXแต่ไม่ได้สร้างอยู่ในเมล็ดส่วนใหญ่)

คุณสามารถแก้ไขได้ด้วยmprotectซึ่งจะช่วยให้คุณสามารถเปลี่ยนแอตทริบิวต์ในหน่วยความจำของหน้า:

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

ด้วยสิ่งนั้นโปรแกรมทดสอบของฉันจะไม่ผิดพลาด แต่ถ้าฉันพยายามเขียนทับจุดสิ้นสุดของ.dtors( 0x8049f18) ด้วยที่อยู่ของฟังก์ชันอื่นฟังก์ชันนั้นก็ยังไม่ทำงาน ส่วนนั้นฉันไม่สามารถเข้าใจได้

หวังว่าคนอื่นจะรู้ว่าสิ่งใดที่ทำให้หน้าเว็บอ่านได้อย่างเดียวและทำไมการแก้ไข.dtorsไม่ดูเหมือนจะทำอะไรในระบบของฉัน


3
ถ้า OP Linux กับท่านไม่สามารถทำให้เขียนได้หน้าปฏิบัติการหรือทำให้ปฏิบัติการหน้าซึ่งเขียนได้ก่อนเว้นแต่คุณลักษณะที่ถูกปิดใช้งานด้วยmprotect paxctl -m
stribika

@stribika อ่ารู้ดี
Michael Mrozek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.