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

This commit is contained in:
Translator 2025-09-29 09:00:33 +00:00
parent 8f5cc37377
commit 1557f8ff52

View File

@ -1,99 +1,99 @@
# iOS Physical Use-After-Free via IOSurface # iOS Physical Use After Free via IOSurface
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Physical use-after-free ## Physical use-after-free
Dit is 'n opsomming van die pos by [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html). Boonop is verdere inligting oor exploits wat hierdie tegniek gebruik te vinde by [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) Dit is 'n opsomming van die pos by [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html). Verder kan meer inligting oor exploits wat hierdie tegniek gebruik gevind word by [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> ### Geheuebestuur in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
Die virtuele geheue-adresruimte vir gebruikersprosesse op iOS strek van **0x0 tot 0x8000000000**. Hierdie adresse kaart egter nie direk na fisiese geheue nie. In plaas daarvan gebruik die kernel **page tables** om virtuele adresse na werklike **fisiese adresse** te vertaal. Die **virtual memory address space** vir gebruikersprosesse op iOS strek van **0x0 to 0x8000000000**. Hierdie adresse kaart egter nie direk na fisiese geheue nie. In plaas daarvan gebruik die **kernel** **page tables** om virtuele adresse na werklike **physical addresses** te vertaal.
#### Levels of Page Tables in iOS #### Levels of Page Tables in iOS
Page tables is hiërargies georganiseer in drie vlakke: Page tables is hiërargies georganiseer in drie vlakke:
1. **L1 Page Table (Level 1)**: 1. **L1 Page Table (Level 1)**:
* Elke inskrywing hier verteenwoordig 'n groot reikafstand van virtuele geheue. * Elke inskrywing hier verteenwoordig 'n groot gebied van virtuele geheue.
* Dit dek **0x1000000000 bytes** (of **256 GB**) van virtuele geheue. * Dit dek **0x1000000000 bytes** (of **256 GB**) virtuele geheue.
2. **L2 Page Table (Level 2)**: 2. **L2 Page Table (Level 2)**:
* 'n Inskrywing hier verteenwoordig 'n kleiner streek van virtuele geheue, spesifiek **0x2000000 bytes** (32 MB). * 'n Inskrywing hier verteenwoordig 'n kleiner streek van virtuele geheue, spesifiek **0x2000000 bytes** (32 MB).
* 'n L1-inskrywing kan na 'n L2-tabel wys as dit nie die hele streek self kan karteer nie. * 'n L1-inskrywing kan na 'n L2-table wys as dit nie die hele streek self kan map nie.
3. **L3 Page Table (Level 3)**: 3. **L3 Page Table (Level 3)**:
* Dit is die fynste vlak, waar elke inskrywing 'n enkele **4 KB** geheuebladsy karteer. * Dit is die fynste vlak, waar elke inskrywing 'n enkele **4 KB** geheuebladsy map.
* 'n L2-inskrywing kan na 'n L3-tabel wys as meer gedetailleerde beheer nodig is. * 'n L2-inskrywing kan na 'n L3-table wys indien meer gedetailleerde beheer benodig word.
#### Mapping Virtual to Physical Memory #### Mapping Virtual to Physical Memory
* **Direct Mapping (Block Mapping)**: * **Direct Mapping (Block Mapping)**:
* Sommige inskrywings in 'n page table karteer direk 'n reeks virtuele adresse na 'n aaneenlopende reeks fisiese adresse (soort van kortpad). * Sommige inskrywings in 'n page table map direk 'n reeks virtuele adresse na 'n aaneenlopende reeks fisiese adresse (soort van kortpad).
* **Pointer to Child Page Table**: * **Pointer to Child Page Table**:
* As fynere beheer nodig is, kan 'n inskrywing in een vlak (bv. L1) na 'n **child page table** op die volgende vlak (bv. L2) wys. * As fynere beheer benodig word, kan 'n inskrywing op een vlak (bv. L1) na 'n child page table op die volgende vlak (bv. L2) wys.
#### Example: Mapping a Virtual Address #### Example: Mapping a Virtual Address
Kom ons sê jy probeer toegang kry tot die virtuele adres **0x1000000000**: Kom ons sê jy probeer toegang kry tot die virtuele adres **0x1000000000**:
1. **L1 Table**: 1. **L1 Table**:
* Die kernel kyk na die L1 page table-inskrywing wat ooreenstem met hierdie virtuele adres. As dit 'n **pointer to an L2 page table** bevat, gaan dit na daardie L2-tabel. * Die kernel kyk na die L1 page table inskrywing wat ooreenstem met hierdie virtuele adres. As dit 'n **pointer to an L2 page table** het, gaan dit na daardie L2-table.
2. **L2 Table**: 2. **L2 Table**:
* Die kernel kyk die L2 page table vir 'n meer gedetailleerde kartering. As hierdie inskrywing na 'n **L3 page table** wys, gaan dit daarheen. * Die kernel kyk die L2 page table na vir 'n meer gedetailleerde mapping. As hierdie inskrywing na 'n **L3 page table** wys, gaan dit verder daarheen.
3. **L3 Table**: 3. **L3 Table**:
* Die kernel soek die finale L3-inskrywing, wat na die **fisiese adres** van die werklike geheuebladsy wys. * Die kernel soek die finale L3-inskrywing, wat na die **physical address** van die werklike geheuebladsy wys.
#### Example of Address Mapping #### Example of Address Mapping
As jy die fisiese adres **0x800004000** in die eerste indeks van die L2-tabel skryf, dan: As jy die fisiese adres **0x800004000** in die eerste indeks van die L2-table skryf, dan:
* Virtuele adresse van **0x1000000000** tot **0x1002000000** karteer na fisiese adresse van **0x800004000** tot **0x802004000**. * Virtuele adresse van **0x1000000000** tot **0x1002000000** map na fisiese adresse van **0x800004000** tot **0x802004000**.
* Dit is 'n **block mapping** op die L2-vlak. * Dit is 'n **block mapping** op die L2-vlak.
Alternatiewelik, as die L2-inskrywing na 'n L3-tabel wys: Alternatiewelik, as die L2-inskrywing na 'n L3-table wys:
* Elke 4 KB-bladsy in die virtuele adresreeks **0x1000000000 -> 0x1002000000** sou deur individuele inskrywings in die L3-tabel gekarteer word. * Elke 4 KB-bladsy in die virtuele adresreeks **0x1000000000 -> 0x1002000000** sou deur individuele inskrywings in die L3-table gemap word.
### Physical use-after-free ### Physical use-after-free
'n **Physical use-after-free** (UAF) gebeur wanneer: 'N **physical use-after-free** (UAF) gebeur wanneer:
1. 'n Proses **alloceer** sekere geheue as **readable and writable**. 1. 'n proses sekere geheue **alloceer** as **leesbaar en skryfbaar**.
2. Die **page tables** word opgedateer om hierdie geheue na 'n spesifieke fisiese adres te karteer wat die proses kan toegang. 2. Die **page tables** word opgedateer om hierdie geheue na 'n spesifieke fisiese adres te map wat die proses kan benader.
3. Die proses **dealloceer** (vry) die geheue. 3. Die proses **dealloceer** (vrylaat) die geheue.
4. Weens 'n **bug**, vergeet die kernel egter om die kartering uit die page tables te verwyder, al merk dit die ooreenstemmende fisiese geheue as vry. 4. Weens 'n **fout**, vergeet die kernel om die mapping uit die page tables te verwyder, selfs al merk dit die ooreenstemmende fisiese geheue as vry.
5. Die kernel kan dan hierdie "vrygemaakte" fisiese geheue **heralloceer** vir ander doeleindes, soos **kernel data**. 5. Die kernel kan dan hierdie “vrygemaakte” fisiese geheue weer **herallokeer** vir ander doeleindes, soos **kernel data**.
6. Aangesien die kartering nie verwyder is nie, kan die proses steeds **lees en skryf** na daardie fisiese geheue. 6. Aangesien die mapping nie verwyder is nie, kan die proses steeds na hierdie fisiese geheue **lees en skryf**.
Dit beteken die proses kan toegang hê tot **bladsye van kernel memory**, wat sensitiewe data of strukture kan bevat, en moontlik 'n aanvaller toelaat om **kernel memory te manipuleer**. Dit beteken die proses kan toegang tot **bladsye van kernel-geheue** kry, wat sensitiewe data of strukture kan bevat, en moontlik 'n aanvaller toelaat om **kernel memory** te manipuleer.
### IOSurface Heap Spray ### IOSurface Heap Spray
Aangesien die aanvaller nie kan beheer watter spesifieke kernel-bladsye aan vrygemaakte geheue toegeken sal word nie, gebruik hulle 'n tegniek genaamd **heap spray**: Aangesien die aanvaller nie kan beheer watter bepaalde kernel-bladsye aan vrygemaakte geheue toegewys sal word nie, gebruik hulle 'n tegniek genaamd **heap spray**:
1. Die aanvaller **skep 'n groot aantal IOSurface objects** in kernel memory. 1. Die aanvaller **skep 'n groot aantal IOSurface objects** in kernel-geheue.
2. Elke IOSurface-object bevat 'n **magic value** in een van sy velde, wat dit maklik maak om te identifiseer. 2. Elke IOSurface-object bevat 'n **magic value** in een van sy velde, wat dit maklik maak om te identifiseer.
3. Hulle **scan die vrygemaakte bladsye** om te sien of enige van hierdie IOSurface-objects op 'n vrygemaakte bladsy geland het. 3. Hulle **skandeer die vrygemaakte bladsye** om te sien of enige van hierdie IOSurface-objekte op 'n vrygemaakte bladsy geland het.
4. Wanneer hulle 'n IOSurface-object op 'n vrygemaakte bladsy vind, kan hulle dit gebruik om **kernel memory te lees en skryf**. 4. Wanneer hulle 'n IOSurface-object op 'n vrygemaakte bladsy vind, kan hulle dit gebruik om **kernel memory** te lees en te skryf.
Meer inligting hieroor by [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) Meer inligting daaroor by [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
> [!TIP] > [!TIP]
> Wees bewus dat iOS 16+ (A12+) toestelle hardeware-mitigasies bring (soos PPL of SPTM) wat physical UAF-tegnieke baie minder lewensvatbaar maak. > Wees bewus dat iOS 16+ (A12+) toestelle hardeware-mitigasies bring (soos PPL of SPTM) wat physical UAF-tegnieke baie minder uitvoerbaar maak.
> PPL afdwing streng MMU-beskermings op bladsye wat verband hou met code signing, entitlements, en sensitiewe kernel data, so selfs as 'n bladsy hergebruik word, word skryfoperasies vanaf userland of gekompromitteerde kernel-kode na PPL-beskermde bladsye geblokkeer. > PPL handhaaf streng MMU-beskerming op bladsye wat verband hou met code signing, entitlements, en sensitiewe kernel-data, so selfs as 'n bladsy weer gebruik word, word skrywe vanaf userland of gekompromitteerde kernel-kode na PPL-beskermde bladsye geblokkeer.
> Secure Page Table Monitor (SPTM) brei PPL uit deur page table-updates self te verhinder. Dit verseker dat selfs bevoorregte kernel-kode nie stilweg vrygemaakte bladsye kan herkarreer of mappings kan verander sonder deur veilige kontroles te gaan nie. > Secure Page Table Monitor (SPTM) brei PPL uit deur page table updates self te verharden. Dit verseker dat selfs bevoorregte kernel-kode nie stilweg vrygemaakte bladsye kan herkaart of mappings kan manipuleer sonder om deur sekure kontrole te gaan nie.
> KTRR (Kernel Text Read-Only Region) sluit die kernel se kodesegment na opstart as read-only. Dit voorkom enige runtime-wysigings aan kernel-kode en sluit 'n groot aanvalsvlak wat physical UAF-exploits dikwels benut, af. > KTRR (Kernel Text Read-Only Region) vergrendel die kernel se code-afdeling as read-only na opstart. Dit voorkom enige runtime-wysigings aan kernel-kode en sluit 'n groot aanvalsvlak af waarop physical UAF-exploits dikwels staatmaak.
> Verder is IOSurface-allocations minder voorspelbaar en moeiliker om in user-accessible areas te karteer, wat die “magic value scanning”-truuk baie minder betroubaar maak. En IOSurface is nou beskerm deur entitlements en sandbox-restriksies. > Boonop is `IOSurface`-allokasies minder voorspelbaar en moeiliker om in user-accessible streke te map, wat die “magic value scanning”-truuk minder betroubaar maak. En `IOSurface` word nou ook deur entitlements en sandbox-restriksies beskerm.
### Step-by-Step Heap Spray Process ### Step-by-Step Heap Spray Process
1. **Spray IOSurface Objects**: Die aanvaller skep baie IOSurface-objects met 'n spesiale identifiseerder ("magic value"). 1. **Spray IOSurface Objects**: Die aanvaller skep baie IOSurface-objekte met 'n spesiale identifiseerder ("magic value").
2. **Scan Freed Pages**: Hulle kontroleer of enige van die objects op 'n vrygemaakte bladsy toegeken is. 2. **Scan Freed Pages**: Hulle kyk of enige van die objekte op 'n vrygemaakte bladsy toegeken is.
3. **Read/Write Kernel Memory**: Deur velde in die IOSurface-object te manipuleer, kry hulle die vermoë om **arbitrary reads and writes** in kernel memory uit te voer. Dit laat hulle toe om: 3. **Read/Write Kernel Memory**: Deur velde in die IOSurface-object te manipuleer, verkry hulle die vermoë om **arbitrary reads and writes** in kernel-geheue uit te voer. Dit laat hulle toe om:
* Een veld te gebruik om **enige 32-bit waarde** in kernel memory te lees. * Een veld te gebruik om **enige 32-bit waarde** in kernel-geheue te lees.
* 'n Ander veld te gebruik om **64-bit waardes te skryf**, waarmee 'n stabiele **kernel read/write primitive** bereik word. * 'n Ander veld te gebruik om **64-bit waardes** te skryf, en sodoende 'n stabiele **kernel read/write primitive** te bereik.
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for: Genereer IOSurface objects met die magic value IOSURFACE\_MAGIC om later daarna te soek:
```c ```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) { void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
if (*nClients >= 0x4000) return; if (*nClients >= 0x4000) return;
@ -114,7 +114,7 @@ io_connect_t id = result.surface_id;
} }
} }
``` ```
Soek na **`IOSurface`**-objekte in 'n vrygemaakte fisiese bladsy: Soek na **`IOSurface`**-voorwerpe in 'n vrygestelde fisiese bladsy:
```c ```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) { 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); io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
@ -148,25 +148,25 @@ free(surfaceIDs);
return 0; return 0;
} }
``` ```
### Bereik Kernel Read/Write met IOSurface ### Bereiking van Kernel Read/Write met IOSurface
Nadat ons beheer oor 'n IOSurface-objek in kernel memory (gemap na 'n vrygemaakte fisiese bladsy wat vanaf userspace toeganklik is) bereik het, kan ons dit gebruik vir arbitrêre kernel read and write operations. Nadat ons beheer oor 'n IOSurface-object in kernel memory bereik het (gemapped na 'n vrygestelde fisiese bladsy wat vanaf userspace toeganklik is), kan ons dit gebruik vir **arbitrary kernel read and write operations**.
**Key Fields in IOSurface** **Key Fields in IOSurface**
Die IOSurface-objek het twee belangrike velde: Die IOSurface-object het twee belangrike velde:
1. **Use Count Pointer**: Laat 'n **32-bit read** toe. 1. **Use Count Pointer**: Maak 'n **32-bit read** moontlik.
2. **Indexed Timestamp Pointer**: Laat 'n **64-bit write** toe. 2. **Indexed Timestamp Pointer**: Maak 'n **64-bit write** moontlik.
Deur hierdie pointers oor te skryf, herlei ons hulle na arbitrêre adresse in kernel memory, wat read/write-vaardighede moontlik maak. Deur hierdie pointers oor te skryf, herlei ons hulle na willekeurige adresse in kernel memory en skep ons read/write-vermoëns.
#### 32-Bit Kernel Read #### 32-Bit Kernel Read
Om 'n read uit te voer: Om 'n read uit te voer:
1. Oorskryf die **use count pointer** sodat dit na die teikenadres minus 'n 0x14-byte offset wys. 1. Oorskryf die **use count pointer** sodat dit na die teikenadres minus 'n 0x14-byte offset wys.
2. Gebruik die `get_use_count` method om die waarde by daardie adres te read. 2. Gebruik die `get_use_count`-metode om die waarde by daardie adres te read.
```c ```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) { uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
uint64_t args[1] = {surfaceID}; uint64_t args[1] = {surfaceID};
@ -184,12 +184,12 @@ iosurface_set_use_count_pointer(info.object, orig);
return value; return value;
} }
``` ```
#### 64-Bit Kernel Write #### 64-bis kernskryf
Om 'n skryf uit te voer: Om 'n skryf uit te voer:
1. Oorskryf die **indexed timestamp pointer** na die teikenadres. 1. Oorskryf die **indexed timestamp pointer** na die teikenadres.
2. Gebruik die `set_indexed_timestamp` metode om 'n 64-bit-waarde te skryf. 2. Gebruik die `set_indexed_timestamp` metode om 'n 64-bis waarde te skryf.
```c ```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) { void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
uint64_t args[3] = {surfaceID, 0, value}; uint64_t args[3] = {surfaceID, 0, value};
@ -206,10 +206,10 @@ iosurface_set_indexed_timestamp_pointer(info.object, orig);
#### Exploit Flow Opsomming #### Exploit Flow Opsomming
1. **Trigger Physical Use-After-Free**: Vrye bladsye is beskikbaar vir hergebruik. 1. **Trigger Physical Use-After-Free**: Vrye bladsye is beskikbaar vir hergebruik.
2. **Spray IOSurface Objects**: Allokeer baie IOSurface objects met 'n unieke "magic value" in kernel memory. 2. **Spray IOSurface Objects**: Ken baie IOSurface objects toe met 'n unieke "magic value" in kernel memory.
3. **Identify Accessible IOSurface**: Lokaliseer 'n IOSurface op 'n vrygemaakte bladsy wat jy beheer. 3. **Identify Accessible IOSurface**: Lokaliseer 'n IOSurface op 'n vrygestelde bladsy wat jy beheer.
4. **Abuse Use-After-Free**: Wysig pointers in die IOSurface object om arbitraire **kernel read/write** via IOSurface-metodes moontlik te maak. 4. **Abuse Use-After-Free**: Wysig pointers in die IOSurface object om arbitrêre **kernel read/write** via IOSurface methods moontlik te maak.
Met hierdie primitiewe verskaf die exploit beheerde **32-bit reads** en **64-bit writes** na kernel memory. Verdere jailbreak-stappe kan meer stabiele read/write primitiewe behels, wat mag vereis dat addisionele beskermings omseil word (bv. PPL op nuwer arm64e devices). Met hierdie primitives verskaf die exploit beheerde **32-bit reads** en **64-bit writes** na kernel memory. Verdere jailbreak-stappe kan meer stabiele read/write primitives vereis, wat die omseiling van addisionele beskermings mag insluit (bv. PPL op nuwer arm64e-toestelle).
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}