iOS Exploiting

Reading time: 15 minutes

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

iOS Exploit Mitigations

  • Code Signing in iOS werk deur te vereis dat elke stuk uitvoerbare kode (apps, libraries, extensions, etc.) kriptografies geteken is met 'n sertifikaat uitgegee deur Apple. Wanneer kode gelaai word, verifieer iOS die digitale handtekening teen Apple se vertroude root. As die handtekening ongeldig, afwesig, of gewysig is, weier die OS om dit te laat loop. Dit keer dat aanvallers kwaadwillige kode in regmatige apps invoeg of unsigned binaries uitvoer, en blokkeer die meeste exploit chains wat staatmaak op die uitvoering van arbitrêre of gemanipuleerde kode.
  • CoreTrust is die iOS-substelsel verantwoordelik vir die afdwing van code signing by runtime. Dit verifieer handtekeninge direk met Apple se root-sertifikaat sonder om op gecachte trust-stores staat te maak, wat beteken slegs binaries wat deur Apple geteken is (of met geldige entitlements) kan uitgevoer word. CoreTrust verseker dat selfs as 'n aanvaller 'n app na installasie manipuleer, stelselbiblioteke wysig, of probeer om unsigned code te laai, die stelsel die uitvoering blokkeer tensy die kode nog steeds behoorlik geteken is. Hierdie streng afdwinging sluit baie post-exploitation vektore wat ouer iOS-weergawes deur swak of omseilbare handtekeningkontroles toegelaat het.
  • Data Execution Prevention (DEP) merk geheuegebiede as non-executable tensy hulle eksplisiet kode bevat. Dit keer dat aanvallers shellcode in data-gebiede (soos die stack of heap) invoeg en dit uitvoer, wat hulle dwing om op meer komplekse tegnieke soos ROP (Return-Oriented Programming) staat te maak.
  • ASLR (Address Space Layout Randomization) randomiseer die geheueadresse van kode, libraries, stack, en heap elke keer as die stelsel loop. Dit maak dit baie moeiliker vir aanvallers om te voorspel waar nuttige instruksies of gadgets is, en breek baie exploit chains wat staatmaak op vaste geheue-lêers.
  • KASLR (Kernel ASLR) pas dieselfde randomiseringskonsep toe op die iOS-kern. Deur die kern se basisadres by elke opstart te skud, voorkom dit dat aanvallers betroubaar kernel-funksies of strukture kan lokaliseer, en verhoog dit die moeilikheidsgraad van kernel-level exploits wat andersins volle stelselbeheer sou kry.
  • Kernel Patch Protection (KPP) ook bekend as AMCC (Apple Mobile File Integrity) in iOS, monitor kontinu die kern se kodebladsye om te verseker dat hulle nie gewysig is nie. As enige tampering opgespoor word—soos 'n exploit wat probeer kernel-funksies te patch of kwaadwillige kode in te voeg—sal die toestel onmiddellik panic en herbegin. Hierdie beskerming maak persistente kernel-exploits baie moeiliker, aangesien aanvallers nie bloot kernel-instruksies kan hook of patch sonder om 'n stelselkrash te veroorsaak nie.
  • Kernel Text Readonly Region (KTRR) is 'n hardware-gebaseerde sekuriteitsfunksie bekendgestel op iOS-toestelle. Dit gebruik die CPU se geheuebeheerder om die kern se kode (text) gedeelte na boot permanent as read-only te merk. Sodra dit vergrendel is, kan selfs die kern self nie hierdie geheuegebied wysig nie. Dit voorkom dat aanvallers—en selfs bevoegde kode—kernel-instruksies by runtime patch, en sluit 'n groot klas exploits wat direk op die wysiging van kernel-kode staatgemaak het, af.
  • Pointer Authentication Codes (PAC) gebruik kriptografiese handtekeninge ingebed in ongebruikte bite van pointers om hul integriteit voor gebruik te verifieer. Wanneer 'n pointer (soos 'n return address of funksiepointer) geskep word, teken die CPU dit met 'n geheime sleutel; voor dereferencing kontroleer die CPU die handtekening. As die pointer gemanipuleer is, misluk die kontrole en stop die uitvoering. Dit keer dat aanvallers vervalste of gekorrupte pointers in memory forgery of hergebruik, en maak tegnieke soos ROP of JOP baie moeiliker om betroubaar uit te voer.
  • Privilege Access never (PAN) is 'n hardware-funksie wat die kern (privileged mode) verhoed om direk toegang tot user-space geheue te kry tensy dit eksplisiet toegang aktiveer. Dit keer dat aanvallers wat kernel code execution verkry het maklik user memory kan lees of skryf om exploits op te skaal of sensitiewe data te steel. Deur strikte skeiding af te dwing, verminder PAN die impak van kernel-exploits en blokkeer baie algemene privilege-escalation tegnieke.
  • Page Protection Layer (PPL) is 'n iOS-sekuriteitsmeganisme wat kritieke kernel-beheerde geheuegebiede beskerm, veral dié wat verband hou met code signing en entitlements. Dit handhaaf streng write-beskermings deur die MMU (Memory Management Unit) en addisionele kontroles, en verseker dat selfs bevoegde kernel-kode nie arbitrary sensitiewe bladsye kan wysig nie. Dit maak dit moeiliker vir aanvallers wat kernel-level uitvoering verkry om sekuriteitskritieke strukture te manipuleer, en bemoeilik persistentie en code-signing omseilings aansienlik.

Old Kernel Heap (Pre-iOS 15 / Pre-A12 era)

Die kernel het 'n zone allocator (kalloc) gebruik wat in vaste-grootte "zones" verdeel is. Elke zone stoor slegs allocations van 'n enkele size class.

From the screenshot:

Zone NameElement SizeExample Use
default.kalloc.1616 bytesBaie klein kernel-structs, pointers.
default.kalloc.3232 bytesKlein structs, object headers.
default.kalloc.6464 bytesIPC messages, klein kernel buffers.
default.kalloc.128128 bytesMedium objects soos dele van OSObject.
default.kalloc.12801280 bytesGroot strukture, IOSurface/graphics metadata.

How it worked:

  • Elke allocation-versoek is na bo afgerond na die naaste zone-grootte. (Byv., 'n 50-byte versoek beland in die kalloc.64 zone).
  • Geheue in elke zone is in 'n freelist gehou — stukke wat deur die kernel vrygestel is, het terug in daardie zone gegaan.
  • As jy 'n 64-byte buffer overflow het, sou jy die volgende objek in dieselfde zone oorskryf.

Dit is waarom heap spraying / feng shui so effektief was: jy kon voorwerpbuurmanne voorspel deur toewysings van dieselfde grootteklas te maak.

The freelist

Binne elke kalloc zone is vrygestelde objekte nie direk aan die stelsel teruggegee nie — hulle het in 'n freelist gegaan, 'n gekoppelde lys van beskikbare stukke.

  • Wanneer 'n stuk vrygestel is, het die kernel 'n pointer by die begin van daardie stuk geskryf → die adres van die volgende vrye stuk in dieselfde zone.

  • Die zone het 'n HEAD-pointer gehou na die eerste vrye stuk.

  • Allocatie het altyd die huidige HEAD gebruik:

  1. Pop HEAD (gee daardie geheue terug aan die aanroeper).

  2. Werk HEAD by = HEAD->next (gestoor in die vrygestelde stuk se header).

  • Vrymaking stoot stukke terug:

  • freed_chunk->next = HEAD

  • HEAD = freed_chunk

So die freelist was net 'n gekoppelde lys gebou binne die vrygestelde geheue self.

Normal state:

Zone page (64-byte chunks for example):
[ A ] [ F ] [ F ] [ A ] [ F ] [ A ] [ F ]

Freelist view:
HEAD ──► [ F ] ──► [ F ] ──► [ F ] ──► [ F ] ──► NULL
(next ptrs stored at start of freed chunks)

Uitbuiting van die freelist

Omdat die eerste 8 bytes van 'n free chunk = freelist pointer, kan 'n aanvaller dit korrupteer:

  1. Heap overflow in 'n aangrensende freed chunk → oorskryf die “next” pointer daarvan.

  2. Use-after-free skryf in 'n freed object → oorskryf die “next” pointer daarvan.

Dan, by die volgende toewysing van daardie grootte:

  • Die allocator haal die gekorrupte chunk uit.

  • Volg die deur die aanvaller verskafde “next” pointer.

  • Gee 'n pointer terug na arbitrêre geheue, wat fake object primitives of targeted overwrite moontlik maak.

Visuele voorbeeld van freelist poisoning:

Before corruption:
HEAD ──► [ F1 ] ──► [ F2 ] ──► [ F3 ] ──► NULL

After attacker overwrite of F1->next:
HEAD ──► [ F1 ]
(next) ──► 0xDEAD_BEEF_CAFE_BABE  (attacker-chosen)

Next alloc of this zone → kernel hands out memory at attacker-controlled address.

Hierdie freelist-ontwerp het eksploitasies baie effektief gemaak voor hardening: voorspelbare bure vanaf heap sprays, raw pointer freelist links, en geen tipe-separasie het aanvallers toegelaat om UAF/overflow-bugs te eskaleer na arbitrêre kernel-geheuebeheer.

Heap Grooming / Feng Shui

Die doel van heap grooming is om die heap layout te vorm sodat wanneer 'n aanvaller 'n overflow of use-after-free veroorsaak, die teiken (slagoffer) objek reg langs 'n aanvaller-beheerde objek sit. Op dié manier, wanneer geheuekorruptie plaasvind, kan die aanvaller betroubaar die slagoffer-objek oorskryf met beheerde data.

Stappe:

  1. Spray allocations (fill the holes)
  • Mettertyd raak die kernel heap gefragmenteer: sommige zones het gatte waar ou objekte vrygestel is.
  • Die aanvaller maak eers baie dummy-allocations om hierdie gapings te vul, sodat die heap “gepak” en voorspelbaar word.
  1. Force new pages
  • Sodra die gapings gevul is, moet die volgende allocations vanaf nuwe pages by die zone kom.
  • Vars pages beteken dat objekte saamgekluster sal wees, nie versprei oor ou gefragmenteerde geheue nie.
  • Dit gee die aanvaller baie beter beheer oor bure.
  1. Place attacker objects
  • Die aanvaller spray weer en skep baie aanvaller-beheerde objekte in daardie nuwe pages.
  • Hierdie objekte is voorspelbaar in grootte en plasing (omdat hulle almal tot dieselfde zone behoort).
  1. Free a controlled object (make a gap)
  • Die aanvaller maak doelbewus een van hul eie objekte vry.
  • Dit skep 'n “gat” in die heap, wat die allocator later vir die volgende allocation van daardie grootte sal hergebruik.
  1. Victim object lands in the hole
  • Die aanvaller trigger nou die kernel om die slagoffer-objek (die een wat hulle wil korrupteer) te allokeer.
  • Aangesien die gat die eerste beskikbare slot in die freelist is, word die slagoffer presies geplaas waar die aanvaller hul objek vrygemaak het.
  1. Overflow / UAF into victim
  • Nou het die aanvaller aanvaller-beheerde objekte rondom die slagoffer.
  • Deur te overflow vanaf een van hul eie objekte (of deur 'n vrygemaakte een te hergebruik), kan hulle betroubaar die slagoffer se geheue-velde oorskryf met gekose waardes.

Hoekom dit werk:

  • Zone allocator voorspelbaarheid: allocations van dieselfde grootte kom altyd uit dieselfde zone.
  • Freelist behavior: nuwe allocations hergebruik die mees onlangs vrygemaakte chunk eerste.
  • Heap sprays: die aanvaller vul geheue met voorspelbare inhoud en beheer die uitleg.
  • Eindresultaat: die aanvaller beheer waar die slagoffer-objek land en watter data langs dit sit.

Moderne Kernel Heap (iOS 15+/A12+ SoCs)

Apple het die allocator gehard en maak heap grooming baie moeiliker:

1. From Classic kalloc to kalloc_type

  • Before: 'n enkele kalloc.<size> zone het bestaan vir elke grootteklas (16, 32, 64, … 1280, ens.). Enige objek van daardie grootte is daar geplaas → aanvaller-objekte kon langs bevoorregte kernel-objekte sit.
  • Now:
  • Kernel-objekte word geallokeer vanaf typed zones (kalloc_type).
  • Elke tipe objek (bv. ipc_port_t, task_t, OSString, OSData) het sy eie toegewyde zone, selfs al het hulle dieselfde grootte.
  • Die mapping tussen objektipe ↔ zone word gegenereer vanaf die kalloc_type system by compile-tyd.

'n Aanvaller kan nie meer waarborg dat beheerde data (OSData) langs sensitiewe kernel-objekte (task_t) van dieselfde grootte eindig nie.

2. Slabs and Per-CPU Caches

  • Die heap is verdeel in slabs (pages geheue wat in vaste-grootte stukke vir daardie zone gesny is).
  • Elke zone het 'n per-CPU cache om kontensie te verminder.
  • Allocation pad:
  1. Probeer per-CPU cache.
  2. As leeg, haal van die globale freelist.
  3. As freelist leeg is, allokeer 'n nuwe slab (een of meer pages).
  • Voordeel: Hierdie desentralisering maak heap sprays minder deterministies, aangesien allocations dalk vanaf verskillende CPU's se caches bevredig word.

3. Randomization inside zones

  • Binne 'n zone word vrygemaakte elemente nie in eenvoudige FIFO/LIFO volgorde teruggegee nie.
  • Moderne XNU gebruik encoded freelist pointers (safe-linking soos Linux, ingevoer ~iOS 14).
  • Elke freelist pointer is XOR-encoded met 'n per-zone geheime cookie.
  • Dit verhoed dat aanvallers 'n vals freelist pointer kan forge as hulle 'n write primitive kry.
  • Sommige allocations word gerandomiseer in hul plasing binne 'n slab, sodat spraying nie adjasensie waarborg nie.

4. Guarded Allocations

  • Sekere kritieke kernel-objekte (bv. credentials, task structures) word geallokeer in guarded zones.
  • Hierdie zones plaas guard pages (unmapped memory) tussen slabs of gebruik redzones rondom objekte.
  • Enige overflow in die guard page trigger 'n fout → onmiddellike panic in plaas van stille korrupsie.

5. Page Protection Layer (PPL) and SPTM

  • Selfs as jy 'n vrygemaakte objek beheer, kan jy nie al die kernel-geheue wysig nie:
  • PPL (Page Protection Layer) dwing af dat sekere gebiede (bv. code signing data, entitlements) read-only is selfs vir die kernel self.
  • Op A15/M2+ devices, word hierdie rol vervang/versterk deur SPTM (Secure Page Table Monitor) + TXM (Trusted Execution Monitor).
  • Hierdie hardware-afgedwonge lae beteken dat aanvallers nie van 'n enkele heap-korrupsie na arbitrêre patching van kritieke security structures kan eskaleer nie.

6. Large Allocations

  • Nie alle allocations gaan deur kalloc_type nie.
  • Baie groot versoeke (bo ~16KB) omseil typed zones en word direk vanuit kernel VM (kmem) via page allocations bedien.
  • Hierdie is minder voorspelbaar, maar ook minder uitbuitbaar, aangesien hulle nie slabs met ander objekte deel nie.

7. Allocation Patterns Attackers Target

Selfs met hierdie beskermings soek aanvallers steeds na:

  • Reference count objects: as jy retain/release tellers kan manipuleer, kan jy use-after-free veroorsaak.
  • Objects with function pointers (vtables): die korruptering van een gee steeds control flow.
  • Shared memory objects (IOSurface, Mach ports): hierdie bly aanvalsbates omdat hulle user ↔ kernel bridging doen.

Maar — anders as voorheen — jy kan nie net OSData spray en verwag dat dit langs task_t beland nie. Jy het type-specific bugs of info leaks nodig om sukses te behaal.

Example: Allocation Flow in Modern Heap

Suppose userspace calls into IOKit to allocate an OSData object:

  1. Type lookupOSData maps to kalloc_type_osdata zone (size 64 bytes).
  2. Check per-CPU cache for free elements.
  • If found → return one.
  • If empty → go to global freelist.
  • If freelist empty → allocate a new slab (page of 4KB → 64 chunks of 64 bytes).
  1. Return chunk to caller.

Freelist pointer protection:

  • Each freed chunk stores the address of the next free chunk, but encoded with a secret key.
  • Overwriting that field with attacker data won’t work unless you know the key.

Comparison Table

FeatureOld Heap (Pre-iOS 15)Modern Heap (iOS 15+ / A12+)
Allocation granularityFixed size buckets (kalloc.16, kalloc.32, etc.)Size + type-based buckets (kalloc_type)
Placement predictabilityHigh (same-size objects side by side)Low (same-type grouping + randomness)
Freelist managementRaw pointers in freed chunks (easy to corrupt)Encoded pointers (safe-linking style)
Adjacent object controlEasy via sprays/frees (feng shui predictable)Hard — typed zones separate attacker objects
Kernel data/code protectionsFew hardware protectionsPPL / SPTM protect page tables & code pages
Exploit reliabilityHigh with heap spraysMuch lower, requires logic bugs or info leaks

(Old) Physical Use-After-Free via IOSurface

ios Physical UAF - IOSurface


Ghidra Install BinDiff

Download BinDiff DMG from https://www.zynamics.com/bindiff/manual and install it.

Open Ghidra with ghidraRun and go to File --> Install Extensions, druk die add-knoppie en kies die pad /Applications/BinDiff/Extra/Ghidra/BinExport en klik OK en isntall it even if there is a version mismatch.

Using BinDiff with Kernel versions

  1. Go to the page https://ipsw.me/ and download the iOS versions you want to diff. These will be .ipsw files.
  2. Decompress until you get the bin format of the kernelcache of both .ipsw files. You have information on how to do this on:

macOS Kernel Extensions & Debugging

  1. Open Ghidra with ghidraRun, create a new project and load the kernelcaches.
  2. Open each kernelcache so they are automatically analyzed by Ghidra.
  3. Then, on the project Window of Ghidra, right click each kernelcache, select Export, select format Binary BinExport (v2) for BinDiff and export them.
  4. Open BinDiff, create a new workspace and add a new diff indicating as primary file the kernelcache that contains the vulnerability and as secondary file the patched kernelcache.

Finding the right XNU version

If you want to check for vulnerabilities in a specific version of iOS, you can check which XNU release version the iOS version uses at [https://www.theiphonewiki.com/wiki/kernel]https://www.theiphonewiki.com/wiki/kernel).

For example, the versions 15.1 RC, 15.1 and 15.1.1 use the version Darwin Kernel Version 21.1.0: Wed Oct 13 19:14:48 PDT 2021; root:xnu-8019.43.1~1/RELEASE_ARM64_T8006.

iMessage/Media Parser Zero-Click Chains

Imessage Media Parser Zero Click Coreaudio Pac Bypass

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks