iOS Exploiting
Tip
Jifunze na fanya mazoezi ya AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
iOS Exploit Mitigations
1. Code Signing / Runtime Signature Verification
Introduced early (iPhone OS → iOS) Hili ni mojawapo ya ulinzi wa msingi: all executable code (apps, dynamic libraries, JIT-ed code, extensions, frameworks, caches) lazima iiswe kwa kadi ya kielektroniki (cryptographically signed) na mnyororo wa vyeti uliotokana na imani ya Apple. Wakati wa runtime, kabla ya kupakia binary kwenye memory (au kabla ya kufanya jumps kwa mipaka fulani), mfumo unakagua signature yake. Ikiwa code imerekebishwa (bit-flipped, patched) au haijasainiwa, load inashindwa.
- Thwarts: hatua ya “classic payload drop + execute” katika exploit chains; arbitrary code injection; kubadilisha binary iliyopo ili kuingiza logic ya kibaya.
- Mechanism detail:
- The Mach-O loader (and dynamic linker) inakagua code pages, segments, entitlements, team IDs, na kwamba signature inashughulikia yaliyomo kwenye file.
- Kwa memory regions kama JIT caches au dynamically generated code, Apple inasimamia kwamba pages zisainwe au zihakikiwe kupitia APIs maalum (mfano
mprotectwith code-sign checks). - Signature inajumuisha entitlements na identifiers; OS inahakikisha kwamba APIs fulani au uwezo wenye privilage zinahitaji entitlements maalum ambazo haziwezi kuiga.
Example
Fikiria exploit inapata code execution katika process na inajaribu kuandika shellcode kwenye heap na kuruka hadi hiyo address. Kwenye iOS, page hiyo ingehitaji kuwekewa flag executable **na** kukidhi vigezo vya code-signature. Kwa kuwa shellcode haijasainiwa na certificate ya Apple, jump itashindwa au mfumo utakataa kufanya region hiyo ya memory kuwa executable.2. CoreTrust
Introduced around iOS 14+ era (or gradually in newer devices / later iOS) CoreTrust ni subsystem inayofanya runtime signature validation ya binaries (pamoja na system na user binaries) dhidi ya Apple’s root certificate badala ya kutegemea cached userland trust stores.
- Thwarts: post-install tampering ya binaries, jailbreak techniques zinazojaribu kubadilisha au ku-patch system libraries au user apps; kuudanganya mfumo kwa kubadilisha trusted binaries kwa vipengele vya kibaya.
- Mechanism detail:
- Badala ya kuamini local trust database au certificate cache, CoreTrust hurejea au kuthibitisha Apple’s root moja kwa moja au kuthibitisha intermediate certificates katika chain salama.
- Inahakikisha kwamba mabadiliko (mfano kwenye filesystem) kwa binaries zilizopo yanatambuliwa na yakatupwe.
- Inafunga entitlements, team IDs, code signing flags, na metadata nyingine kwenye binary wakati wa load.
Example
Jailbreak inaweza kujaribu kubadilisha `SpringBoard` au `libsystem` kwa version iliyopachikwa ili kupata persistence. Lakini wakati loader ya OS au CoreTrust inakatazama, inagundua mismatch ya signature (au entitlements zilizorekebishwa) na inakataa kuendesha.3. Data Execution Prevention (DEP / NX / W^X)
Introduced in many OSes earlier; iOS had NX-bit / w^x for a long time DEP inasimamia kwamba pages zilizowekwa writable (kwa data) zisiwe executable, na pages zilizowekwa executable zisiwe writable. Huwezi tu kuandika shellcode kwenye heap au stack na kuirexecute.
- Thwarts: direct shellcode execution; classic buffer-overflow → jump to injected shellcode.
- Mechanism detail:
- The MMU / memory protection flags (via page tables) zinafanya utofauti huo.
- Jaribio lolote la kuweka writable page kuwa executable hufanya system check (na inakatazwa au inahitaji code-sign approval).
- Mara nyingi, kufanya pages ziwe executable kunahitaji kupitia OS APIs ambazo zinaweka constraints au checks za ziada.
Example
Overflow inaandika shellcode kwenye heap. Mshambuliaji anajaribu `mprotect(heap_addr, size, PROT_EXEC)` ili kuiweka executable. Lakini mfumo unakataza au unathibitisha kuwa page mpya lazima ipitie code-sign constraints (ambazo shellcode haiwezi).4. Address Space Layout Randomization (ASLR)
Introduced in iOS ~4–5 era (roughly iOS 4–5 timeframe) ASLR inarandamiza base addresses za memory regions muhimu: libraries, heap, stack, n.k., kila kuanzishwa kwa process. Addresses za gadgets hubadilika kati ya runs.
- Thwarts: hardcoding gadget addresses kwa ROP/JOP; static exploit chains; kuruka kwa blind hadi offsets zilizojulikana.
- Mechanism detail:
- Kila loaded library / dynamic module inarebased kwa randomized offset.
- Stack na heap base pointers zinapewa randomness (chini ya entropy fulani).
- Wakati mwingine regions nyingine (mfano mmap allocations) pia zinarandamizwa.
- Ikiwa imeunganishwa na mitigations za information-leak, inalazimisha mshambuliaji kwanza ku-leak an address au pointer ili kugundua base addresses wakati wa runtime.
Example
ROP chain inategemea gadget kwenye `0x….lib + offset`. Lakini kwa kuwa `lib` imerebased kwa njia tofauti kila run, chain iliyowekwa haifanyi kazi. Exploit lazima kwanza i-leak base address ya module kabla ya kuhesabu gadget addresses.5. Kernel Address Space Layout Randomization (KASLR)
Introduced in iOS ~ (iOS 5 / iOS 6 timeframe) Kama ASLR ya userland, KASLR inarandamiza base ya kernel text na structure nyingine za kernel wakati wa boot.
- Thwarts: kernel-level exploits zinazotegemea location fasta ya kernel code au data; static kernel exploits.
- Mechanism detail:
- Kila boot, base address ya kernel inarandamizwa (ndani ya range).
- Kernel data structures (kama
task_structs,vm_map, n.k.) pia zinaweza kuhamishwa au kupata offsets. - Washambuliaji lazima kwanza wa-leak kernel pointers au kutumia information disclosure vulnerabilities ili kuhesabu offsets kabla ya kukabiliana na kernel structures au code.
Example
Vulnerability ya local inalenga kuharibu kernel function pointer (mfano katika `vtable`) kwenye `KERN_BASE + offset`. Lakini kwa kuwa `KERN_BASE` haijulikani, mshambuliaji lazima a-leak kwanza (mfano kupitia read primitive) kabla ya kuhesabu address sahihi ya kufanya corruption.6. Kernel Patch Protection (KPP / AMCC)
Introduced in newer iOS / A-series hardware (post around iOS 15–16 era or newer chips) KPP (aka AMCC) inashika uadilifu wa kernel text pages (kwa hash au checksum). Ikiwa inagundua tampering (patches, inline hooks, code modifications) nje ya windows zilizokubaliwa, inasababisha kernel panic au reboot.
- Thwarts: persistent kernel patching (kurekebisha kernel instructions), inline hooks, static function overwrites.
- Mechanism detail:
- Module ya hardware au firmware inafuatilia kernel text region.
- Mara kwa mara au kwa mahitaji inarashidisha pages na ikilinganisha na values zinazotarajiwa.
- Iwapo kuna mismatch nje ya windows za updates zenye faida, inapanic device (ili kuzuia patch yenye madhumuni mabaya).
- Washambuliaji lazima waepuke detection windows au watumie legitimate patch paths.
Example
Exploit inajaribu ku-patch kernel function prologue (mfano `memcmp`) ili kuingilia ant calls. Lakini KPP inagundua kuwa hash ya code page hailetei na inasababisha kernel panic, ikirusha device kabla patch haijaweza kusimama.7. Kernel Text Read‐Only Region (KTRR)
Introduced in modern SoCs (post ~A12 / newer hardware) KTRR ni mechanism iliyotekelezwa kwa hardware: mara kernel text inafungwa mapema wakati wa boot, inakuwa read-only kutoka EL1 (the kernel), ikizuia uandishi zaidi wa code pages.
- Thwarts: mabadiliko yoyote ya kernel code baada ya boot (mfano patching, in-place code injection) kwa level ya privilage EL1.
- Mechanism detail:
- Wakati wa boot (katika secure/bootloader stage), memory controller (au unit ya hardware salama) inaweka physical pages za kernel text kama read-only.
- Hata kama exploit inapata full kernel privileges, haiwezi kuandika kwenye pages hizo ili ku-patch instructions.
- Ili kuzibadilisha, mshambuliaji lazima kwanza a-kompromaiti boot chain, au ku-subvert KTRR yenyewe.
Example
Privilege-escalation exploit inaruka ndani ya EL1 na kuandika trampoline kwenye kernel function (mfano katika `syscall` handler). Lakini kwa kuwa pages zimefungwa read-only na KTRR, write inashindwa (au inachochea fault), hivyo patches hazitatekelezwa.8. Pointer Authentication Codes (PAC)
Introduced with ARMv8.3 (hardware), Apple beginning with A12 / iOS ~12+
- PAC ni feature ya hardware iliyowasilishwa kwenye ARMv8.3-A ili kugundua uharibifu wa pointer values (return addresses, function pointers, certain data pointers) kwa kuweka sahihi ndogo ya cryptographic (MAC) katika bits za juu zisizotumika za pointer.
- Sahihi (“PAC”) hupatikana kwa pointer value pamoja na modifier (context value, mf: stack pointer au data nyingine). Hivyo pointer ile ile katika contexts tofauti inapata PAC tofauti.
- Wakati wa matumizi, kabla ya kufanya dereference au branch kwa pointer hiyo, instruction ya authenticate inakagua PAC. Ikiwa sahihi, PAC inaondolewa na pointer safi inapatikana; ikiwa sio, pointer inakuwa “poisoned” (au fault inazinduliwa).
- Keys zinazotumika kwa kuunda/kuhakiki PAC zinaishi katika privileged registers (EL1, kernel) na hazipatikani kutoka user mode.
- Kwa sababu si bits zote za 64-bit zinatumika katika address space nyingi (mfano 48-bit), bits za juu ni “spare” na zinaweza kubeba PAC bila kubadilisha effective address.
Architectural Basis & Key Types
-
ARMv8.3 inatambulisha five 128-bit keys (kila moja ikitekelezwa kupitia two 64-bit system registers) kwa pointer authentication.
-
APIAKey — kwa instruction pointers (domain “I”, key A)
-
APIBKey — key ya pili ya instruction pointer (domain “I”, key B)
-
APDAKey — kwa data pointers (domain “D”, key A)
-
APDBKey — kwa data pointers (domain “D”, key B)
-
APGAKey — key “generic”, kwa kusaini non-pointer data au matumizi mengine ya generic
-
Keys hizi zimo katika privileged system registers (inazopatikana tu katika EL1/EL2 n.k.), hazipatikani kutoka user mode.
-
PAC hukadiriwa kwa njia ya cryptographic (ARM inapendekeza QARMA kama algorithm) kutumia:
- The pointer value (canonical portion)
- A modifier (context value, kama salt)
- The secret key
- Taaratibu za ndani za tweak Ikiwa PAC inayotokana inafanana na ile iliyowekwa kwenye bits za juu za pointer, authentication inafanikiwa.
Instruction Families
Naming convention ni: PAC / AUT / XPAC, kisha herufi za domain.
PACxxinstructions sign pointer na kuweka PACAUTxxinstructions authenticate + strip (thibitisha na ondoa PAC)XPACxxinstructions strip bila validating
Domains / suffixes:
| Mnemonic | Meaning / Domain | Key / Domain | Example Usage in Assembly |
|---|---|---|---|
| PACIA | Sign instruction pointer with APIAKey | “I, A” | PACIA X0, X1 — sign pointer in X0 using APIAKey with modifier X1 |
| PACIB | Sign instruction pointer with APIBKey | “I, B” | PACIB X2, X3 |
| PACDA | Sign data pointer with APDAKey | “D, A” | PACDA X4, X5 |
| PACDB | Sign data pointer with APDBKey | “D, B” | PACDB X6, X7 |
| PACG / PACGA | Generic (non-pointer) signing with APGAKey | “G” | PACGA X8, X9, X10 (sign X9 with modifier X10 into X8) |
| AUTIA | Authenticate APIA-signed instruction pointer & strip PAC | “I, A” | AUTIA X0, X1 — check PAC on X0 using modifier X1, then strip |
| AUTIB | Authenticate APIB domain | “I, B” | AUTIB X2, X3 |
| AUTDA | Authenticate APDA-signed data pointer | “D, A” | AUTDA X4, X5 |
| AUTDB | Authenticate APDB-signed data pointer | “D, B” | AUTDB X6, X7 |
| AUTGA | Authenticate generic / blob (APGA) | “G” | AUTGA X8, X9, X10 (validate generic) |
| XPACI | Strip PAC (instruction pointer, no validation) | “I” | XPACI X0 — remove PAC from X0 (instruction domain) |
| XPACD | Strip PAC (data pointer, no validation) | “D” | XPACD X4 — remove PAC from data pointer in X4 |
There are specialized / alias forms:
PACIASPis shorthand forPACIA X30, SP(sign the link register using SP as modifier)AUTIASPisAUTIA X30, SP(authenticate link register with SP)- Combined forms like
RETAA,RETAB(authenticate-and-return) orBLRAA(authenticate & branch) exist in ARM extensions / compiler support. - Also zero-modifier variants:
PACIZA/PACIZBwhere the modifier is implicitly zero, etc.
Modifiers
Lengo kuu la modifier ni kufunga PAC kwa context maalum ili address ile ile iliyosainiwa katika contexts tofauti ipate PAC tofauti. Hii inazuia reuse rahisi ya pointer across frames au objects. Ni kama kuongeza salt kwenye hash.
Kwa hivyo:
- modifier ni context value (reg nyingine) ambayo inachanganywa katika ugawaji wa PAC. Chaguo za kawaida: stack pointer (
SP), frame pointer, au object ID. - Kutumia SP kama modifier ni kawaida kwa return address signing: PAC inafungwa kwa stack frame maalum. Ukijaribu kutumia LR katika frame tofauti, modifier hubadilika, hivyo PAC validation inashindwa.
- Pointer ile ile iliyosainiwa kwa modifiers tofauti inatoa PAC tofauti.
- Modifier haifai kuwa siri, lakini ni bora isiwe inakontrolliwa na mshambuliaji.
- Kwa instructions zinazofanya sign/verify pointers ambapo hakuna modifier muhimu, baadhi za form hutumia zero au constant iliyokamilishwa.
Apple / iOS / XNU Customizations & Observations
- Apple implementation ya PAC inajumuisha per-boot diversifiers ili keys au tweaks zibadilike kila boot, kuzuia reuse across boots.
- Wanao pia cross-domain mitigations ili PAC zilizotumwa katika user mode zisizitumike kwa urahisi katika kernel mode, n.k.
- Kwenye Apple M1 / Apple Silicon, reverse engineering ilionyesha kwamba kuna nine modifier types na system registers za Apple kwa control ya keys.
- Apple inatumia PAC katika subsystems nyingi za kernel: return address signing, pointer integrity katika kernel data, signed thread contexts, n.k.
- Google Project Zero ilionyesha jinsi chini ya read/write primitives zenye nguvu za memory katika kernel, mtu angeweza kuforge kernel PACs (kwa A keys) kwenye A12-era devices, lakini Apple ilirekebisha njia nyingi hizo.
- Kwenye system ya Apple, baadhi ya keys ni global across kernel, wakati processes za user zinaweza kupata randomness ya per-process keys.
PAC Bypasses
- Kernel-mode PAC: theoretical vs real bypasses
- Kwa sababu kernel PAC keys na logic zimewekwa kwa karibu (privileged registers, diversifiers, domain isolation), kuforge arbitrary signed kernel pointers ni ngumu sana.
- Azad’s 2020 “iOS Kernel PAC, One Year Later” inaripoti kwamba katika iOS 12-13, alikuta bypasses chache za part (signing gadgets, reuse of signed states, unprotected indirect branches) lakini hakuna bypass ya generic kabisa. bazad.github.io
- Apple “Dark Magic” customizations zimepunguza zaidi surfaces zinazoweza kutumika (domain switching, per-key enabling bits). i.blackhat.com
- Kuna CVE-2023-32424 inayojulikana ya kernel PAC bypass kwenye Apple silicon (M1/M2) iliyoripotiwa na Zecao Cai et al. i.blackhat.com
- Lakini bypasses hizi mara nyingi zinategemea gadgets maalum au bugs za implementation; si bypass zote za kimsingi.
Kwa hivyo kernel PAC inachukuliwa kuwa highly robust, ingawa si kamilifu.
- User-mode / runtime PAC bypass techniques
Hizi ni za kawaida zaidi, na zinachukua nafasi ya mapungufu katika matumizi ya PAC kwenye dynamic linking / runtime frameworks. Hapa chini ni aina, kwa mifano.
2.1 Shared Cache / A key issues
-
The dyld shared cache ni blob kubwa iliyolinkiwa mapema ya system frameworks na libraries. Kwa sababu inashirikiwa sana, function pointers ndani ya shared cache zimekuwa “pre-signed” na kutumika na processes nyingi. Washambuliaji wanawalenga pointers hizi zilizosainiwa kama “PAC oracles”.
-
Baadhi ya bypass techniques hujaribu kutoa au kureuse A-key signed pointers zilizomo katika shared cache na kuzitumia katika gadgets.
-
Mzungumzo wa “No Clicks Required” unaelezea jinsi ya kujenga oracle juu ya shared cache ili kubaini relative addresses na kuziingiza na signed pointers ili ku-pasua PAC. saelo.github.io
-
Pia, imports za function pointers kutoka shared libraries katika userspace zilipatikana kuwa hazilindwa vya kutosha na PAC, kuruhusu mshambuliaji kupata function pointers bila kubadilisha signature. (Project Zero bug entry) bugs.chromium.org
2.2 dlsym(3) / dynamic symbol resolution
-
Bypass mojawapo inayojulikana ni kupiga
dlsym()kupata function pointer ambayo tayari imesasishwa (already signed) (signed with A-key, diversifier zero) kisha kuitumia. Kwa sababudlsyminarudisha legitimately signed pointer, kutumia hiyo pointer kunaweza kuepusha hitaji la kuforge PAC. -
Blog ya Epsilon inaelezea jinsi baadhi ya bypasses zinatumia hili: kupiga
dlsym("someSym")hurudisha signed pointer na inaweza kutumiwa kwa indirect calls. blog.epsilon-sec.com -
Synacktiv “iOS 18.4 — dlsym considered harmful” inaelezea bug: baadhi ya symbols zilizotatuliwa kupitia
dlsymkwenye iOS 18.4 zinarudisha pointers zilizosainiwa vibaya (au na diversifiers buggy), kuruhusu PAC bypass isiyokusudiwa. Synacktiv -
Logic ya dyld kwa dlsym inajumuisha: wakati
result->isCode, wanamsign pointer iliyorejeshwa na__builtin_ptrauth_sign_unauthenticated(..., key_asia, 0), yaani context zero. blog.epsilon-sec.com
Hivyo, dlsym ni vector ya mara kwa mara katika user-mode PAC bypasses.
2.3 Other DYLD / runtime relocations
-
DYLD loader na dynamic relocation logic ni ngumu na wakati mwingine inamepuka mapping pages kama read/write ili kufanya relocations, kisha kuzirudisha kuwa read-only. Washambuliaji hutumia windows hizi. Hotuba za Synacktiv zinaelezea “Operation Triangulation”, bypass inayotegemea timing kwa PAC kupitia dynamic relocations. Synacktiv
-
DYLD pages sasa zinalindwa na SPRR / VM_FLAGS_TPRO (bila baadhi za protection flags kwa dyld). Lakini matoleo ya awali yalikuwa na ulinzi dhaifu. Synacktiv
-
Katika WebKit exploit chains, DYLD loader mara nyingi ni lengo la PAC bypass. Slides zinaelezea kuwa PAC bypass nyingi zimewalenga DYLD loader (kupitia relocation, interposer hooks). Synacktiv
2.4 NSPredicate / NSExpression / ObjC / SLOP
-
Katika userland exploit chains, Objective-C runtime methods kama
NSPredicate,NSExpressionauNSInvocationzinatumika kusafirisha simu za control bila kuonekana wazi pointer forging. -
Kwenye iOS zamani (kabla ya PAC), exploit ilitumia fake NSInvocation objects kupiga selectors yoyote kwenye memory iliyodhibitiwa. Kwa PAC, inahitaji marekebisho. Lakini tekniki ya SLOP (SeLector Oriented Programming) imetumiwa pia chini ya PAC. Project Zero
-
Mbinu ya asili ya SLOP iliruhusu kuunganisha ObjC calls kwa kuunda fake invocations; bypass inategemea kwamba ISA au selector pointers mara nyingine hazilindwa kikamilifu na PAC. Project Zero
-
Katika mazingira ambapo pointer authentication imewekwa kwa sehemu, methods / selectors / target pointers inaweza isizidi kuwa na ulinzi wa PAC, ikitoa nafasi ya bypass.
Example Flow
Example Signing & Authenticating
``` ; Example: function prologue / return address protection my_func: stp x29, x30, [sp, #-0x20]! ; push frame pointer + LR mov x29, sp PACIASP ; sign LR (x30) using SP as modifier ; … body … mov sp, x29 ldp x29, x30, [sp], #0x20 ; restore AUTIASP ; authenticate & strip PAC ret; Example: indirect function pointer stored in a struct ; suppose X1 contains a function pointer PACDA X1, X2 ; sign data pointer X1 with context X2 STR X1, [X0] ; store signed pointer
; later retrieval: LDR X1, [X0] AUTDA X1, X2 ; authenticate & strip BLR X1 ; branch to valid target
; Example: stripping for comparison (unsafe) LDR X1, [X0] XPACI X1 ; strip PAC (instruction domain) CMP X1, #some_label_address BEQ matched_label
</details>
<details>
<summary>Mfano</summary>
A buffer overflow inaandika juu anwani ya kurudi kwenye stack. Mshambuliaji anaandika anwani ya gadget inayolengwa lakini hawezi kuhesabu PAC sahihi. Wakati kazi inarudisha, maagizo ya CPU `AUTIA` yanatoa hitilafu kwa sababu ya kutofanana kwa PAC. Mnyororo unashindwa.
Project Zero’s analysis on A12 (iPhone XS) ilionyesha jinsi Apple’s PAC inavyotumiwa na mbinu za kutengeneza PAC ikiwa mshambuliaji ana memory read/write primitive.
</details>
### 9. **Branch Target Identification (BTI)**
**Introduced with ARMv8.5 (later hardware)**
BTI ni kipengele cha hardware kinachokagua **indirect branch targets**: wakati `blr` au indirect calls/jumps zinaendeshwa, lengo lazima lianze na **BTI landing pad** (`BTI j` au `BTI c`). Kuruka ndani ya anwani za gadget ambazo hazina landing pad husababisha exception.
LLVM’s implementation inatoa variants tatu za maagizo ya BTI na jinsi zinavyolingana na aina za branch.
| BTI Variant | What it permits (which branch types) | Typical placement / use case |
|-------------|----------------------------------------|-------------------------------|
| **BTI C** | Targets of *call*-style indirect branches (e.g. `BLR`, or `BR` using X16/X17) | Weka mwanzoni mwa functions ambazo zinaweza kuitwa indirectly |
| **BTI J** | Targets of *jump*-style branches (e.g. `BR` used for tail calls) | Iwekwa mwanzoni mwa blocks zinazofikiwa kwa njia ya jump tables au tail-calls |
| **BTI JC** | Acts as both C and J | Inaweza kulengwa na call au jump branches |
- Katika code iliyotengenezwa na branch target enforcement, compilers huingiza maagizo ya BTI (C, J, au JC) kwenye kila indirect-branch target halali (mwanzo wa functions au blocks zinazofikiwa kwa jumps) ili indirect branches zifanye kazi tu kwa maeneo hayo.
- **Direct branches / calls** (yaani anwani zenye fixed `B`, `BL`) **hazijafungwa** na BTI. Dhana ni kwamba code pages zinaaminika na mshambuliaji hawezi kuzibadilisha (hivyo direct branches ni salama).
- Pia, maagizo ya **RET / return** kwa kawaida hayafungwa na BTI kwa sababu anwani za return zinatakiwa zilitengenezwe kutoka PAC au mekanimu za return signing.
#### Mechanism and enforcement
- Wakati CPU inatafsiri **indirect branch (BLR / BR)** kwenye ukurasa uliotambulika kama “guarded / BTI-enabled,” inakagua kama maagizo ya kwanza ya anwani ya lengo ni BTI halali (C, J, au JC kama inaruhusiwa). Ikiwa siyo, hutokea **Branch Target Exception**.
- Encoding ya BTI imeundwa kutumia opcodes zilizokuwapo kama NOPs (katika matoleo ya awali ya ARM). Hivyo binaries zilizo BTI-enabled zinabaki backward-compatible: kwenye hardware bila BTI, maagizo hayo yanachukuliwa kama NOPs.
- Compiler passes zinazoongeza BTIs zinaweka hivyo tu pale zinapohitajika: functions ambazo zinaweza kuitwa indirectly, au basic blocks zinazolengwa na jumps.
- Baadhi ya patches na code za LLVM zinaonyesha kwamba BTI haingizwa kwa *blocks zote* — ni kwa zile tu zilizo potential branch targets (kwa mfano kutoka switch / jump tables).
#### BTI + PAC synergy
PAC inalinda thamani ya pointer (chanzo) — inahakikisha mnyororo wa indirect calls / returns haujarushwa kwa mabadiliko.
BTI inahakikisha kwamba hata pointer halali lazima inalenga tu entry points zilizo sahihi zilizo na alama.
Pamoja, mshambuliaji anahitaji pointer halali yenye PAC sahihi na kwamba lengo linapaswa kuwa na BTI iliyowekwa hapo. Hii inafanya iwe ngumu zaidi kutengeneza gadgets za exploit.
#### Mfano
<details>
<summary>Mfano</summary>
Exploit inajaribu kupeleka mtiririko kwa gadget kwenye `0xABCDEF` ambayo haianzi na `BTI c`. CPU, inapotekeleza `blr x0`, inakagua lengo na inakataza kwa sababu rasilimali za maagizo hazijumuishi landing pad halali. Kwa hivyo gadgets nyingi zinakuwa zisizotumika isipokuwa zinapopewa prefix ya BTI.
</details>
### 10. **Privileged Access Never (PAN) & Privileged Execute Never (PXN)**
**Introduced in more recent ARMv8 extensions / iOS support (for hardened kernel)**
#### PAN (Privileged Access Never)
- **PAN** ni kipengele kilichotolewa katika **ARMv8.1-A** kinachozuia **privileged code** (EL1 au EL2) kutoka **kusoma au kuandika** kumbukumbu iliyoainishwa kama **user-accessible (EL0)**, isipokuwa PAN imezimwa wazi.
- Wazo ni kwamba: hata kama kernel imepotoshwa au kuibiwa, haiwezi ku-referenz pointer za user-space bila kwanza *kuzima* PAN, hivyo kupunguza hatari za exploits za `ret2usr` au matumizi mabaya ya buffers zinazoendeshwa na user.
- Wakati PAN imewekwa (PSTATE.PAN = 1), maagizo yoyote ya privileged load/store yanayofikia anwani ya virtual iliyo “accessible at EL0” yatasababisha **permission fault**.
- Kernel, inapohitaji kwa mujibu kusoma/kuandika memory ya user (mf. copy data to/from user buffers), lazima **waziie muda mfupi PAN** (au tumia maagizo “unprivileged load/store”) ili kuruhusu ufikiaji huo.
- Katika Linux kwenye ARM64, msaada wa PAN ulianzishwa karibu 2015: patches za kernel ziliunda ugunduzi wa kipengele, na kubadilisha `get_user` / `put_user` n.k. na matoleo ambayo yanafuta PAN wakati wa ufikiaji wa memory ya user.
**Nuance / limitation / bug muhimu**
- Kama ilivyotajwa na Siguza na wengine, kasoro ya spec (au tabia isiyo wazi) katika muundo wa ARM inamaanisha kwamba **execute-only user mappings** (`--x`) huenda **zisizowafanya PAN kazi**. Kwa maneno mengine, kama ukurasa wa user umewekwa executable lakini bila ruhusa ya kusoma, jaribio la kernel kusoma linaweza kupitisha PAN kwa sababu usanifu unaweza kuchukulia “accessible at EL0” kuhitaji ruhusa ya kusoma, si tu execute. Hii inatoa njia ya kupitisha PAN katika usanifu fulani.
- Kwa sababu hiyo, ikiwa iOS / XNU inaruhusu execute-only user pages (kama baadhi ya JIT au code-cache setups zinavyoweza), kernel inaweza kusoma kutoka kwao hata PAN ikiwa imeamilishwa. Hii ni eneo la tahadhari linalojulikana katika baadhi ya mifumo ya ARMv8+.
#### PXN (Privileged eXecute Never)
- **PXN** ni bit ya page table (katika entries za page table, leaf au block entries) inayosema kuwa ukurasa hauwezi kutekelezwa kwa mode ya privileged (yaani wakati EL1 inafanya execute).
- PXN inazuia kernel (au code yoyote ya privileged) kujumia ndani au kutekeleza maagizo kutoka kwa page za user hata kama control imehamishwa. Kwa kufanya hivyo, inazuia redirection ya control-flow kwenye code ya user kutoka kwa kernel.
- Pamoja na PAN, hii inahakikisha kwamba:
1. Kernel haiwezi (kwa default) kusoma au kuandika data ya user (PAN)
2. Kernel haiwezi kutekeleza code ya user (PXN)
- Katika format ya ARMv8 page table, entries za leaf zina bit `PXN` (na pia `UXN` kwa unprivileged execute-never) katika bits za mali.
Hivyo hata kama kernel ina function pointer iliyoharibika inayolenga memory ya user, na ilijaribu kuruka huko, bit ya PXN itasababisha fault.
#### Memory-permission model & how PAN and PXN map to page table bits
Ili kuelewa jinsi PAN / PXN zinavyofanya kazi, unahitaji kuona jinsi ARM inavyofanya translation na modeli ya ruhusa (imefupishwa):
- Kila page au block entry ina fields za mali zikiwemo **AP[2:1]** kwa ruhusa za upatikanaji (kusoma/kuandika, privileged vs unprivileged) na bits **UXN / PXN** kwa vizuizi vya execute-never.
- Wakati PSTATE.PAN ni 1 (imewezeshwa), hardware inatekeleza semantics zilizobadilishwa: ufikiaji wa privileged kwa pages zilizotambuliwa kama “accessible by EL0” (yaani user-accessible) unazuiwa (fault).
- Kwa sababu ya kasoro iliyotajwa, pages zilizowekwa execute-only (bila ruhusa ya kusoma) huenda zisitambuliwe kama “accessible by EL0” katika utekelezaji fulani, hivyo kupitisha PAN.
- Wakati PXN ya ukurasa imewekwa, hata kama instruction fetch inakuja kutoka privilege level ya juu, utekelezaji unakataliwa.
#### Matumizi ya kernel ya PAN / PXN katika OS iliyoimarishwa (mf. iOS / XNU)
Katika muundo wa kernel uliothibitishwa (kama vile Apple inaweza kutumia):
- Kernel inamilisha PAN kwa default (hivyo code ya privileged imewekwa kwa mipaka).
- Katika njia ambazo zinahitaji kwa mujibu kusoma au kuandika buffers za user (mf. syscall buffer copy, I/O, read/write user pointer), kernel inakataza PAN kwa muda (au inatumia maagizo maalum) ili kuruhusu ufikiaji.
- Baada ya kumaliza ufikiaji wa data ya user, lazima itumie tena PAN.
- PXN inatekelezwa kupitia page tables: user pages zina PXN = 1 (hivyo kernel haiwezi kuzitekeleza), kernel pages hazina PXN (hivyo code ya kernel inaweza kutekelezwa).
- Kernel lazima ihakikishe kuwa hakuna njia za code zinazosababisha mtiririko wa utekelezaji kwenda katika maeneo ya memory ya user (ambayo ingetimiza PXN) — hivyo mnyororo za exploit zinazotegemea “kuruka ndani kwa shellcode inayodhibitiwa na user” zinazuia.
Kwa sababu ya kupitishwa kwa PAN kupitia execute-only pages, katika mfumo halisi, Apple inaweza kuzima au kuzuia execute-only user pages, au kutengeneza mbinu za kuzunguka kasoro ya spec.
#### Surfaces za kushambuliwa, kupitisha, na mitigations
- **PAN bypass via execute-only pages**: kama ilivyoshughulikiwa, spec ina pengo: pages za user zilizo execute-only (bila ruhusa ya kusoma) huenda zisizingatiwe kama “accessible at EL0,” hivyo PAN haitazuia kernel kusoma kutoka kwao katika utekelezaji fulani. Hii inampa mshambuliaji njia isiyo ya kawaida ya kuingiza data kupitia sehemu za “execute-only.”
- **Temporal window exploit**: ikiwa kernel inazima PAN kwa dirisha lenye muda mrefu kuliko inavyohitajika, race au njia ya uhalifu inaweza kutumia dirisha hilo kufanya ufikiaji wa memory ya user uliofanyika bila kusimamiwa.
- **Forgotten re-enable**: ikiwa njia za code zinashindwa kurekebisha PAN tena, shughuli za baadaye za kernel zinaweza vibaya kufikia memory ya user.
- **Misconfiguration of PXN**: ikiwa page tables hazoweka PXN kwenye user pages au kuunganisha vibaya user code pages, kernel inaweza kujaribiwa kuendesha code ya user.
- **Speculation / side-channels**: kama ilivyo kwa kupitishwa kwa speculative, kunaweza kuwa na athari za microarchitectural ambazo husababisha uvunjaji wa muda mfupi wa ukaguzi wa PAN / PXN (hata hivyo mashambulizi kama hayo yanategemea sana kubuni kwa CPU).
- **Complex interactions**: Katika vipengele vilivyokompleksika (mf. JIT, shared memory, maeneo ya code ya just-in-time), kernel inaweza kuhitaji udhibiti wa mfululizo wa ufikiaji au utekelezaji katika maeneo ya user-mapped; kubuni hilo salama chini ya vizuizi vya PAN/PXN si rahisi.
#### Mfano
<details>
<summary>Mfano wa Msimbo</summary>
Here are illustrative pseudo-assembly sequences showing enabling/disabling PAN around user memory access, and how a fault might occur.
// Suppose kernel entry point, PAN is enabled (privileged code cannot access user memory by default)
; Kernel receives a syscall with user pointer in X0 ; wants to read an integer from user space mov X1, X0 ; X1 = user pointer
; disable PAN to allow privileged access to user memory MSR PSTATE.PAN, #0 ; clear PAN bit, disabling the restriction
ldr W2, [X1] ; now allowed load from user address
; re-enable PAN before doing other kernel logic MSR PSTATE.PAN, #1 ; set PAN
; … further kernel work …
; Later, suppose an exploit corrupts a pointer to a user-space code page and jumps there BR X3 ; branch to X3 (which points into user memory)
; Because the target page is marked PXN = 1 for privileged execution, ; the CPU throws an exception (fault) and rejects execution
If the kernel had **not** set PXN on that user page, then the branch might succeed — which would be insecure.
If the kernel forgets to re-enable PAN after user memory access, it opens a window where further kernel logic might accidentally read/write arbitrary user memory.
If the user pointer is into an execute-only page (user page with only execute permission, no read/write), under the PAN spec bug, `ldr W2, [X1]` might **not** fault even with PAN enabled, enabling a bypass exploit, depending on implementation.
</details>
<details>
<summary>Example</summary>
A kernel vulnerability tries to take a user-provided function pointer and call it in kernel context (i.e. `call user_buffer`). Under PAN/PXN, that operation is disallowed or faults.
</details>
---
### 11. **Top Byte Ignore (TBI) / Pointer Tagging**
**Introduced in ARMv8.5 / newer (or optional extension)**
TBI means the top byte (most-significant byte) of a 64-bit pointer is ignored by address translation. This lets OS or hardware embed **tag bits** in the pointer’s top byte without affecting the actual address.
- TBI stands for **Top Byte Ignore** (sometimes called *Address Tagging*). It is a hardware feature (available in many ARMv8+ implementations) that **ignores the top 8 bits** (bits 63:56) of a 64-bit pointer when performing **address translation / load/store / instruction fetch**.
- In effect, the CPU treats a pointer `0xTTxxxx_xxxx_xxxx` (where `TT` = top byte) as `0x00xxxx_xxxx_xxxx` for the purposes of address translation, ignoring (masking off) the top byte. The top byte can be used by software to store **metadata / tag bits**.
- This gives software “free” in-band space to embed a byte of tag in each pointer without altering which memory location it refers to.
- The architecture ensures that loads, stores, and instruction fetch treat the pointer with its top byte masked (i.e. tag stripped off) before performing the actual memory access.
Thus TBI decouples the **logical pointer** (pointer + tag) from the **physical address** used for memory operations.
#### Why TBI: Use cases and motivation
- **Pointer tagging / metadata**: You can store extra metadata (e.g. object type, version, bounds, integrity tags) in that top byte. When you later use the pointer, the tag is ignored at hardware level, so you don’t need to strip manually for the memory access.
- **Memory tagging / MTE (Memory Tagging Extension)**: TBI is the base hardware mechanism that MTE builds on. In ARMv8.5, the **Memory Tagging Extension** uses bits 59:56 of the pointer as a **logical tag** and checks it against an **allocation tag** stored in memory.
- **Enhanced security & integrity**: By combining TBI with pointer authentication (PAC) or runtime checks, you can force not just the pointer value but also the tag to be correct. An attacker overwriting a pointer without the correct tag will produce a mismatched tag.
- **Compatibility**: Because TBI is optional and tag bits are ignored by hardware, existing untagged code continues to operate normally. The tag bits effectively become “don’t care” bits for legacy code.
#### Example
<details>
<summary>Example</summary>
A function pointer included a tag in its top byte (say `0xAA`). An exploit overwrites the pointer low bits but neglects the tag, so when the kernel verifies or sanitizes, the pointer fails or is rejected.
</details>
---
### 12. **Page Protection Layer (PPL)**
**Introduced in late iOS / modern hardware (iOS ~17 / Apple silicon / high-end models)** (some reports show PPL circa macOS / Apple silicon, but Apple is bringing analogous protections to iOS)
- PPL is designed as an **intra-kernel protection boundary**: even if the kernel (EL1) is compromised and has read/write capabilities, **it should not be able to freely modify** certain **sensitive pages** (especially page tables, code-signing metadata, kernel code pages, entitlements, trust caches, etc.).
- It effectively creates a **“kernel within the kernel”** — a smaller trusted component (PPL) with **elevated privileges** that alone can modify protected pages. Other kernel code must call into PPL routines to effect changes.
- This reduces the attack surface for kernel exploits: even with full arbitrary R/W/execute in kernel mode, exploit code must also somehow get into the PPL domain (or bypass PPL) to modify critical structures.
- On newer Apple silicon (A15+ / M2+), Apple is transitioning to **SPTM (Secure Page Table Monitor)**, which in many cases replaces PPL for page-table protection on those platforms.
Here’s how PPL is believed to operate, based on public analysis:
#### Use of APRR / permission routing (APRR = Access Permission ReRouting)
- Apple hardware uses a mechanism called **APRR (Access Permission ReRouting)**, which allows page table entries (PTEs) to contain small indices, rather than full permission bits. Those indices are mapped via APRR registers to actual permissions. This allows dynamic remapping of permissions per domain.
- PPL leverages APRR to segregate privilege within kernel context: only the PPL domain is permitted to update the mapping between indices and effective permissions. That is, when non-PPL kernel code writes a PTE or tries to flip permission bits, the APRR logic disallows it (or enforces read-only mapping).
- PPL code itself runs in a restricted region (e.g. `__PPLTEXT`) which is normally non-executable or non-writable until entry gates temporarily allow it. The kernel calls PPL entry points (“PPL routines”) to perform sensitive operations.
#### Gate / Entry & Exit
- When the kernel needs to modify a protected page (e.g. change permissions of a kernel code page, or modify page tables), it calls into a **PPL wrapper** routine, which does validation and then transitions into the PPL domain. Outside that domain, the protected pages are effectively read-only or non-modifiable by the main kernel.
- During PPL entry, the APRR mappings are adjusted so that memory pages in the PPL region are set to **executable & writable** within PPL. Upon exit, they are returned to read-only / non-writable. This ensures that only well-audited PPL routines can write to protected pages.
- Outside PPL, attempts by kernel code to write to those protected pages will fault (permission denied) because the APRR mapping for that code domain doesn’t permit writing.
#### Protected page categories
The pages that PPL typically protects include:
- Page table structures (translation table entries, mapping metadata)
- Kernel code pages, especially those containing critical logic
- Code-sign metadata (trust caches, signature blobs)
- Entitlement tables, signature enforcement tables
- Other high-value kernel structures where a patch would allow bypassing signature checks or credentials manipulation
The idea is that even if the kernel memory is fully controlled, the attacker cannot simply patch or rewrite these pages, unless they also compromise PPL routines or bypass PPL.
#### Known Bypasses & Vulnerabilities
1. **Project Zero’s PPL bypass (stale TLB trick)**
- A public writeup by Project Zero describes a bypass involving **stale TLB entries**.
- The idea:
1. Allocate two physical pages A and B, mark them as PPL pages (so they are protected).
2. Map two virtual addresses P and Q whose L3 translation table pages come from A and B.
3. Spin a thread to continuously access Q, keeping its TLB entry alive.
4. Call `pmap_remove_options()` to remove mappings starting at P; due to a bug, the code mistakenly removes the TTEs for both P and Q, but only invalidates the TLB entry for P, leaving Q’s stale entry live.
5. Reuse B (page Q’s table) to map arbitrary memory (e.g. PPL-protected pages). Because the stale TLB entry still maps Q’s old mapping, that mapping remains valid for that context.
6. Through this, the attacker can put writable mapping of PPL-protected pages in place without going through PPL interface.
- This exploit required fine control of physical mapping and TLB behavior. It demonstrates that a security boundary relying on TLB / mapping correctness must be extremely careful about TLB invalidations and mapping consistency.
- Project Zero commented that bypasses like this are subtle and rare, but possible in complex systems. Still, they regard PPL as a solid mitigation.
2. **Other potential hazards & constraints**
- If a kernel exploit can directly enter PPL routines (via calling the PPL wrappers), it might bypass restrictions. Thus argument validation is critical.
- Bugs in the PPL code itself (e.g. arithmetic overflow, boundary checks) can allow out-of-bounds modifications inside PPL. Project Zero observed that such a bug in `pmap_remove_options_internal()` was exploited in their bypass.
- The PPL boundary is irrevocably tied to hardware enforcement (APRR, memory controller), so it's only as strong as the hardware implementation.
#### Example
<details>
<summary>Code Example</summary>
Here’s a simplified pseudocode / logic showing how a kernel might call into PPL to modify protected pages:
```c
// In kernel (outside PPL domain)
function kernel_modify_pptable(pt_addr, new_entry) {
// validate arguments, etc.
return ppl_call_modify(pt_addr, new_entry) // call PPL wrapper
}
// In PPL (trusted domain)
function ppl_call_modify(pt_addr, new_entry) {
// temporarily enable write access to protected pages (via APRR adjustments)
aprr_set_index_for_write(PPL_INDEX)
// perform the modification
*pt_addr = new_entry
// restore permissions (make pages read-only again)
aprr_restore_default()
return success
}
// If kernel code outside PPL does:
*pt_addr = new_entry // a direct write
// It will fault because APRR mapping for non-PPL domain disallows write to that page
The kernel inaweza kufanya shughuli nyingi za kawaida, lakini ni kupitia ppl_call_* routines pekee ambapo inaweza kubadilisha protected mappings au kupatch code.
Mfano
Jaribio la kernel exploit linafanya overwrite ya entitlement table, au kuzima code-sign enforcement kwa kubadilisha kernel signature blob. Kwa sababu ukurasa huo umelinziwa na PPL, kuandika kunazuiawa isipokuwa kupitia PPL interface. Hivyo hata ukiwa na kernel code execution, huwezi kupitisha code-sign constraints au kubadilisha credential data kwa hiari. Kwenye iOS 17+ baadhi ya vifaa vinatumia SPTM kuongeza kutenganisha kurasa zinazosimamiwa na PPL.PPL → SPTM / Replacements / Future
- On Apple’s modern SoCs (A15 or later, M2 or later), Apple supports SPTM (Secure Page Table Monitor), which replaces PPL for page table protections.
- Apple anataja katika nyaraka: “Page Protection Layer (PPL) and Secure Page Table Monitor (SPTM) enforce execution of signed and trusted code … PPL manages the page table permission overrides … Secure Page Table Monitor replaces PPL on supported platforms.”
- Miundombinu ya SPTM inaonekana kuhamisha utekelezaji wa sera zaidi kwenye monitor yenye haki zaidi nje ya udhibiti wa kernel, ikipunguza zaidi boundary ya kuaminika.
MTE | EMTE | MIE
Hapa kuna maelezo ya kiwango cha juu kuhusu jinsi EMTE inavyofanya kazi chini ya usanidi wa Apple wa MIE:
- Tag assignment
- Wakati memory inapopangwa (mfano katika kernel au user space kupitia secure allocators), secret tag inapatikana kwa blokio hilo.
- Pointer inayorudishwa kwa user au kernel inajumuisha tag hiyo katika high bits (ikitumia TBI / top byte ignore mechanisms).
- Tag checking on access
- Kila unapofanya load au store ukitumia pointer, hardware inakagua kama tag ya pointer inafanana na tag ya block ya memory (allocation tag). Ikiwa haifanani, inafanya fault mara moja (kwa sababu ni synchronous).
- Kwa sababu ni synchronous, hakuna dirisha la “delayed detection”.
- Retagging on free / reuse
- Wakati memory inatolewa, allocator hubadilisha tag ya block (hivyo pointers za zamani zenye tag za kale hazitafanana tena).
- Use-after-free pointer basi itakuwa na tag iliyochakaa na itazipinga wakati itakapofikiwa.
- Neighbor-tag differentiation to catch overflows
- Allocations jirani zinapewa tags tofauti. Ikiwa buffer overflow inapita ndani ya memory ya jirani, mismatch ya tag husababisha fault.
- Hii ni nguvu sana kwa kukamata overflows ndogo ambazo zinapita boundary.
- Tag confidentiality enforcement
- Apple lazima isitumie tag values kutolewa (kwa sababu kama mshambuliaji atajua tag, angeweza kutengeneza pointers zenye tags sahihi).
- Wanajumuisha ulinzi (microarchitectural / speculative controls) kuzuia chaguzi za upande (side-channel) za tag bits.
- Kernel and user-space integration
- Apple inatumia EMTE si tu katika user-space bali pia katika kernel / OS-critical components (kutoa kinga kwa kernel dhidi ya memory corruption).
- Hardware/OS inahakikisha sheria za tag zinatumika hata wakati kernel inatekeleza kwa niaba ya user space.
Mfano
``` Allocate A = 0x1000, assign tag T1 Allocate B = 0x2000, assign tag T2// pointer P points into A with tag T1 P = (T1 << 56) | 0x1000
// Valid store *(P + offset) = value // tag T1 matches allocation → allowed
// Overflow attempt: P’ = P + size_of_A (into B region) *(P’ + delta) = value → pointer includes tag T1 but memory block has tag T2 → mismatch → fault
// Free A, allocator retags it to T3 free(A)
// Use-after-free: *(P) = value → pointer still has old tag T1, memory region is now T3 → mismatch → fault
</details>
#### Mipaka & changamoto
- **Intrablock overflows**: If overflow stays within the same allocation (doesn’t cross boundary) and the tag remains the same, tag mismatch does not catch it.
- **Tag width limitation**: Only a few bits (e.g. 4 bits, or small domain) are available for tag—limited namespace.
- **Side-channel leaks**: If tag bits can be leaked (via cache / speculative execution), attacker may learn valid tags and bypass. Apple’s tag confidentiality enforcement is meant to mitigate this.
- **Performance overhead**: Tag checks each load/store add cost; Apple must optimize hardware to push overhead low.
- **Compatibility & fallback**: On older hardware or parts that don't support EMTE, fallback must exist. Apple claims MIE is only enabled on devices with support.
- **Complex allocator logic**: The allocator must manage tags, retagging, aligning boundaries, and avoid mis-tag collisions. Bugs in allocator logic could introduce vulnerabilities.
- **Mixed memory / hybrid areas**: Some memory may remain untagged (legacy), making interoperability trickier.
- **Speculative / transient attacks**: As with many microarchitectural protections, speculative execution or micro-op fusions might bypass checks transiently or leak tag bits.
- **Limited to supported regions**: Apple might only enforce EMTE in selective, high-risk areas (kernel, security-critical subsystems), not universally.
---
## Key enhancements / differences compared to standard MTE
Here are the improvements and changes Apple emphasizes:
| Feature | Original MTE | EMTE (Apple’s enhanced) / MIE |
|---|---|---|
| **Check mode** | Supports synchronous and asynchronous modes. In async, tag mismatches are reported later (delayed)| Apple insists on **synchronous mode** by default—tag mismatches are caught immediately, no delay/race windows allowed.|
| **Coverage of non-tagged memory** | Accesses to non-tagged memory (e.g. globals) may bypass checks in some implementations | EMTE requires that accesses from a tagged region to non-tagged memory also validate tag knowledge, making it harder to bypass by mixing allocations.|
| **Tag confidentiality / secrecy** | Tags might be observable or leaked via side channels | Apple adds **Tag Confidentiality Enforcement**, which attempts to prevent leakage of tag values (via speculative side-channels etc.).|
| **Allocator integration & retagging** | MTE leaves much of allocator logic to software | Apple’s secure typed allocators (kalloc_type, xzone malloc, etc.) integrate with EMTE: when memory is allocated or freed, tags are managed at fine granularity.|
| **Always-on by default** | In many platforms, MTE is optional or off by default | Apple enables EMTE / MIE by default on supported hardware (e.g. iPhone 17 / A19) for kernel and many user processes.|
Because Apple controls both the hardware and software stack, it can enforce EMTE tightly, avoid performance pitfalls, and close side-channel holes.
---
## How EMTE works in practice (Apple / MIE)
Here’s a higher-level description of how EMTE operates under Apple’s MIE setup:
1. **Tag assignment**
- When memory is allocated (e.g. in kernel or user space via secure allocators), a **secret tag** is assigned to that block.
- The pointer returned to the user or kernel includes that tag in its high bits (using TBI / top byte ignore mechanisms).
2. **Tag checking on access**
- Whenever a load or store is executed using a pointer, the hardware checks that the pointer’s tag matches the memory block’s tag (allocation tag). If mismatch, it faults immediately (since synchronous).
- Because it's synchronous, there is no “delayed detection” window.
3. **Retagging on free / reuse**
- When memory is freed, the allocator changes the block’s tag (so older pointers with old tags no longer match).
- A use-after-free pointer would therefore have a stale tag and mismatch when accessed.
4. **Neighbor-tag differentiation to catch overflows**
- Adjacent allocations are given distinct tags. If a buffer overflow spills into neighbor’s memory, tag mismatch causes a fault.
- This is especially powerful in catching small overflows that cross boundary.
5. **Tag confidentiality enforcement**
- Apple must prevent tag values being leaked (because if attacker learns the tag, they could craft pointers with correct tags).
- They include protections (microarchitectural / speculative controls) to avoid side-channel leakage of tag bits.
6. **Kernel and user-space integration**
- Apple uses EMTE not just in user-space but also in kernel / OS-critical components (to guard kernel against memory corruption).
- The hardware/OS ensures tag rules apply even when kernel is executing on behalf of user space.
Because EMTE is built into MIE, Apple uses EMTE in synchronous mode across key attack surfaces, not as opt-in or debugging mode.
---
## Exception handling in XNU
When an **exception** occurs (e.g., `EXC_BAD_ACCESS`, `EXC_BAD_INSTRUCTION`, `EXC_CRASH`, `EXC_ARM_PAC`, etc.), the **Mach layer** of the XNU kernel is responsible for intercepting it before it becomes a UNIX-style **signal** (like `SIGSEGV`, `SIGBUS`, `SIGILL`, ...).
This process involves multiple layers of exception propagation and handling before reaching user space or being converted to a BSD signal.
### Exception Flow (High-Level)
1. **CPU triggers a synchronous exception** (e.g., invalid pointer dereference, PAC failure, illegal instruction, etc.).
2. **Low-level trap handler** runs (`trap.c`, `exception.c` in XNU source).
3. The trap handler calls **`exception_triage()`**, the core of the Mach exception handling.
4. `exception_triage()` decides how to route the exception:
- First to the **thread's exception port**.
- Then to the **task's exception port**.
- Then to the **host's exception port** (often `launchd` or `ReportCrash`).
If none of these ports handle the exception, the kernel may:
- **Convert it into a BSD signal** (for user-space processes).
- **Panic** (for kernel-space exceptions).
### Core Function: `exception_triage()`
The function `exception_triage()` routes Mach exceptions up the chain of possible handlers until one handles it or until it's finally fatal. It's defined in `osfmk/kern/exception.c`.
```c
void exception_triage(exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt);
Mtiririko wa Mwito wa Kawaida:
exception_triage() └── exception_deliver() ├── exception_deliver_thread() ├── exception_deliver_task() └── exception_deliver_host()
Kama vyote vinashindwa → vinashughulikiwa na bsd_exception() → vitafsiriwa kuwa signal kama SIGSEGV.
Exception Ports
Kila Mach object (thread, task, host) kinaweza kusajili exception ports, ambazo ndiyo sehemu ambapo exception messages hutumwa.
Zimefafanuliwa na API:
task_set_exception_ports()
thread_set_exception_ports()
host_set_exception_ports()
Kila exception port ina:
- A mask (ni exceptions gani inazotaka kupokea)
- A port name (Mach port ya kupokea ujumbe)
- A behavior (jinsi kernel inavyotuma ujumbe)
- A flavor (ni thread state gani kujumuishwa)
Debuggers na Ushughulikiaji wa Exceptions
A debugger (mf., LLDB) huweka exception port kwenye task au thread lengwa, kawaida kwa kutumia task_set_exception_ports().
Wakati exception inapotokea:
- Ujumbe wa Mach unatumwa kwa mchakato wa debugger.
- Debugger inaweza kuamua kushughulikia (kuendelea, kubadilisha registers, kukwepa instruction) au kusiushughulikie exception.
- Ikiwa debugger haishughulikii, exception husambaa hadi ngazi inayofuata (task → host).
Mtiririko wa EXC_BAD_ACCESS
-
Thread inatafutisha pointer isiyo halali → CPU inaibua Data Abort.
-
Kernel trap handler huuita
exception_triage(EXC_BAD_ACCESS, ...). -
Ujumbe umetumwa kwa:
-
Thread port → (debugger inaweza kukamata breakpoint).
-
Ikiwa debugger haitumii/haishughulikii → Task port → (mshughulikiaji wa kiwango cha process).
-
Ikiwa pia haishughulikii → Host port (kwa kawaida ReportCrash).
- Kama hakuna anayeshughulikia →
bsd_exception()hubadilisha kuwaSIGSEGV.
PAC Exceptions
Wakati Pointer Authentication (PAC) inashindwa (signature haifai), special Mach exception inainuliwa:
EXC_ARM_PAC(type)- Codes zinaweza kujumuisha maelezo (mf., aina ya key, aina ya pointer).
Ikiwa binary ina flag TFRO_PAC_EXC_FATAL, kernel itatendea kushindwa kwa PAC kama fatal, ikiepuka kukamatwa na debugger. Hii ni ili kuzuia wadukuzi kutumia debuggers kupitisha ukaguzi wa PAC na imewezeshwa kwa platform binaries.
Software Breakpoints
Software breakpoint (int3 on x86, brk on ARM64) hutekelezwa kwa kusababisha fault kwa makusudi.
Debugger huchukua hili kupitia exception port:
- Inabadilisha instruction pointer au memory.
- Inarudisha instruction ya awali.
- Inaendelea utekelezaji.
Mekanizimu ile ile ndiyo inakuwezesha “kukamata” PAC exception — isipokuwa TFRO_PAC_EXC_FATAL imewekwa, ambapo haiwafiki debugger.
Ubadilishaji hadi BSD Signals
Ikiwa hakuna mshughulikiaji anayekubali exception:
-
Kernel huita
task_exception_notify() → bsd_exception(). -
Hii inaweka ramani Mach exceptions kwa signals:
| Mach Exception | Signal |
|---|---|
| EXC_BAD_ACCESS | SIGSEGV or SIGBUS |
| EXC_BAD_INSTRUCTION | SIGILL |
| EXC_ARITHMETIC | SIGFPE |
| EXC_SOFTWARE | SIGTRAP |
| EXC_BREAKPOINT | SIGTRAP |
| EXC_CRASH | SIGKILL |
| EXC_ARM_PAC | SIGILL (on non-fatal) |
Faili Muhimu katika Chanzo cha XNU
-
osfmk/kern/exception.c→ Core yaexception_triage(),exception_deliver_*(). -
bsd/kern/kern_sig.c→ Mantiki ya utoaji wa signal. -
osfmk/arm64/trap.c→ Handlers za trap za kiwango cha chini. -
osfmk/mach/exc.h→ Codes za exception na miundo. -
osfmk/kern/task.c→ Usanidi wa task exception port.
Old Kernel Heap (Pre-iOS 15 / Pre-A12 era)
Kernel ilitumia zone allocator (kalloc) iliyogawanywa katika “zones” za ukubwa uliotenganywa. Kila zone ilihifadhi tu allocations za daraja moja ya ukubwa.
Kutokana na picha:
| Jina la Zone | Ukubwa wa Element | Mfano wa Matumizi |
|---|---|---|
default.kalloc.16 | 16 bytes | Struct ndogo sana za kernel, pointers. |
default.kalloc.32 | 32 bytes | Struct ndogo, object headers. |
default.kalloc.64 | 64 bytes | IPC messages, buffers ndogo za kernel. |
default.kalloc.128 | 128 bytes | Vitu vya wastani kama sehemu za OSObject. |
| … | … | … |
default.kalloc.1280 | 1280 bytes | Miundo mikubwa, IOSurface/graphics metadata. |
Jinsi ilivyofanya kazi:
- Kila ombi la allocation linakaribiwa juu (rounded up) hadi ukubwa wa zone iliyo karibu.
(Mf., ombi la 50-byte linaingia katika zone yakalloc.64). - Memory katika kila zone ilihifadhiwa katika free list — vipande vilivyotolewa na kernel vilirejea katika zone hiyo.
- Ikiwa utakaza buffer ya 64-byte (overflow), utaandika juu ya object inayofuata katika zone ile ile.
Hii ndiyo sababu heap spraying / feng shui ilikuwa yenye ufanisi: unaweza kutabiri majirani wa object kwa kusambaza allocations za daraja moja ya ukubwa.
The freelist
Ndani ya kila kalloc zone, vitu vilivyotolewa havirudishiwi moja kwa moja kwa mfumo — vilingia kwenye freelist, orodha ya linked ya vipande vinavyopatikana.
-
Wakati kipande kilipotolewa, kernel iliandika pointer mwanzoni mwa kipande hicho → anwani ya kipande kinachofuata kinachopatikana katika zone ile ile.
-
Zone ilibaki na HEAD pointer kwa kipande cha kwanza kilichopatikana.
-
Allocation daima ilitumia HEAD ya sasa:
-
Pop HEAD (rudi memory hiyo kwa mtumaji).
-
Sasisha HEAD = HEAD->next (iloandikwa kwenye header ya kipande kilichotolewa).
-
Kutoa (freeing) kulisukuma vipande kurudi:
-
freed_chunk->next = HEAD -
HEAD = freed_chunk
Hivyo freelist ilikuwa ni orodha ya linked iliyojengwa ndani ya memory iliyotolewa yenyewe.
Hali ya kawaida:
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)
Kutumia freelist
Kwa sababu 8 bytes za kwanza za free chunk = freelist pointer, mshambuliaji anaweza kuiharibu:
-
Heap overflow ndani ya free chunk jirani → kuandika juu ya “next” pointer yake.
-
Use-after-free kuandika ndani ya freed object → kuandika juu ya “next” pointer yake.
Kisha, kwenye allocation inayofuata ya ukubwa huo:
-
Allocator inatoa corrupted chunk.
-
Inafuata “next” pointer iliyotolewa na mshambuliaji.
-
Inarudisha pointer kwa memory yoyote, ikiruhusu fake object primitives au targeted overwrite.
Mfano wa kuona wa 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.
This freelist design ilifanya exploitation kuwa yenye ufanisi mkubwa kabla ya hardening: neighbors za predictable kutoka heap sprays, raw pointer freelist links, na kutokuwepo kwa type separation kuliruhusu attackers kuinua UAF/overflow bugs hadi kudhibiti arbitrary kernel memory.
Heap Grooming / Feng Shui
The goal of heap grooming is to shape the heap layout ili wakati attacker atakayesababisha overflow au use-after-free, object lengwa (victim) iwe karibu kabisa na attacker-controlled object.
Kwa njia hiyo, wakati corruption ya memory inapotokea, attacker anaweza kwa uhakika kuandika juu ya victim object kwa data iliyodhibitiwa.
Steps:
- Spray allocations (fill the holes)
- Kwa muda, kernel heap inagawanyika: baadhi ya zones zina holes ambapo objects za zamani zilifunguliwa (freed).
- Attacker kwanza hufanya allocations nyingi za dummy kujaa gaps hizi, hivyo heap inakuwa “packed” na predictable.
- Force new pages
- Mara holes zimejazwa, allocations zinazofuata lazima zitoke kwenye pages mpya zilizoongezwa kwenye zone.
- Pages mpya zinamaanisha objects zitatangazwa pamoja, sio kuenea katika fragmented old memory.
- Hii inampa attacker udhibiti mzuri wa neighbors.
- Place attacker objects
- Attacker sasa anafanya spray tena, akitengeneza objects nyingi za attacker-controlled katika pages hizo mpya.
- Objects hizi zina ukubwa na placement inayoweza kutabiriwa (kwa sababu zote zinatoka kwenye zone moja).
- Free a controlled object (make a gap)
- Attacker kwa makusudi anafree moja ya objects zao.
- Hii inaunda “hole” kwenye heap, ambayo allocator itatumia tena kwa allocation inayofuata ya size hiyo.
- Victim object lands in the hole
- Attacker anasababisha kernel kuallocate victim object (ile wanayotaka kuharibu).
- Kwa kuwa hole ndiyo slot ya kwanza inayopatikana kwenye freelist, victim inawekwa hasa palipo attacker alifungua object yake.
- Overflow / UAF into victim
- Sasa attacker ana attacker-controlled objects karibu na victim.
- Kwa kuoverflow kutoka kwenye moja ya objects zao (au kutumia freed one), wanaweza kwa uhakika kuandika juu ya memory fields za victim kwa values walizochagua.
Why it works:
- Zone allocator predictability: allocations za size moja daima zinatoka kwenye zone ileile.
- Freelist behavior: allocations mpya zinatumia chunk zilizofungwa hivi karibuni kwanza.
- Heap sprays: attacker anajaza memory na content inayotabirika na anadhibiti layout.
- End result: attacker anadhibiti wapi victim object inapatikana na ni data gani iko karibu nayo.
Modern Kernel Heap (iOS 15+/A12+ SoCs)
Apple imeimarisha allocator na kufanya heap grooming kuwa ngumu zaidi:
1. From Classic kalloc to kalloc_type
- Before: zone moja
kalloc.<size>ilikuwepo kwa kila size class (16, 32, 64, … 1280, nk). Kila object ya size hiyo ilipelekwa hapo → attacker objects zingeweza kukaa karibu na privileged kernel objects. - Now:
- Kernel objects zinallocate-wa kutoka kwenye typed zones (
kalloc_type). - Kila type ya object (mfano,
ipc_port_t,task_t,OSString,OSData) ina zone yake maalum, hata kama zina size sawa. - Mapping kati ya object type ↔ zone inatengenezwa kutoka kwa kalloc_type system wakati wa compile.
Attacker hawezi tena kuhakikisha kwamba controlled data (OSData) itamalizika ikikaribu sensitive kernel objects (task_t) za size sawa.
2. Slabs and Per-CPU Caches
- Heap imegawanywa katika slabs (pages za memory zilizogawanywa katika chunks za fixed-size kwa zone hiyo).
- Kila zone ina per-CPU cache kupunguza contention.
- Allocation path:
- Jaribu per-CPU cache.
- Ikiwa tupu, chukua kutoka global freelist.
- Ikiwa freelist tupu, allocate slab mpya (page moja au zaidi).
- Faida: decentralization hii inafanya heap sprays kuwa si deterministic, kwa sababu allocations zinaweza kutimizwa kutoka caches za CPUs tofauti.
3. Randomization inside zones
- Ndani ya zone, elements zilizofungwa hazirudishiwa kwa FIFO/LIFO rahisi.
- XNU ya kisasa inatumia encoded freelist pointers (safe-linking kama Linux, ilitambulishwa ~iOS 14).
- Kila freelist pointer imeXOR-encoded na cookie ya siri ya zone.
- Hii inazuia attackers kuunda fake freelist pointer ikiwa wanapata write primitive.
- Baadhi allocations zina randomized placement ndani ya slab, hivyo spraying haisemi adjacency kwa uhakika.
4. Guarded Allocations
- Baadhi critical kernel objects (mfano, credentials, task structures) zinallocate-wa katika guarded zones.
- Zones hizi zinaweka guard pages (memory isiyopangwa) kati ya slabs au kutumia redzones karibu na objects.
- Overflow yoyote ndani ya guard page inasababisha fault → panic mara moja badala ya corruption iliyonyamazishwa.
5. Page Protection Layer (PPL) and SPTM
- Hata ukidhibiti freed object, huwezi kubadilisha sehemu zote za kernel memory:
- PPL (Page Protection Layer) inawalinda kwamba maeneo maalum (mfano, code signing data, entitlements) ni read-only hata kwa kernel yenyewe.
- Kwenye A15/M2+ devices, jukumu hili limebadilishwa/imetekelezwa zaidi kwa SPTM (Secure Page Table Monitor) + TXM (Trusted Execution Monitor).
- Mipaka hii iliyotekelezwa kwa hardware inamaanisha attackers hawawezi kuinuka kutoka heap corruption moja hadi kuandika arbitrary kwenye critical security structures.
- (Added / Enhanced): pia, PAC (Pointer Authentication Codes) inatumika katika kernel kulinda pointers (hasa function pointers, vtables) ili kuifanya forging au corruption yao kuwa ngumu zaidi.
- (Added / Enhanced): zones zinaweza kutekeleza zone_require / zone enforcement, yaani object iliyofungwa inaweza kurejeshwa tu kupitia zone sahihi ya aina yake; frees za cross-zone zisizo sahihi zinaweza kusababisha panic au kukataliwa. (Apple anazungumzia hili katika posts zao za memory safety)
6. Large Allocations
- Sio allocations zote zinapita kupitia
kalloc_type. - Maombi makubwa sana (juu ya ~16 KB) hupita typed zones na hutolewa moja kwa moja kutoka kernel VM (kmem) kupitia page allocations.
- Hizi ni zisizotabirika sana, lakini pia si rahisi kutumika, kwa sababu hazishiriki slabs na objects nyingine.
7. Allocation Patterns Attackers Target
Hata kwa ulinzi huu, attackers bado wanaangalia:
- Reference count objects: ikiwa unaweza kubadilisha retain/release counters, unaweza kusababisha use-after-free.
- Objects with function pointers (vtables): kuharibu moja bado huleta control flow.
- Shared memory objects (IOSurface, Mach ports): hizi bado ni malengo kwa sababu zinatoka user ↔ kernel.
Lakini — tofauti na zamani — huwezi tu kufanya spray ya OSData ukiwa unatarajia ikamgeuke kuwa jirani na task_t. Unahitaji type-specific bugs au info leaks ili kufanikiwa.
Example: Allocation Flow in Modern Heap
Suppose userspace calls into IOKit to allocate an OSData object:
- Type lookup →
OSDatainamelezwa kwakalloc_type_osdatazone (size 64 bytes). - Angalia per-CPU cache kwa elements za bure.
- Ikiwa imetokea → rudisha moja.
- Ikiwa tupu → nenda kwa global freelist.
- Ikiwa freelist tupu → allocate slab mpya (page ya 4KB → 64 chunks za 64 bytes).
- Rudi chunk kwa caller.
Freelist pointer protection:
- Kila freed chunk inaweka address ya next free chunk, lakini imeencoded na key ya siri.
- Kuandika juu ya field hiyo kwa attacker data haitafanya kazi isipokuwa ukijua key.
Comparison Table
| Feature | Old Heap (Pre-iOS 15) | Modern Heap (iOS 15+ / A12+) |
|---|---|---|
| Allocation granularity | Fixed size buckets (kalloc.16, kalloc.32, etc.) | Size + type-based buckets (kalloc_type) |
| Placement predictability | High (same-size objects side by side) | Low (same-type grouping + randomness) |
| Freelist management | Raw pointers in freed chunks (easy to corrupt) | Encoded pointers (safe-linking style) |
| Adjacent object control | Easy via sprays/frees (feng shui predictable) | Hard — typed zones separate attacker objects |
| Kernel data/code protections | Few hardware protections | PPL / SPTM protect page tables & code pages, and PAC protects pointers |
| Allocation reuse validation | None (freelist pointers raw) | zone_require / zone enforcement |
| Exploit reliability | High with heap sprays | Much lower, requires logic bugs or info leaks |
| Large allocations handling | All small allocations managed equally | Large ones bypass zones → handled via VM |
Modern Userland Heap (iOS, macOS — type-aware / xzone malloc)
Katika matoleo ya hivi karibuni ya Apple OS (hasa iOS 17+), Apple iliweka allocator salama zaidi ya userland, xzone malloc (XZM). Hii ni analog ya user-space kwa kernel’s kalloc_type, ikitumia type awareness, metadata isolation, na memory tagging safeguards.
Goals & Design Principles
- Type segregation / type awareness: kuunganisha allocations kwa type au usage (pointer vs data) ili kuzuia type confusion na cross-type reuse.
- Metadata isolation: kutenganisha heap metadata (mfano free lists, size/state bits) kutoka payloads za object ili out-of-bounds writes zisizoathiri metadata.
- Guard pages / redzones: kuweka unmapped pages au padding karibu na allocations ili kugundua overflows.
- Memory tagging (EMTE / MIE): kufanya kazi pamoja na hardware tagging kugundua use-after-free, out-of-bounds, na invalid accesses.
- Scalable performance: kutunza overhead ndogo, kuepuka fragmentation nyingi, na kusaidia allocations nyingi kwa sekunde kwa latency ndogo.
Architecture & Components
Hapa chini ni vipengele vikuu vya xzone allocator:
Segment Groups & Zones
- Segment groups huzigawanya address space kwa usage categories: mfano
data,pointer_xzones,data_large,pointer_large. - Kila segment ina segments (VM ranges) zinazoshikilia allocations za category hiyo.
- Kila segment una metadata slab (eneo tofauti la VM) linalohifadhi metadata (mfano free/used bits, size classes) kwa segment hiyo. Hii ya out-of-line (OOL) metadata inahakikisha metadata haichanganyi na payloads za object, ikipunguza corruption kutoka overflows.
- Segments hugawanywa katika chunks (slices) ambazo kwa upande wake zigawanywa kuwa blocks (allocation units). Chunk imeambatana na size class na segment group maalum (yaani blocks zote ndani ya chunk zinashiriki size & category).
- Kwa allocations ndogo / za kati, itatumia fixed-size chunks; kwa kubwa/massive, inaweza kufanya mapping tofauti.
Chunks & Blocks
- Chunk ni eneo (mara nyingi kuridhika na pages kadhaa) lililotengwa kwa allocations za size class moja ndani ya group.
- Ndani ya chunk, blocks ni slots zinazopatikana kwa allocations. Freed blocks zinafuatiliwa kupitia metadata slab — mfano kupitia bitmaps au free lists zilizohifadhiwa out-of-line.
- Kati ya chunks (au ndani), guard slices / guard pages zinaweza kuingizwa (mfano, unmapped slices) kugundua out-of-bounds writes.
Type / Type ID
- Kila allocation site (au wito wa malloc, calloc, nk) inaambatanishwa na type identifier (
malloc_type_id_t) ambayo inaeleza aina ya object inayokataliwa. Type ID hiyo inapitishwa kwa allocator, ambayo hutumia kuchagua segment / zone inayotumika kwa allocation. - Kwa sababu ya hili, hata ikiwa allocations mbili zina size sawa, zinaweza kuingia zones tofauti kabisa ikiwa types zao ni tofauti.
- Katika toleo za mapema za iOS 17, APIs sio zote (mfano, CFAllocator) zilikuwa type-aware kabisa; Apple ilitatua udhaifu huo katika iOS 18.
Allocation & Freeing Workflow
Hapa kuna muhtasari wa jinsi allocation na deallocation zinavyofanya kazi katika xzone:
- malloc / calloc / realloc / typed alloc inaitwa na size na type ID.
- Allocator inatumia type ID kuchagua segment group / zone sahihi.
- Ndani ya zone/segment, inatafuta chunk yenye free blocks za size inayotakiwa.
- Inaweza kushauriana na local caches / per-thread pools au free block lists kutoka metadata.
- Ikiwa hakuna free block, inaweza allocate chunk mpya katika zone hiyo.
- Metadata slab inasasishwa (free bit inafutwa, bookkeeping).
- Ikiwa memory tagging (EMTE) iko, block iliyorudishwa inapata tag, na metadata inasasishwa kuonyesha state yake ya “live”.
- Wakati
free()inaitwa:
- Block inatambulishwa kama freed katika metadata (kupitia OOL slab).
- Block inaweza kuwekwa katika free list au pooled kwa reuse.
- Hiari, yaliyomo ya block yanaweza kufutwa au kufichuliwa (poisoned) kupunguza data leaks au use-after-free exploitation.
- Hardware tag inayohusishwa na block inaweza kuharibiwa au kure-tagged.
- Ikiwa chunk nzima inakuwa free (blocks zote zimefutwa), allocator inaweza reclaim chunk hiyo (kuunmap au kurudisha kwa OS) chini ya pressure ya memory.
Security Features & Hardening
Hizi ni defenses zilizojengwa ndani ya xzone ya userland:
| Feature | Purpose | Notes |
|---|---|---|
| Metadata decoupling | Prevent overflow from corrupting metadata | Metadata lives in separate VM region (metadata slab) |
| Guard pages / unmapped slices | Catch out-of-bounds writes | Helps detect buffer overflows rather than silently corrupting adjacent blocks |
| Type-based segregation | Prevent cross-type reuse & type confusion | Even same-size allocations from different types go to different zones |
| Memory Tagging (EMTE / MIE) | Detect invalid access, stale references, OOB, UAF | xzone works in concert with hardware EMTE in synchronous mode (“Memory Integrity Enforcement”) |
| Delayed reuse / poisoning / zap | Reduce chance of use-after-free exploitation | Freed blocks may be poisoned, zeroed, or quarantined before reuse |
| Chunk reclamation / dynamic unmapping | Reduce memory waste and fragmentation | Entire chunks may be unmapped when unused |
| Randomization / placement variation | Prevent deterministic adjacency | Blocks in a chunk and chunk selection may have randomized aspects |
| Segregation of “data-only” allocations | Separate allocations that don’t store pointers | Reduces attacker control over metadata or control fields |
Interaction with Memory Integrity Enforcement (MIE / EMTE)
- MIE (Memory Integrity Enforcement) ya Apple ni hardware + OS framework inayowezesha Enhanced Memory Tagging Extension (EMTE) katika mode ya always-on, synchronous across maeneo makubwa ya attack surface.
- xzone allocator ni msingi muhimu wa MIE katika user space: allocations zinazofanywa kupitia xzone zinapata tags, na accesses zinakaguliwa na hardware.
- Katika MIE, allocator, tag assignment, metadata management, na tag confidentiality enforcement zimeunganishwa kuhakikisha kwamba memory errors (mfano stale reads, OOB, UAF) zinagunduliwa mara moja, sio kutumika baadaye.
- Ikiwa unataka, naweza pia kuunda cheat-sheet au mchoro wa xzone internals kwa kitabu chako. Unataka nifanye hivyo ifuatayo?
- :contentReference[oai:20]{index=20}
(Old) Physical Use-After-Free via IOSurface
Ghidra Install BinDiff
Download BinDiff DMG kutoka https://www.zynamics.com/bindiff/manual and install it.
Open Ghidra with ghidraRun and go to File –> Install Extensions, press the add button and select the path /Applications/BinDiff/Extra/Ghidra/BinExport and click OK and isntall it even if there is a version mismatch.
Using BinDiff with Kernel versions
- Go to the page https://ipsw.me/ and download the iOS versions you want to diff. These will be
.ipswfiles. - Decompress until you get the bin format of the kernelcache of both
.ipswfiles. You have information on how to do this on:
macOS Kernel Extensions & Kernelcache
- Open Ghidra with
ghidraRun, create a new project and load the kernelcaches. - Open each kernelcache so they are automatically analyzed by Ghidra.
- Then, on the project Window of Ghidra, right click each kernelcache, select
Export, select formatBinary BinExport (v2) for BinDiffand export them. - 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.
JSKit-Based Safari Chains and PREYHUNTER Stagers
Renderer RCE abstraction with JSKit
- Reusable entry: Hivi karibuni chains za in-the-wild zilitumia WebKit JIT bug (patched kama CVE-2023-41993) kupata tu arbitrary read/write ya JavaScript-level. Exploit mara moja iligeuza primitive hiyo hadi framework iliyonunuliwa inayoitwa JSKit, hivyo bug yoyote ya baadaye ya Safari inahitaji tu kutoa primitive ile ile.
- Version abstraction & PAC bypasses: JSKit inajumuisha support kwa safu kubwa ya iOS releases pamoja na moduli mbalimbali za kuchagua za Pointer Authentication Code bypass. Framework inafingerprint target build, inachagua PAC bypass logic inayofaa, na inathibitisha kila hatua (primitive validation, shellcode launch) kabla ya kuendelea.
- Manual Mach-O mapping: JSKit inachambua Mach-O headers moja kwa moja kutoka memory, inaamua symbols inayohitajika ndani ya dyld-cached images, na inaweza kualika Mach-O payloads ziendelee bila kuziandika kwenye disk. Hii inafanya renderer process kubaki in-memory tu na kuepuka code-signature checks zinazohusishwa na filesystem artifacts.
- Portfolio model: Debug strings kama “exploit number 7” zinaonyesha kwamba suppliers wanatunza exploits nyingi zinazoweza kubadilishwa. Mara primitive ya JS inafanana na interface ya JSKit, sehemu nyingine za chain hazibadiliki kati ya campaigns.
Kernel bridge: IPC UAF -> code-sign bypass pattern
- Kernel IPC UAF (CVE-2023-41992): Stage ya pili, ikiwa bado inafanya kazi ndani ya Safari context, inasababisha kernel use-after-free katika IPC code, inare-allocate object iliyofunguliwa kutoka userland, na inatumia dangling pointers kupeleka hadi arbitrary kernel read/write. Stage pia inareuse PAC bypass material iliyohesabiwa awali na JSKit badala ya kuunda upya.
- Code-signing bypass (CVE-2023-41991): Pamoja na kernel R/W inapatikana, exploit ina-patch trust cache / code-signing structures hivyo payloads zisizosisitishwa zinaweza kutekeleza kama
system. Stage kisha inafungua huduma nyepesi ya kernel R/W kwa payloads za baadaye. - Composed pattern: Chain hii inaonyesha recipe inayoweza kutumika tena ambayo defenders wanapaswa kutegemea kuendelea mbele:
WebKit renderer RCE -> kernel IPC UAF -> kernel arbitrary R/W -> code-sign bypass -> unsigned system stager
Moduli za helper na watcher za PREYHUNTER
-
Watcher anti-analysis: Binary maalum ya Watcher inafanya profaili ya kifaa kwa kuendelea na inasimamisha kill-chain pale mazingira ya utafiti yanapotambuliwa. Inachunguza
security.mac.amfi.developer_mode_status, uwepo wa console yadiagnosticd, localesUSauIL, alama za jailbreak kama Cydia, michakato kamabash,tcpdump,frida,sshd, aucheckrain, mobile AV apps (McAfee, AvastMobileSecurity, NortonMobileSecurity), mipangilio ya proxy ya HTTP ya kawaida, na custom root CAs. Kosa lolote la ukaguzi linazuia utoaji wa payload zaidi. -
Helper surveillance hooks: Kipengele cha helper husikizana na hatua nyingine kupitia
/tmp/helper.sock, kisha inaleta seti za hook zilizoitwa DMHooker na UMHooker. Hizi hooks zinagusa njia za sauti za VOIP (rekodi zinawekwa chini ya/private/var/tmp/l/voip_%lu_%u_PART.m4a), zinaweka keylogger ya mfumo mzima, zinachukua picha bila UI, na ku-hook SpringBoard ili kuzima arifa ambazo vitendo hivyo kawaida vingesababisha. Kwa hivyo helper hutumika kama tabaka la kuthibitisha kwa siri + uangalizi mwepesi kabla ya implants nzito kama Predator kuzinduliwa. -
HiddenDot indicator suppression in SpringBoard: Kwa injection ya code kwenye kernel, Predator inahook
SBSensorActivityDataProvider._handleNewDomainData:(mhimili wa kukusanya shughuli za sensor). Hook inafanya pointer ya Objective-Cself(x0) kuwa sifuri hivyo wito unakuwa[nil _handleNewDomainData:newData], ukiacha masasisho ya kamera/mikrofoni na kuzima vidoti vya kijani na machungwa. -
Mach exception-based hooking flow (DMHooker): Hooks zinatekelezwa kupitia
EXC_BREAKPOINT+ exception ports, kishathread_set_statehubadilisha rejista na utekelezaji unaendelea. Return code2ina maana “endelea na modified thread state.” -
PAC-aware redirection for camera access checks: Katika
mediaserverd, pattern-scan (kwa mfanomemmem) hupata routine binafsi karibu naFigVideoCaptureSourceCreateWithSourceInfondani yaCMCapture.framework. Hook inarudisha3ili kurekebisha kwa kutumia pre-signed PAC cached return address, ikitimiza PAC huku ikiepuka ukaguzi. -
VoIP capture pipeline in
mediaserverd: InahookAudioConverterNewnaAudioConverterConvertComplexBuffer+52kushika buffers, kubaini sample rate kutoka kwa ukubwa wa buffer, kubadilisha float32 PCM → int16 kwa NEON, downmix 4-channel hadi stereo, na kuhifadhi kupitiaExtAudioFileWrite(). Moduli ya VoIP yenyewe haisitishi viashiria, hivyo waendeshaji lazima waamsha HiddenDot tofauti.
WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)
Webkit Dfg Store Barrier Uaf Angle Oob
iMessage/Media Parser Zero-Click Chains
Imessage Media Parser Zero Click Coreaudio Pac Bypass
Marejeleo
- https://www.jamf.com/blog/predator-spyware-ios-recording-indicator-bypass-analysis/
- Google Threat Intelligence – Intellexa zero-day exploits continue
Tip
Jifunze na fanya mazoezi ya AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.


