mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['', 'src/binary-exploitation/ios-exploiting/ios-physical-uaf
This commit is contained in:
		
							parent
							
								
									ebb7a1b19e
								
							
						
					
					
						commit
						b3abdaa2b7
					
				| @ -1,99 +1,99 @@ | ||||
| # iOS Physical Use-After-Free via IOSurface | ||||
| # iOS Physische use-after-free via IOSurface | ||||
| 
 | ||||
| {{#include ../../banners/hacktricks-training.md}} | ||||
| 
 | ||||
| 
 | ||||
| ## Physical use-after-free | ||||
| ## Physischer use-after-free | ||||
| 
 | ||||
| This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) | ||||
| Dies ist eine Zusammenfassung des Beitrags von [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html). Weitere Informationen zu Exploits, die diese Technik verwenden, finden sich in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) | ||||
| 
 | ||||
| ### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a> | ||||
| ### Speicherverwaltung in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a> | ||||
| 
 | ||||
| Der **virtuelle Adressraum** für User-Prozesse auf iOS reicht von **0x0 bis 0x8000000000**. Diese Adressen zeigen jedoch nicht direkt auf den physischen Speicher. Stattdessen übersetzt der **kernel** virtuelle Adressen über **page tables** in tatsächliche **physische Adressen**. | ||||
| Der **virtuelle Adressraum** für Benutzerprozesse unter iOS reicht von **0x0 bis 0x8000000000**. Diese Adressen werden jedoch nicht direkt auf physischen Speicher abgebildet. Stattdessen verwendet der **Kernel** **Seitentabellen**, um virtuelle Adressen in tatsächliche **physische Adressen** zu übersetzen. | ||||
| 
 | ||||
| #### Levels of Page Tables in iOS | ||||
| #### Ebenen der Seitentabellen in iOS | ||||
| 
 | ||||
| Page tables sind hierarchisch in drei Ebenen organisiert: | ||||
| Seitentabellen sind hierarchisch in drei Ebenen organisiert: | ||||
| 
 | ||||
| 1. **L1 Page Table (Level 1)**: | ||||
| * Jeder Eintrag repräsentiert einen großen Bereich des virtuellen Speichers. | ||||
| * Deckt **0x1000000000 bytes** (oder **256 GB**) virtuellen Speicher ab. | ||||
| * Jeder Eintrag repräsentiert hier einen großen Bereich des virtuellen Speichers. | ||||
| * Er deckt **0x1000000000 Bytes** (oder **256 GB**) virtuellen Speicher ab. | ||||
| 2. **L2 Page Table (Level 2)**: | ||||
| * Ein Eintrag repräsentiert einen kleineren Bereich von **0x2000000 bytes** (32 MB). | ||||
| * Ein L1-Eintrag kann auf eine L2-Tabelle zeigen, wenn er den gesamten Bereich nicht direkt mappt. | ||||
| * Ein Eintrag repräsentiert hier einen kleineren Bereich des virtuellen Speichers, nämlich **0x2000000 Bytes** (32 MB). | ||||
| * Ein L1-Eintrag kann auf eine L2-Tabelle zeigen, wenn er den gesamten Bereich nicht selbst abbilden kann. | ||||
| 3. **L3 Page Table (Level 3)**: | ||||
| * Die feinste Ebene, bei der jeder Eintrag eine einzelne **4 KB**-Speicherseite abbildet. | ||||
| * Ein L2-Eintrag kann auf eine L3-Tabelle zeigen, wenn detailliertere Kontrolle nötig ist. | ||||
| * Dies ist die feinste Ebene, in der jeder Eintrag eine einzelne **4 KB** Speicherseite abbildet. | ||||
| * Ein L2-Eintrag kann auf eine L3-Tabelle zeigen, wenn eine feinere Auflösung erforderlich ist. | ||||
| 
 | ||||
| #### Mapping Virtual to Physical Memory | ||||
| #### Abbildung von virtuellem zu physischem Speicher | ||||
| 
 | ||||
| * **Direct Mapping (Block Mapping)**: | ||||
| * Manche Einträge in einer page table mappen direkt einen Bereich virtueller Adressen auf einen zusammenhängenden Bereich physischer Adressen (wie eine Abkürzung). | ||||
| * **Pointer to Child Page Table**: | ||||
| * Wenn feinere Kontrolle benötigt wird, kann ein Eintrag auf einer Ebene (z. B. L1) auf eine **child page table** der nächsten Ebene (z. B. L2) zeigen. | ||||
| * **Direkte Abbildung (Block Mapping)**: | ||||
| * Einige Einträge in einer Seitentabelle **bilden direkt einen Bereich virtueller Adressen** auf einen zusammenhängenden Bereich physischer Adressen ab (wie eine Abkürzung). | ||||
| * **Zeiger auf untergeordnete Seitentabelle**: | ||||
| * Wenn eine feinere Steuerung notwendig ist, kann ein Eintrag einer Ebene (z. B. L1) auf eine **untergeordnete Seitentabelle** der nächsten Ebene (z. B. L2) zeigen. | ||||
| 
 | ||||
| #### Example: Mapping a Virtual Address | ||||
| #### Beispiel: Abbildung einer virtuellen Adresse | ||||
| 
 | ||||
| Angenommen, du versuchst auf die virtuelle Adresse **0x1000000000** zuzugreifen: | ||||
| Angenommen, Sie greifen auf die virtuelle Adresse **0x1000000000** zu: | ||||
| 
 | ||||
| 1. **L1 Table**: | ||||
| * Der kernel überprüft den L1-Page-Table-Eintrag, der dieser virtuellen Adresse entspricht. Zeigt er auf eine **L2 page table**, geht er zu dieser L2-Tabelle. | ||||
| * Der Kernel prüft den L1-Seitentabelleneintrag, der dieser virtuellen Adresse entspricht. Wenn dieser einen **Zeiger auf eine L2-Seitentabelle** enthält, geht er zu dieser L2-Tabelle. | ||||
| 2. **L2 Table**: | ||||
| * Der kernel prüft die L2-Page-Table für eine detailliertere Zuordnung. Zeigt dieser Eintrag auf eine **L3 page table**, geht es weiter dorthin. | ||||
| * Der Kernel prüft die L2-Seitentabelle für eine detailliertere Abbildung. Wenn dieser Eintrag auf eine **L3-Seitentabelle** zeigt, geht er dorthin. | ||||
| 3. **L3 Table**: | ||||
| * Der kernel liest den finalen L3-Eintrag aus, der auf die **physische Adresse** der tatsächlichen Speicherseite zeigt. | ||||
| * Der Kernel sucht den finalen L3-Eintrag, der auf die **physische Adresse** der tatsächlichen Speicherseite zeigt. | ||||
| 
 | ||||
| #### Example of Address Mapping | ||||
| #### Beispiel einer Adressabbildung | ||||
| 
 | ||||
| Wenn du die physische Adresse **0x800004000** in den ersten Index der L2-Tabelle schreibst, dann: | ||||
| Wenn Sie die physische Adresse **0x800004000** in den ersten Index der L2-Tabelle schreiben, dann: | ||||
| 
 | ||||
| * Virtuelle Adressen von **0x1000000000** bis **0x1002000000** werden auf physische Adressen von **0x800004000** bis **0x802004000** abgebildet. | ||||
| * Das ist ein **Block Mapping** auf L2-Ebene. | ||||
| * Das ist eine **Block-Abbildung** auf L2-Ebene. | ||||
| 
 | ||||
| Alternativ, wenn der L2-Eintrag auf eine L3-Tabelle zeigt: | ||||
| 
 | ||||
| * Jede 4 KB-Seite im virtuellen Adressbereich **0x1000000000 -> 0x1002000000** würde durch einzelne Einträge in der L3-Tabelle gemappt werden. | ||||
| * Jede 4 KB-Seite im virtuellen Adressbereich **0x1000000000 -> 0x1002000000** würde durch einzelne Einträge in der L3-Tabelle abgebildet werden. | ||||
| 
 | ||||
| ### Physical use-after-free | ||||
| ### Physischer use-after-free | ||||
| 
 | ||||
| Ein **physical use-after-free** (UAF) tritt auf, wenn: | ||||
| Ein **physischer use-after-free** (UAF) tritt auf, wenn: | ||||
| 
 | ||||
| 1. Ein Prozess Speicher als **readable and writable** allokiert. | ||||
| 2. Die **page tables** aktualisiert werden, sodass dieser Speicher auf eine bestimmte physische Adresse gemappt wird, auf die der Prozess zugreifen kann. | ||||
| 3. Der Prozess den Speicher **dealloziert** (freigibt). | ||||
| 4. Aufgrund eines **Bugs** vergisst der kernel jedoch, die Zuordnung aus den page tables zu entfernen, obwohl der entsprechende physische Speicher als frei markiert wird. | ||||
| 5. Der kernel kann diesen "freigegebenen" physischen Speicher dann für andere Zwecke neu allozieren, z. B. für **kernel data**. | ||||
| 6. Da die Zuordnung nicht entfernt wurde, kann der Prozess weiterhin auf diesen physischen Speicher **lesen und schreiben**. | ||||
| 1. Ein Prozess etwas Speicher als **lesbar und beschreibbar** alloziert. | ||||
| 2. Die **Seitentabellen** werden aktualisiert, um diesen Speicher auf eine bestimmte physische Adresse abzubilden, auf die der Prozess zugreifen kann. | ||||
| 3. Der Prozess **deallokiert** (freigibt) den Speicher. | ||||
| 4. Aufgrund eines **Fehlers** vergisst der Kernel jedoch, die Abbildung aus den Seitentabellen zu entfernen, obwohl er den entsprechenden physischen Speicher als frei markiert. | ||||
| 5. Der Kernel kann diesen "freigegebenen" physischen Speicher dann für andere Zwecke neu verwenden, z. B. für **Kernel-Daten**. | ||||
| 6. Da die Abbildung nicht entfernt wurde, kann der Prozess weiterhin **auf diesen physischen Speicher lesen und schreiben**. | ||||
| 
 | ||||
| Das bedeutet, der Prozess kann auf **Seiten von kernel-Speicher** zugreifen, die sensible Daten oder Strukturen enthalten können, was einem Angreifer ermöglichen könnte, **kernel memory** zu manipulieren. | ||||
| Das bedeutet, dass der Prozess auf **Seiten des Kernel-Speichers** zugreifen kann, die sensible Daten oder Strukturen enthalten könnten, und einem Angreifer möglicherweise erlauben, **Kernel-Speicher zu manipulieren**. | ||||
| 
 | ||||
| ### IOSurface Heap Spray | ||||
| 
 | ||||
| Da der Angreifer nicht kontrollieren kann, welche spezifischen kernel-Seiten einer freigegebenen Seite zugewiesen werden, verwendet er die Technik **heap spray**: | ||||
| Da der Angreifer nicht kontrollieren kann, welche spezifischen Kernel-Seiten für den freigegebenen Speicher verwendet werden, nutzt er eine Technik namens **Heap Spray**: | ||||
| 
 | ||||
| 1. Der Angreifer **erstellt eine große Anzahl von IOSurface-Objekten** im kernel-Speicher. | ||||
| 2. Jedes IOSurface-Objekt enthält einen **magic value** in einem seiner Felder, der das Identifizieren erleichtert. | ||||
| 3. Sie **scannen die freigegebenen Seiten**, um zu sehen, ob eines dieser IOSurface-Objekte auf einer freigegebenen Seite gelandet ist. | ||||
| 4. Wenn sie ein IOSurface-Objekt auf einer freigegebenen Seite finden, können sie es verwenden, um **kernel memory** zu lesen und zu schreiben. | ||||
| 1. Der Angreifer **erstellt eine große Anzahl von IOSurface-Objekten** im Kernel-Speicher. | ||||
| 2. Jedes IOSurface-Objekt enthält einen **magischen Wert** in einem seiner Felder, wodurch es leicht zu identifizieren ist. | ||||
| 3. Sie **scannen die freigegebenen Seiten**, um zu sehen, ob sich eines dieser IOSurface-Objekte auf einer freigegebenen Seite niedergelassen hat. | ||||
| 4. Wenn sie ein IOSurface-Objekt auf einer freigegebenen Seite finden, können sie es nutzen, um **Kernel-Speicher zu lesen und zu schreiben**. | ||||
| 
 | ||||
| Mehr Infos dazu in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) | ||||
| 
 | ||||
| > [!TIP] | ||||
| > Beachte, dass iOS 16+ (A12+) Geräte Hardware-Mitigationen (wie PPL oder SPTM) bringen, die physical UAF-Techniken deutlich weniger praktikabel machen. | ||||
| > PPL erzwingt strikte MMU-Schutzmechanismen auf Seiten, die mit Code-Signing, Entitlements und sensiblen kernel-Daten zusammenhängen. Selbst wenn eine Seite wiederverwendet wird, werden Writes aus userland oder kompromittiertem kernel-Code auf PPL-geschützte Seiten blockiert. | ||||
| > Secure Page Table Monitor (SPTM) erweitert PPL, indem es page table-Updates selbst härter absichert. Es stellt sicher, dass selbst privilegierter kernel-Code nicht stillschweigend freed pages remappen oder Mappings ohne sichere Checks manipulieren kann. | ||||
| > KTRR (Kernel Text Read-Only Region) sperrt den Kernel-Code-Bereich nach dem Boot als read-only. Das verhindert Laufzeit-Modifikationen am Kernel-Code und schließt einen großen Angriffsvektor, auf den physical UAF-Exploits oft angewiesen sind. | ||||
| > Außerdem sind IOSurface-Allocations weniger vorhersehbar und schwerer in benutzerzugängliche Regionen zu mappen, wodurch der „Magic-Value-Scanning“-Trick deutlich unzuverlässiger wird. Und IOSurface ist jetzt durch Entitlements und Sandbox-Restriktionen geschützt. | ||||
| > Beachte, dass iOS 16+ (A12+) Geräte Hardware-Mitigationen (wie PPL oder SPTM) mitbringen, die physische UAF-Techniken deutlich weniger praktikabel machen. | ||||
| > PPL erzwingt strikte MMU-Schutzmaßnahmen für Seiten, die mit code signing, entitlements und sensiblen Kernel-Daten zusammenhängen. Somit werden Schreibzugriffe aus userland oder von kompromittiertem Kernel-Code auf PPL-geschützte Seiten blockiert. | ||||
| > Secure Page Table Monitor (SPTM) erweitert PPL, indem es die Seitentabellenupdates selbst härtert. Es stellt sicher, dass selbst privilegierter Kernel-Code nicht stillschweigend freigegebene Seiten remappen oder Abbildungen manipulieren kann, ohne sichere Prüfungen zu durchlaufen. | ||||
| > KTRR (Kernel Text Read-Only Region) sperrt den Code-Bereich des Kernels nach dem Boot als read-only. Das verhindert Laufzeitänderungen am Kernel-Code und schließt damit einen großen Angriffsvektor, auf den physische UAF-Exploits oft angewiesen sind. | ||||
| > Außerdem sind `IOSurface`-Allokationen weniger vorhersehbar und schwieriger in benutzerzugängliche Regionen zu mappen, was den „magischer Wert“-Scan wesentlich unzuverlässiger macht. Und `IOSurface` ist jetzt durch entitlements und sandbox-Beschränkungen geschützt. | ||||
| 
 | ||||
| ### Step-by-Step Heap Spray Process | ||||
| ### Schritt-für-Schritt Heap Spray-Prozess | ||||
| 
 | ||||
| 1. **Spray IOSurface Objects**: Der Angreifer erzeugt viele IOSurface-Objekte mit einem speziellen Identifier ("magic value"). | ||||
| 2. **Scan Freed Pages**: Sie prüfen, ob eines der Objekte auf einer freigegebenen Seite zugewiesen wurde. | ||||
| 3. **Read/Write Kernel Memory**: Durch Manipulation von Feldern im IOSurface-Objekt erlangen sie die Fähigkeit zu **arbitrary reads and writes** im kernel-Speicher. Das erlaubt ihnen: | ||||
| * Ein Feld zu verwenden, um **jeden 32-bit Wert** im kernel-Speicher zu lesen. | ||||
| * Ein anderes Feld zu verwenden, um **64-bit Werte zu schreiben**, wodurch eine stabile **kernel read/write primitive** entsteht. | ||||
| 1. **Spray IOSurface Objects**: Der Angreifer erstellt viele IOSurface-Objekte mit einem speziellen Bezeichner ("magischer Wert"). | ||||
| 2. **Scan Freed Pages**: Sie prüfen, ob eines der Objekte auf einer freigegebenen Seite alloziert wurde. | ||||
| 3. **Read/Write Kernel Memory**: Durch Manipulation von Feldern im IOSurface-Objekt erlangen sie die Fähigkeit zu **beliebigen Reads und Writes** im Kernel-Speicher. Das erlaubt ihnen: | ||||
| * Ein Feld zu verwenden, um **jeden 32-Bit-Wert** im Kernel-Speicher zu lesen. | ||||
| * Ein anderes Feld zu verwenden, um **64-Bit-Werte zu schreiben**, wodurch ein stabiler **Kernel read/write primitive** entsteht. | ||||
| 
 | ||||
| Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for: | ||||
| Erzeuge IOSurface-Objekte mit dem magischen Wert IOSURFACE\_MAGIC, um später danach zu suchen: | ||||
| ```c | ||||
| void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) { | ||||
| if (*nClients >= 0x4000) return; | ||||
| @ -148,25 +148,25 @@ free(surfaceIDs); | ||||
| return 0; | ||||
| } | ||||
| ``` | ||||
| ### Erreichen von Kernel-Lese-/Schreibzugriff mit IOSurface | ||||
| ### Kernel-Lese-/Schreibzugriff mit IOSurface erreichen | ||||
| 
 | ||||
| Nachdem Kontrolle über ein IOSurface-Objekt im Kernel-Speicher erreicht wurde (auf eine freigegebene physische Seite abgebildet, die aus dem userspace zugänglich ist), können wir es für **beliebige Kernel-Lese- und Schreiboperationen** verwenden. | ||||
| Nachdem Kontrolle über ein IOSurface-Objekt im Kernel-Speicher erreicht wurde (auf eine freigegebene physische Seite abgebildet, die vom userspace zugänglich ist), können wir es für **beliebige Kernel-Lese- und Schreiboperationen** verwenden. | ||||
| 
 | ||||
| **Wichtige Felder in IOSurface** | ||||
| 
 | ||||
| Das IOSurface-Objekt hat zwei entscheidende Felder: | ||||
| Die IOSurface hat zwei entscheidende Felder: | ||||
| 
 | ||||
| 1. **Use Count Pointer**: Ermöglicht ein **32-Bit read**. | ||||
| 2. **Indexed Timestamp Pointer**: Ermöglicht ein **64-Bit write**. | ||||
| 1. **Use Count Pointer**: Ermöglicht ein **32-bit read**.   | ||||
| 2. **Indexed Timestamp Pointer**: Ermöglicht ein **64-bit write**. | ||||
| 
 | ||||
| Indem wir diese Zeiger überschreiben, leiten wir sie auf beliebige Adressen im Kernel-Speicher um und ermöglichen Lese-/Schreibzugriff. | ||||
| Durch Überschreiben dieser Pointer leiten wir sie auf beliebige Adressen im Kernel-Speicher um und ermöglichen so Lese-/Schreibzugriff. | ||||
| 
 | ||||
| #### 32-Bit Kernel-Lesezugriff | ||||
| 
 | ||||
| Um einen Lesevorgang durchzuführen: | ||||
| Um einen Lesezugriff durchzuführen: | ||||
| 
 | ||||
| 1. Überschreibe den **use count pointer**, sodass er auf die Zieladresse minus einem 0x14-Byte-Offset zeigt. | ||||
| 2. Verwende die Methode `get_use_count`, um den Wert an dieser Adresse zu lesen. | ||||
| 1. Überschreibe den **use count pointer**, sodass er auf die Zieladresse minus einem 0x14-Byte-Offset zeigt.   | ||||
| 2. Benutze die Methode `get_use_count`, um den Wert an dieser Adresse zu lesen. | ||||
| ```c | ||||
| uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) { | ||||
| uint64_t args[1] = {surfaceID}; | ||||
| @ -184,12 +184,12 @@ iosurface_set_use_count_pointer(info.object, orig); | ||||
| return value; | ||||
| } | ||||
| ``` | ||||
| #### 64-Bit Kernel-Schreiben | ||||
| #### 64-Bit Kernel Write | ||||
| 
 | ||||
| Um einen Schreibvorgang auszuführen: | ||||
| Um einen Schreibvorgang durchzuführen: | ||||
| 
 | ||||
| 1. Überschreibe den **indexierten Zeitstempelzeiger** mit der Zieladresse. | ||||
| 2. Verwende die `set_indexed_timestamp`-Methode, um einen 64-Bit-Wert zu schreiben. | ||||
| 1. Überschreibe den **indexed timestamp pointer** auf die Zieladresse. | ||||
| 2. Verwende die Methode `set_indexed_timestamp`, um einen 64-Bit-Wert zu schreiben. | ||||
| ```c | ||||
| void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) { | ||||
| uint64_t args[3] = {surfaceID, 0, value}; | ||||
| @ -206,10 +206,10 @@ iosurface_set_indexed_timestamp_pointer(info.object, orig); | ||||
| #### Zusammenfassung des Exploit-Ablaufs | ||||
| 
 | ||||
| 1. **Trigger Physical Use-After-Free**: Freie Seiten stehen zur Wiederverwendung zur Verfügung. | ||||
| 2. **Spray IOSurface Objects**: Viele IOSurface-Objekte mit einem eindeutigen "magic value" im kernel memory allozieren. | ||||
| 3. **Identify Accessible IOSurface**: Eine IOSurface auf einer freigegebenen Seite finden, die Sie kontrollieren. | ||||
| 4. **Abuse Use-After-Free**: Pointer im IOSurface-Objekt manipulieren, um über IOSurface methods beliebiges **kernel read/write** zu ermöglichen. | ||||
| 2. **Spray IOSurface Objects**: Allokiere viele IOSurface-Objekte mit einem eindeutigen "magic value" im Kernel-Speicher. | ||||
| 3. **Identify Accessible IOSurface**: Finde ein IOSurface auf einer freigegebenen Seite, die du kontrollierst. | ||||
| 4. **Abuse Use-After-Free**: Ändere Pointer im IOSurface-Objekt, um über IOSurface-Methoden beliebige **kernel read/write** zu ermöglichen. | ||||
| 
 | ||||
| Mit diesen Primitiven stellt der Exploit kontrollierte **32-bit reads** und **64-bit writes** auf kernel memory bereit. Weitere Jailbreak-Schritte könnten stabilere read/write-Primitiven erfordern, die zusätzliche Schutzmechanismen umgehen müssen (z. B. PPL auf neueren arm64e-Geräten). | ||||
| Mit diesen Primitiven ermöglicht der Exploit kontrollierte **32-bit reads** und **64-bit writes** auf den Kernel-Speicher. Weitere jailbreak-Schritte könnten stabilere read/write primitives erfordern, die das Umgehen zusätzlicher Schutzmechanismen nötig machen (z. B. PPL auf neueren arm64e-Geräten). | ||||
| 
 | ||||
| {{#include ../../banners/hacktricks-training.md}} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user