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

iOS Exploit Mitigations

1. Code Signing / Runtime Signature Verification

Introduced early (iPhone OS → iOS) Hii ni moja ya kinga za msingi: code zote zinazotekelezwa (apps, dynamic libraries, JIT-ed code, extensions, frameworks, caches) lazima ziwe zimesainiwa kwa njia ya cryptographic na mnyororo wa vyeti ulioanzia kwenye chanzo cha Apple. Wakati wa runtime, kabla ya kupeleka binary kwenye memory (au kabla ya kutenda jumps kuvuka mipaka fulani), mfumo unakagua saini yake. Ikiwa code imebadilishwa (bit-flipped, patched) au haina saini, uingizaji unashindikana.

  • Inazuia: hatua ya “classic payload drop + execute” katika exploit chains; injection ya arbitrary code; kubadilisha binary iliyopo kuingiza mantiki mbaya.
  • Maelezo ya mekanismu:
  • The Mach-O loader (na dynamic linker) hukagua code pages, segments, entitlements, team IDs, na kwamba saini inafunika yaliyomo kwenye faili.
  • Kwa maeneo ya memory kama JIT caches au code inayozalishwa dinamikali, Apple inalazimisha kwamba pages ziwe zimesainiwa au kuthibitishwa kupitia APIs maalumu (mfano mprotect with code-sign checks).
  • Saini inajumuisha entitlements na identifiers; OS inalazimisha kwamba API fulani au uwezo wenye privelege unahitaji entitlements maalumu ambazo haziwezi kuigizwa.
Example Tuseme exploit inapata code execution katika process na inajaribu kuandika shellcode kwenye heap na kuruka kuelekea. Katika iOS, page hiyo ingehitaji kuwekewa alama executable **na** kukidhi vigezo vya code-signature. Kwa sababu shellcode haisainiwa na cheti cha Apple, jump itanukia au mfumo utakata kuifanya memory region hiyo iwe executable.

2. CoreTrust

Introduced around iOS 14+ era (or gradually in newer devices / later iOS) CoreTrust ni subsystem inayofanya runtime signature validation ya binaries (ikijumlisha system na user binaries) dhidi ya Apple’s root certificate badala ya kutegemea cached userland trust stores.

  • Inazuia: kuharibu binaries baada ya installation, jailbreak techniques zinazojaribu kubadilisha au kupatch system libraries au user apps; kudanganya mfumo kwa kubadilisha binaries zinazotambulika na vitendo vibaya.
  • Maelezo ya mekanismu:
  • Badala ya kuamini local trust database au certificate cache, CoreTrust inafanya reference kwa root ya Apple moja kwa moja au kuthibitisha intermediate certificates katika mnyororo salama.
  • Inahakikisha kwamba mabadiliko (mfano kwenye filesystem) kwa binaries zilizopo yanatambuliwa na kukataliwa.
  • Inashikilia entitlements, team IDs, code signing flags, na metadata nyingine kwa binary wakati wa load.
Example Jailbreak inaweza kujaribu kubadilisha `SpringBoard` au `libsystem` kwa version iliyopatchiwa kupata persistence. Lakini wakati loader ya OS au CoreTrust inakagua, inagundua kutofanana kwa saini (au entitlements zilizo badilika) na inakataza 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 inalazimisha kwamba pages zilizotajwa kuwa writable (kwa data) zisiwe executable, na pages zilizotajwa kuwa executable zisiwe writable. Huwezi tu kuandika shellcode kwenye heap au stack na kuiteketeza.

  • Inazuia: execution ya shellcode moja kwa moja; classic buffer-overflow → jump kwenda injected shellcode.
  • Maelezo ya mekanismu:
  • MMU / memory protection flags (kupitia page tables) zinafanya utofauti huo.
  • Jaribio lolote la kuweka writable page kuwa executable linasababisha ukaguzi wa mfumo (na ama hukatazwa au linahitaji idhini ya code-sign).
  • Katika mengi ya kesi, kufanya pages ziwe executable kunahitaji kupitia OS APIs ambazo zinalazimisha masharti au ukaguzi zaidi.
Example Overflow inaandika shellcode kwenye heap. Mshambuliaji anajaribu `mprotect(heap_addr, size, PROT_EXEC)` ili kuiifanya executable. Lakini mfumo unakataa au unathibitisha kwamba page mpya lazima ipitie vigezo vya code-sign (ambavyo shellcode haiwezi).

4. Address Space Layout Randomization (ASLR)

Introduced in iOS ~4–5 era (roughly iOS 4–5 timeframe) ASLR inarandamiza base addresses za maeneo muhimu ya memory: libraries, heap, stack, n.k., kila kuanzisha process. Anuai za gadgets hubadilika kati ya run.

  • Inazuia: hardcoding anaddresses za gadgets kwa ROP/JOP; exploit chains static; kuruka kinyume kwa offsets zilizo wazi.
  • Maelezo ya mekanismu:
  • Kila library iliyopakiwa / dynamic module inarekebishwa (rebased) kwenye offset iliyorandamizwa.
  • Stack na heap base pointers zinarandamizwa (chini ya mipaka ya entropy).
  • Wakati mwingine maeneo mengine (mfano mmap allocations) pia yarandamizwa.
  • Ukiwashiliana na mitigations za information-leak, inawalazimisha mshambuliaji kwanza kutokeza anaddress au pointer ili kugundua base addresses wakati wa runtime.
Example ROP chain inategemea gadget kwenye `0x….lib + offset`. Lakini kwa kuwa `lib` imehamishwa tofauti kila run, chain iliyosakinishwa inashindwa. Exploit lazima kwanza ifichue 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 user, KASLR inarandamiza base ya kernel text na miundo mingine ya kernel wakati wa boot.

  • Inazuia: kernel-level exploits zinazotegemea mahali maalumu pa kernel code au data; static kernel exploits.
  • Maelezo ya mekanismu:
  • Kila boot, base address ya kernel inarandamizwa (katika range fulani).
  • Data structures za kernel (kama task_structs, vm_map, n.k.) pia zinaweza kuhamishwa au kupangwa kwa offsets.
  • Washambuliaji lazima kwanza wachome pointers za kernel au watumie vulnerabilities za information disclosure ili kuhesabu offsets kabla ya kubadilisha kernel structures au code.
Example Vulnerability ya lokal inakusudia kuharibu kernel function pointer (mfano kwenye `vtable`) kwa `KERN_BASE + offset`. Lakini kwa kuwa `KERN_BASE` haijulikani, mshambuliaji lazima atokeze kwanza (mfano kwa read primitive) kabla ya kuhesabu address sahihi ya kuharibu.

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) inafuatilia kwa mara kwa mara integriti ya kernel text pages (kupitia hash au checksum). Ikiwa inagundua kuharibiwa (patches, inline hooks, mabadiliko ya code) nje ya windows zilizoidhinishwa, inasababisha kernel panic au reboot.

  • Inazuia: patching ya kudumu ya kernel (kubadilisha maelekezo ya kernel), inline hooks, kuandika tena function statiki.
  • Maelezo ya mekanismu:
  • Moduli ya hardware au firmware inafuatilia eneo la kernel text.
  • Kwa vipindi vya mara kwa mara au on-demand inare-hash pages na kulinganisha na thamani zinazotarajiwa.
  • Ikiwa kuna mismatch nje ya windows za update zisizo hatari, inafanya panic kwa kifaa (ili kuepuka patchi za kudumu za mbaya).
  • Washambuliaji lazima waiache windows za ugunduzi au watumie njia halali za patch.
Example Exploit inajaribu kupatch prologue ya kernel function (mfano `memcmp`) ili kuchukua maelekezo. Lakini KPP inagundua kuwa page ya code hairi haikubaliki na inasababisha kernel panic, ikifunga kifaa kabla patch iwe imara.

7. Kernel Text Read‐Only Region (KTRR)

Introduced in modern SoCs (post ~A12 / newer hardware) KTRR ni mekanismu inayolindwa na hardware: mara kernel text imefungwa mapema wakati wa boot, inakuwa read-only kutoka EL1 (kernel), ikizuia kuandika zaidi kwenye code pages.

  • Inazuia: mabadiliko yoyote ya kernel code baada ya boot (mfano patching, code injection in-place) kwa ngazi ya udhibiti EL1.
  • Maelezo ya mekanismu:
  • Wakati wa boot (katika hatua ya secure/bootloader), memory controller (au unit ya hardware salama) inaweka physical pages za kernel text kuwa read-only.
  • Hata kama exploit inapata privileges kamili za kernel, haiwezi kuandika kwenye pages hizo ili kupatch instructions.
  • Ili kuzibadilisha, mshambuliaji lazima kwanza aendelee kuvunja chain ya boot, au kuharibu KTRR yenyewe.
Example Exploit ya privilege-escalation inaruka kuingia EL1 na kuandika trampoline kwenye kernel function (mfano katika `syscall` handler). Lakini kwa sababu pages zimefungwa read-only na KTRR, kuandika kunashindwa (au kunasababisha fault), hivyo patch haitekelezwi.

8. Pointer Authentication Codes (PAC)

Introduced with ARMv8.3 (hardware), Apple beginning with A12 / iOS ~12+

  • PAC ni kipengele cha hardware kilichowasilishwa katika ARMv8.3-A kutambua uharibu wa pointer values (return addresses, function pointers, certain data pointers) kwa kuingiza saini ndogo ya cryptographic (“MAC”) katika bits za juu zisizotumika za pointer.
  • Saini (“PAC”) huhesabiwa juu ya pointer value pamoja na modifier (thamani ya context, mfano stack pointer au data inayotofautisha). Kwa hivyo pointer ile ile katika context tofauti inapata PAC tofauti.
  • Wakati wa matumizi, kabla ya dereferencing au branching kupitia pointer hiyo, maagizo ya authenticate hukagua PAC. Ikiwa halali, PAC inaondolewa na pointer safi inapatikana; ikiwa si sahihi, pointer inakuwa “poisoned” (au fault inatolewa).
  • Vifunguo vinavyotumika kutengeneza/kuhakiki PAC viko katika rejista za kiwango cha privelege (EL1, kernel) na haviwezi kusomwa moja kwa moja kutoka user mode.
  • Kwa sababu si bit zote za 64 za pointer zinatumika katika mifumo mingi (mfano 48-bit address space), bits za juu ni “spare” na zinaweza kuhifadhi PAC bila kubadilisha address halisi.

Architectural Basis & Key Types

  • ARMv8.3 inatambulisha vifunguo vitano vya 128-bit (kila kimojawapo kinatekelezwa kupitia rejista mbili za 64-bit) kwa pointer authentication.

  • APIAKey — kwa instruction pointers (domain “I”, key A)

  • APIBKey — key ya pili ya instruction pointers (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 data isiyo-pointer au matumizi mengine ya jumla

  • Vifunguo hivi vinahifadhiwa katika system registers za privelege (zinazopatikana tu kwa EL1/EL2 n.k.), hazipatikani kutoka user mode.

  • PAC huhesabiwa kupitia kazi ya cryptographic (ARM inapendekeza QARMA kama algorithm) ikitumia:

  1. Thamani ya pointer (sehemu canonical)
  2. modifier (thamani ya context, kama salt)
  3. siri key
  4. logic ya tweak ndani Ikiwa PAC inayotokana inalingana na ile iliyohifadhiwa katika bits za juu za pointer, authentication inafanikiwa.

Instruction Families

Mchoro wa majina ni: PAC / AUT / XPAC, kisha herufi za domain.

  • PACxx maagizo husaini pointer na kuingiza PAC
  • AUTxx maagizo huthibitisha + hutoa (validate na kuondoa PAC)
  • XPACxx maagizo huondoa PAC bila kuthibitisha

Domains / nafupisho:

MnemonicMeaning / DomainKey / DomainExample Usage in Assembly
PACIASign instruction pointer with APIAKey“I, A”PACIA X0, X1 — sign pointer in X0 using APIAKey with modifier X1
PACIBSign instruction pointer with APIBKey“I, B”PACIB X2, X3
PACDASign data pointer with APDAKey“D, A”PACDA X4, X5
PACDBSign data pointer with APDBKey“D, B”PACDB X6, X7
PACG / PACGAGeneric (non-pointer) signing with APGAKey“G”PACGA X8, X9, X10 (sign X9 with modifier X10 into X8)
AUTIAAuthenticate APIA-signed instruction pointer & strip PAC“I, A”AUTIA X0, X1 — check PAC on X0 using modifier X1, then strip
AUTIBAuthenticate APIB domain“I, B”AUTIB X2, X3
AUTDAAuthenticate APDA-signed data pointer“D, A”AUTDA X4, X5
AUTDBAuthenticate APDB-signed data pointer“D, B”AUTDB X6, X7
AUTGAAuthenticate generic / blob (APGA)“G”AUTGA X8, X9, X10 (validate generic)
XPACIStrip PAC (instruction pointer, no validation)“I”XPACI X0 — remove PAC from X0 (instruction domain)
XPACDStrip PAC (data pointer, no validation)“D”XPACD X4 — remove PAC from data pointer in X4

Kuna fomu maalumu / alias:

  • PACIASP ni ufupisho wa PACIA X30, SP (saini link register ukitumia SP kama modifier)
  • AUTIASP ni AUTIA X30, SP (thibitisha link register ukitumia SP)
  • Fomu zilizochanganywa kama RETAA, RETAB (authenticate-and-return) au BLRAA (authenticate & branch) zipo katika nyongeza za ARM / msaada wa compiler.
  • Pia kuna variant zisizo na modifier: PACIZA / PACIZB ambapo modifier ni implicitly zero, n.k.

Modifiers

Lengo kuu la modifier ni kufunga PAC kwa context maalumu ili pointer ile ile iliyo sainiwa katika context tofauti itengeneze PAC tofauti. Hii inazuia kutumia pointer moja kwa moja katika frames au objects tofauti. Ni kama kuongeza salt kwa hash.

Kwa hivyo:

  • modifier ni thamani ya context (rejista nyingine) inayojumishwa kwenye utengenezaji wa PAC. Chaguo za kawaida: stack pointer (SP), frame pointer, au object ID.
  • Kutumia SP kama modifier ni kawaida kwa signing ya return address: PAC inafungwa kwa frame ya stack maalumu. Ikiwa utajaribu kutumia LR katika frame tofauti, modifier inabadilika, basi uthibitisho wa PAC unashindwa.
  • Pointer ile ile iliyosainiwa kwa modifiers tofauti itatoa PAC tofauti.
  • modifier haihitaji kuwa siri, lakini ni bora isiwe chini ya udhibiti wa mshambuliaji.
  • Kwa maagizo yanayosaini au kuhakiki pointers ambako hakuna modifier yenye maana, baadhi ya fomu zinatumia zero au constant ya implicit.

Apple / iOS / XNU Customizations & Observations

  • Implementations za Apple za PAC zinajumuisha per-boot diversifiers hivyo vifunguo au tweaks hubadilika kila boot, kuzuia matumizi tena kati ya boots.
  • Pia zinajumuisha cross-domain mitigations ili PAC zilizotiwa saini katika user mode zisizotumika kirahisi tena katika kernel mode, n.k.
  • Katika Apple M1 / Apple Silicon, reverse engineering ilionyesha kuwa kuna aina tisa za modifier na rejista za system maalumu za Apple kwa udhibiti wa keys.
  • Apple inatumia PAC katika subsystems nyingi za kernel: kusaini return addresses, integriti ya pointers katika kernel data, signed thread contexts, n.k.
  • Google Project Zero ilionyesha jinsi kwa primitive ya kusoma/kuandika memory yenye nguvu katika kernel, mtu angeweza kuunda PAC za kernel (kwa A keys) kwenye vifaa vya A12-era, lakini Apple ilifunga njia nyingi za hayo.
  • Katika mfumo wa Apple, baadhi ya keys ni global across kernel, wakati processes za user zinaweza kupata randomness ya per-process kwa keys.

PAC Bypasses

  1. Kernel-mode PAC: theoretical vs real bypasses
  • Kwa sababu keys na mantiki za kernel PAC zinadhibitiwa kwa ukali (rejista za privelege, diversifiers, domain isolation), kuunda pointer zilizosainiwa za kernel kwa hiari ni ngumu sana.
  • Azad’s 2020 “iOS Kernel PAC, One Year Later” inaripoti kuwa katika iOS 12-13, alipata bypasses za sehemu (signing gadgets, reuse ya signed states, indirect branches zisizolindwa) lakini hakuna bypass ya jumla. bazad.github.io
  • Apple’s “Dark Magic” customizations zinapunguza zaidi maeneo ya kutegemewa (domain switching, per-key enabling bits). i.blackhat.com
  • Kuna CVE inayojulikana ya kernel PAC bypass CVE-2023-32424 kwenye Apple silicon (M1/M2) iliyoripotiwa na Zecao Cai et al. i.blackhat.com
  • Lakini bypasses hizi mara nyingi zinategemea gadgets maalumu au bugs za implemention; si za matumizi ya jumla.

Hivyo kernel PAC inachukuliwa kuwa imara sana, ingawa si kamili.

  1. User-mode / runtime PAC bypass techniques

Hizi zinatokea mara kwa mara, na hutumia mapungufu jinsi PAC inavyotekelezwa au kutumika katika dynamic linking / runtime frameworks. Hapa chini ni madaraja, na mifano.

2.1 Shared Cache / A key issues

  • The dyld shared cache ni blob kubwa ya pre-linked system frameworks na libraries. Kwa sababu inashirikiwa sana, function pointers ndani ya shared cache zinakuwa “pre-signed” kisha zikitumika na processes nyingi. Washambuliaji wanawalenga hizi pointers tayari zimesainiwa kama “PAC oracles”.

  • Baadhi ya mbinu za bypass zinajaribu kutoa au kutumia A-key signed pointers zilizopo kwenye shared cache na kuzitumia katika gadgets.

  • Mzungumzo wa “No Clicks Required” unaelezea jinsi ya kujenga oracle juu ya shared cache ili kufahamu addresses za relative na kuziunganisha na pointers zilizotiwa saini ili kuzuia PAC. saelo.github.io

  • Pia, imports za function pointers kutoka shared libraries katika userspace zilizotambuliwa zilipatikana kuwa hazilindwa vya kutosha na PAC, zikimruhusu mshambuliaji kupata function pointers bila kubadilisha saini yao. (Project Zero bug entry) bugs.chromium.org

2.2 dlsym(3) / dynamic symbol resolution

  • Mojawapo ya bypass inayojulikana ni kuita dlsym() kupata function pointer ambayo tayari imeandikwa saini (signed with A-key, diversifier zero) na kisha kuitumia. Kwa sababu dlsym inarudisha pointer iliyo sahihi kisheria, kutumia hiyo kunakwepa haja ya kuigiza PAC.

  • Blog ya Epsilon inaelezea jinsi baadhi ya bypasses zinatumia hili: kuita dlsym("someSym") hurudisha pointer iliyosainiwa na inaweza kutumika kwa indirect calls. blog.epsilon-sec.com

  • Synacktiv’s “iOS 18.4 — dlsym considered harmful” inaelezea bug: symbols fulani zilizorekebishwa kupitia dlsym kwenye iOS 18.4 zinarudisha pointers zilizosainiwa vibaya (au zilizo na diversifiers buggy), kuweka uwezo wa bypass ya PAC bila kutarajia. Synacktiv

  • Logic katika dyld kwa dlsym inajumuisha: wakati result->isCode, wanamsaini pointer iliyorejeshwa kwa __builtin_ptrauth_sign_unauthenticated(..., key_asia, 0), yaani context zero. blog.epsilon-sec.com

Kwa hivyo, dlsym ni vector ya mara kwa mara katika bypasses za user-mode PAC.

2.3 Other DYLD / runtime relocations

  • Loader ya DYLD na logic ya dynamic relocation ni tata na kwa wakati mwingine huwa inamepanga pages kuwa read/write kufanya relocations, kisha kuzirudisha read-only. Washambuliaji hutumia windows hizi. Mzungumzo wa Synacktiv unaelezea “Operation Triangulation”, bypass ya PAC inayotegemea timing kupitia dynamic relocations. Synacktiv

  • DYLD pages sasa zinalindwa kwa SPRR / VM_FLAGS_TPRO (bendera za ulinzi kwa dyld). Lakini toleo la awali lilikuwa na ulinzi dhaifu. Synacktiv

  • Katika webkit exploit chains, DYLD loader mara nyingi ni lengo la PAC bypass. Slides zinaonyesha kuwa bypass nyingi za PAC zimetegemea DYLD loader (kupitia relocation, interposer hooks). Synacktiv

2.4 NSPredicate / NSExpression / ObjC / SLOP

  • Katika exploit chains za userland, Objective-C runtime methods kama NSPredicate, NSExpression au NSInvocation hutumika kusafirisha wito za control bila kuonekana wazi kwa kuigiza pointers.

  • Katika iOS ya zamani (kabla ya PAC), exploit ilitumia fake NSInvocation objects kuita selectors yoyote kwenye memory iliyodhibitiwa. Kwa PAC, mbinu zilihitajika mabadiliko. Lakini mbinu ya SLOP (SeLector Oriented Programming) ilitengenezwa tena chini ya PAC pia. Project Zero

  • Mbinu ya asili ya SLOP iliruhusu kuunganisha ObjC calls kwa kuunda fake invocations; bypass inategemea kwamba ISA au selector pointers wakati mwingine hazilindwa kabisa na PAC. Project Zero

  • Katika mazingira ambapo pointer authentication inatekelezwa kwa sehemu, methods / selectors / target pointers huenda hazilindwi kwa PAC kwa njia kamili, zikitoa fursa 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>Example</summary>
Overflow ya buffer hubadilisha anwani ya return kwenye stack. Mshambuliaji anaandika anwani ya gadget inayolengwa lakini hawezi kuhesabu PAC sahihi. Wakati function inarudisha, instruction ya CPU `AUTIA` inatoa fault kwa sababu PAC haikutoshea. Mnyororo unashindwa.
Project Zero’s analysis on A12 (iPhone XS) ilionyesha jinsi Apple’s PAC inavyotumika na mbinu za kutengeneza PACs ikiwa mshambuliaji ana primitive ya kusoma/kuandika memory.
</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, target lazima ianze na **BTI landing pad** (`BTI j` au `BTI c`). Kuruka ndani ya anwani za gadget ambazo hazina landing pad husababisha exception.

LLVM’s implementation inataja aina tatu za BTI instructions 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) | Put at entry of functions that may be called indirectly |
| **BTI J** | Targets of *jump*-style branches (e.g. `BR` used for tail calls) | Placed at the beginning of blocks reachable by jump tables or tail-calls |
| **BTI JC** | Acts as both C and J | Can be targeted by either call or jump branches |

- Katika code iliyokomilishwa na branch target enforcement, compilers huingiza BTI instruction (C, J, au JC) kwenye kila valid indirect-branch target (mwanzoni mwa functions au blocks zinazofikiwa kwa jumps) ili indirect branches ziweze kufanikiwa tu kwenye sehemu hizo.
- **Direct branches / calls** (yaani anwani zinazoendelea `B`, `BL`) **hazizuiwi** na BTI. Dhihirisho ni kwamba code pages zinaaminika na mshambuliaji hawezi kuzibadilisha (kwa hivyo direct branches ni salama).
- Pia, **RET / return** instructions kwa ujumla hazizuiliwi na BTI kwa sababu anwani za return zinatulindwa kupitia PAC au mekanisimu za return signing.

#### Mechanism and enforcement

- Wakati CPU inatafsiri **indirect branch (BLR / BR)** kwenye page iliyotumwa kama “guarded / BTI-enabled,” inakagua kama instruction ya kwanza kwenye anwani ya target ni BTI halali (C, J, au JC kama zilivyo ruhusiwa). Ikiwa siyo, hutokea **Branch Target Exception**.
- BTI instruction encoding imeundwa kutumia opcodes ambazo awali zilihifadhiwa kwa NOPs (katika matoleo ya ARM ya awali). Hivyo binaries zilizo BTI-enabled zinabaki compatible nyuma: kwenye hardware bila BTI support, instructions hizo zinafanya kazi kama NOPs.
- Compiler passes zinazoongeza BTIs huzuia kuingiza BTI tu pale inapo hitajika: functions ambazo zinaweza kuitwa indirectly, au basic blocks zinazolengwa na jumps.
- Baadhi ya patches na code za LLVM zinaonyesha kwamba BTI haingeingizwa kwa *kila* basic block — ni kwa blocks ambazo zinaweza kuwa branch targets pekee (mfano kutoka switch / jump tables).

#### BTI + PAC synergy

PAC inalinda thamani ya pointer (chanzo) — inahakikisha mnyororo wa indirect calls / returns haujakatwakatwa.

BTI inahakikisha kwamba hata pointer halali lazima ilenge tu entry points zilizo marked ipasavyo.

Ikiwa vimeunganishwa, mshambuliaji anahitaji pointer halali yenye PAC sahihi na kwamba target lazima iwe na BTI imewekwa hapo. Hii inafanya kuwa ngumu zaidi kujenga gadget za exploit.

#### Example


<details>
<summary>Example</summary>
Exploit inajaribu kupinda hadi gadget kwenye `0xABCDEF` ambayo haianza na `BTI c`. CPU, inapotekeleza `blr x0`, inakagua target na inatoa fault kwa sababu alignment ya instruction haina landing pad halali. Hivyo gadgets nyingi zinakuwa zisizotumika isipokuwa zile zenye 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 kilichowasilishwa katika **ARMv8.1-A** kinachozuia **privileged code** (EL1 or EL2) kutoka **kusoma au kuandika** memory iliyo marked kama **user-accessible (EL0)**, isipokuwa PAN imezimwa kwa wazi.
- Wazo ni: hata kama kernel imeledeshwa au imebambikiwa, haiwezi ku-referenza pointers za user-space kiholela bila kwanza *kuzima* PAN, hivyo kupunguza hatari za exploits za mtindo wa **`ret2usr`** au matumizi mabaya ya buffers zinazoendeshwa na user.
- Wakati PAN imewezeshwa (PSTATE.PAN = 1), instruction yoyote ya privileged load/store inayofikia virtual address inayosemwa “accessible at EL0” husababisha **permission fault**.
- Kernel, wakati inahitaji kwa njia halali kufikia memory ya user-space (mfano copy data to/from user buffers), lazima **kuzima PAN kwa muda** (au kutumia instructions za “unprivileged load/store”) ili kuruhusu upatikanaji huo.
- Katika Linux kwenye ARM64, support ya PAN ilianzishwa takriban 2015: patches za kernel ziliongeza utambuzi wa kipengele, na kubadilisha `get_user` / `put_user` nk. na variantes ambazo zinafuta PAN wakati wa ufikaji wa memory za user.

**Key nuance / limitation / bug**
- Kama ilivyobainishwa na Siguza na wengine, hitilafu ya specification (au tabia isiyoeleweka) katika muundo wa ARM inamaanisha kwamba **execute-only user mappings** (`--x`) huenda **zisizokuwa chini ya PAN**. Kwa maneno mengine, ikiwa page ya user imewekwa executable bila ruhusa ya kusoma, jaribio la kernel kusoma linaweza kupitisha PAN kwa sababu architecture inachukulia “accessible at EL0” inahitaji ruhusa ya kusoma, sio tu execute. Hii inasababisha PAN bypass katika mipangilio fulani.
- Kwa sababu hiyo, ikiwa iOS / XNU inaruhusu pages za user ambazo ni execute-only (kama baadhi ya mipangilio ya JIT au code-cache), kernel huenda ikasoma kutoka kwenye hizo hata PAN ikiwa imewezeshwa. Hii ni eneo nyembamba la kawaida linaloweza kutumika katika baadhi ya ARMv8+ systems.

#### PXN (Privileged eXecute Never)

- **PXN** ni bit ya page table (katika page table entries, leaf au block entries) inayoonyesha kwamba page haiwezi kutekelezwa wakati inafanywa kwa privileged mode (yaani EL1 inapoendeshwa).
- PXN inazuia kernel (au code yoyote ya privileged) kutoka kuruka ndani au kutekeleza instruction kutoka kwenye user-space pages hata kama control imevurugwa. Kwa vitendo, inazuia redirection ya control-flow ya kernel kwenda kwenye memory ya user.
- Imeunganishwa na PAN, hii inahakikisha kwamba:
1. Kernel haiwezi (kwa default) kusoma au kuandika data ya user-space (PAN)
2. Kernel haiwezi kutekeleza code ya user-space (PXN)
- Katika ARMv8 page table format, entries za leaf zina bit ya `PXN` (na pia `UXN` kwa unprivileged execute-never) katika attribute bits zao.

Hivyo hata kama kernel ina pointer ya function iliyo corrupted ikielekeza kwenye memory ya user, na ikajaribu ku-branch 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 translation na permission model ya ARM inavyofanya kazi (imefupishwa):

- Kila page au block entry ina fields za attribute zikiwemo **AP[2:1]** kwa access permissions (read/write, privileged vs unprivileged) na bits za **UXN / PXN** kwa vizuizi vya execute-never.
- Wakati PSTATE.PAN ni 1 (imewezeshwa), hardware inatekeleza semantics zilizobadilishwa: privileged accesses kwa pages zilizo marked kama “accessible by EL0” (yaani user-accessible) zinakataliwa (fault).
- Kwa sababu ya bug iliyotajwa, pages zilizowekwa kuwa executable tu (bila ruhusa ya kusoma) huenda zisihesabiwe kama “accessible by EL0” chini ya utekelezaji fulani, hivyo kupitisha PAN.
- Wakati PXN ya page imewekwa, hata ikiwa instruction fetch inatoka kwa privilege level ya juu, utekelezaji unakatazwa.

#### Kernel usage of PAN / PXN in a hardened OS (e.g. iOS / XNU)

Katika muundo wa kernel ulioimarishwa (kama Apple inaweza kutumia):

- Kernel inawasha PAN kwa default (kwa hivyo code ya privileged imekatazwa).
- Katika njia zinazohitaji kwa hiari kusoma au kuandika buffers za user (mfano syscall buffer copy, I/O, read/write user pointer), kernel kwa muda **inakoma PAN** au inatumia instructions maalum kuziondoa.
- Baada ya kumaliza ufikaji wa data za user, lazima iwashe tena PAN.
- PXN inatekelezwa kupitia page tables: pages za user zina PXN = 1 (kwa hivyo kernel hawezi kuzitekeleza), pages za kernel hazina PXN (kwa hivyo code ya kernel inaweza kutekelezwa).
- Kernel lazima ihakikishe kwamba hakuna njia za code zitakazosababisha flow ya utekelezaji kwenda kwenye memory za user (ambazo zingeweza kupitisha PXN) — hivyo chain za exploit zinazotegemea “kuruka ndani ya shellcode ya user” zinazuamiwa.

Kwa sababu ya PAN bypass kupitia execute-only pages, katika mfumo halisi, Apple huenda ikazima au kupiga marufuku execute-only user pages, au kurekebisha hitilafu ya specification.

#### Attack surfaces, bypasses, and mitigations

- **PAN bypass via execute-only pages**: kama ilivyojadiliwa, spec ina nafasi: pages za user zenye execute-only (hakuna read perm) huenda zisihesabiwe kama “accessible at EL0,” hivyo PAN haitazuia kernel kusoma kutoka kwenye pages hizo katika utekelezaji fulani. Hii hutoa njia isiyo ya kawaida kwa mshambuliaji kuingiza data kupitia sehemu za “execute-only.”
- **Temporal window exploit**: ikiwa kernel inazima PAN kwa dirisha lenye muda mrefu zaidi ya inavyohitajika, race au njia mbaya inaweza kutumia dirisha hilo kufanya ufikaji usiolengwa wa memory za user.
- **Forgotten re-enable**: ikiwa njia za code zinashindwa kuwashe tena PAN, operesheni za kernel zisizofuata zinaweza kwa makosa kufikia memory ya user.
- **Misconfiguration of PXN**: ikiwa page tables hazowekwa PXN kwa user pages au kupangwa vibaya pages za code za user, kernel inaweza kushawishwa kutekeleza code ya user-space.
- **Speculation / side-channels**: sawa na speculative bypasses, kunaweza kuwa na athari za microarchitectural zinazosababisha uvunjaji wa muda wa PAN / PXN checks (ingawa mashambulizi kama hayo yanategemea sana muundo wa CPU).
- **Complex interactions**: Katika vipengele vya juu zaidi (mfano JIT, shared memory, eneo za code za just-in-time), kernel inaweza kuhitaji udhibiti wa karibu kuruhusu ufikaji fulani wa memory au utekelezaji katika regions za user; kubuni hayo salama chini ya vizingiti vya PAN/PXN si rahisi.

#### Example

<details>
<summary>Code Example</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

Ikiwa kernel haikuwa imeweka PXN kwenye ukurasa huo wa mtumiaji, basi tawi linaweza kufanikiwa — jambo ambalo lingekuwa lisilo salama.

Ikiwa kernel itasahau kuweka PAN tena baada ya upatikanaji wa kumbukumbu ya mtumiaji, inafungua dirisha ambapo mantiki nyingine za kernel zinaweza kwa bahati nasibu kusoma/kuandika kumbukumbu yoyote ya mtumiaji.

Ikiwa pointer ya mtumiaji inamaanisha ukurasa wa execute-only (ukurasa wa mtumiaji unaoruhusu tu utekelezaji, bila read/write), chini ya hitilafu ya spec ya PAN, `ldr W2, [X1]` inaweza **kuto**fanya fault hata PAN ikiwa imewezeshwa, kuwezesha bypass exploit, kulingana na utekelezaji.

</details>

<details>
<summary>Example</summary>
Udhaifu wa kernel hujaribu kuchukua function pointer iliyotolewa na mtumiaji na kuitisha katika muktadha wa kernel (yaani `call user_buffer`). Chini ya PAN/PXN, operesheni hiyo hairuhusiwi au husababisha fault.
</details>

---

### 11. **Top Byte Ignore (TBI) / Pointer Tagging**
**Iliyotambulishwa katika ARMv8.5 / mpya zaidi (au extension ya hiari)**
TBI inamaanisha top byte (most-significant byte) ya pointer ya 64-bit inapuuzwa na tafsiri ya anwani. Hii inaruhusu OS au hardware kuweka **tag bits** kwenye top byte ya pointer bila kuathiri anwani halisi.

- TBI inasimama kwa **Top Byte Ignore** (wakati mwingine huitwa *Address Tagging*). Ni kipengele cha hardware (kinachopatikana katika utekelezaji mwingi wa ARMv8+) kinacho **puuza 8 bit za juu** (bits 63:56) za pointer ya 64-bit wakati wa kufanya **address translation / load/store / instruction fetch**.
- Kwa vitendo, CPU hutawala pointer `0xTTxxxx_xxxx_xxxx` (ambapo `TT` = top byte) kama `0x00xxxx_xxxx_xxxx` kwa madhumuni ya tafsiri ya anwani, ikipuuzia (kuweka mask) top byte. Top byte inaweza kutumika na programu kuhifadhi **metadata / tag bits**.
- Hii inatoa programu nafasi ya in-band ya bure kuweka byte ya tag katika kila pointer bila kubadilisha eneo la kumbukumbu linalorejelewa.
- Mimaraka ya usanifu inahakikisha kuwa loads, stores, na instruction fetch hufanya kazi na pointer ambayo top byte imewekwa mask (yaani tag imeondolewa) kabla ya kufanya upatikanaji wa kumbukumbu.

Kwa hivyo TBI inatenganisha **logical pointer** (pointer + tag) kutoka kwa **physical address** inayotumika kwa operesheni za kumbukumbu.

#### Kwa Nini TBI: Matumizi na motisha

- **Pointer tagging / metadata**: Unaweza kuhifadhi metadata ya ziada (km., aina ya kitu, toleo, bounds, integrity tags) katika top byte hiyo. Ukiitumia pointer baadaye, tag inapuuzwa kwa ngazi ya hardware, kwa hivyo hautahitaji kuiondoa kwa mkono kabla ya upatikanaji wa kumbukumbu.
- **Memory tagging / MTE (Memory Tagging Extension)**: TBI ni mekanismo msingi wa hardware ambao MTE inajenga juu yake. Katika ARMv8.5, Memory Tagging Extension inatumia bits 59:56 za pointer kama **logical tag** na kuikagua dhidi ya **allocation tag** iliyohifadhiwa katika kumbukumbu.
- **Usalama na uadilifu ulioboreshwa**: Kwa kuunganisha TBI na pointer authentication (PAC) au ukaguzi wa runtime, unaweza kulazimisha si tu thamani ya pointer bali pia tag iwe sahihi. Mshambulizi anayebadilisha pointer bila tag sahihi atasababisha tag isiyolingana.
- **Ulinganifu**: Kwa kuwa TBI ni hiari na tag bits zinapuuzwa na hardware, nambari zisizo na tag za zamani zinaendelea kufanya kazi kawaida. Tag bits zinakuwa kama “don’t care” bits kwa nambari za zamani.

#### Mfano
<details>
<summary>Example</summary>
Function pointer ilikuwa na tag katika top byte yake (kwa mfano `0xAA`). Exploit inafunika bits za chini za pointer lakini inasahau tag, hivyo wakati kernel inathibitisha au kusanitize, pointer inashindwa au inakataliwa.
</details>

---

### 12. **Page Protection Layer (PPL)**
**Iliyotambulishwa katika iOS za karibuni / hardware ya kisasa (iOS ~17 / Apple silicon / mifano ya high-end)** (ripoti zingine zinaonyesha PPL kuanzia macOS / Apple silicon, lakini Apple inaletenga ulinzi sawia kwa iOS)

- PPL imeundwa kama mpaka wa ulinzi ndani ya kernel: hata kama kernel (EL1) imevamiwa na ina uwezo wa read/write, **haitakiwe kuweza kubadilisha kwa uhuru** baadhi ya **ukurasa nyeti** (hasa page tables, metadata ya code-signing, kurasa za msimbo wa kernel, entitlements, trust caches, n.k.).
- Inaunda kwa vitendo **“kernel ndani ya kernel”** — sehemu ndogo iliyothibitishwa (PPL) yenye **idhadhari zilizoinuliwa** pekee inaweza kubadilisha kurasa zilizoindwa. Msimbo mwingine wa kernel lazima uite taratibu za PPL ili kufanya mabadiliko.
- Hii inapunguza uso wa mashambulizi kwa exploits za kernel: hata ukiwa na arbitrary R/W/execute katika mode ya kernel, msimbo wa exploit lazima pia aingie katika uwanja wa PPL (au apite juu ya PPL) ili kubadilisha muundo muhimu.
- Kwenye Apple silicon za kisasa (A15+ / M2+), Apple inabadilisha kuelekea **SPTM (Secure Page Table Monitor)**, ambao katika visa vingi unachukua nafasi ya PPL kwa ulinzi wa page-table katika majukwaa hayo.

Hapa ni jinsi PPL inavyodhaniwa kufanya kazi, kulingana na uchambuzi wa umma:

#### Matumizi ya APRR / permission routing (APRR = Access Permission ReRouting)

- Hardware ya Apple inatumia mekanismo inayoitwa **APRR (Access Permission ReRouting)**, ambayo inaruhusu entry za page table (PTEs) kuwa na indices ndogo, badala ya bits kamili za ruhusa. Indices hizo huwekwa ramani kupitia rejista za APRR hadi ruhusa halisi. Hii inaruhusu upangaji wa nguvu wa ruhusa kwa kila domain.
- PPL inatumia APRR kutenganisha mamlaka ndani ya muktadha wa kernel: ni tu uwanja wa PPL unaoruhusiwa kusasisha ramani kati ya indices na ruhusa za kweli. Yaani, wakati msimbo wa kernel usio-PPL unaandika PTE au kujaribu kubadili bits za ruhusa, mantiki ya APRR inakataa (au inaweka kama read-only).
- Msimbo wa PPL unafanya kazi ndani ya eneo lililodhibitiwa (km. `__PPLTEXT`) ambalo kwa kawaida si executable au si writable hadi milango ya entry yawezeke kwa muda mfupi. Kernel inaita pointi za entry za PPL (“PPL routines”) kufanya operesheni nyeti.

#### Mlango / Entry & Exit

- Wakati kernel inahitaji kubadilisha ukurasa uliolindwa (km. kubadilisha ruhusa za ukurasa wa msimbo wa kernel, au kubadilisha page tables), inaita katika taratibu za **PPL wrapper**, ambayo hufanya uthibitisho kisha kuingia katika uwanja wa PPL. Nje ya uwanja huo, kurasa zilizo lindwa kwa vitendo zinakuwa read-only au hazitobadiliki na kernel kuu.
- Wakati wa kuingia PPL, ramani za APRR zinawekwa ili kuruhusu kurasa za eneo la PPL kuwa **executable & writable** ndani ya PPL. Baada ya kutoka, zinarejeshwa kuwa read-only / non-writable. Hii inahakikisha kuwa ni taratibu za PPL zilizothibitishwa tu zinaweza kuandika kurasa zilizo lindwa.
- Nje ya PPL, jaribio la msimbo wa kernel kuandika kwenye hizo kurasa litasababisha fault (permission denied) kwa sababu ramani ya APRR kwa domain hiyo ya msimbo haikubali uandishi.

#### Aina za kurasa zilizo lindwa

Kurasa ambazo PPL kwa kawaida inalinda ni pamoja na:

- Miundo ya page table (translation table entries, metadata za mapping)
- Kurasa za msimbo wa kernel, hasa zile zenye mantiki muhimu
- Metadata ya code-sign (trust caches, signature blobs)
- Jedwali za entitlements, meza za utekelezaji wa signature
- Miundo mingine ya kernel yenye thamani kubwa ambapo urekebishaji ungeruhusu kuvuka ukaguzi wa saini au kuharibu udhibitisho wa haki

Wazo ni kwamba hata kama kumbukumbu ya kernel iko chini ya udhibiti kamili, mshambuliaji hawezi tu kuiba au kuandika upya kurasa hizi, isipokuwa awe pia ameiba taratibu za PPL au apite juu ya PPL.

#### Bypasses & Udhaifu Zilizojulikana

1. **Project Zero’s PPL bypass (stale TLB trick)**

- Kifungu cha umma cha Project Zero kimeelezea bypass inayohusisha **stale TLB entries**.
- Wazo ni:

1. Tenga kurasa mbili za fizikali A na B, uzitaje kurasa za PPL (hivyo zinalinganiswa kama zilizo lindwa).
2. Ramisha anwani mbili za virtual P na Q ambazo L3 translation table pages zinatoka kwenye A na B.
3. Zungusha thread ili kufikia Q mara kwa mara, ukiweka entry yake ya TLB hai.
4. Ita `pmap_remove_options()` kuondoa mappings kuanzia P; kutokana na hitilafu, msimbo huondoa TTEs kwa P na Q, lakini inabadilisha invalidation ya TLB kwa P pekee, ikiacha entry ya TLB ya Q kuwa stale hai.
5. Tumia tena B (ukurasa wa jedwali wa Q) kuramisha kumbukumbu yoyote (km. kurasa zilizolindwa za PPL) kwa anwani zinazofaa. Kwa sababu entry ya stale TLB bado inaonyesha mapping ya zamani ya Q, ramani hiyo inabaki halali kwa muktadha huo.
6. Kupitia hili, mshambuliaji anaweza kuweka mapping inayoweza kuandikwa ya kurasa za PPL bila kupitia interface ya PPL.

- Exploit hii ilihitaji udhibiti mzuri wa ramani za fizikali na tabia ya TLB. Inaonyesha kwamba mpaka wa usalama unaotegemea TLB / usahihi wa ramani lazima kuwa makini sana kuhusu invalidations za TLB na usawazisho wa ramani.

- Project Zero walitoa maoni kuwa bypass za aina hii ni za ndogo na adimu, lakini zinawezekana katika mifumo tata. Hata hivyo, wanataja PPL kama upunguzaji thabiti.

2. **Hatari nyingine za uwezekano & masharti**

- Ikiwa exploit ya kernel inaweza kuingia moja kwa moja katika taratibu za PPL (kwa kuita PPL wrappers), inaweza kupita vikwazo. Hivyo uthibitisho wa hoja (argument validation) ni muhimu.
- Mende katika msimbo wa PPL yenyewe (km. arithmetic overflow, ukosefu wa ukaguzi wa mipaka) zinaweza kuruhusu mabadiliko nje ya mipaka ndani ya PPL. Project Zero waligundua kuwa hitilafu kama hiyo katika `pmap_remove_options_internal()` ilitumika katika bypass yao.
- Mpaka wa PPL umefungwa kisawasawa na utekelezaji wa hardware (APRR, memory controller), hivyo ni kama nguvu ya ulinzi inavyotegemea utekelezaji wa hardware.

#### Mfano
<details>
<summary>Code Example</summary>
Hapa kuna pseudocode iliyorahisishwa / mantiki inayoonyesha jinsi kernel inaweza kuita PPL ili kubadilisha kurasa zilizo lindwa:
```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

Kernels inaweza kufanya operesheni nyingi za kawaida, lakini kupitia tu ppl_call_* routines inaweza kubadilisha protected mappings au kurekebisha code.

Mfano Kernel exploit inajaribu kuandika juu ya entitlement table, au kuzima utekelezaji wa code-sign kwa kubadilisha kernel signature blob. Kwa kuwa ukurasa huo umeprotektiwa na PPL, uandishi unazuiachiwa isipokuwa ukitumia PPL interface. Hivyo hata ukiwa na kernel code execution, huwezi kuondoka vikwazo vya code-sign au kubadilisha data za credentials kiholela. Katika iOS 17+ baadhi ya vifaa vinatumia SPTM ili kutenganisha zaidi PPL-managed pages.

PPL → SPTM / Mbadala / Baadaye

  • Katika SoCs za kisasa za Apple (A15 au baadaye, M2 au baadaye), Apple inaunga mkono SPTM (Secure Page Table Monitor), ambayo inabadilisha PPL kwa ulinzi wa page table.
  • Apple inataja 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.”
  • Mimarike ya SPTM inaonekana kuhamisha utekelezaji wa sera zaidi kwa monitor yenye hadhi ya juu zaidi nje ya udhibiti wa kernel, na hivyo kupunguza mpaka wa kuamini.

MTE | EMTE | MIE

Hapa kuna maelezo ya ngazi ya juu jinsi EMTE inavyofanya kazi chini ya usanidi wa MIE wa Apple:

  1. Kuwekwa kwa tag
  • Wakati memory inapokatwa (mf. katika kernel au user space kupitia secure allocators), tag ya siri hutolewa kwa block hiyo.
  • Pointer inayorudiwa kwa user au kernel inajumuisha tag hiyo katika high bits zake (ikitumia TBI / top byte ignore mechanisms).
  1. Ukaguzi wa tag wakati wa kufikia
  • Kila wakati load au store inatekelezwa kwa kutumia pointer, hardware inakagua kwamba tag ya pointer inalingana na tag ya memory block (allocation tag). Ikiwa haifanani, huleta fault mara moja (kwa sababu ni synchronous).
  • Kwa kuwa ni synchronous, hakuna dirisha la “delayed detection”.
  1. Kuretagisha baada ya free / reuse
  • Wakati memory inafutwa, allocator hubadilisha tag ya block (hivyo pointers za zamani zenye tags za zamani hazitalingana tena).
  • Use-after-free pointer itakuwa na tag iliyokuwa stale na itashindwa wakati wa kufikiwa.
  1. Tofauti za neighbor-tag kugundua overflows
  • Allocations jirani zinapewa tags tofauti. Ikiwa buffer overflow inapovuja ndani ya memory ya jirani, kutokulingana kwa tag kusababisha fault.
  • Hii ni yenye nguvu hasa kugundua overflows ndogo zinazovuka boundary.
  1. Utekelezaji wa usiri wa tag
  • Apple lazima izui tag values kuvuja (kwa sababu kama attacker atajua tag, anaweza kuunda pointers zenye tags sahihi).
  • Wanaingiza ulinzi (microarchitectural / speculative controls) ili kuepuka side-channel leakage ya tag bits.
  1. Uingiliano wa kernel na user-space
  • Apple inatumia EMTE sio tu katika user-space bali pia katika kernel / vipengele muhimu vya OS (kuilinda 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>

#### Mikomo & changamoto

- **Intrablock overflows**: Ikiwa overflow inabaki ndani ya allocation ile ile (haivuki boundary) na tag inabaki ile ile, tag mismatch haitagunduliwa.
- **Tag width limitation**: Bits chache tu (mf. 4 bits, au domain ndogo) zinapatikana kwa tag—namespace ndogo.
- **Side-channel leaks**: Ikiwa tag bits zinaweza ku-leak (kupitia cache / speculative execution), mshambuliaji anaweza kujua tag sahihi na kuipita. Apple’s tag confidentiality enforcement inalenga kupunguza hili.
- **Performance overhead**: Tag checks kwa kila load/store huongeza gharama; Apple lazima i-optimize hardware kupunguza overhead.
- **Compatibility & fallback**: Kwenye hardware ya zamani au sehemu zisizounga mkono EMTE, lazima kuwe na fallback. Apple inadai MIE imewezeshwa tu kwenye vifaa vinavyounga mkono.
- **Complex allocator logic**: Allocator lazima idhibiti tags, retagging, kupanga mipaka, na kuepuka mis-tag collisions. Bugs katika logic ya allocator zinaweza kuleta udhaifu.
- **Mixed memory / hybrid areas**: Sehemu fulani za memory zinaweza kubaki zisizotag (legacy), hivyo kufanya interoperability kuwa ngumu.
- **Speculative / transient attacks**: Kama ilivyo kwa kinga nyingi za microarchitectural, speculative execution au micro-op fusions zinaweza kupita checks kwa muda mfupi au ku-leak tag bits.
- **Limited to supported regions**: Apple inaweza ku-enforce EMTE tu katika maeneo maalum yenye hatari kubwa (kernel, security-critical subsystems), sio ulimwenguni kote.

---

## Maboresho muhimu / tofauti ikilinganishwa na standard MTE

Hapa kuna maboresho na mabadiliko Apple anavyosisitiza:

| Sifa | Original MTE | EMTE (Apple’s enhanced) / MIE |
|---|---|---|
| **Hali ya ukaguzi** | Inasaidia synchronous na asynchronous modes. Katika async, tag mismatches huripotiwa baadaye (imecheleweshwa) | Apple inasisitiza **synchronous mode** kwa chaguo-msingi—tag mismatches zinalindwa mara moja, hakuna dirisha la kuchelewa/lengo la race.|
| **Coverage of non-tagged memory** | Upatikanaji wa non-tagged memory (mf. globals) unaweza kupita checks katika utekelezaji fulani | EMTE inahitaji kwamba upatikanaji kutoka eneo lililotag kwenda non-tagged memory pia uhakiki maarifa ya tag, kufanya kupita kwa mixing allocations kunekuwa ngumu.|
| **Tag confidentiality / secrecy** | Tags zinaweza kuonekana au leaked kupitia side channels | Apple inaongeza **Tag Confidentiality Enforcement**, inayojaribu kuzuia leakage ya tag values (kwa kupitia speculative side-channels n.k.).|
| **Allocator integration & retagging** | MTE inaacha sehemu kubwa ya logic ya allocator kwa software | Secure typed allocators za Apple (kalloc_type, xzone malloc, n.k.) zinaunganishwa na EMTE: wakati memory inapotengwa au kuachiliwa, tags zinadhibitiwa kwa granularity ndogo.|
| **Always-on by default** | Katika majukwaa mengi, MTE ni hiari au imezimwa kwa chaguo-msingi | Apple inawasha EMTE / MIE kwa chaguo-msingi kwenye hardware zinazo support (mf. iPhone 17 / A19) kwa kernel na michakato mingi za user-space.|

Kwa kuwa Apple inadhibiti hardware na software stack, inaweza ku-enforce EMTE kwa ukali, kuepuka matatizo ya performance, na kufunga mianya ya side-channel.

---

## Jinsi EMTE inavyofanya kazi kwa vitendo (Apple / MIE)

Hii ni maelezo ya juu ya jinsi EMTE inavyofanya kazi chini ya usanidi wa Apple MIE:

1. **Tag assignment**
- Wakati memory inapotengwa (mf. katika kernel au user space kupitia secure allocators), **secret tag** inateuliwa kwa block hiyo.
- Pointer inayorejeshwa kwa user au kernel ina tag hiyo katika high bits zake (kutumia TBI / top byte ignore mechanisms).

2. **Tag checking on access**
- Kila mara load au store inapotekelezwa kwa kutumia pointer, hardware inakagua kuwa tag ya pointer inafanana na tag ya memory block (allocation tag). Ikiwa kuna mismatch, inatoa fault mara moja (kwa kuwa synchronous).
- Kwa kuwa ni synchronous, hakuna dirisha la “delayed detection”.

3. **Retagging on free / reuse**
- Wakati memory inapoachiliwa, allocator hubadili tag ya block (hivyo pointers za zamani zenye tags za zamani hazitafanana tena).
- Use-after-free pointer kwa hivyo itakuwa na tag ya zamani na itafikia mismatch wakati ya access.

4. **Neighbor-tag differentiation to catch overflows**
- Allocations zinazofuatana zinapewa tags tofauti. Ikiwa buffer overflow itafikia memory ya jirani, tag mismatch itasababisha fault.
- Hii ni yenye nguvu hasa katika kugundua overflows ndogo zinazovuka boundary.

5. **Tag confidentiality enforcement**
- Apple lazima izuie tag values ku-leaked (kwa kuwa kama mshambuliaji atajua tag, anaweza kutengeneza pointers zenye tag sahihi).
- Wanawekeza kinga (microarchitectural / speculative controls) ili kuzuia side-channel leakage ya tag bits.

6. **Kernel and user-space integration**
- Apple inatumia EMTE sio tu katika user-space bali pia katika kernel / OS-critical components (kwa kulinda kernel dhidi ya memory corruption).
- Hardware/OS inahakikisha sheria za tag zinafanya kazi hata wakati kernel inatekeleza kwa niaba ya user space.

Kwa kuwa EMTE imejengwa ndani ya MIE, Apple inatumia EMTE katika synchronous mode kwenye maeneo muhimu ya mashambulizi, sio kama chaguo la kujiandikisha au mode ya debugging.

---

## Utunzaji wa exceptions katika XNU

Wakati **exception** inatokea (mf. `EXC_BAD_ACCESS`, `EXC_BAD_INSTRUCTION`, `EXC_CRASH`, `EXC_ARM_PAC`, n.k.), tabaka la **Mach** la kernel ya XNU linahusika kuikamata kabla haijawa signal ya mtindo wa UNIX (kama `SIGSEGV`, `SIGBUS`, `SIGILL`, ...).

Mchakato huu unahusisha tabaka mbalimbali za propagation na handling za exception kabla ya kufika user space au kubadilishwa kuwa BSD signal.

### Mtiririko wa exception (Ngazi ya juu)

1.  **CPU inatoa synchronous exception** (mf., invalid pointer dereference, PAC failure, illegal instruction, n.k.).

2.  **Low-level trap handler** inafanya kazi (`trap.c`, `exception.c` katika chanzo cha XNU).

3.  Trap handler inaita **`exception_triage()`**, kiini cha Mach exception handling.

4.  `exception_triage()` inaamua jinsi ya kupitisha exception:

-   Kwanza kwa **thread's exception port**.

-   Kisha kwa **task's exception port**.

-   Kisha kwa **host's exception port** (mara nyingi `launchd` au `ReportCrash`).

Ikiwa hakuna miongoni mwa ports hizi itakayoshughulikia exception, kernel inaweza:

-   **Kuibadilisha kuwa BSD signal** (kwa michakato ya user-space).

-   **Kusababisha Panic** (kwa exceptions za kernel-space).


### Kazi Kuu: `exception_triage()`

Kazi `exception_triage()` inapita Mach exceptions hadi mnyororo wa handlers zinazowezekana hadi mmoja atashughulikia au mpaka iwe hatari kabisa. Imefafanuliwa katika `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 Wito wa Kawaida:

exception_triage() └── exception_deliver() ├── exception_deliver_thread() ├── exception_deliver_task() └── exception_deliver_host()

Kama zote zikishindwa → zinashughulikiwa na bsd_exception() → zimetafsiriwa kuwa ishara kama SIGSEGV.

Exception Ports

Kila Mach object (thread, task, host) inaweza kusajili exception ports, ambapo exception messages hutumwa.

Zimefafanuliwa na API:

task_set_exception_ports()
thread_set_exception_ports()
host_set_exception_ports()

Kila exception port ina:

  • Mask (ni exceptions gani inataka kupokea)
  • Port name (Mach port ya kupokea messages)
  • Behavior (jinsi kernel inatuma message)
  • Flavor (ni thread state gani kujumuishwa)

Debuggers and Exception Handling

Debugger (mfano, LLDB) huweka exception port kwenye target task au thread, kawaida kwa kutumia task_set_exception_ports().

Wakati exception inapotokea:

  • Mach message inatumiwa kwa debugger process.
  • Debugger inaweza kuamua kushughulikia (resume, badilisha registers, ruka instruction) au kusiushughulikie exception.
  • Ikiwa debugger haishughulikii, exception huendelea kwa ngazi inayofuata (task → host).

Flow of EXC_BAD_ACCESS

  1. Thread ina dereference pointer isiyo halali → CPU huinua Data Abort.

  2. Kernel trap handler inaita exception_triage(EXC_BAD_ACCESS, ...).

  3. Message inatumwa kwa:

  • Thread port → (debugger inaweza kuingilia breakpoint).

  • Ikiwa debugger inaepuka → Task port → (process-level handler).

  • Ikiwa inaepukwa → Host port (kawaida ReportCrash).

  1. Ikiwa hakuna anayeshughulikia → bsd_exception() hubadilisha kuwa SIGSEGV.

PAC Exceptions

Wakati Pointer Authentication (PAC) inashindwa (signature haifanani), exception maalum ya Mach inainuliwa:

  • EXC_ARM_PAC (type)
  • Codes zinaweza kujumuisha maelezo (mfano, aina ya key, aina ya pointer).

Ikiwa binary ina flag TFRO_PAC_EXC_FATAL, kernel huchukulia kushindwa kwa PAC kama kifo (fatal), ikiepuka debugger kuingilia. Hii ni kuzuia washambuliaji kutumia debuggers kupitisha ukaguzi wa PAC na imewezeshwa kwa platform binaries.

Software Breakpoints

Software breakpoint (int3 kwenye x86, brk kwenye ARM64) inatekelezwa kwa kusababisha fault kutakaswa kwa uhakika.
Debugger inakamata hili kupitia exception port:

  • Inabadilisha instruction pointer au memory.
  • Inarejesha instruction asilia.
  • Inafufua utekelezaji.

Mekaniki hii ile ile ndio inakuwezesha “kushika” PAC exception — isipokuwa TFRO_PAC_EXC_FATAL imewekwa, ambapo haitafika kwa debugger.

Conversion to BSD Signals

Ikiwa hakuna handler anayekubali exception:

  • Kernel hunaita task_exception_notify() → bsd_exception().

  • Hii inafananisha Mach exceptions na signals:

Mach ExceptionSignal
EXC_BAD_ACCESSSIGSEGV or SIGBUS
EXC_BAD_INSTRUCTIONSIGILL
EXC_ARITHMETICSIGFPE
EXC_SOFTWARESIGTRAP
EXC_BREAKPOINTSIGTRAP
EXC_CRASHSIGKILL
EXC_ARM_PACSIGILL (on non-fatal)

Key Files in XNU Source

  • osfmk/kern/exception.c → Core ya exception_triage(), exception_deliver_*().

  • bsd/kern/kern_sig.c → Mantiki ya delivery ya signal.

  • osfmk/arm64/trap.c → Low-level trap handlers.

  • osfmk/mach/exc.h → Exception codes na structures.

  • osfmk/kern/task.c → Task exception port setup.


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

Kernel ilitumia zone allocator (kalloc) iliyogawanywa katika “zones” za ukubwa uliowekwa. Kila zone ilihifadhi tu allocations za daraja moja ya ukubwa.

Kutoka kwenye screenshot:

Zone NameElement SizeExample Use
default.kalloc.1616 bytesStruct ndogo sana za kernel, pointers.
default.kalloc.3232 bytesStruct ndogo, headers za object.
default.kalloc.6464 bytesIPC messages, buffers ndogo za kernel.
default.kalloc.128128 bytesVitu vya kati kama sehemu za OSObject.
default.kalloc.12801280 bytesStructures kubwa, IOSurface/graphics metadata.

Jinsi ilivyofanya kazi:

  • Kila ombi la allocation lilizounganishwa juu hadi ukubwa wa zone unaofaa. (Mfano, ombi la 50-byte linaenda kwenye kalloc.64 zone).
  • Memory katika kila zone ilihifadhiwa kwenye free list — chunks zilizofunguliwa na kernel zilirudi kwenye zone hiyo.
  • Ikiwa ulivunja buffer ya 64-byte, ungefuta kitu kingine kilichofuata katika zone ile ile.

Hii ndicho kilichofanya heap spraying / feng shui kuwa yenye ufanisi: unaweza kutabiri majirani wa object kwa kupuliza allocations za daraja moja ya ukubwa.

The freelist

Ndani ya kila kalloc zone, vitu vilivyofunguliwa havirudishiwi moja kwa moja kwa system — vilaingia kwenye freelist, linked list ya chunks zilizopatikana.

  • Wakati chunk ilifunguliwa, kernel iliandika pointer mwanzoni mwa chunk hiyo → anwani ya chunk inayofuata ya bure katika zone ile ile.

  • Zone ilihifadhi pointer ya HEAD kwa chunk ya kwanza ya bure.

  • Allocation kila mara ilitumia HEAD ya sasa:

  1. Pop HEAD (rudi memory hiyo kwa mteja).

  2. Sasisha HEAD = HEAD->next (ilimwaga kwenye header ya chunk iliyofunguliwa).

  • Kufungua kulisukuma chunks nyuma:

  • freed_chunk->next = HEAD

  • HEAD = freed_chunk

Hivyo freelist ilikuwa tu linked list iliyojengwa ndani ya memory iliyofunguliwa.

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 baiti 8 za kwanza za free chunk = freelist pointer, mshambuliaji anaweza kuziharibu:

  1. Heap overflow katika free chunk jirani → kuandika upya pointer yake ya “next”.

  2. Use-after-free kuandika ndani ya object iliyofutwa → kuandika upya pointer yake ya “next”.

Kisha, wakati wa allocation inayofuata ya ukubwa huo:

  • Allocator inatoa (pops) chunk iliyoharibiwa.

  • Inafuata pointer ya “next” iliyoambatanishwa na mshambuliaji.

  • Inarudisha pointer kwa memory yoyote ile, kuruhusu 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 made exploitation highly effective pre-hardening: predictable neighbors from heap sprays, raw pointer freelist links, and no type separation allowed attackers to escalate UAF/overflow bugs into arbitrary kernel memory control.

Heap Grooming / Feng Shui

The goal of heap grooming is to shape the heap layout so that when an attacker triggers an overflow or use-after-free, the target (victim) object sits right next to an attacker-controlled object.
That way, when memory corruption happens, the attacker can reliably overwrite the victim object with controlled data.

Hatua:

  1. Spray allocations (fill the holes)
  • Kwa kipindi fulani, kernel heap hupata fragmentation: baadhi ya zones zina mianya ambapo vitu vya zamani viliachwa.
  • Mshambulizi kwanza hufanya allocations nyingi za dummy kujaza mapengo haya, hivyo heap inakuwa “imejazwa” na inabakia isiyotabirika.
  1. Force new pages
  • Mara mapengo yapo yamejazwa, allocations zinazofuata lazima zitoke kutoka kwa new pages zilizoongezwa kwenye zone.
  • Pages safi zinamaanisha vitu vitaangukia pamoja, si kuenea kwenye memory iliyoxfragmented.
  • Hii huwapa mshambulizi udhibiti mzuri wa majirani.
  1. Place attacker objects
  • Mshambulizi sasa anafanya spray tena, akitengeneza vitu vingi vinavyodhibitiwa na mshambulizi kwenye page mpya hizo.
  • Vitu hivi vina ukubwa na nafasi zinazotarajiwa (kwa sababu vinatoka kwenye zone ile ile).
  1. Free a controlled object (make a gap)
  • Mshambulizi kwa makusudi anatoa moja ya vitu vyake.
  • Hii inaunda “pengo” katika heap, ambalo allocator baadaye litareuse kwa allocation inayofuata ya size hiyo.
  1. Victim object lands in the hole
  • Mshambulizi anasababisha kernel kuallocate object la victim (ile wanayotaka kuharibu).
  • Kwa kuwa pengo ndilo slot la kwanza linalopatikana kwenye freelist, victim inawekwa mahali palipoachwa na mshambulizi.
  1. Overflow / UAF into victim
  • Sasa mshambulizi ana vitu vinavyodhibitiwa karibu na victim.
  • Kwa kutoa overflow kutoka kwa moja ya vitu vyake (au kwa kutumia tena kilichofunguliwa), wanaweza kwa uaminifu kuandika juu ya fields za memory ya victim na values walizochagua.

Kwanini inafanya kazi:

  • Zone allocator predictability: allocations za size ile ile daima hutoka kwenye zone ile ile.
  • Freelist behavior: allocations mpya zinatumia chunk zilizofungwa hivi karibuni kwanza.
  • Heap sprays: mshambulizi anajaza memory na content inayotarajiwa na kudhibiti layout.
  • Matokeo: mshambulizi anadhibiti wapi object ya victim inaangukia na data gani iko karibu nayo.

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

Apple imesababisha ugumu kwenye allocator na kuifanya heap grooming iwe ngumu zaidi:

1. From Classic kalloc to kalloc_type

  • Before: a single kalloc.<size> zone existed for each size class (16, 32, 64, … 1280, etc.). Any object of that size was placed there → attacker objects could sit next to privileged kernel objects.
  • Now:
  • Kernel objects are allocated from typed zones (kalloc_type).
  • Each type of object (e.g., ipc_port_t, task_t, OSString, OSData) has its own dedicated zone, even if they’re the same size.
  • The mapping between object type ↔ zone is generated from the kalloc_type system at compile time.

Mshambulizi hawezi tena kuhakikisha kwamba controlled data (OSData) itaishia karibu na sensitive kernel objects (task_t) za size ile ile.

2. Slabs and Per-CPU Caches

  • Heap imegawanywa katika slabs (pages za memory zilizo katwakatwa kuwa chunks za size imara kwa zone hiyo).
  • Kila zone ina per-CPU cache kupunguza contention.
  • Allocation path:
  1. Jaribu per-CPU cache.
  2. Ikiwa iko tupu, chukua kutoka global freelist.
  3. Ikiwa freelist ni tupu, allocate slab mpya (kurasa moja au zaidi).
  • Faida: decentralization hii inafanya heap sprays zisizotabirika sana, kwa sababu allocations zinaweza kutolewa kutoka caches za CPU tofauti.

3. Randomization inside zones

  • Ndani ya zone, elementi zilizofunguliwa hazirudishiwi kwa FIFO/LIFO rahisi.
  • XNU ya kisasa inatumia encoded freelist pointers (safe-linking style iliyopatikana karibu iOS 14).
  • Kila freelist pointer ime XOR-encoded na cookie ya siri ya zone.
  • Hii inazuia mshambulizi kutengeneza fake freelist pointer atakapopata write primitive.
  • Baadhi allocations zina randomized placement ndani ya slab, hivyo spraying haibahatiki kuleta adjacency.

4. Guarded Allocations

  • Vitu muhimu za kernel (mfano, credentials, task structures) zinatolewa katika guarded zones.
  • Zones hizi zinaweka guard pages (memory isiyo mapped) kati ya slabs au kutumia redzones karibu na objects.
  • Overflow kwenye guard page husababisha fault → panic mara moja badala ya uharibifu wa kimya.

5. Page Protection Layer (PPL) and SPTM

  • Hata ukiweza kudhibiti object iliyofunguliwa, huwezi kubadilisha sehemu zote za kernel memory:
  • PPL (Page Protection Layer) inatamka kwamba maeneo fulani (mfano, code signing data, entitlements) ni read-only hata kwa kernel yenyewe.
  • Kwa A15/M2+ devices, jukumu hili limebadilishwa/limetengenezwa zaidi na SPTM (Secure Page Table Monitor) + TXM (Trusted Execution Monitor).
  • Tabaka hizi zinazotungwa na hardware zinamaanisha mshambulizi hawawezi kupanua kutoka heap corruption moja hadi kukarabati arbitrary ya structures muhimu za usalama.
  • (Added / Enhanced): pia, PAC (Pointer Authentication Codes) inatumika kwenye kernel kulinda pointers (hasa function pointers, vtables) hivyo kutengeneza au kuharibu pointers kunakuwa ngumu zaidi.
  • (Added / Enhanced): zones zinaweza kutekeleza zone_require / zone enforcement, yaani object iliyofunguliwa inaweza tu kurudishwa kupitia typed zone yake sahihi; frees isiyo sahihi kati ya zones inaweza kusababisha panic au kukataliwa. (Apple inataja hili katika machapisho yao ya memory safety)

6. Large Allocations

  • Sio allocations zote zinapitisha kalloc_type.
  • Maombi makubwa sana (zaidi 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 kutumiwa, kwa sababu hazishiriki slabs na vitu vingine.

7. Allocation Patterns Attackers Target

Hata kwa ulinzi huu, mashambulizi bado wanatafuta:

  • Reference count objects: ukiona unaweza kuathiri retain/release counters, unaweza kusababisha use-after-free.
  • Objects with function pointers (vtables): kuharibu moja bado hutoa control flow.
  • Shared memory objects (IOSurface, Mach ports): hizi bado ni malengo kwa sababu zinaunganisha user ↔ kernel.

Lakini — tofauti na zamani — huwezi tu kushotora OSData na kutegemea itakayekaribiana 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:

  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:

  • Kila freed chunk inahifadhi address ya next free chunk, lakini imekodishwa na key ya siri.
  • Kuandika juu ya field hiyo kwa data ya mshambulizi haitafanya kazi isipokuwa unajua 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, and PAC protects pointers
Allocation reuse validationNone (freelist pointers raw)zone_require / zone enforcement
Exploit reliabilityHigh with heap spraysMuch lower, requires logic bugs or info leaks
Large allocations handlingAll small allocations managed equallyLarge ones bypass zones → handled via VM

Modern Userland Heap (iOS, macOS — type-aware / xzone malloc)

In recent Apple OS versions (especially iOS 17+), Apple introduced a more secure userland allocator, xzone malloc (XZM). This is the user-space analog to the kernel’s kalloc_type, applying type awareness, metadata isolation, and memory tagging safeguards.

Goals & Design Principles

  • Type segregation / type awareness: group allocations by type or usage (pointer vs data) to prevent type confusion and cross-type reuse.
  • Metadata isolation: separate heap metadata (e.g. free lists, size/state bits) from object payloads so that out-of-bounds writes are less likely to corrupt metadata.
  • Guard pages / redzones: insert unmapped pages or padding around allocations to catch overflows.
  • Memory tagging (EMTE / MIE): work in conjunction with hardware tagging to detect use-after-free, out-of-bounds, and invalid accesses.
  • Scalable performance: maintain low overhead, avoid excessive fragmentation, and support many allocations per second with low latency.

Architecture & Components

Below are the main elements in the xzone allocator:

Segment Groups & Zones

  • Segment groups partition the address space by usage categories: e.g. data, pointer_xzones, data_large, pointer_large.
  • Each segment group contains segments (VM ranges) that host allocations for that category.
  • Associated with each segment is a metadata slab (separate VM area) that stores metadata (e.g. free/used bits, size classes) for that segment. This out-of-line (OOL) metadata ensures that metadata is not intermingled with object payloads, mitigating corruption from overflows.
  • Segments are carved into chunks (slices) which in turn are subdivided into blocks (allocation units). A chunk is tied to a specific size class and segment group (i.e. all blocks in a chunk share the same size & category).
  • For small / medium allocations, it will use fixed-size chunks; for large/huges, it may map separately.

Chunks & Blocks

  • A chunk is a region (often several pages) dedicated to allocations of one size class within a group.
  • Inside a chunk, blocks are slots available for allocations. Freed blocks are tracked via the metadata slab — e.g. via bitmaps or free lists stored out-of-line.
  • Between chunks (or within), guard slices / guard pages may be inserted (e.g. unmapped slices) to catch out-of-bounds writes.

Type / Type ID

  • Every allocation site (or call to malloc, calloc, etc.) is associated with a type identifier (a malloc_type_id_t) which encodes what kind of object is being allocated. That type ID is passed to the allocator, which uses it to select which zone / segment to serve the allocation.
  • Because of this, even if two allocations have the same size, they may go into entirely different zones if their types differ.
  • In early iOS 17 versions, not all APIs (e.g. CFAllocator) were fully type-aware; Apple addressed some of those weaknesses in iOS 18.

Allocation & Freeing Workflow

Here is a high-level flow of how allocation and deallocation operate in xzone:

  1. malloc / calloc / realloc / typed alloc is invoked with a size and type ID.
  2. The allocator uses the type ID to pick the correct segment group / zone.
  3. Within that zone/segment, it seeks a chunk that has free blocks of the requested size.
  • It may consult local caches / per-thread pools or free block lists from metadata.
  • If no free block is available, it may allocate a new chunk in that zone.
  1. The metadata slab is updated (free bit cleared, bookkeeping).
  2. If memory tagging (EMTE) is in play, the returned block gets a tag assigned, and metadata is updated to reflect its “live” state.
  3. When free() is called:
  • The block is marked as freed in metadata (via OOL slab).
  • The block may be placed into a free list or pooled for reuse.
  • Optionally, block contents may be cleared or poisoned to reduce data leaks or use-after-free exploitation.
  • The hardware tag associated with the block may be invalidated or re-tagged.
  • If an entire chunk becomes free (all blocks freed), the allocator may reclaim that chunk (unmap it or return to OS) under memory pressure.

Security Features & Hardening

These are the defenses built into modern userland xzone:

FeaturePurposeNotes
Metadata decouplingPrevent overflow from corrupting metadataMetadata lives in separate VM region (metadata slab)
Guard pages / unmapped slicesCatch out-of-bounds writesHelps detect buffer overflows rather than silently corrupting adjacent blocks
Type-based segregationPrevent cross-type reuse & type confusionEven same-size allocations from different types go to different zones
Memory Tagging (EMTE / MIE)Detect invalid access, stale references, OOB, UAFxzone works in concert with hardware EMTE in synchronous mode (“Memory Integrity Enforcement”)
Delayed reuse / poisoning / zapReduce chance of use-after-free exploitationFreed blocks may be poisoned, zeroed, or quarantined before reuse
Chunk reclamation / dynamic unmappingReduce memory waste and fragmentationEntire chunks may be unmapped when unused
Randomization / placement variationPrevent deterministic adjacencyBlocks in a chunk and chunk selection may have randomized aspects
Segregation of “data-only” allocationsSeparate allocations that don’t store pointersReduces attacker control over metadata or control fields

Interaction with Memory Integrity Enforcement (MIE / EMTE)

  • Apple’s MIE (Memory Integrity Enforcement) is the hardware + OS framework that brings Enhanced Memory Tagging Extension (EMTE) into always-on, synchronous mode across major attack surfaces.
  • xzone allocator is a fundamental foundation of MIE in user space: allocations done via xzone get tags, and accesses are checked by hardware.
  • In MIE, the allocator, tag assignment, metadata management, and tag confidentiality enforcement are integrated to ensure that memory errors (e.g. stale reads, OOB, UAF) are caught immediately, not exploited later.

If you like, I can also generate a cheat-sheet or diagram of xzone internals for your book. Do you want me to do that next?
:contentReference[oai:20]{index=20}

(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, 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

  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 & Kernelcache

  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.

JSKit-Based Safari Chains and PREYHUNTER Stagers

Renderer RCE abstraction with JSKit

  • Reusable entry: Recent in-the-wild chains abused a WebKit JIT bug (patched as CVE-2023-41993) purely to gain JavaScript-level arbitrary read/write. The exploit immediately pivots into a purchased framework called JSKit, so any future Safari bug only needs to deliver the same primitive.
  • Version abstraction & PAC bypasses: JSKit bundles support for a wide range of iOS releases together with multiple, selectable Pointer Authentication Code bypass modules. The framework fingerprints the target build, selects the appropriate PAC bypass logic, and verifies every step (primitive validation, shellcode launch) before progressing.
  • Manual Mach-O mapping: JSKit parses Mach-O headers directly from memory, resolves the symbols it needs inside dyld-cached images, and can manually map additional Mach-O payloads without writing them to disk. This keeps the renderer process in-memory only and evades code-signature checks tied to filesystem artifacts.
  • Portfolio model: Debug strings such as “exploit number 7” show that the suppliers maintain multiple interchangeable WebKit exploits. Once the JS primitive matches JSKit’s interface, the rest of the chain is unchanged across campaigns.

Kernel bridge: IPC UAF -> code-sign bypass pattern

  • Kernel IPC UAF (CVE-2023-41992): The second stage, still running inside the Safari context, triggers a kernel use-after-free in IPC code, re-allocates the freed object from userland, and abuses the dangling pointers to pivot into arbitrary kernel read/write. The stage also reuses PAC bypass material previously computed by JSKit instead of re-deriving it.
  • Code-signing bypass (CVE-2023-41991): With kernel R/W available, the exploit patches the trust cache / code-signing structures so unsigned payloads execute as system. The stage then exposes a lightweight kernel R/W service to later payloads.
  • Composed pattern: This chain demonstrates a reusable recipe that defenders should expect going forward:
WebKit renderer RCE -> kernel IPC UAF -> kernel arbitrary R/W -> code-sign bypass -> unsigned system stager

PREYHUNTER helper & watcher modules

  • Watcher anti-analysis: Binary maalum ya watcher huendelea kuchambua kifaa na kuahirisha kill-chain mara tu mazingira ya utafiti yanapotambuliwa. Huinagua security.mac.amfi.developer_mode_status, uwepo wa console ya diagnosticd, locales US au IL, alama za jailbreak kama Cydia, michakato kama bash, tcpdump, frida, sshd, au checkrain, mobile AV apps (McAfee, AvastMobileSecurity, NortonMobileSecurity), mipangilio ya proxy ya HTTP ya desturi, na custom root CAs. Kukosa kupita kwenye ukaguzi wowote kunazuia utoaji wa payload zaidi.
  • Helper surveillance hooks: Komponenti ya helper huwasiliana na hatua nyingine kupitia /tmp/helper.sock, kisha inabeba seti za hook zilizoitwa DMHooker na UMHooker. Hooks hizi zinagusa njia za sauti za VOIP (rekeodi ziko chini ya /private/var/tmp/l/voip_%lu_%u_PART.m4a), zinaweka system-wide keylogger, zinachukua picha bila UI, na zinahook SpringBoard ili kusimamisha arifa ambazo vitendo hivyo kawaida vingeibua. Kwa hivyo helper hufanya kazi kama tabaka la kimyakimya la uthibitisho + uangalizi mwepesi kabla ya implants nzito kama Predator kutupwa.

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

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