Libc Protections

Erlernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Chunk-Alignment-Durchsetzung

Malloc allokiert Speicher in 8-Byte (32-Bit) oder 16-Byte (64-Bit) Gruppierungen. Dies bedeutet, dass das Ende von Chunks in 32-Bit-Systemen mit 0x8 und in 64-Bit-Systemen mit 0x0 ausgerichtet sein sollte. Das Sicherheitsmerkmal überprüft, ob jeder Chunk an diesen spezifischen Stellen korrekt ausgerichtet ist, bevor ein Zeiger aus einem Bin verwendet wird.

Sicherheitsvorteile

Die Durchsetzung der Chunk-Ausrichtung in 64-Bit-Systemen verbessert die Sicherheit von Malloc erheblich, indem sie die Platzierung gefälschter Chunks auf nur 1 von 16 Adressen beschränkt. Dies erschwert Exploitationsversuche erheblich, insbesondere in Szenarien, in denen der Benutzer nur begrenzte Kontrolle über Eingabewerte hat, was Angriffe komplexer und schwieriger ausführbar macht.

  • Fastbin-Angriff auf __malloc_hook

Die neuen Ausrichtungsregeln in Malloc vereiteln auch einen klassischen Angriff, der den __malloc_hook betrifft. Früher konnten Angreifer Chunk-Größen manipulieren, um diesen Funktionszeiger zu überschreiben und Codeausführung zu erlangen. Die strikten Ausrichtungsanforderungen stellen nun sicher, dass solche Manipulationen nicht mehr möglich sind, was eine häufige Ausnutzungsroute schließt und die Gesamtsicherheit verbessert.

Zeigerverschleierung bei fastbins und tcache

Zeigerverschleierung ist eine Sicherheitsverbesserung, die dazu dient, fastbin- und tcache-Fd-Zeiger bei Speicherverwaltungsvorgängen zu schützen. Diese Technik hilft, bestimmte Arten von Speicher-Exploit-Taktiken zu verhindern, insbesondere solche, die keine durchgesickerten Speicherinformationen erfordern oder die Speicherpositionen direkt relativ zu bekannten Positionen manipulieren (relative Überschreibungen).

Der Kern dieser Technik ist eine Verschleierungsformel:

Neuer_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 behebt eine Schwachstelle, die in der deterministischen Natur der am wenigsten signifikanten 12 Bits von Speicheradressen liegt, die aufgrund von Systemarchitektur-Einschränkungen typischerweise vorhersehbar sind. Durch das Verschieben der Bits wird der vorhersehbare Teil aus der Gleichung entfernt, die Zufälligkeit des neuen, verschleierten Zeigers verbessert und schützt somit vor Angriffen, die auf der Vorhersagbarkeit dieser Bits beruhen.

Dieser verschleierte Zeiger nutzt die bereits vorhandene Zufälligkeit durch die Address Space Layout Randomization (ASLR), die Adressen, die von Programmen verwendet werden, zufällig macht, um es Angreifern schwer zu machen, das Speicherlayout eines Prozesses vorherzusagen.

Das Entschleiern des Zeigers, um die ursprüngliche Adresse abzurufen, beinhaltet die Verwendung derselben XOR-Operation. Hier wird der verschleierte Zeiger als P in der Formel behandelt, und wenn er mit dem unveränderten Speicherort (L) XOR-verknüpft wird, wird der ursprüngliche Zeiger offengelegt. Diese Symmetrie beim Verschleiern und Entschleiern gewährleistet, dass das System Zeiger effizient codieren und decodieren kann, ohne signifikante Overheads zu verursachen, und die Sicherheit gegen Angriffe, die Speicherzeiger manipulieren, erheblich erhöht.

Sicherheitsvorteile

Die Zeigerverschleierung zielt darauf ab, partielle und vollständige Zeigerüberschreibungen im Heap-Management zu verhindern, was eine erhebliche Sicherheitsverbesserung darstellt. Diese Funktion beeinflusst Exploit-Techniken auf verschiedene Weise:

  1. Verhinderung von Bye-Byte-Relativen Überschreibungen: Früher konnten Angreifer einen Teil eines Zeigers ändern, um Heap-Chunks ohne genaue Adressen umzuleiten, eine Technik, die im leckfreien House of Roman-Exploit offensichtlich ist. Mit der Zeigerverschleierung erfordern solche relativen Überschreibungen ohne ein Heap-Leck jetzt Brute-Force, was ihre Erfolgschancen drastisch reduziert.

  2. Erhöhte Schwierigkeit von Tcache-Bin/Fastbin-Angriffen: Häufige Angriffe, die Funktionszeiger (wie __malloc_hook) überschreiben, indem sie fastbin- oder tcache-Einträge manipulieren, werden behindert. Zum Beispiel könnte ein Angriff das Leaken einer LibC-Adresse beinhalten, das Freigeben eines Chunks in den tcache-Bin und dann das Überschreiben des Fd-Zeigers, um ihn zur __malloc_hook für beliebige Codeausführung umzuleiten. Mit der Zeigerverschleierung müssen diese Zeiger korrekt verschleiert sein, was ein Heap-Leck für eine genaue Manipulation erforderlich macht, wodurch die Ausnutzungshürde erhöht wird.

  3. Erfordernis von Heap-Lecks an Nicht-Heap-Positionen: Das Erstellen eines gefälschten Chunks in Nicht-Heap-Bereichen (wie dem Stack, dem .bss-Abschnitt oder PLT/GOT) erfordert jetzt auch ein Heap-Leck aufgrund der Notwendigkeit der Zeigerverschleierung. Dies erhöht die Komplexität bei der Ausnutzung dieser Bereiche, ähnlich der Anforderung an die Manipulation von LibC-Adressen.

  4. Das Leaken von Heap-Adressen wird schwieriger: Die Zeigerverschleierung beschränkt die Nützlichkeit von Fd-Zeigern in fastbin- und tcache-Bins als Quellen für Heap-Adresslecks. Zeiger in unsortierten, kleinen und großen Bins bleiben jedoch unverschleiert und sind daher weiterhin für das Leaken von Adressen verwendbar. Diese Verschiebung zwingt Angreifer dazu, diese Bins nach ausnutzbaren Informationen zu durchsuchen, obwohl einige Techniken möglicherweise immer noch das Entschleiern von Zeigern vor einem Leck ermöglichen, wenn auch mit Einschränkungen.

Entschlüsselung von Zeigern mit einem Heap-Leck

Für eine bessere Erklärung des Prozesses überprüfen Sie den Originalbeitrag hier.

Algorithmusübersicht

Die Formel für das Verschleiern und Entschleiern von Zeigern lautet:

Neuer_Ptr = (L >> 12) XOR P

Dabei ist L der Speicherort und P der Fd-Zeiger. Wenn L um 12 Bits nach rechts verschoben wird, erhalten Sie die oberen 12 Bits von P, da der verschobene Teil von L null sein wird und die entsprechenden Bits von P unverändert bleiben.

Wichtige Schritte im Algorithmus:

  1. Erstes Leaken der signifikantesten Bits: Durch XOR-Verknüpfung des verschobenen L mit P erhalten Sie effektiv die oberen 12 Bits von P, da der verschobene Teil von L null ist und die entsprechenden Bits von P unverändert bleiben.

  2. Wiederherstellung von Zeigerbits: Da XOR reversibel ist, ermöglicht es, das Ergebnis und einen der Operanden zu kennen, den anderen Operanden zu berechnen. Diese Eigenschaft wird verwendet, um den gesamten Satz von Bits für P zu deduzieren, indem bekannte Bitsets sukzessive mit Teilen des verschleierten Zeigers XOR-verknüpft werden.

  3. Iteratives Entschleiern: 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 verschleierten Zeigers zu decodieren, bis alle Bits wiederhergestellt sind.

  4. Behandlung deterministischer Bits: Die letzten 12 Bits von L gehen aufgrund der Verschiebung verloren, sind jedoch deterministisch und können nach dem Prozess rekonstruiert werden.

Eine Implementierung dieses Algorithmus finden Sie hier: https://github.com/mdulin2/mangle

Pointer Guard

Pointer Guard ist eine Exploit-Minderungstechnik, die in glibc verwendet wird, um gespeicherte Funktionszeiger zu schützen, insbesondere solche, die von Bibliotheksaufrufen wie atexit() registriert wurden. Dieser Schutz beinhaltet das Verwirren der Zeiger durch XOR-Verknüpfung mit einem im Thread-Datenbereich gespeicherten Geheimnis (fs:0x30) und Anwendung einer bitweisen Rotation. Dieser Mechanismus zielt darauf ab, zu verhindern, dass Angreifer die Kontrollflussübernahme durch Überschreiben von Funktionszeigern durchführen.

Bypassing Pointer Guard mit einem Leak

  1. Verständnis der Pointer Guard Operationen: Das Verwirren (Mangeln) von Zeigern wird mit dem PTR_MANGLE-Makro durchgeführt, das den Zeiger mit einem 64-Bit-Geheimnis XOR-verknüpft und dann eine Linksrotation um 0x11 Bits durchführt. Die Umkehrung zur Wiederherstellung des Original-Zeigers wird von PTR_DEMANGLE behandelt.

  2. Angriffsstrategie: Der Angriff basiert auf einem Known-Plaintext-Ansatz, bei dem der Angreifer sowohl die Original- als auch die veränderten Versionen eines Zeigers kennen muss, um das für das Verwirren verwendete Geheimnis abzuleiten.

  3. Ausnutzen bekannter Klartexte:

  • Identifizierung fester Funktionszeiger: Durch Untersuchung des glibc-Quellcodes oder initialisierter Funktionszeiger-Tabellen (wie __libc_pthread_functions) kann ein Angreifer vorhersehbare Funktionszeiger finden.

  • Berechnung des Geheimnisses: Unter Verwendung eines bekannten Funktionszeigers wie __pthread_attr_destroy und seiner veränderten Version aus der Funktionszeiger-Tabelle kann das Geheimnis berechnet werden, indem der veränderte Zeiger rückwärts rotiert (Rechtsrotation) und dann mit der Adresse der Funktion XOR-verknüpft wird.

  1. Alternative Klartexte: Der Angreifer kann auch versuchen, Zeiger mit bekannten Werten wie 0 oder -1 zu verändern, um zu sehen, ob diese identifizierbare Muster im Speicher erzeugen, die möglicherweise das Geheimnis offenbaren, wenn diese Muster in Speicherauszügen gefunden werden.

  2. Praktische Anwendung: Nach Berechnung des Geheimnisses kann ein Angreifer Zeiger auf kontrollierte Weise manipulieren und somit den Pointer Guard-Schutz in einer Mehrfadenanwendung umgehen, wenn er die Basisadresse von libc kennt und die Fähigkeit besitzt, beliebige Speicherorte zu lesen.

Referenzen

Last updated