
kfd, kurz für Kernel-Dateideskriptor, ist ein Projekt zum Lesen und Schreiben von Kernel-Speicher auf Apple-Geräten.
Kurzer Hinweis: Ich habe nicht vor, Offsets für andere Geräte und iOS-Versionen hinzuzufügen.
kfd, kurz für kernel file descriptor, ist ein Projekt zum Lesen und Schreiben von Kernel-Speicher auf Apple-Geräten. Es nutzt verschiedene Sicherheitslücken, die ausgenutzt werden können, um hängende PTEs (dangling PTEs) zu erhalten, die im Folgenden als PUAF-Primitive bezeichnet werden, kurz für „physical use-after-free“. Anschließend belegt es bestimmte Kernel-Objekte innerhalb dieser physischen Seiten neu und manipuliert sie direkt aus dem User Space über die hängenden PTEs, um eine KRKW-Primitive zu erreichen, kurz für „kernel read/write“. Der Exploit-Code ist vollständig in einer Bibliothek enthalten, libkfd, aber das Projekt enthält auch einfache ausführbare Wrapper für iOS und macOS. Die öffentliche API von libkfd ist recht klein und intuitiv:
enum puaf_method {
puaf_physpuppet,
puaf_smith,
puaf_landa,
};
enum kread_method {
kread_kqueue_workloop_ctl,
kread_sem_open,
};
enum kwrite_method {
kwrite_dup,
kwrite_sem_open,
};
u64 kopen(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method);
void kread(u64 kfd, u64 kaddr, void* uaddr, u64 size);
void kwrite(u64 kfd, void* uaddr, u64 kaddr, u64 size);
void kclose(u64 kfd);
kopen() öffnet konzeptionell einen „Kernel-Dateideskriptor“. Es nimmt die folgenden 4 Argumente entgegen:
puaf_pages: Die Zielanzahl physischer Seiten mit hängenden PTEs.puaf_method: Die Methode zum Erlangen der PUAF-Primitive, mit den folgenden Optionen:
puaf_physpuppet:
puaf_smith:
puaf_landa:
kread_method: Die Methode, mit der die anfängliche kread()-Primitive erlangt wird.kwrite_method: Die Methode, mit der die anfängliche -Primitive erlangt wird.Wenn der Exploit erfolgreich ist, gibt kopen() einen 64-Bit-opaken Dateideskriptor zurück. In der Praxis ist dies nur ein User-Space-Zeiger auf eine Struktur, die von libkfd benötigt wird. Da auf diese Struktur jedoch nicht außerhalb der Bibliothek zugegriffen werden sollte, wird sie als opaker Integer zurückgegeben. Wenn der Exploit fehlschlägt, gibt die Bibliothek eine Fehlermeldung aus, schläft 30 Sekunden lang und beendet sich mit dem Statuscode 1. Sie schläft 30 Sekunden lang, weil der Kernel beim Beenden für bestimmte PUAF-Methoden, die nach KRKW eine gewisse Bereinigung erfordern (z. B. puaf_smith), einen Panic auslösen könnte.
kread() und kwrite() sind das User-Space-Pendant zu copyout() bzw. copyin(). Bitte beachten Sie, dass die Optionen für kread_method und kwrite_method in einem separaten Write-up beschrieben werden. Darüber hinaus können die anfänglichen Primitive, die diese Methoden gewähren, verwendet werden, um eine bessere KRKW-Primitive aufzubauen. Schließlich schließt kclose() einfach den Kernel-Dateideskriptor. Alle nehmen den opaken Integer, der von kopen() zurückgegeben wird, als erstes Argument entgegen.
In Xcode öffnen Sie den Hauptordner des Projekts und schließen Sie Ihr iOS-Gerät an.
Navigieren Sie in einem Terminal zum Hauptordner des Projekts.
Optional können Sie, um die globalen und pro-Prozess geltenden Dateideskriptor-Limits zu erhöhen, was die Erfolgsquote insbesondere bei mehreren aufeinanderfolgenden Läufen verbessert, den Befehl make s eingeben und das sudo-Passwort tippen.
make b ein.make r ein.make br ein.Diese README hat einen Überblick auf hoher Ebene über das kfd-Projekt gegeben. Sobald eine PUAF-Primitive erzielt wurde, ist der Rest des Exploits generisch. Daher habe ich den gemeinsamen Teil der Exploits in ein eigenes Write-up aufgenommen:
Darüber hinaus habe ich den vulnerability-spezifischen Teil der Exploits, die zum Erzielen der PUAF-Primitive verwendet werden, in einzelne Write-ups aufgeteilt, die unten in chronologischer Reihenfolge der Entdeckung aufgeführt sind:
Bitte beachten Sie jedoch, dass diese Write-ups für ein Publikum geschrieben wurden, das bereits mit dem virtuellen Speichersystem von XNU vertraut ist.
kwrite()