Translated ['', 'src/binary-exploitation/ios-exploiting/ios-physical-uaf

This commit is contained in:
Translator 2025-09-29 08:59:57 +00:00
parent 2843d10b51
commit b18f82c28a

View File

@ -1,19 +1,19 @@
# iOS Physical Use-After-Free via IOSurface
# iOS Physical Use After Free via IOSurface
{{#include ../../banners/hacktricks-training.md}}
## Physical use-after-free
## Fizički use-after-free
Ovo je sažetak posta sa [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html). Pored toga, dodatne informacije o exploit-u koji koristi ovu tehniku mogu se naći u [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd).
Ovo je sažetak posta sa [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html), a dodatne informacije o exploit-u koji koristi ovu tehniku mogu se naći na [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>
### Upravljanje memorijom u XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
The **virtuelni adresni prostor** za korisničke procese na iOS obuhvata od **0x0 do 0x8000000000**. Međutim, ove adrese se ne preslikavaju direktno na fizičku memoriju. Umesto toga, kernel koristi **page tables** da prevede virtuelne adrese u stvarne **physical addresses**.
Virtuelni adresni prostor za procese korisnika na iOS-u prostire se od **0x0 do 0x8000000000**. Međutim, ove adrese se ne preslikavaju direktno na fizičku memoriju. Umesto toga, **kernel** koristi **page tables** da prevede virtuelne adrese u stvarne **fizičke adrese**.
#### Levels of Page Tables in iOS
#### Nivoi page tabela u iOS-u
Page tables su organizovane hijerarhijski u tri nivoa:
Page table-ovi su organizovani hijerarhijski u tri nivoa:
1. **L1 Page Table (Level 1)**:
* Svaki unos ovde predstavlja veliki opseg virtuelne memorije.
@ -25,25 +25,25 @@ Page tables su organizovane hijerarhijski u tri nivoa:
* Ovo je najfiniji nivo, gde svaki unos mapira jednu **4 KB** memorijsku stranicu.
* L2 unos može pokazivati na L3 tabelu ako je potrebna detaljnija kontrola.
#### Mapping Virtual to Physical Memory
#### Mapiranje virtuelne u fizičku memoriju
* **Direct Mapping (Block Mapping)**:
* Neki unosi u page table direktno **mapiraju opseg virtuelnih adresa** u kontinualan opseg fizičkih adresa (kao prečica).
* Neki unosi u page tabeli direktno **mapiraju opseg virtuelnih adresa** na kontinualan opseg fizičkih adresa (kao prečica).
* **Pointer to Child Page Table**:
* Ako je potrebna finija kontrola, unos na jednom nivou (npr. L1) može pokazivati na **child page table** na sledećem nivou (npr. L2).
#### Example: Mapping a Virtual Address
#### Primer: mapiranje virtuelne adrese
Recimo da pokušate da pristupite virtuelnoj adresi **0x1000000000**:
1. **L1 Table**:
* Kernel proverava L1 page table unos koji odgovara toj virtuelnoj adresi. Ako ima **pointer to an L2 page table**, prelazi na tu L2 tabelu.
* Kernel proverava odgovarajući unos u L1 page tabeli za ovu virtuelnu adresu. Ako ima **pointer** ka L2 page tabeli, prelazi u tu L2 tabelu.
2. **L2 Table**:
* Kernel proverava L2 page table za detaljnije preslikavanje. Ako taj unos pokazuje na **L3 page table**, prelazi dalje.
* Kernel proverava L2 page tabelu za detaljnije mapiranje. Ako ovaj unos pokazuje na **L3 page table**, prelazi se tamo.
3. **L3 Table**:
* Kernel traži konačni L3 unos, koji pokazuje na **fizičku adresu** stvarne memorijske stranice.
* Kernel pregleda finalni L3 unos, koji pokazuje na **fizičku adresu** stvarne memorijske stranice.
#### Example of Address Mapping
#### Primer mapiranja adresa
Ako upišete fizičku adresu **0x800004000** u prvi indeks L2 tabele, onda:
@ -52,48 +52,48 @@ Ako upišete fizičku adresu **0x800004000** u prvi indeks L2 tabele, onda:
Alternativno, ako L2 unos pokazuje na L3 tabelu:
* Svaka 4 KB stranica u virtuelnom adresnom opsegu **0x1000000000 -> 0x1002000000** biće mapirana pojedinačnim unosima u L3 tabeli.
* Svaka 4 KB stranica u virtuelnom adresnom opsegu **0x1000000000 -> 0x1002000000** bi bila mapirana pojedinačnim unosima u L3 tabeli.
### Physical use-after-free
A **physical use-after-free** (UAF) se dešava kada:
Physički use-after-free (UAF) se dešava kada:
1. Proces **alokira** memoriju kao **readable and writable**.
2. **Page tables** se ažuriraju da mapiraju tu memoriju na specifičnu fizičku adresu kojoj proces može pristupiti.
1. Proces **alokira** neku memoriju kao **readable i writable**.
2. **Page tables** su ažurirane da mapiraju ovu memoriju na specifičnu fizičku adresu kojoj proces može pristupiti.
3. Proces **dealocira** (oslobodi) memoriju.
4. Međutim, zbog buga, kernel **zaboravi da ukloni mapping** iz page tables, iako je odgovarajuća fizička memorija označena kao slobodna.
5. Kernel može potom **ponovo alocirati tu "slobodnu" fizičku memoriju** za druge potrebe, npr. kernel podatke.
6. Pošto mapping nije uklonjen, proces i dalje može **čitati i pisati** u tu fizičku memoriju.
4. Međutim, zbog **baga**, kernel **zaboravi da ukloni mapiranje** iz page tabela, iako označi odgovarajuću fizičku memoriju kao slobodnu.
5. Kernel zatim može **ponovo alocirati ovu "oslobođenu" fizičku memoriju** za druge svrhe, kao što su **kernel podaci**.
6. Pošto mapiranje nije uklonjeno, proces i dalje može **čitati i pisati** tu fizičku memoriju.
To znači da proces može pristupiti **stranicama kernel memorije**, koje mogu sadržavati osetljive podatke ili strukture, potencijalno omogućavajući napadaču da **manipuliše kernel memorijom**.
### IOSurface Heap Spray
Pošto napadač ne može da kontroliše koje će konkretne kernel stranice biti dodeljene oslobođenoj memoriji, koristi tehniku zvanu **heap spray**:
Pošto napadač ne može kontrolisati koje konkretne kernel stranice će biti dodeljene oslobođenoj memoriji, koristi se tehnika zvana **heap spray**:
1. Napadač **kreira veliki broj IOSurface objekata** u kernel memoriji.
2. Svaki IOSurface objekat sadrži **magic value** u jednom od svojih polja, što olakšava identifikaciju.
3. Oni **skeniraju oslobođene stranice** da vide da li su neki od tih IOSurface objekata završili na oslobođenoj stranici.
4. Kada nađu IOSurface objekat na oslobođenoj stranici, mogu ga iskoristiti da **čitaju i pišu kernel memoriju**.
2. Svaki IOSurface objekat sadrži **magničnu vrednost** u jednom od svojih polja, što ga čini lakim za identifikaciju.
3. Oni **skeniraju oslobođene stranice** da vide da li je neki od ovih IOSurface objekata dospeo na oslobođenu stranicu.
4. Kada pronađu IOSurface objekat na oslobođenoj stranici, mogu ga iskoristiti za **čitanje i pisanje kernel memorije**.
Više informacija o ovome u [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
Više informacija o ovome na [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
> [!TIP]
> Imajte na umu da iOS 16+ (A12+) uređaji uvode hardverske mitigacije (kao što su PPL ili SPTM) koje čine physical UAF tehnike znatno manje izvodljivim.
> PPL nameće stroge MMU zaštite na stranicama vezanim za code signing, entitlements i osetljive kernel podatke, tako da, čak i ako se stranica ponovo iskoristi, pisanja iz userlanda ili kompromitovanog kernel koda na PPL-zaštićene stranice bivaju blokirana.
> Secure Page Table Monitor (SPTM) proširuje PPL tako što ojačava same page table update-ove. On osigurava da čak ni privilegovani kernel kod ne može neprimetno remap-ovati oslobođene stranice ili menjati mape bez prolaska kroz sigurne provere.
> KTRR (Kernel Text Read-Only Region) zaključava kernel-ov kod kao read-only nakon boot-a. Ovo onemogućava bilo kakve runtime modifikacije kernel koda, zatvarajući značajan napadni vektor na koji se physical UAF exploit-i često oslanjaju.
> Pored toga, IOSurface alokacije su manje predvidive i teže se mapiraju u user-accessible regione, što čini trik sa “magic value scanning” mnogo manje pouzdanim. I IOSurface sada zahteva entitlements i podleže sandbox ograničenjima.
> Imajte na umu da iOS 16+ (A12+) uređaji uvode hardverske mitigacije (kao što su PPL ili SPTM) koje čine fizičke UAF tehnike znatno manje izvodljivim.
> PPL nameće stroga MMU ograničenja na stranicama vezanim za code signing, entitlements i osetljive kernel podatke, pa čak i ako se stranica ponovo koristi, upisi iz userlanda ili kompromitovanog kernel koda u PPL-zaštićene stranice su blokirani.
> Secure Page Table Monitor (SPTM) proširuje PPL tako što ojačava same page table update-ove. On osigurava da čak ni privilegovani kernel kod ne može neprimetno remapirati oslobođene stranice ili menjati mapiranja bez prolaska kroz sigurnosne provere.
> KTRR (Kernel Text Read-Only Region) zaključava sekciju kernel koda kao samo za čitanje posle boot-a. Ovo sprečava bilo kakve izmene kernel koda u toku rada, zatvarajući jedan od glavnih vektora napada na koji se fizički UAF exploiti često oslanjaju.
> Pored toga, `IOSurface` alokacije su manje predvidljive i teže ih je mapirati u user-accessible regione, što čini trik sa skeniranjem "magične vrednosti" mnogo manje pouzdanim. I `IOSurface` je sada zaštićen entitlements i sandbox ograničenjima.
### Step-by-Step Heap Spray Process
1. **Spray IOSurface Objects**: Napadač kreira mnoge IOSurface objekte sa specijalnim identifikatorom ("magic value").
2. **Scan Freed Pages**: Proveravaju da li je bilo koji od objekata alociran na oslobođenoj stranici.
3. **Read/Write Kernel Memory**: Manipulacijom polja u IOSurface objektu, dobijaju mogućnost za **arbitrary reads and writes** u kernel memoriji. Ovo im omogućava da:
* Koriste jedno polje za **čitati bilo koju 32-bit vrednost** u kernel memoriji.
* Koriste drugo polje za **pisati 64-bit vrednosti**, ostvarujući stabilan **kernel read/write primitive**.
1. **Spray IOSurface Objects**: Napadač kreira mnogo IOSurface objekata sa specijalnim identifikatorom ("magic value").
2. **Scan Freed Pages**: Proveravaju da li je neki od objekata alociran na oslobođenoj stranici.
3. **Read/Write Kernel Memory**: Manipulacijom polja u IOSurface objektu, stiču sposobnost da izvode **arbitrary reads and writes** u kernel memoriji. To im omogućava da:
* Iskoriste jedno polje da **čitaju bilo koju 32-bit vrednost** u kernel memoriji.
* Iskoriste drugo polje da **pišu 64-bit vrednosti**, postižući stabilan **kernel read/write primitive**.
Generate IOSurface objects with the magic value IOSURFACE_MAGIC to later search for:
Generišite IOSurface objekte sa magičnom vrednošću IOSURFACE\_MAGIC za kasnije pretraživanje:
```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
if (*nClients >= 0x4000) return;
@ -114,7 +114,7 @@ io_connect_t id = result.surface_id;
}
}
```
Pretražite **`IOSurface`** objekte u jednoj oslobođenoj fizičkoj stranici:
Pretražite objekte **`IOSurface`** u jednoj oslobođenoj fizičkoj stranici:
```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);
@ -148,25 +148,25 @@ free(surfaceIDs);
return 0;
}
```
### Postizanje Kernel Read/Write with IOSurface
### Postizanje čitanja/pisanja u kernelu pomoću IOSurface
Nakon što preuzmemo kontrolu nad IOSurface objektom u kernel memoriji (mapiranom na oslobođenu fizičku stranicu dostupnu iz userspace-a), možemo ga koristiti za proizvoljne kernel operacije čitanja i pisanja.
Nakon što se uspostavi kontrola nad IOSurface objektom u kernel memoriji (mapiran na oslobođenu fizičku stranicu kojoj korisnički prostor ima pristup), možemo ga iskoristiti za **arbitrary kernel read and write operations**.
**Key Fields in IOSurface**
**Ključna polja u IOSurface**
IOSurface objekat ima dva ključna polja:
1. **Use Count Pointer**: Omogućava **32-bit read**.
2. **Indexed Timestamp Pointer**: Omogućava **64-bit write**.
Prepisivanjem ovih pokazivača preusmeravamo ih na proizvoljne adrese u kernel memoriji, čime omogućavamo mogućnosti read/write.
Prepisivanjem ovih pokazivača preusmeravamo ih na proizvoljne adrese u kernel memoriji, čime dobijamo mogućnost čitanja/pisanja.
#### 32-Bit Kernel Read
Da izvršimo čitanje:
Za izvođenje čitanja:
1. Prepišite **use count pointer** da pokazuje na ciljnu adresu umanjenu za offset od 0x14 bajta.
2. Koristite metodu `get_use_count` da pročitate vrednost na toj adresi.
2. Koristite `get_use_count` method da pročitate vrednost na toj adresi.
```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 upis u kernel
#### 64-Bit Kernel Write
Da biste izvršili upis:
1. Prepišite **indexed timestamp pointer** na ciljnu adresu.
2. Koristite `set_indexed_timestamp` metodu da upišete 64-bit vrednost.
1. Prepišite **indexed timestamp pointer** da pokazuje na ciljnu adresu.
2. Koristite `set_indexed_timestamp` metodu da upišete 64-bitnu vrednost.
```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
uint64_t args[3] = {surfaceID, 0, value};
@ -205,11 +205,11 @@ iosurface_set_indexed_timestamp_pointer(info.object, orig);
```
#### Exploit Flow Recap
1. **Trigger Physical Use-After-Free**: Slobodne stranice postaju dostupne za ponovnu upotrebu.
2. **Spray IOSurface Objects**: Alocirajte mnogo IOSurface objekata sa jedinstvenom "magic value" u kernel memory.
1. **Trigger Physical Use-After-Free**: Slobodne stranice su dostupne za ponovnu upotrebu.
2. **Spray IOSurface Objects**: Alocirajte mnogo IOSurface objekata sa jedinstvenom "magic value" u kernel memoriji.
3. **Identify Accessible IOSurface**: Pronađite IOSurface na oslobođenoj stranici kojom upravljate.
4. **Abuse Use-After-Free**: Izmenite pokazivače u IOSurface objektu kako biste omogućili proizvoljno **kernel read/write** preko IOSurface metoda.
4. **Abuse Use-After-Free**: Izmenite pokazivače u IOSurface objektu kako biste omogućili proizvoljno **kernel read/write** putem IOSurface metoda.
Sa ovim primitivima, exploit obezbeđuje kontrolisane **32-bit reads** i **64-bit writes** u kernel memory. Dalji koraci za jailbreak mogli bi uključivati stabilnije read/write primitive, koje mogu zahtevati zaobilaženje dodatnih zaštita (npr. PPL na novijim arm64e uređajima).
Sa ovim primitivima, exploit obezbeđuje kontrolisano **32-bit reads** i **64-bit writes** u kernel memoriju. Dalji koraci za jailbreak mogu uključivati stabilnije read/write primitive, koje mogu zahtevati zaobilaženje dodatnih zaštita (npr. PPL na novijim arm64e uređajima).
{{#include ../../banners/hacktricks-training.md}}