Unsorted Bin Attack

Unterstützen Sie HackTricks

Grundlegende Informationen

Für weitere Informationen darüber, was ein unsortierter Bin ist, überprüfen Sie diese Seite:

Bins & Memory Allocations

Unsortierte Listen können die Adresse zu unsorted_chunks (av) in der bk-Adresse des Chunks schreiben. Daher kann ein Angreifer, wenn er die Adresse des bk-Zeigers in einem Chunk im unsortierten Bin ändern kann, in der Lage sein, diese Adresse an eine beliebige Adresse zu schreiben, was hilfreich sein könnte, um Glibc-Adressen zu leaken oder einige Verteidigungen zu umgehen.

Also ermöglicht dieser Angriff im Grunde genommen, eine große Zahl an einer beliebigen Adresse zu setzen. Diese große Zahl ist eine Adresse, die eine Heap-Adresse oder eine Glibc-Adresse sein könnte. Ein typisches Ziel ist global_max_fast, um die Erstellung von Fast-Bin-Bins mit größeren Größen zu ermöglichen (und von einem unsortierten Bin-Angriff zu einem Fast-Bin-Angriff überzugehen).

Wenn Sie sich das Beispiel unter https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle ansehen und 0x4000 und 0x5000 anstelle von 0x400 und 0x500 als Chunk-Größen verwenden (um Tcache zu vermeiden), können Sie sehen, dass heutzutage der Fehler malloc(): unsorted double linked list corrupted ausgelöst wird.

Daher erfordert dieser unsortierte Bin-Angriff jetzt (unter anderen Überprüfungen) auch, dass die doppelt verkettete Liste korrigiert werden kann, sodass dies umgangen wird victim->bk->fd == victim oder nicht victim->fd == av (arena), was bedeutet, dass die Adresse, an der wir schreiben möchten, die Adresse des gefälschten Chunks an ihrer fd-Position haben muss und dass der gefälschte Chunk fd auf die Arena zeigt.

Beachten Sie, dass dieser Angriff den unsortierten Bin beschädigt (daher auch klein und groß). Daher können wir jetzt nur noch Zuweisungen aus dem Fast-Bin verwenden (ein komplexeres Programm könnte andere Zuweisungen durchführen und abstürzen), und um dies auszulösen, müssen wir die gleiche Größe zuweisen, oder das Programm wird abstürzen.

Beachten Sie, dass das Überschreiben von global_max_fast in diesem Fall hilfreich sein könnte, in der Annahme, dass der Fast-Bin in der Lage sein wird, sich um alle anderen Zuweisungen zu kümmern, bis das Exploit abgeschlossen ist.

Der Code von guyinatuxedo erklärt dies sehr gut, obwohl, wenn Sie die mallocs so ändern, dass sie Speicher in ausreichender Größe zuweisen, sodass sie nicht in einem Tcache enden, können Sie sehen, dass der zuvor erwähnte Fehler auftritt und diese Technik verhindert: malloc(): unsorted double linked list corrupted

Unsorted Bin Infoleak-Angriff

Dies ist eigentlich ein sehr grundlegendes Konzept. Die Chunks im unsortierten Bin werden Zeiger haben. Der erste Chunk im unsortierten Bin wird tatsächlich die fd- und bk-Links haben, die auf einen Teil der Hauptarena (Glibc) zeigen. Daher, wenn Sie einen Chunk in einen unsortierten Bin platzieren und ihn lesen können (use after free) oder ihn erneut zuweisen, ohne mindestens 1 der Zeiger zu überschreiben, um ihn dann zu lesen, können Sie ein Glibc-Infoleak haben.

Ein ähnlicher Angriff, der in diesem Write-up verwendet wurde, bestand darin, eine 4-Chunks-Struktur (A, B, C und D - D diente nur dazu, eine Konsolidierung mit dem Top-Chunk zu verhindern) zu missbrauchen, sodass ein Null-Byte-Überlauf in B verwendet wurde, um C anzuzeigen, dass B nicht verwendet wurde. Außerdem wurde in B die Daten prev_size geändert, sodass die Größe anstelle der Größe von B A+B war. Dann wurde C deallokiert und mit A+B konsolidiert (aber B war immer noch in Benutzung). Es wurde ein neuer Chunk der Größe A allokiert, und dann wurden die geleakten Adressen von libc in B geschrieben, von wo aus sie geleakt wurden.

Referenzen & Weitere Beispiele

  • Das Ziel besteht darin, eine globale Variable mit einem Wert größer als 4869 zu überschreiben, um die Flagge zu erhalten, wobei PIE nicht aktiviert ist.

  • Es ist möglich, Chunks beliebiger Größe zu generieren, und es gibt einen Heap-Überlauf mit der gewünschten Größe.

  • Der Angriff beginnt mit der Erstellung von 3 Chunks: Chunk0, um den Überlauf zu missbrauchen, Chunk1, um überlaufen zu werden, und Chunk2, damit der Top-Chunk die vorherigen nicht konsolidiert.

  • Dann wird Chunk1 freigegeben und Chunk0 wird überlaufen, sodass der bk-Zeiger von Chunk1 auf bk = magic - 0x10 zeigt.

  • Anschließend wird Chunk3 mit derselben Größe wie Chunk1 allokiert, was den unsortierten Bin-Angriff auslöst und den Wert der globalen Variablen ändert, sodass es möglich ist, die Flagge zu erhalten.

  • Die Merge-Funktion ist anfällig, da sie, wenn beide übergebenen Indizes gleich sind, darauf reallociert und dann freigegeben wird, aber einen Zeiger auf diesen freigegebenen Bereich zurückgibt, der verwendet werden kann.

  • Daher werden 2 Chunks erstellt: Chunk0, der mit sich selbst zusammengeführt wird, und Chunk1, um eine Konsolidierung mit dem Top-Chunk zu verhindern. Dann wird die Merge-Funktion zweimal mit Chunk0 aufgerufen, was zu einem Use-after-Free führt.

  • Dann wird die view-Funktion mit Index 2 aufgerufen (der Index des Use-after-Free-Chunks), was eine libc-Adresse leakt.

  • Da das Binärprogramm Schutzmechanismen hat, um nur Größen größer als global_max_fast zu allozieren, sodass kein Fastbin verwendet wird, wird ein unsortierter Bin-Angriff verwendet, um die globale Variable global_max_fast zu überschreiben.

  • Dann ist es möglich, die Edit-Funktion mit dem Index 2 (dem Use-after-Free-Zeiger) aufzurufen und den bk-Zeiger so zu überschreiben, dass er auf p64(global_max_fast-0x10) zeigt. Anschließend wird durch das Erstellen eines neuen Chunks die zuvor kompromittierte freie Adresse (0x20) verwendet, um den unsortierten Bin-Angriff auszulösen und das global_max_fast zu überschreiben, wobei ein sehr großer Wert erreicht wird, der es nun ermöglicht, Chunks in Fast-Bins zu erstellen.

  • Nun wird ein Fast-Bin-Angriff durchgeführt:

  • Zunächst wird festgestellt, dass es möglich ist, mit schnellen Chunks der Größe 200 am Speicherort __free_hook zu arbeiten:

  • gef➤  p &__free_hook

$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000

  • Wenn es uns gelingt, einen schnellen Chunk der Größe 0x200 an dieser Stelle zu erhalten, wird es möglich sein, einen Funktionszeiger zu überschreiben, der ausgeführt wird.

  • Dafür wird ein neuer Chunk der Größe 0xfc erstellt und die zusammengeführte Funktion wird zweimal mit diesem Zeiger aufgerufen, auf diese Weise erhalten wir einen Zeiger auf einen freigegebenen Chunk der Größe 0xfc*2 = 0x1f8 im schnellen Bin.

  • Dann wird die Edit-Funktion in diesem Chunk aufgerufen, um die fd-Adresse dieses schnellen Bins so zu ändern, dass sie auf die vorherige __free_hook-Funktion zeigt.

  • Anschließend wird ein Chunk der Größe 0x1f8 erstellt, um aus dem schnellen Bin den vorherigen nutzlosen Chunk abzurufen, sodass ein weiterer Chunk der Größe 0x1f8 erstellt wird, um einen schnellen Bin-Chunk im __free_hook zu erhalten, der mit der Adresse der system-Funktion überschrieben wird.

  • Und schließlich wird ein Chunk mit dem String /bin/sh\x00 freigegeben, indem die Löschfunktion aufgerufen wird, die die __free_hook-Funktion auslöst, die auf system mit /bin/sh\x00 als Parameter zeigt.

  • Ein weiteres Beispiel für die Ausnutzung eines 1B-Überlaufs, um Chunks im unsortierten Bin zu konsolidieren und eine libc-Infoleak zu erhalten und dann einen schnellen Bin-Angriff durchzuführen, um den malloc-Hook mit einer One-Gadget-Adresse zu überschreiben

  • Wir können nur Chunks der Größe größer als 0x100 zuweisen.

  • Überschreiben Sie global_max_fast mithilfe eines Unsorted Bin-Angriffs (funktioniert 1/16 Mal aufgrund von ASLR, da wir 12 Bits ändern müssen, aber 16 Bits ändern müssen).

  • Schneller Bin-Angriff, um ein globales Array von Chunks zu ändern. Dies ermöglicht ein beliebiges Lese-/Schreib-Primitive, mit dem das GOT geändert und eine Funktion so eingestellt werden kann, dass sie auf system zeigt.

Unterstützen Sie HackTricks

Last updated