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 .ctors
GOT 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
/ .bss
vẫn có thể ghi trong trang riêng của họ, nhưng những người khác 0x8049000-0x804a000
thì 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 .dtors
dường như không làm gì trên hệ thống của tôi