Dies ist 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
$
Für den Uneingeweihten: gcc erstellt .dtors
in der ausführbaren Datei von elf ein Destruktorsegment , das nach dem main()
Beenden aufgerufen wird . Diese Tabelle ist seit langem beschreibbar und es sieht so aus, als ob es in meinem Fall sein sollte (siehe readelf
Ausgabe). Der Versuch, in die Tabelle zu schreiben, führt jedoch zu einem Segfault.
Mir ist klar, dass es in letzter Zeit eine Bewegung in Richtung schreibgeschützter .dtors, plt, gegeben hat, aber was ich nicht verstehe, ist readelf
die Nichtübereinstimmung zwischen und dem Segfault.
memory
gcc
segmentation-fault
Fixee
quelle
quelle
Antworten:
Diese Abschnitte sind mit GNU_RELRO (schreibgeschützte Verschiebungen) gekennzeichnet. Dies bedeutet, dass diese Abschnitte schreibgeschützt sind, sobald der dynamische Lader alle Verschiebungen behoben hat (zum Ladezeitpunkt gibt es dort keine verzögerten Verschiebungen). Beachten Sie, dass sich der größte Teil
.got.plt
auf einer anderen Seite befindet und daher nicht behandelt wird.Sie können das Linker-Skript mit sehen
ld --verbose
, wenn Sie nach RELRO suchen, finden Sie etwas Ähnliches wie:Dies bedeutet, dass die RELRO-Abschnitte 12 Byte lang enden
.got.plt
(Zeiger auf dynamische Linkerfunktionen sind bereits aufgelöst und können daher als schreibgeschützt markiert werden).Das gehärtete Gentoo-Projekt enthält einige Dokumentationen zu RELRO unter http://www.gentoo.at/proj/en/hardened/hardened-toolchain.xml#RELRO .
quelle
Ich kann sagen, warum es fehlschlägt, obwohl ich nicht weiß, welcher Teil des Systems dafür verantwortlich ist. Während
.dtors
es in der Binärdatei als beschreibbar markiert ist, sieht es so aus, als würde es (zusammen mit.ctors
dem GOT und einigen anderen Dingen) einer separaten, nicht beschreibbaren Seite im Speicher zugeordnet. Auf meinem System.dtors
wird gesetzt bei0x8049f14
:Wenn ich die ausführbare Datei ausführe und überprüfe
/proc/PID/maps
, sehe ich:.data
/.bss
Sind noch beschreibbar in ihrer eigenen Seite, aber die andere in0x8049000-0x804a000
nicht sind. Ich gehe davon aus, dass dies ein Sicherheitsmerkmal im Kernel ist (wie Sie sagten, "es hat in letzter Zeit eine Bewegung in Richtung schreibgeschützter .dtors, plt, got" gegeben), aber ich weiß nicht genau, wie es heißt (OpenBSD hat etwas sehr Ähnliches namens W ^ X ; Linux hat PaX , ist aber in den meisten Kerneln nicht eingebaut)Sie können es umgehen
mprotect
, indem Sie die speicherinternen Attribute einer Seite ändern:Damit stürzt mein Testprogramm nicht ab, aber wenn ich versuche, den End-Sentinel von
.dtors
(0x8049f18
) mit der Adresse einer anderen Funktion zu überschreiben , wird diese Funktion immer noch nicht ausgeführt. diesen Teil kann ich nicht herausfinden.Hoffentlich weiß jemand anderes, was dafür verantwortlich ist, dass die Seite schreibgeschützt ist, und warum das Ändern
.dtors
auf meinem System nichts zu bewirken scheintquelle
mprotect
eine ausführbare Seite nicht beschreibbar machen oder eine Seite ausführbar machen kann, die zuvor beschreibbar war, es sei denn, diese Funktion ist mit deaktiviertpaxctl -m
.