.dtor trông có thể ghi được, nhưng cố gắng viết segfault


9

Đây là Ubuntu 9.04, 2.6.28-11-máy chủ, 32 bit 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
$

Đối với người không quen thuộc: gcc tạo ra một phân đoạn hủy diệt .dtors, trong phần thực thi elf, được gọi sau khi main()thoát. Bảng này từ lâu đã có thể ghi được, và có vẻ như nó phải nằm trong trường hợp của tôi (xem readelfđầu ra). Nhưng cố gắng ghi vào bảng gây ra một segfault.

Tôi nhận ra rằng đã có một phong trào hướng tới các công cụ chỉ đọc, plt, đã nhận được gần đây, nhưng điều tôi không hiểu là sự không phù hợp giữa readelfvà segfault.


Câu hỏi thực sự là tại sao bạn muốn nó có thể ghi được?
alex

1
Tôi đang dạy một lớp bảo mật liên quan đến việc phá vỡ một loạt các chương trình dễ bị tổn thương, nhưng một bài tập liên quan đến việc viết thư cho .dtor để thực thi shellcode. Nó không còn hoạt động và tôi đang cố gắng theo dõi vấn đề.
Fixee

Sự không phù hợp là do có thể có một số thay đổi dữ liệu (cần được sửa trước khi đánh dấu chỉ đọc và dù sao cũng không thể lười biếng, do đó sẽ không đổi khi cố định) ở đó.
ninjalj

Câu trả lời:


5

Các phần đó được đánh dấu GNU_RELRO (định vị lại chỉ đọc), có nghĩa là ngay khi bộ tải động đã cố định (tại thời điểm tải, không có sự di chuyển lười biếng nào ở đó) tất cả các di dời, nó đánh dấu các phần đó chỉ đọc. Lưu ý rằng hầu hết .got.pltlà trên một trang khác, vì vậy không được điều trị.

Bạn có thể thấy tập lệnh liên kết với ld --verbose, nếu bạn tìm kiếm RELRO, bạn sẽ tìm thấy một cái gì đó tương tự:

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

điều đó có nghĩa là các phần RELRO kết thúc 12 byte vào .got.plt(các con trỏ tới các hàm liên kết động đã được giải quyết, do đó có thể được đánh dấu chỉ đọc).

Dự án Gentoo cứng đã có một số tài liệu về RELRO tại http://www.gentoo.at/proj/en/hardened/hardened-toolchain.xml#RELRO .


5

Tôi có thể nói tại sao nó thất bại, mặc dù tôi thực sự không biết phần nào của hệ thống chịu trách nhiệm. Mặc dù .dtorsđược đánh dấu có thể ghi trong nhị phân, nhưng có vẻ như nó (cùng với .ctorsGOT và một vài thứ khác) đang được ánh xạ vào một trang riêng biệt, không thể ghi trong bộ nhớ. Trên hệ thống của tôi, .dtorsđang được đặt tại 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

Nếu tôi chạy tệp thực thi và kiểm tra /proc/PID/maps, tôi thấy:

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/ .bssvẫn có thể ghi trong trang riêng của họ, nhưng những người khác 0x8049000-0x804a000thì không. Tôi giả sử đây là một tính năng bảo mật trong kernel (như bạn đã nói, "đã có một sự chuyển động về phía chỉ đọc. W ^ X ; Linux có PaX , nhưng không được tích hợp vào hầu hết các hạt nhân)

Bạn có thể di chuyển xung quanh nó mprotect, cho phép bạn thay đổi các thuộc tính trong bộ nhớ của trang:

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

Với điều đó, chương trình thử nghiệm của tôi không gặp sự cố, nhưng nếu tôi cố ghi đè lên phần kết thúc của .dtors( 0x8049f18) bằng địa chỉ của hàm khác, thì hàm đó vẫn không thực thi; phần đó tôi không thể tìm ra.

Hy vọng rằng ai đó khác biết những gì chịu trách nhiệm làm cho trang chỉ đọc và tại sao sửa đổi .dtorsdường như không làm gì trên hệ thống của tôi


3
Nếu OP Linux với PaX mprotectkhông thể tạo một trang thực thi có thể ghi hoặc tạo một trang có thể thực thi được trước khi trừ khi tính năng đó bị vô hiệu hóa paxctl -m.
stribika

@stribika À, điều tốt cần biết
Michael Mrozek
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.