이것은 우분투 9.04, 2.6.28-11 서버, 32 비트 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 .dtors
는 엘프 실행 파일에 소멸자 세그먼트를 작성합니다 main()
. 이 테이블은 오랫동안 쓸 수 있었으며 필자의 경우에는 readelf
출력 해야합니다 . 그러나 테이블에 쓰려고하면 segfault가 발생합니다.
읽기 전용 .dtors, plt로 최근에 움직 였다는 것을 알고 있지만 이해하지 못하는 readelf
것은 segfault 와의 불일치 입니다.
답변
이러한 섹션은 GNU_RELRO (읽기 전용 재배치)로 표시됩니다. 즉, 동적 로더가 모든 재배치를 수정 한 직후 (로드 시간에 지연된 재배치가 없음) 해당 섹션을 읽기 전용으로 표시합니다. 대부분은 .got.plt
다른 페이지에 있으므로 치료를받지 않습니다.
ld --verbose
RELRO를 검색하면 다음과 유사한 링커 스크립트를 볼 수 있습니다 .
.got : { *(.got) }
. = DATA_SEGMENT_RELRO_END (12, .);
.got.plt : { *(.got.plt) }
이는 RELRO 섹션이 12 바이트로 끝나는 것을 의미합니다 .got.plt
(동적 링커 기능에 대한 포인터는 이미 해결되었으므로 읽기 전용으로 표시 될 수 있음).
강화 된 젠투 프로젝트에는 http://www.gentoo.at/proj/en/hardened/hardened-toolchain.xml#RELRO 에 RELRO에 대한 문서가 있습니다.
답변
실제로 시스템의 어떤 부분이 책임이 있는지 알지 못하지만 왜 실패했는지 알 수 있습니다. .dtors
바이너리에서 쓰기 가능으로 표시되어 있지만 ( .ctors
GOT 및 기타 몇 가지 와 함께) 바이너리 에서 메모리에 별도의 쓰기 불가능한 페이지에 매핑되는 것처럼 보입니다 . 내 시스템 .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
수 없습니다. 나는 이것이 커널의 보안 기능이라고 가정한다. W ^ X ; Linux에는 PaX 가 있지만 대부분의 커널에는 내장되어 있지 않습니다)
mprotect
페이지의 메모리 내 속성을 변경할 수있는으로 해결할 수 있습니다 .
mprotect((void*)0x8049000, 4096, PROT_WRITE);
이로 인해 테스트 프로그램이 충돌하지 않지만 다른 함수의 주소로 .dtors
( 0x8049f18
) 의 끝 센티넬을 덮어 쓰려고 해도 해당 함수는 여전히 실행되지 않습니다. 그 부분은 알아낼 수 없습니다.
다른 사람이 페이지를 읽기 전용으로 만드는 책임이 무엇인지, 그리고 왜 수정 .dtors
이 내 시스템에서 아무런 영향을 미치지 않는지 알고 싶습니다.