Libc Protections
Last updated
Last updated
Lerne & übe AWS-Hacking:HackTricks Training AWS Red Team Expert (ARTE) Lerne & übe GCP-Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Malloc allokiert Speicher in 8-Byte (32-Bit) oder 16-Byte (64-Bit) Gruppen. Das bedeutet, dass das Ende der Chunks in 32-Bit-Systemen mit 0x8 und in 64-Bit-Systemen mit 0x0 ausgerichtet sein sollte. Die Sicherheitsfunktion überprüft, dass jeder Chunk an diesen spezifischen Stellen korrekt ausgerichtet ist, bevor ein Zeiger aus einem Bin verwendet wird.
Die Durchsetzung der Chunk-Ausrichtung in 64-Bit-Systemen verbessert die Sicherheit von Malloc erheblich, indem sie die Platzierung von gefälschten Chunks auf nur 1 von 16 Adressen beschränkt. Dies erschwert die Ausnutzung, insbesondere in Szenarien, in denen der Benutzer nur begrenzte Kontrolle über Eingabewerte hat, was Angriffe komplexer und schwieriger auszuführen macht.
Fastbin-Angriff auf __malloc_hook
Die neuen Ausrichtungsregeln in Malloc vereiteln auch einen klassischen Angriff, der den __malloc_hook
betrifft. Zuvor konnten Angreifer die Chunk-Größen manipulieren, um diesen Funktionszeiger zu überschreiben und Codeausführung zu erlangen. Jetzt stellt die strenge Ausrichtungsanforderung sicher, dass solche Manipulationen nicht mehr möglich sind, wodurch ein häufiger Ausnutzungsweg geschlossen und die allgemeine Sicherheit erhöht wird.
Zeigerverwirrung ist eine Sicherheitsverbesserung, die verwendet wird, um Fastbin- und Tcache-Fd-Zeiger in Speicherverwaltungsoperationen zu schützen. Diese Technik hilft, bestimmte Arten von Speicher-Ausnutzungs-Taktiken zu verhindern, insbesondere solche, die keine geleakten Speicherinformationen erfordern oder die Speicherorte direkt relativ zu bekannten Positionen manipulieren (relative Überschreibungen).
Der Kern dieser Technik ist eine Obfuskationsformel:
New_Ptr = (L >> 12) XOR P
L ist der Speicherort des Zeigers.
P ist der tatsächliche Fastbin/Tcache-Fd-Zeiger.
Der Grund für die bitweise Verschiebung des Speicherorts (L) um 12 Bits nach rechts vor der XOR-Operation ist entscheidend. Diese Manipulation adressiert eine Schwachstelle, die in der deterministischen Natur der 12 am wenigsten signifikanten Bits von Speicheradressen liegt, die aufgrund von Einschränkungen der Systemarchitektur typischerweise vorhersehbar sind. Durch das Verschieben der Bits wird der vorhersehbare Teil aus der Gleichung entfernt, was die Zufälligkeit des neuen, verwirrten Zeigers erhöht und somit vor Ausnutzungen schützt, die auf der Vorhersehbarkeit dieser Bits basieren.
Dieser verwirrte Zeiger nutzt die vorhandene Zufälligkeit, die durch Address Space Layout Randomization (ASLR) bereitgestellt wird, die Adressen randomisiert, die von Programmen verwendet werden, um es Angreifern zu erschweren, das Speicherlayout eines Prozesses vorherzusagen.
Entwirren des Zeigers, um die ursprüngliche Adresse abzurufen, erfolgt durch die Verwendung derselben XOR-Operation. Hier wird der verwirrte Zeiger als P in der Formel behandelt, und wenn er mit dem unveränderten Speicherort (L) XORed wird, wird der ursprüngliche Zeiger offenbart. Diese Symmetrie in der Verwirrung und Entwirrung stellt sicher, dass das System Zeiger effizient kodieren und dekodieren kann, ohne signifikante Überkopfkosten, während die Sicherheit gegen Angriffe, die Speicherzeiger manipulieren, erheblich erhöht wird.
Die Zeigerverwirrung zielt darauf ab, teilweise und vollständige Zeigerüberschreibungen im Heap-Management zu verhindern, was eine erhebliche Verbesserung der Sicherheit darstellt. Diese Funktion beeinflusst Ausnutzungstechniken auf verschiedene Weise:
Verhinderung von Byte-zu-Byte-relativen Überschreibungen: Zuvor konnten Angreifer einen Teil eines Zeigers ändern, um Heap-Chunks an andere Standorte umzuleiten, ohne die genauen Adressen zu kennen, eine Technik, die im leakless House of Roman-Exploit offensichtlich ist. Mit der Zeigerverwirrung erfordern solche relativen Überschreibungen ohne einen Heap-Leak jetzt Brute-Forcing, was die Wahrscheinlichkeit ihres Erfolgs drastisch verringert.
Erhöhte Schwierigkeit von Tcache-Bin/Fastbin-Angriffen: Häufige Angriffe, die Funktionszeiger (wie __malloc_hook
) durch Manipulation von Fastbin- oder Tcache-Einträgen überschreiben, werden behindert. Zum Beispiel könnte ein Angriff darin bestehen, eine LibC-Adresse zu leaken, einen Chunk in den Tcache-Bin freizugeben und dann den Fd-Zeiger zu überschreiben, um ihn auf __malloc_hook
umzuleiten, um beliebigen Code auszuführen. Mit der Zeigerverwirrung müssen diese Zeiger korrekt verwirrt sein, was einen Heap-Leak für eine genaue Manipulation erforderlich macht, wodurch die Ausnutzungsbarriere erhöht wird.
Anforderung von Heap-Leaks in Nicht-Heap-Standorten: Das Erstellen eines gefälschten Chunks in Nicht-Heap-Bereichen (wie dem Stack, dem .bss-Bereich oder PLT/GOT) erfordert jetzt ebenfalls einen Heap-Leak aufgrund der Notwendigkeit der Zeigerverwirrung. Dies erhöht die Komplexität der Ausnutzung dieser Bereiche, ähnlich wie die Anforderung zur Manipulation von LibC-Adressen.
Leaking von Heap-Adressen wird herausfordernder: Die Zeigerverwirrung schränkt die Nützlichkeit von Fd-Zeigern in Fastbin- und Tcache-Bins als Quellen für Heap-Adresse-Leaks ein. Allerdings bleiben Zeiger in unsortierten, kleinen und großen Bins unverwirrt und somit weiterhin nutzbar für das Leaken von Adressen. Diese Verschiebung zwingt Angreifer dazu, diese Bins nach ausnutzbaren Informationen zu durchsuchen, obwohl einige Techniken möglicherweise immer noch das Entwirren von Zeigern vor einem Leak ermöglichen, wenn auch mit Einschränkungen.
Für eine bessere Erklärung des Prozesses überprüfe den ursprünglichen Beitrag hier.
Die Formel, die für das Verwirren und Entwirren von Zeigern verwendet wird, ist:
New_Ptr = (L >> 12) XOR P
Wobei L der Speicherort und P der Fd-Zeiger ist. Wenn L um 12 Bits nach rechts verschoben wird, werden die signifikantesten Bits von P offengelegt, aufgrund der Natur von XOR, das 0 ausgibt, wenn Bits mit sich selbst XORed werden.
Wichtige Schritte im Algorithmus:
Erster Leak der signifikantesten Bits: Durch das XORen des verschobenen L mit P erhält man effektiv die obersten 12 Bits von P, da der verschobene Teil von L null sein wird, wodurch die entsprechenden Bits von P unverändert bleiben.
Wiederherstellung der Zeigerbits: Da XOR umkehrbar ist, ermöglicht das Wissen um das Ergebnis und einen der Operanden, den anderen Operanden zu berechnen. Diese Eigenschaft wird verwendet, um die gesamte Menge von Bits für P abzuleiten, indem nacheinander bekannte Bitmengen mit Teilen des verwirrten Zeigers XORed werden.
Iteratives Entwirren: Der Prozess wird wiederholt, wobei jedes Mal die neu entdeckten Bits von P aus dem vorherigen Schritt verwendet werden, um das nächste Segment des verwirrten Zeigers zu dekodieren, bis alle Bits wiederhergestellt sind.
Umgang mit deterministischen Bits: Die letzten 12 Bits von L gehen aufgrund der Verschiebung verloren, sind jedoch deterministisch und können nachträglich rekonstruiert werden.
Eine Implementierung dieses Algorithmus findest du hier: https://github.com/mdulin2/mangle
Der Zeigerschutz ist eine Technik zur Minderung von Ausnutzungen, die in glibc verwendet wird, um gespeicherte Funktionszeiger zu schützen, insbesondere solche, die durch Bibliotheksaufrufe wie atexit()
registriert werden. Dieser Schutz umfasst das Verwirren der Zeiger, indem sie mit einem geheimen Wert, der in den Thread-Daten (fs:0x30
) gespeichert ist, XORed und eine bitweise Rotation angewendet wird. Dieser Mechanismus zielt darauf ab, Angreifern zu verhindern, den Kontrollfluss zu übernehmen, indem sie Funktionszeiger überschreiben.
Verstehen der Zeigerschutzoperationen: Das Verwirren (Mangling) der Zeiger erfolgt mit dem PTR_MANGLE
-Makro, das den Zeiger mit einem 64-Bit-Geheimnis XORed und dann eine linke Rotation von 0x11 Bits durchführt. Die Umkehroperation zum Wiederherstellen des ursprünglichen Zeigers wird von PTR_DEMANGLE
durchgeführt.
Angriffsstrategie: Der Angriff basiert auf einem bekannten Klartextansatz, bei dem der Angreifer sowohl die ursprüngliche als auch die verwirrte Version eines Zeigers kennen muss, um das Geheimnis zu deduzieren, das für das Verwirren verwendet wurde.
Ausnutzung bekannter Klartexte:
Identifizierung fester Funktionszeiger: Durch die Untersuchung des glibc-Quellcodes oder der initialisierten Funktionszeigertabellen (wie __libc_pthread_functions
) kann ein Angreifer vorhersehbare Funktionszeiger finden.
Berechnung des Geheimnisses: Mit einem bekannten Funktionszeiger wie __pthread_attr_destroy
und seiner verwirrten Version aus der Funktionszeigertabelle kann das Geheimnis berechnet werden, indem der verwirrte Zeiger rückwärts rotiert (Rechtsrotation) und dann mit der Adresse der Funktion XORed wird.
Alternative Klartexte: Der Angreifer kann auch versuchen, Zeiger mit bekannten Werten wie 0 oder -1 zu verwirren, um zu sehen, ob diese identifizierbare Muster im Speicher erzeugen, die möglicherweise das Geheimnis offenbaren, wenn diese Muster in Speicherauszügen gefunden werden.
Praktische Anwendung: Nachdem das Geheimnis berechnet wurde, kann ein Angreifer Zeiger auf kontrollierte Weise manipulieren und somit den Zeigerschutz in einer multithreaded Anwendung mit Kenntnis der libc-Basisadresse und der Fähigkeit, beliebige Speicherorte zu lesen, umgehen.
Lerne & übe AWS-Hacking:HackTricks Training AWS Red Team Expert (ARTE) Lerne & übe GCP-Hacking: HackTricks Training GCP Red Team Expert (GRTE)