
Ein Binary Ninja Plugin, das per Brute-Force ermittelte XFG-Hashes verwendet, um präzise Funktionsprototypen wiederherzustellen.
Dieses Repository enthält Skripte zum Generieren und Nachschlagen von eXtended-Flow-Guard-Hashes.
Eine ausführliche Beschreibung der Funktionsweise ist in Ausgabe 22 des International Jouranl Of Proof Of Concept || GTFO verfügbar.
Meine Arbeit an diesem PoC wurde durch die Leute bei Quarkslab erheblich vereinfacht, die umfangreiches Reverse Engineering relevanter Teile des MS-Compilers durchgeführt haben. Ihre ausführliche Beschreibung, wie XFG-Hashes berechnet werden, kann hier gelesen werden: https://blog.quarkslab.com/how-the-msvc-compiler-generates-xfg-function-prototype-hashes.html
Hinweis: Dies „bricht“ XFG als Exploit-Mitigation in keiner Weise, sondern missbraucht lediglich seine Nebeneffekte, um Funktionen ohne Symbole zu beleuchten.
Kurz gesagt erweitert XFG, wie es unter Windows implementiert ist, die Exploit-Mitigation von Control Flow Guard und macht sie strenger, indem die möglichen Ziele indirekter Funktionsaufrufe nicht nur auf gültige Funktionseinstiegspunkte, sondern auf Funktionen mit passender Signatur beschränkt werden. Dazu wird für jede Funktion ein XFG-Hash berechnet und zur Laufzeit gegen ihn geprüft. Die Hashes basieren ausschließlich auf dem Funktionsprototyp (also Aufrufkonvention, Argumente und deren Typen). Daher können wir sie für bekannte Typen vorab berechnen und später für Funktionen in unbekannten Binärdateien nachschlagen.
Wenn die Suche erfolgreich ist, können wir uns zu 100 % sicher sein, was die genaue Anzahl und die Typen aller Argumente sowie den Rückgabewert der Funktion betrifft. Das kann für Binärdateien und Funktionen ohne öffentliche Symbole äußerst nützlich sein.
Ich lade dich ein, den vollständigen Artikel in PoC||GTFO zu lesen, der von einem nahegelegenen Mirror bereitgestellt wird.
Die Skripte sind:
Um diese Skripte zu verwenden, müsstest du zuerst gen_function_prototypes.py modifizieren, um „primitive Typen“, Strukturen oder Enums hinzuzufügen, die für das Ziel spezifisch sind, das du betrachtest. Außerdem solltest du festlegen, bis zu wie viele Argumente du per Brute-Force durchgehen möchtest. Bis zu 3 dauert eine Minute, bis zu 4 einen Tag ...
Nachdem die Funktionsprototypen aller Kombinationen generiert wurden, solltest du gen_hash_from_ast.py ausführen, das die zuvor generierte Datei Zeile für Zeile parst und den entsprechenden XFG-Hash erzeugt.
Wenn das abgeschlossen ist, hast du eine SQLite-Datenbank mit Funktionsprototypen und ihren passenden XFG-Hashes. Ein sehr einfaches Binary-Ninja-Plugin ist in xfg_analyzer.py enthalten. Wenn es gegen eine XFG-geschützte Binärdatei ausgeführt wird, findet es alle XFG-Hashes, schlägt sie in der Datenbank nach und wendet, falls eine Übereinstimmung gefunden wird, den neuen Funktionsprototyp auf die definierte Funktion an.
Beachte, dass dies nur ein PoC ist. Um wirklich nützlich zu sein, sollte eine riesige Datenbank mit Hashes (möglicherweise gespeist mit allen Struktur-/Enum-Namen aus den Windows-Header-Dateien) erzeugt und für Online-Nachschlageabfragen verfügbar gemacht werden. Außerdem wäre es ein sehr unterhaltsames Projekt, diese Idee auf C++-XFG-Hashes auszuweiten.
Du kannst den Code in diesem Repository frei verwenden. Wenn du ihn nützlich findest, würde ich gerne von dir hören.