iOS Exploiting

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

iOS Exploit Mitigations

1. Code Signing / Runtime Signature Verification

Introduced early (iPhone OS → iOS) यह एक मौलिक सुरक्षा है: सभी executable code (apps, dynamic libraries, JIT-ed code, extensions, frameworks, caches) को Apple के trust में रूटेड certificate chain से cryptographically signed होना आवश्यक है। runtime पर, किसी binary को memory में load करने से पहले (या कुछ boundaries के पार jumps करने से पहले), सिस्टम इसकी signature को चेक करता है। यदि कोड modify हुआ है (bit-flipped, patched) या unsigned है, तो load असफल हो जाता है।

  • Thwarts: exploit chains में “classic payload drop + execute” चरण; arbitrary code injection; किसी existing binary में malicious logic insert करना।
  • Mechanism detail:
  • Mach-O loader (और dynamic linker) code pages, segments, entitlements, team IDs और यह कि signature फाइल की contents को कवर करती है या नहीं, चेक करता है।
  • JIT caches या dynamically generated code जैसी memory regions के लिए, Apple यह enforce करता है कि pages signed हों या कुछ special APIs (e.g. mprotect with code-sign checks) के जरिए validate हों।
  • signature में entitlements और identifiers शामिल होते हैं; OS यह enforce करता है कि कुछ APIs या privileged capabilities के लिए specific entitlements आवश्यक हैं जिन्हें forge नहीं किया जा सकता।
Example मान लीजिए किसी exploit से किसी process में code execution मिल जाता है और वह heap में shellcode लिखकर वहां jump करने की कोशिश करता है। iOS पर, उस page को executable flag के साथ होना चाहिए और code-signature constraints को पूरा करना होगा। चूंकि shellcode Apple के certificate से sign नहीं है, jump fail हो जाता है या सिस्टम उस memory region को executable बनाने से इनकार कर देता है।

2. CoreTrust

Introduced around iOS 14+ era (or gradually in newer devices / later iOS) CoreTrust वह subsystem है जो binaries (system और user दोनों) की runtime signature validation Apple के root certificate के खिलाफ करता है बजाय कि cached userland trust stores पर भरोसा करने के।

  • Thwarts: binaries की post-install tampering, jailbreaking techniques जो system libraries या user apps को swap/patch करने की कोशिश करते हैं; trusted binaries को malicious counterparts से बदलकर सिस्टम को trick करना।
  • Mechanism detail:
  • स्थानीय trust database या certificate cache पर भरोसा करने के बजाय, CoreTrust सीधे Apple के root की ओर refer करता है या secure chain में intermediate certificates को verify करता है।
  • यह सुनिश्चित करता है कि existing binaries में filesystem पर हुए modifications (e.g. changes) detect और reject हो जाएं।
  • यह entitlements, team IDs, code signing flags और अन्य metadata को binary के साथ load time पर जोड़ता है और enforce करता है।
Example एक jailbreak कोशिश कर सकता है `SpringBoard` या `libsystem` को patched version से replace करके persistence पाने की। पर जब OS का loader या CoreTrust check करता है, तो signature mismatch (या modified entitlements) दिखते हैं और execute करने से इनकार कर दिया जाता है।

3. Data Execution Prevention (DEP / NX / W^X)

Introduced in many OSes earlier; iOS had NX-bit / w^x for a long time DEP enforce करता है कि writable (data) pages non-executable हों, और executable pages non-writable हों। आप बस heap या stack में shellcode लिखकर उसे execute नहीं कर सकते।

  • Thwarts: direct shellcode execution; classic buffer-overflow → injected shellcode पर jump।
  • Mechanism detail:
  • MMU / memory protection flags (page tables के जरिए) अलगाव enforce करते हैं।
  • किसी writable page को executable बनाने की कोशिश पर system check trigger होता है (और या तो forbidden होता है या code-sign approval की ज़रूरत होती है)।
  • कई मामलों में, pages को executable बनाने के लिए OS APIs से गुजरना पड़ता है जो अतिरिक्त constraints/checks लगाते हैं।
Example एक overflow shellcode को heap पर लिखता है। attacker `mprotect(heap_addr, size, PROT_EXEC)` करने की कोशिश करता है ताकि इसे executable बनाया जा सके। पर सिस्टम refuse करता है या validate करता है कि नया page code-sign constraints पास करे (जो shellcode नहीं करेगा)।

4. Address Space Layout Randomization (ASLR)

Introduced in iOS ~4–5 era (roughly iOS 4–5 timeframe) ASLR key memory regions — libraries, heap, stack, आदि — के base addresses को हर process launch पर randomize करता है। gadgets के addresses runs के बीच बदलते हैं।

  • Thwarts: ROP/JOP के लिए gadget addresses hardcode करना; static exploit chains; known offsets पर blind jumping।
  • Mechanism detail:
  • हर loaded library / dynamic module को randomized offset पर rebase किया जाता है।
  • Stack और heap base pointers randomize होते हैं (कुछ entropy limits के भीतर)।
  • कभी-कभी अन्य regions (e.g. mmap allocations) भी randomize होते हैं।
  • information-leak mitigations के साथ मिलकर, attacker को runtime पर base addresses discover करने के लिए पहले किसी address या pointer को leak करना पड़ता है।
Example एक ROP chain किसी gadget को `0x….lib + offset` पर expect करता है। पर चूँकि `lib` हर run पर अलग relocate होता है, hardcoded chain fail हो जाता है। exploit को module का base address पता करने के लिए पहले कोई address leak करना होगा ताकि gadget addresses गणना की जा सकें।

5. Kernel Address Space Layout Randomization (KASLR)

Introduced in iOS ~ (iOS 5 / iOS 6 timeframe) user ASLR के समान, KASLR boot time पर kernel text और अन्य kernel structures के base को randomize करता है।

  • Thwarts: kernel-level exploits जो kernel code या data के fixed location पर निर्भर करते हैं; static kernel exploits।
  • Mechanism detail:
  • हर boot पर kernel का base address randomize होता है (एक range के भीतर)।
  • Kernel data structures (जैसे task_structs, vm_map, आदि) भी relocate या offset किए जा सकते हैं।
  • Attackers को kernel pointers leak करने या information disclosure vulnerabilities का उपयोग करके offsets ज्ञात करने की ज़रूरत होती है, फिर ही वे kernel structures या code hijack कर सकते हैं।
Example एक local vulnerability kernel function pointer (उदा. `vtable` में) को corrupt करने का लक्ष्य रखता है जो `KERN_BASE + offset` पर है। पर चूँकि `KERN_BASE` unknown है, attacker को पहले इसे leak करना होगा (उदा. read primitive के माध्यम से) ताकि corruption के लिए सही address गणना की जा सके।

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) kernel text pages की integrity को लगातार monitor करता है (hash या checksum के जरिए)। यदि यह tampering (patches, inline hooks, code modifications) detect करता है जो allowed windows के बाहर होता है, तो यह kernel panic या reboot trigger करता है।

  • Thwarts: persistent kernel patching (kernel instructions modify करना), inline hooks, static function overwrites।
  • Mechanism detail:
  • एक hardware या firmware module kernel text region की निगरानी करता है।
  • यह periodical या on-demand pages को re-hash करता है और expected values के साथ compare करता है।
  • यदि mismatches benign update windows के बाहर पाए जाते हैं, तो यह device को panic कर देता है (ताकि persistent malicious patch से बचा जा सके)।
  • Attackers को या तो detection windows से बचना होगा या legitimate patch paths का उपयोग करना होगा।
Example एक exploit kernel function prologue (उदा. `memcmp`) में patch करने की कोशिश करता है ताकि calls intercept कर सके। पर KPP notice करता है कि code page का hash अब expected value से मेल नहीं खाता और kernel panic trigger कर देता है, जिससे device crash हो जाता है और patch stabilise होने से पहले ही नाकाम हो जाता है।

7. Kernel Text Read‐Only Region (KTRR)

Introduced in modern SoCs (post ~A12 / newer hardware) KTRR एक hardware-enforced mechanism है: एक बार kernel text early boot के दौरान lock हो जाने के बाद, यह EL1 (kernel) से उन pages को read-only बना देता है, जिससे code pages पर आगे लिखाई रोकी जा सके।

  • Thwarts: boot के बाद kernel code में किसी भी तरह के modification (उदा. patching, in-place code injection) को EL1 privilege level से।
  • Mechanism detail:
  • boot के दौरान (secure/bootloader stage में), memory controller (या कोई secure hardware unit) physical pages को जो kernel text को contain करते हैं, read-only mark कर देता है।
  • भले ही कोई exploit full kernel privileges पाकर भी आ जाए, वह उन pages को लिख नहीं सकता।
  • उन्हें modify करने के लिए attacker को पहले boot chain compromise करनी होगी, या KTRR को ही subvert करना होगा।
Example एक privilege-escalation exploit EL1 में कूदकर kernel function में trampoline लिखने की कोशिश करता है (उदा. `syscall` handler में)। पर क्योंकि pages KTRR द्वारा read-only lock हैं, write fail होता है (या fault trigger होता है), इसलिए patches apply नहीं होते।

8. Pointer Authentication Codes (PAC)

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

  • PAC एक hardware feature है जो pointer values (return addresses, function pointers, certain data pointers) के tampering का पता लगाने के लिए इंडेंट किया गया छोटा cryptographic signature (एक “MAC”) pointer के unused high bits में embed करता है।
  • signature (“PAC”) pointer value के साथ-साथ एक modifier (context value, जैसे stack pointer या कोई distinguishing data) पर compute किया जाता है। इस तरह उसी pointer value को अलग contexts में अलग PAC मिलता है।
  • उपयोग के समय, pointer को dereference या branch करने से पहले, एक authenticate instruction PAC को चेक करता है। यदि valid है, PAC strip कर दिया जाता है और pure pointer मिल जाता है; यदि invalid है, pointer “poisoned” बन जाता है (या fault उठता है)।
  • PAC बनाने/validate करने के लिए उपयोग होने वाली keys privileged registers (EL1, kernel) में रहती हैं और user mode से सीधे readable नहीं होतीं।
  • चूँकि बहुत से सिस्टम में 64-bit pointer के सभी bits उपयोग में नहीं होते (उदा. 48-bit address space), upper bits spare होते हैं और PAC को बिना प्रभाव डाले वहाँ रखा जा सकता है।

Architectural Basis & Key Types

  • ARMv8.3 में five 128-bit keys introduce हुए हैं (प्रत्येक दो 64-bit system registers के जरिए implement)।

  • APIAKey — instruction pointers के लिए (domain “I”, key A)

  • APIBKey — दूसरा instruction pointer key (domain “I”, key B)

  • APDAKey — data pointers के लिए (domain “D”, key A)

  • APDBKey — data pointers के लिए (domain “D”, key B)

  • APGAKey — “generic” key, non-pointer data या अन्य generic उपयोगों के लिए

  • ये keys privileged system registers में store होते हैं ( केवल EL1/EL2 आदि पर accessible), user mode से access नहीं होते।

  • PAC एक cryptographic function के जरिए compute होता है (ARM QARMA algorithm सुझाता है) जिसका input है:

  1. Pointer value (canonical portion)
  2. एक modifier (context value, जैसे salt)
  3. Secret key
  4. कुछ internal tweak logic यदि resulting PAC pointer के upper bits में स्थित value से match करता है तो authentication सफल होता है।

Instruction Families

नामकरण convention है: PAC / AUT / XPAC, फिर domain letters।

  • PACxx instructions pointer को sign करती हैं और PAC insert करती हैं
  • AUTxx instructions authenticate + strip करती हैं (validate और PAC remove)
  • XPACxx instructions बिना validate किए PAC strip करती हैं

Domains / suffixes:

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

There are specialized / alias forms:

  • PACIASP is shorthand for PACIA X30, SP (sign the link register using SP as modifier)
  • AUTIASP is AUTIA X30, SP (authenticate link register with SP)
  • Combined forms like RETAA, RETAB (authenticate-and-return) or BLRAA (authenticate & branch) exist in ARM extensions / compiler support.
  • Also zero-modifier variants: PACIZA / PACIZB where the modifier is implicitly zero, etc.

Modifiers

modifier का मुख्य उद्देश्य PAC को specific context के साथ bind करना है ताकि एक ही address को अलग contexts में sign करने पर अलग PAC मिले। यह pointer reuse across frames या objects को रोकता है। यह एक तरह से hash में salt जोड़ने जैसा है।

इसलिए:

  • modifier एक context value (दूसरा register) है जो PAC computation में mix होता है। आम choices: stack pointer (SP), frame pointer, या कोई object ID।
  • SP को modifier के रूप में उपयोग करना return address signing के लिए सामान्य है: PAC specific stack frame से जुड़ जाता है। यदि आप LR को किसी अलग frame में reuse करने की कोशिश करेंगे, तो modifier बदल जाएगा और PAC validation fail हो जाएगा।
  • एक ही pointer value को अलग modifiers के साथ sign करने पर अलग PAC मिलती है।
  • modifier secret होने की आवश्यकता नहीं है, पर ideally यह attacker-controlled नहीं होना चाहिए।
  • उन instructions के लिए जो pointers sign/verify करते हैं जहां कोई meaningful modifier नहीं है, कुछ forms zero या implicit constant का उपयोग करते हैं।

Apple / iOS / XNU Customizations & Observations

  • Apple की PAC implementation में per-boot diversifiers शामिल हैं ताकि keys या tweaks हर boot पर बदलें, जिससे boots के बीच reuse से बचा जा सके।
  • वे cross-domain mitigations भी डालते हैं ताकि user mode में sign किए गए PACs को kernel mode में आसानी से reuse न किया जा सके।
  • Apple Silicon (M1) पर reverse engineering से पता चला कि वहाँ nine modifier types और key control के लिए Apple-specific system registers हैं।
  • Apple PAC को कई kernel subsystems में उपयोग करता है: return address signing, kernel data में pointer integrity, signed thread contexts, आदि।
  • Google Project Zero ने दिखाया कि powerful memory read/write primitive के तहत kernel में, किसी समय kernel PACs (A keys के लिए) forge किए जा सकते हैं (A12-era devices पर), पर Apple ने उन paths को patch किया।
  • Apple के सिस्टम में कुछ keys global across kernel हो सकते हैं, जबकि user processes को per-process key randomness मिल सकती है।

PAC Bypasses

  1. Kernel-mode PAC: theoretical vs real bypasses
  • क्योंकि kernel PAC keys और logic tightly controlled हैं (privileged registers, diversifiers, domain isolation), arbitrary signed kernel pointers forge करना बहुत कठिन है।
  • Azad का 2020 “iOS Kernel PAC, One Year Later” रिपोर्ट करता है कि iOS 12-13 में उन्होंने कुछ partial bypasses पाए (signing gadgets, reuse of signed states, unprotected indirect branches) पर कोई full generic bypass नहीं मिला। bazad.github.io
  • Apple’s “Dark Magic” customizations exploitable surfaces को और सिकोड़ते हैं (domain switching, per-key enabling bits)। i.blackhat.com
  • एक जाना-माना kernel PAC bypass CVE-2023-32424 Apple silicon (M1/M2) पर Zecao Cai et al. द्वारा रिपोर्ट किया गया। i.blackhat.com
  • पर ये bypasses अक्सर बहुत specific gadgets या implementation bugs पर निर्भर करते हैं; ये general-purpose bypass नहीं होते।

इसलिए kernel PAC को highly robust माना जाता है, हालांकि यह परफेक्ट नहीं है।

  1. User-mode / runtime PAC bypass techniques

ये ज्यादा आम हैं, और PAC के लागू होने के तरीके या runtime frameworks में imperfections का फायदा उठाते हैं। नीचे classes और examples दिए गए हैं।

2.1 Shared Cache / A key issues

  • dyld shared cache एक बड़ा pre-linked blob है system frameworks और libraries का। क्योंकि यह बहुत साझा होता है, shared cache के अंदर function pointers पहले से “pre-signed” होते हैं और कई processes द्वारा उपयोग किए जाते हैं। Attackers इन already-signed pointers को “PAC oracles” के रूप में target करते हैं।

  • कुछ bypass techniques shared cache में मौजूद A-key signed pointers को extract या reuse करने की कोशिश करते हैं और उन्हें gadgets के साथ मिलाते हैं।

  • “No Clicks Required” talk ने shared cache पर एक oracle बनाने और relative addresses infer करने तथा signed pointers के साथ combine करने के बारे में बताया जिससे PAC bypass संभव होता है। saelo.github.io

  • साथ ही, userspace में shared libraries से imported function pointers को पर्याप्त रूप से PAC-protected नहीं पाया गया, जिससे attacker function pointers पा सकता था बिना signature बदलने के। (Project Zero bug entry) bugs.chromium.org

2.2 dlsym(3) / dynamic symbol resolution

  • एक ज्ञात bypass यह है कि dlsym() को call करके एक already signed function pointer (A-key से signed, diversifier zero) प्राप्त किया जा सकता है और फिर उसे उपयोग किया जा सकता है। क्योंकि dlsym legitimately signed pointer लौटाता है, इसे उपयोग करने से PAC forge करने की आवश्यकता नहीं रहती।

  • Epsilon का ब्लॉग बताता है कि कुछ bypasses इस तरह exploit करते हैं: dlsym("someSym") एक signed pointer देता है जिसे indirect calls के लिए इस्तेमाल किया जा सकता है। blog.epsilon-sec.com

  • Synacktiv का “iOS 18.4 — dlsym considered harmful” बताता है कि iOS 18.4 पर कुछ symbols जो dlsym से resolve होते हैं, pointers return करते थे जो गलती से signed थे (या buggy diversifiers के साथ), जिससे अनिच्छित PAC bypass संभव हुआ। Synacktiv

  • dyld में dlsym के लिए logic में है: जब result->isCode होता है, वे returned pointer को __builtin_ptrauth_sign_unauthenticated(..., key_asia, 0) के साथ sign करते हैं, यानी context zero। blog.epsilon-sec.com

इसलिए, dlsym user-mode PAC bypasses में अक्सर vector होता है।

2.3 Other DYLD / runtime relocations

  • DYLD loader और dynamic relocation logic जटिल है और कभी-कभी relocations करने के लिए pages को temporary रूप से read/write के रूप में map किया जाता है, फिर उन्हें read-only पर switch किया जाता है। Attackers इन windows का फायदा उठाते हैं। Synacktiv की talk “Operation Triangulation” dynamic relocations के माध्यम से timing-based PAC bypass का वर्णन करती है। Synacktiv

  • DYLD pages अब SPRR / VM_FLAGS_TPRO के साथ protected हैं (dyld के लिए कुछ protection flags)। पर पुराने versions में weaker guards थे। Synacktiv

  • WebKit exploit chains में, DYLD loader अक्सर PAC bypass का target होता है। slides में बताया गया है कि कई PAC bypasses ने DYLD loader को लक्ष्य बनाया है (relocation, interposer hooks के जरिए)। Synacktiv

2.4 NSPredicate / NSExpression / ObjC / SLOP

  • userland exploit chains में, Objective-C runtime methods जैसे NSPredicate, NSExpression या NSInvocation 控制 कॉल को smuggle करने के लिए उपयोग किए जाते हैं बिना स्पष्ट pointer forging के।

  • पुराने iOS (PAC से पहले) पर, एक exploit ने fake NSInvocation objects का उपयोग arbitrary selectors call करने के लिए किया था। PAC के साथ, तकनीक में संशोधन की आवश्यकता पड़ी। पर SLOP (SeLector Oriented Programming) को PAC के तहत भी विस्तारित किया गया है। Project Zero

  • मूल SLOP तकनीक fake invocations बनाकर ObjC calls की chaining करने की अनुमति देती थी; bypass इस तथ्य पर निर्भर करता है कि ISA या selector pointers कभी-कभी पूरी तरह से PAC-protected नहीं होते। Project Zero

  • उन environments में जहाँ pointer authentication आंशिक रूप से लागू है, methods / selectors / target pointers हमेशा PAC protection के अधीन नहीं होते, जिससे 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>उदाहरण</summary>
A buffer overflow overwrites a return address on the stack. The attacker writes the target gadget address but cannot compute the correct PAC. When the function returns, the CPU’s `AUTIA` instruction faults because the PAC mismatch. The chain fails.
Project Zero’s analysis on A12 (iPhone XS) showed how Apple’s PAC is used and methods of forging PACs if an attacker has a memory read/write primitive.
</details>


### 9. **Branch Target Identification (BTI)**
**Introduced with ARMv8.5 (later hardware)**
BTI एक हार्डवेयर सुविधा है जो **indirect branch targets** की जाँच करती है: जब `blr` या indirect calls/jumps निष्पादित होते हैं, तब लक्ष्य का आरंभ एक **BTI landing pad** (`BTI j` या `BTI c`) से होना चाहिए। जिन gadget पतों में landing pad नहीं होता, उन पर स्किप करने पर exception ट्रिगर होता है।

LLVM की implementation तीन प्रकार के BTI निर्देशों और वे किस तरह से 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) | उन functions के entry पर रखा जाता है जिन्हें indirect रूप से कॉल किया जा सकता है |
| **BTI J** | Targets of *jump*-style branches (e.g. `BR` used for tail calls) | उन blocks की शुरुआत में रखा जाता है जो jump tables या tail-calls द्वारा पहुँचने योग्य हों |
| **BTI JC** | Acts as both C and J | किसी भी call या jump branch द्वारा लक्ष्य बनाया जा सकता है |

- Branch target enforcement के साथ compile किए गए कोड में, compilers प्रत्येक वैध indirect-branch target (function की शुरुआत या jump द्वारा पहुँचने योग्य blocks) पर BTI निर्देश (C, J, या JC) डालते हैं ताकि indirect branches केवल उन ही स्थानों पर सफल हों।
- **Direct branches / calls** (यानी fixed-address `B`, `BL`) BTI द्वारा **सीमित नहीं** होते। मान्यता यह है कि code pages भरोसेमंद हैं और attacker उन्हें बदल नहीं सकता (इसलिए direct branches सुरक्षित माने जाते हैं)।
- साथ ही, **RET / return** निर्देश सामान्यतः BTI द्वारा प्रतिबंधित नहीं होते क्योंकि return addresses को PAC या return signing mechanisms के जरिए संरक्षित किया जाता है।

#### Mechanism and enforcement

- जब CPU किसी page को “guarded / BTI-enabled” के रूप में चिह्नित पृष्ठ में एक **indirect branch (BLR / BR)** को decode करता है, तो यह जाँचता है कि target address का पहला निर्देश एक वैध BTI (C, J, या JC जैसा कि अनुमति है) है या नहीं। यदि नहीं, तो एक **Branch Target Exception** होती है।
- BTI निर्देश का encoding पुराने ARM संस्करणों में NOPs के लिए पूर्व-अवकाशित opcodes को पुन: उपयोग करने के लिए डिज़ाइन किया गया है। इसलिए BTI-enabled binaries backward-compatible रहेंगे: जिन हार्डवेयर में BTI समर्थन नहीं है, उन पर वे निर्देश NOPs की तरह कार्य करेंगे।
- BTI जोड़ने वाले compiler passes उन्हें केवल जहाँ जरूरत हो वहाँ डालते हैं: वे functions जो indirect रूप से कॉल हो सकते हैं, या basic blocks जो jumps द्वारा लक्षित होते हैं।
- कुछ patches और LLVM कोड दिखाते हैं कि BTI सभी basic blocks के लिए नहीं डाला जाता — केवल उन blocks के लिए जो संभावित branch targets होते हैं (उदा. switch / jump tables से)।

#### BTI + PAC synergy

PAC pointer मान (source) की रक्षा करता है — यह सुनिश्चित करता है कि indirect calls / returns की श्रृंखला छेड़छाड़ नहीं हुई है।

BTI यह सुनिश्चित करता है कि भले ही pointer वैध हो, वह केवल सही रूप से चिह्नित entry points को ही लक्षित कर सकता है।

संयोजित रूप से, एक attacker को एक वैध pointer के साथ सही PAC और यह कि लक्ष्य पर BTI मौजूद है — दोनों की आवश्यकता होती है। इससे exploit gadgets बनाना कठिन हो जाता है।

#### Example


<details>
<summary>उदाहरण</summary>
एक exploit `0xABCDEF` पर मौजूद gadget में pivot करने की कोशिश करता है जो `BTI c` से शुरू नहीं होता। CPU जब `blr x0` निष्पादित करता है, तो यह लक्ष्य की जाँच करता है और fault कर देता है क्योंकि instruction alignment में वैध landing pad शामिल नहीं है। इस प्रकार कई gadgets तब तक अनुपयोगी बन जाते हैं जब तक उनके पास BTI prefix न हो।
</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** एक ऐसी सुविधा है जो **ARMv8.1-A** में पेश की गई थी और यह **privileged code** (EL1 या EL2) को **user-accessible (EL0)** के रूप में चिह्नित मेमोरी को **पढ़ने या लिखने** से रोकती है, जब तक कि PAN को स्पष्ट रूप से अक्षम न किया गया हो।
- विचार यह है: भले ही kernel को धोखा दिया जाए या compromised हो, वह user-space pointers को बिना PAN क्लियर किए arbitrary तरीके से dereference नहीं कर सकता, इस प्रकार `ret2usr` स्टाइल के exploits या user-controlled buffers के दुरुपयोग के जोखिम को कम करता है।
- जब PAN सक्षम होता है (`PSTATE.PAN = 1`), कोई भी privileged load/store निर्देश जो ऐसी वर्चुअल एड्रेस तक पहुँचने की कोशिश करता है जो “accessible at EL0” के रूप में है, वह एक **permission fault** ट्रिगर करता है।
- जब kernel को वैध रूप से user-space memory तक पहुँचने की आवश्यकता होती है (उदा. user buffers में से/में डेटा copy करना), तो kernel को PAN को **अस्थायी रूप से disable** करना पड़ता है (या “unprivileged load/store” निर्देशों का उपयोग करना पड़ता है) ताकि वह पहुंच कर सके।
- Linux पर ARM64 में PAN समर्थन लगभग 2015 के आसपास जोड़ा गया था: kernel patches ने इस सुविधा का पता लगाने और `get_user` / `put_user` आदि को उन वैरिएंट्स से बदलने का काम किया जो user memory accesses के आसपास PAN को क्लियर करते हैं।

**Key nuance / limitation / bug**
- जैसा कि Siguza और अन्य लोगों ने बताया, ARM के डिजाइन में एक specification bug (या ambiguous व्यवहार) का अर्थ है कि **execute-only user mappings** (`--x`) PAN को **trigger** नहीं कर सकती। दूसरे शब्दों में, अगर किसी user पृष्ठ को execute के लिए चिह्नित किया गया है पर पढ़ने की अनुमति नहीं है, तो kernel का read प्रयास PAN को बाईपास कर सकता है क्योंकि आर्किटेक्चर “accessible at EL0” के लिए readable permission को आवश्यक मानता है, सिर्फ executable को नहीं। यह कुछ ARMv8+ सिस्टम्स में PAN बाईपास की ओर ले जाता है।
- इस वजह से, यदि iOS / XNU execute-only user pages की अनुमति देता है (जैसा कि कुछ JIT या code-cache सेटअप में हो सकता है), तो kernel PAN सक्षम होने पर भी उनसे पढ़ सकता है। यह कुछ ARMv8+ सिस्टमों में ज्ञात सूक्ष्म exploitable क्षेत्र है।

#### PXN (Privileged eXecute Never)

- **PXN** एक page table flag है (page table entries, leaf या block entries में) जो संकेत देता है कि पृष्ठ **privileged mode में निष्पादित नहीं किया जा सकता** (यानी जब EL1 उसे execute करने की कोशिश करे)।
- PXN kernel (या कोई भी privileged code) को user-space पृष्ठों में जाकर instructions execute करने से रोकता है भले ही control diverted हो। प्रभावी रूप से, यह kernel-level control-flow को user memory में redirect होने से रोकता है।
- PAN के साथ मिलकर, यह सुनिश्चित करता है कि:
1. Kernel डिफ़ॉल्ट रूप से user-space डेटा को पढ़ या लिख नहीं सकता (PAN)
2. Kernel user-space कोड को निष्पादित नहीं कर सकता (PXN)
- ARMv8 page table format में, leaf entries में एक `PXN` बिट होता है (और unprivileged execute-never के लिए `UXN`) जो attribute bits में होता है।

इसलिए भले ही kernel के पास कोई corrupted function pointer user memory की ओर इशारा कर रहा हो, और वह वहाँ branch करने की कोशिश करे, PXN बिट fault करवा देगा।

#### Memory-permission model & how PAN and PXN map to page table bits

PAN / PXN को समझने के लिए, आपको ARM के translation और permission मॉडल को देखना होगा (सरलीकृत):

- प्रत्येक page या block entry में attribute fields होते हैं जिनमें **AP[2:1]** शामिल हैं (access permissions: read/write, privileged vs unprivileged) और execute-never प्रतिबंधों के लिए **UXN / PXN** बिट्स होते हैं।
- जब `PSTATE.PAN` 1 होता है (सक्षम), हार्डवेयर संशोधित semantics लागू करता है: privileged accesses उन पृष्ठों के लिए जो “accessible by EL0” चिह्नित हैं, उन्हें अस्वीकार कर देता है (fault)।
- उल्लेखित बग के कारण, केवल executable (पढ़ने की अनुमति नहीं) के रूप में चिह्नित पृष्ठ कुछ implementations में “accessible by EL0” नहीं माने जा सकते, इस प्रकार PAN बाईपास हो सकता है।
- जब किसी पृष्ठ का PXN बिट सेट होता है, तो भले ही instruction fetch उच्च privilege स्तर से हो, निष्पादन प्रतिबंधित होता है।

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

एक hardened kernel डिज़ाइन में (जैसे Apple संभवतः उपयोग करता है):

- Kernel डिफ़ॉल्ट रूप से PAN सक्षम करता है (इसलिए privileged code प्रतिबंधित रहता है)।
- उन मार्गों में जिन्हें वैध रूप से user buffers पढ़ने/लिखने की आवश्यकता होती है (जैसे syscall buffer copy, I/O, read/write user pointer), kernel अस्थायी रूप से **PAN disable** करता है या user memory तक पहुँचने के लिए विशेष निर्देशों का उपयोग करता है।
- user डेटा पहुँच पूरी करने के बाद, उसे PAN को पुनः सक्षम करना चाहिए।
- PXN page tables के माध्यम से लागू होता है: user pages में PXN = 1 होता है (ताकि kernel उन्हें execute न कर सके), kernel pages में PXN नहीं होता (ताकि kernel code को निष्पादित किया जा सके)।
- Kernel को यह सुनिश्चित करना चाहिए कि कोई भी कोड पथ execution flow को user memory क्षेत्रों में न ले जाए (जो PXN को बाईपास करेगा) — इसलिए “user-controlled shellcode में jump” पर आधारित exploit chains ब्लॉक हो जाते हैं।

उल्लिखित PAN bypass के कारण, वास्तविक सिस्टम में Apple execute-only user pages को अक्षम या प्रतिबंधित कर सकता है, या specification कमजोरी के चारों ओर पैच कर सकता है।


#### Attack surfaces, bypasses, and mitigations

- **PAN bypass via execute-only pages**: जैसा कि चर्चा हुई, spec में एक गैप है: execute-only (no read perm) user पृष्ठ कुछ implementations में “accessible at EL0” नहीं माने जा सकते, इसलिए PAN kernel reads को ब्लॉक नहीं करेगा। इससे attacker को execute-only sections के माध्यम से डेटा खिलाने का एक असामान्य रास्ता मिलता है।
- **Temporal window exploit**: यदि kernel PAN को आवश्यक समय से अधिक देर के लिए disable कर देता है, तो एक race या malicious path उस विंडो का उपयोग करके अनचाहे user memory access कर सकता है।
- **Forgotten re-enable**: यदि कोड पाथ PAN को पुनः सक्षम करना भूल जाते हैं, तो बाद के kernel operations गलत तरीके से user memory तक पहुँच सकते हैं।
- **Misconfiguration of PXN**: यदि page tables user pages पर PXN सेट नहीं करते या user code pages को गलत तरीके से map करते हैं, तो kernel को user-space code निष्पादित कराने के लिए बहकाया जा सकता है।
- **Speculation / side-channels**: speculative bypasses के समान, ऐसे माइक्रोआर्किटेक्चरल side-effects हो सकते हैं जो PAN / PXN चेक्स के ट्रांज़िएंट उल्लंघन पैदा करते हैं (हालाँकि ऐसे हमले CPU डिज़ाइन पर बहुत निर्भर करते हैं)।
- **Complex interactions**: उन्नत सुविधाओं (जैसे JIT, shared memory, just-in-time code regions) में kernel को कुछ user-mapped क्षेत्रों पर वैध रूप से नियंत्रण की आवश्यकता हो सकती है; PAN/PXN प्रतिबंधों के तहत उन तक सुरक्षित पहुंच का डिज़ाइन जटिल होता है।


#### Example

<details>
<summary>कोड उदाहरण</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.

यदि kernel ने उस user पृष्ठ पर **PXN सेट नहीं किया** होता, तो वह branch सफल हो सकता था — जो असुरक्षित होगा।

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.

यदि kernel user मेमोरी एक्सेस के बाद PAN को फिर से सक्षम करना भूल जाता है, तो यह एक विंडो खोल देता है जहाँ आगे की kernel लॉजिक गलती से arbitrary user मेमोरी पढ़/लिख सकती है या लिख सकती है।

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.

यदि user pointer किसी execute-only पेज में है (केवल execute अनुमति, read/write नहीं), तो PAN spec बग के तहत, `ldr W2, [X1]` PAN सक्षम होने के बावजूद भी fault **नही** कर सकता है, जिससे implementation पर निर्भर करते हुए bypass exploit संभव हो जाता है।

</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.

एक kernel vulnerability user-प्रदान किया हुआ function pointer लेकर उसे kernel संदर्भ में कॉल करने की कोशिश करती है (जैसे `call user_buffer`)। PAN/PXN के अंतर्गत, वह ऑपरेशन प्रतिबंधित है या fault करता है।
</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.

एक function pointer के शीर्ष बाइट में एक tag (`0xAA` मान लो) शामिल था। एक exploit pointer के नीचे के बिट्स को ओवरराइट कर देता है पर tag को छोड़ देता है, इसलिए जब kernel सत्यापन या sanitize करता है तो pointer असफल होता है या अस्वीकार हो जाता है।
</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 कई सामान्य ऑपरेशन कर सकता है, लेकिन केवल ppl_call_* routines के माध्यम से ही यह protected mappings बदल सकता है या code को patch कर सकता है।

Example A kernel exploit कोशिश करता है entitlement table को overwrite करने की, या code-sign enforcement को disable करने की kernel signature blob को modify करके। क्योंकि वह page PPL-protected है, write block हो जाता है जब तक कि PPL interface के माध्यम से न किया जाए। इसलिए kernel code execution होने के बावजूद, आप code-sign constraints को bypass नहीं कर सकते या credential data को मनमानी तरीके से modify नहीं कर सकते। On iOS 17+ certain devices SPTM का उपयोग करते हैं ताकि PPL-managed pages को और अलग किया जा सके।

PPL → SPTM / प्रतिस्थापन / भविष्य

  • 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 calls out in documentation: “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.”
  • The SPTM architecture likely shifts more policy enforcement into a higher-privileged monitor outside kernel control, further reducing the trust boundary.

MTE | EMTE | MIE

यहाँ Apple के MIE सेटअप के अंतर्गत EMTE कैसे कार्य करता है, उसका उच्च-स्तरीय वर्णन है:

  1. Tag assignment
  • जब memory allocate की जाती है (उदा. kernel या user space में secure allocators के माध्यम से), उस ब्लॉक को एक secret tag असाइन किया जाता है।
  • user या kernel को लौटाया गया pointer उसके high bits में वह tag शामिल करता है (TBI / top byte ignore mechanisms का उपयोग करके)।
  1. Tag checking on access
  • जब भी pointer का उपयोग करके कोई load या store किया जाता है, hardware यह चेक करता है कि pointer का tag memory block के tag (allocation tag) से मेल खाता है। अगर mismatch होता है तो तुरंत fault होता है (क्योंकि synchronous)।
  • चूँकि यह synchronous है, इसलिए कोई “delayed detection” विंडो नहीं होती।
  1. Retagging on free / reuse
  • जब memory free होती है, allocator ब्लॉक का tag बदल देता है (जिससे पुराने pointers जिनके पास पुराने tags हैं वे अब मेल नहीं खाते)।
  • इसलिए use-after-free pointer के पास stale tag होगा और एक्सेस करने पर mismatch होगा।
  1. Neighbor-tag differentiation to catch overflows
  • पास के allocations को अलग tags दिए जाते हैं। अगर buffer overflow पड़कर पड़ोसी की memory में चला जाता है, तो tag mismatch fault पैदा करेगा।
  • यह boundary पार करने वाले छोटे overflows पकड़ने में विशेष रूप से प्रभावी है।
  1. Tag confidentiality enforcement
  • Apple को tag values के leaked होने से रोकना होगा (क्योंकि अगर attacker tag सीख लेता है, तो वे सही tags वाले pointers बना सकते हैं)।
  • वे protections (microarchitectural / speculative controls) शामिल करते हैं ताकि side-channel leakage of tag bits से बचा जा सके।
  1. Kernel and user-space integration
  • Apple EMTE का उपयोग केवल user-space में नहीं बल्कि kernel / OS-critical components में भी करता है (kernel को memory corruption से बचाने के लिए)।
  • Hardware/OS यह सुनिश्चित करते हैं कि tag rules लागू रहें, भले ही kernel user space की ओर से execute कर रहा हो।
Example ``` 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>

#### सीमाएँ और चुनौतियाँ

- **Intrablock overflows**: यदि overflow उसी allocation के भीतर रहता है (boundary पार नहीं करता) और tag समान रहता है, तो tag mismatch इसे पकड़ने में विफल रहता है।
- **Tag width limitation**: टैग के लिए केवल कुछ बिट्स उपलब्ध होते हैं (उदा. 4 बिट्स, या छोटा डोमेन) — नामस्थान सीमित है।
- **Side-channel leaks**: यदि tag bits cache / speculative execution के माध्यम से leak हो सकते हैं, तो attacker मान्य tags जानकर बायपास कर सकता है। Apple की tag confidentiality enforcement इसे कम करने के लिए है।
- **Performance overhead**: प्रत्येक load/store पर tag checks लागत जोड़ते हैं; Apple को हार्डवेयर को optimize करना होगा ताकि ओवरहेड कम रहे।
- **Compatibility & fallback**: पुराने हार्डवेयर या उन हिस्सों पर जो EMTE को सपोर्ट नहीं करते, fallback मौजूद होना चाहिए। Apple का दावा है कि MIE केवल उन डिवाइसों पर enabled है जिनमें समर्थन है।
- **Complex allocator logic**: allocator को tags, retagging, boundary alignment और mis-tag collisions से बचाव संभालना होगा। allocator logic में बग्स नई vulnerabilities ला सकते हैं।
- **Mixed memory / hybrid areas**: कुछ मेमोरी untagged रह सकती है (legacy), जिससे interoperability कठिन हो सकती है।
- **Speculative / transient attacks**: कई microarchitectural protections की तरह, speculative execution या micro-op fusions checks को transient रूप से बायपास कर सकते हैं या tag bits को leak कर सकते हैं।
- **Limited to supported regions**: Apple संभवतः EMTE को selective, high-risk क्षेत्रों (kernel, security-critical subsystems) में ही लागू करेगा, सार्वभौमिक रूप से नहीं।


---

## मानक MTE के मुकाबले मुख्य सुधार / अंतर

यहाँ Apple द्वारा जोर दिए गए सुधार और परिवर्तन हैं:

| 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.|

क्योंकि Apple हार्डवेयर और सॉफ़्टवेयर स्टैक दोनों नियंत्रित करता है, यह EMTE को कसी हुई तरीके से लागू कर सकता है, performance pitfalls से बच सकता है और side-channel कमजोरियों को बंद कर सकता है।

---

## वास्तविक उपयोग में EMTE कैसे काम करता है (Apple / MIE)

नीचे Apple के MIE सेटअप में EMTE के संचालन का उच्च-स्तरीय वर्णन है:

1. **Tag assignment**
- जब मेमोरी allocate की जाती है (उदा. kernel या user space में secure allocators के माध्यम से), उस ब्लॉक को एक **secret tag** सौंपा जाता है।
- user या kernel को लौटाया गया pointer उस tag को उसके high bits में शामिल करता है (TBI / top byte ignore mechanisms का उपयोग करते हुए)।

2. **Tag checking on access**
- जब भी किसी pointer का उपयोग करके कोई load या store executed होता है, हार्डवेयर चेक करता है कि pointer का tag मेमोरी ब्लॉक के tag (allocation tag) से मेल खाता है या नहीं। यदि mismatch है, तो यह तुरंत fault करता है (क्योंकि synchronous)।
- चूँकि यह synchronous है, इसलिए कोई “delayed detection” विंडो नहीं होती।

3. **Retagging on free / reuse**
- जब मेमोरी free की जाती है, allocator ब्लॉक का tag बदल देता है (ताकि पुराने pointers जिनके tags stale हैं वे मैच न करें)।
- इसलिए use-after-free pointer के पास stale tag होगा और access पर mismatch होगा।

4. **Neighbor-tag differentiation to catch overflows**
- आस-पास के allocations को अलग-अलग tags दिए जाते हैं। यदि कोई buffer overflow पड़ोसी की मेमोरी में फैलता है, तो tag mismatch fault पैदा करेगा।
- यह छोटे overflows को पकड़ने में विशेष रूप से प्रभावी है जो सीमा पार करते हैं।

5. **Tag confidentiality enforcement**
- Apple को tag values के leak होने से रोकना होगा (क्योंकि यदि attacker tag जान लेता है, तो वह सही tags वाले pointers बना सकता है)।
- वे side-channel leakage से बचने के लिए संरक्षण (microarchitectural / speculative controls) शामिल करते हैं।

6. **Kernel and user-space integration**
- Apple EMTE का उपयोग केवल user-space में ही नहीं बल्कि kernel / OS-critical components में भी करता है (kernel को memory corruption से बचाने के लिए)।
- हार्डवेयर/OS सुनिश्चित करते हैं कि tag नियम तब भी लागू हों जब kernel user space के लिए execute कर रहा हो।

क्योंकि EMTE MIE में बिल्ट है, Apple मुख्य attack surfaces में synchronous mode में EMTE का उपयोग करता है, न कि इसे opt-in या debugging मोड के रूप में।

---

## XNU में Exception handling

जब कोई **exception** होती है (उदा., `EXC_BAD_ACCESS`, `EXC_BAD_INSTRUCTION`, `EXC_CRASH`, `EXC_ARM_PAC`, आदि), तो XNU kernel की **Mach layer** इसे UNIX-style **signal** (जैसे `SIGSEGV`, `SIGBUS`, `SIGILL`, ...) बनने से पहले intercept करने की जिम्मेदार होती है।

यह प्रक्रिया user space तक पहुँचने या BSD signal में परिवर्तित होने से पहले exception propagation और handling की कई परतों को शामिल करती है।


### Exception Flow (High-Level)

1.  **CPU triggers a synchronous exception** (उदा., invalid pointer dereference, PAC failure, illegal instruction, आदि)।

2.  **Low-level trap handler** चलता है (`trap.c`, `exception.c` in XNU source)।

3.  trap handler **`exception_triage()`** को कॉल करता है, जो Mach exception handling का core है।

4.  `exception_triage()` तय करता है कि exception कैसे route किया जाए:

-   सबसे पहले **thread's exception port** को।
-   फिर **task's exception port** को।
-   फिर **host's exception port** को (अक्सर `launchd` या `ReportCrash`)।

यदि इन में से कोई भी port exception को handle नहीं करता, तो kernel कर सकता है:

-   **Convert it into a BSD signal** (user-space processes के लिए)।
-   **Panic** (kernel-space exceptions के लिए)。


### Core Function: `exception_triage()`

फ़ंक्शन `exception_triage()` Mach exceptions को संभावित handlers की चैन में route करता है जब तक कि कोई handle न कर दे या अंततः fatal न हो जाए। इसे `osfmk/kern/exception.c` में परिभाषित किया गया है।
```c
void exception_triage(exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt);

सामान्य कॉल फ्लो:

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

If all fail → handled by bsd_exception() → translated into a signal like SIGSEGV.

Exception Ports

प्रत्येक Mach object (thread, task, host) अपने exception ports को रजिस्टर कर सकता है, जहाँ exception संदेश भेजे जाते हैं।

इन्हें API द्वारा परिभाषित किया गया है:

task_set_exception_ports()
thread_set_exception_ports()
host_set_exception_ports()

Each exception port has:

  • A mask (which exceptions it wants to receive)
  • A port name (Mach port to receive messages)
  • A behavior (how the kernel sends the message)
  • A flavor (which thread state to include)

Debuggers and Exception Handling

A debugger (e.g., LLDB) sets an exception port on the target task or thread, usually using task_set_exception_ports().

When an exception occurs:

  • The Mach message is sent to the debugger process.
  • The debugger can decide to handle (resume, modify registers, skip instruction) or not handle the exception.
  • If the debugger doesn’t handle it, the exception propagates to the next level (task → host).

Flow of EXC_BAD_ACCESS

  1. Thread dereferences invalid pointer → CPU raises Data Abort.

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

  3. Message sent to:

  • Thread port → (debugger can intercept breakpoint).

  • If debugger ignores → Task port → (process-level handler).

  • If ignored → Host port (usually ReportCrash).

  1. If no one handles → bsd_exception() translates to SIGSEGV.

PAC Exceptions

When Pointer Authentication (PAC) fails (signature mismatch), a special Mach exception is raised:

  • EXC_ARM_PAC (type)
  • Codes may include details (e.g., key type, pointer type).

If the binary has the flag TFRO_PAC_EXC_FATAL, the kernel treats PAC failures as fatal, bypassing debugger interception. This is to prevent attackers from using debuggers to bypass PAC checks and it’s enabled for platform binaries.

Software Breakpoints

A software breakpoint (int3 on x86, brk on ARM64) is implemented by causing a deliberate fault.
The debugger catches this via the exception port:

  • Modifies instruction pointer or memory.
  • Restores original instruction.
  • Resumes execution.

This same mechanism is what allows you to “catch” a PAC exception — unless TFRO_PAC_EXC_FATAL is set, in which case it never reaches the debugger.

Conversion to BSD Signals

If no handler accepts the exception:

  • Kernel calls task_exception_notify() → bsd_exception().

  • This maps Mach exceptions to 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 of exception_triage(), exception_deliver_*().

  • bsd/kern/kern_sig.c → Signal delivery logic.

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

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

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


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

The kernel used a zone allocator (kalloc) divided into fixed-size “zones.” Each zone only stores allocations of a single size class.

From the screenshot:

Zone NameElement SizeExample Use
default.kalloc.1616 bytesVery small kernel structs, pointers.
default.kalloc.3232 bytesSmall structs, object headers.
default.kalloc.6464 bytesIPC messages, tiny kernel buffers.
default.kalloc.128128 bytesMedium objects like parts of OSObject.
default.kalloc.12801280 bytesLarge structures, IOSurface/graphics metadata.

How it worked:

  • Each allocation request gets rounded up to the nearest zone size. (E.g., a 50-byte request lands in the kalloc.64 zone).
  • Memory in each zone was kept in a free list — chunks freed by the kernel went back into that zone.
  • If you overflowed a 64-byte buffer, you’d overwrite the next object in the same zone.

This is why heap spraying / feng shui was so effective: you could predict object neighbors by spraying allocations of the same size class.

The freelist

Inside each kalloc zone, freed objects weren’t returned directly to the system — they went into a freelist, a linked list of available chunks.

  • When a chunk was freed, the kernel wrote a pointer at the start of that chunk → the address of the next free chunk in the same zone.

  • The zone kept a HEAD pointer to the first free chunk.

  • Allocation always used the current HEAD:

  1. Pop HEAD (return that memory to the caller).

  2. Update HEAD = HEAD->next (stored in the freed chunk’s header).

  • Freeing pushed chunks back:

  • freed_chunk->next = HEAD

  • HEAD = freed_chunk

So the freelist was just a linked list built inside the freed memory itself.

Normal state:

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

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

Exploiting the freelist

क्योंकि किसी free chunk के पहले 8 bytes freelist pointer के बराबर होते हैं, एक attacker इसे corrupt कर सकता है:

  1. Heap overflow पास के freed chunk में → इसके “next” pointer को overwrite कर देना।

  2. Use-after-free किसी freed object में write करना → इसके “next” pointer को overwrite कर देना।

फिर, उस size के अगले allocation पर:

  • allocator corrupted chunk को pop करता है।
  • attacker-supplied “next” pointer का पालन करता है।
  • arbitrary memory के लिए pointer return करता है, जिससे fake object primitives या targeted overwrite संभव हो जाते हैं।

Visual example of 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 डिज़ाइन हार्डनिंग से पहले exploitation को अत्यंत प्रभावी बनाती थी: predictable neighbors from heap sprays, raw pointer freelist links, और कोई type separation न होने के कारण attackers UAF/overflow बग्स को arbitrary kernel memory नियंत्रण में escalate कर सकते थे।

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.

Steps:

  1. Spray allocations (fill the holes)
  • Over time, the kernel heap gets fragmented: some zones have holes where old objects were freed.
  • The attacker first makes lots of dummy allocations to fill these gaps, so the heap becomes “packed” and predictable.
  1. Force new pages
  • Once the holes are filled, the next allocations must come from new pages added to the zone.
  • Fresh pages mean objects will be clustered together, not scattered across old fragmented memory.
  • This gives the attacker much better control of neighbors.
  1. Place attacker objects
  • The attacker now sprays again, creating lots of attacker-controlled objects in those new pages.
  • These objects are predictable in size and placement (since they all belong to the same zone).
  1. Free a controlled object (make a gap)
  • The attacker deliberately frees one of their own objects.
  • This creates a “hole” in the heap, which the allocator will later reuse for the next allocation of that size.
  1. Victim object lands in the hole
  • The attacker triggers the kernel to allocate the victim object (the one they want to corrupt).
  • Since the hole is the first available slot in the freelist, the victim is placed exactly where the attacker freed their object.
  1. Overflow / UAF into victim
  • Now the attacker has attacker-controlled objects around the victim.
  • By overflowing from one of their own objects (or reusing a freed one), they can reliably overwrite the victim’s memory fields with chosen values.

Why it works:

  • Zone allocator predictability: allocations of the same size always come from the same zone.
  • Freelist behavior: new allocations reuse the most recently freed chunk first.
  • Heap sprays: attacker fills memory with predictable content and controls layout.
  • End result: attacker controls where the victim object lands and what data sits next to it.

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

Apple ने allocator को hardened किया और heap grooming को बहुत कठिन बना दिया:

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.

An attacker can no longer guarantee that controlled data (OSData) ends up adjacent to sensitive kernel objects (task_t) of the same size.

2. Slabs and Per-CPU Caches

  • The heap is divided into slabs (pages of memory carved into fixed-size chunks for that zone).
  • Each zone has a per-CPU cache to reduce contention.
  • Allocation path:
  1. Try per-CPU cache.
  2. If empty, pull from the global freelist.
  3. If freelist is empty, allocate a new slab (one or more pages).
  • Benefit: This decentralization makes heap sprays less deterministic, since allocations may be satisfied from different CPUs’ caches.

3. Randomization inside zones

  • Within a zone, freed elements are not handed back in simple FIFO/LIFO order.
  • Modern XNU uses encoded freelist pointers (safe-linking like Linux, introduced ~iOS 14).
  • Each freelist pointer is XOR-encoded with a per-zone secret cookie.
  • This prevents attackers from forging a fake freelist pointer if they gain a write primitive.
  • Some allocations are randomized in their placement within a slab, so spraying doesn’t guarantee adjacency.

4. Guarded Allocations

  • Certain critical kernel objects (e.g., credentials, task structures) are allocated in guarded zones.
  • These zones insert guard pages (unmapped memory) between slabs or use redzones around objects.
  • Any overflow into the guard page triggers a fault → immediate panic instead of silent corruption.

5. Page Protection Layer (PPL) and SPTM

Even if you control a freed object, you can’t modify all of kernel memory:

  • PPL (Page Protection Layer) enforces that certain regions (e.g., code signing data, entitlements) are read-only even to the kernel itself.
  • On A15/M2+ devices, this role is replaced/enhanced by SPTM (Secure Page Table Monitor) + TXM (Trusted Execution Monitor).
  • These hardware-enforced layers mean attackers can’t escalate from a single heap corruption to arbitrary patching of critical security structures.
  • (Added / Enhanced): also, PAC (Pointer Authentication Codes) is used in the kernel to protect pointers (especially function pointers, vtables) so that forging or corrupting them becomes harder.
  • (Added / Enhanced): zones may enforce zone_require / zone enforcement, i.e. that an object freed can only be returned through its correct typed zone; invalid cross-zone frees may panic or be rejected. (Apple alludes to this in their memory safety posts)

6. Large Allocations

  • Not all allocations go through kalloc_type.
  • Very large requests (above ~16 KB) bypass typed zones and are served directly from kernel VM (kmem) via page allocations.
  • These are less predictable, but also less exploitable, since they don’t share slabs with other objects.

7. Allocation Patterns Attackers Target

Even with these protections, attackers still look for:

  • Reference count objects: if you can tamper with retain/release counters, you may cause use-after-free.
  • Objects with function pointers (vtables): corrupting one still yields control flow.
  • Shared memory objects (IOSurface, Mach ports): these are still attack targets because they bridge user ↔ kernel.

But — unlike before — you can’t just spray OSData and expect it to neighbor a task_t. You need type-specific bugs or info leaks to succeed.

Example: Allocation Flow in Modern Heap

Suppose userspace calls into IOKit to allocate an OSData object:

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

Freelist pointer protection:

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

Comparison Table

फ़ीचरपुराना Heap (Pre-iOS 15)आधुनिक Heap (iOS 15+ / A12+)
Allocation granularityFixed size buckets (kalloc.16, kalloc.32, आदि)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 attacker objects को अलग करते हैं
Kernel data/code protectionsFew hardware protectionsPPL / SPTM page tables & code pages को protect करते हैं, और PAC pointers को protect करता है
Allocation reuse validationNone (freelist pointers raw)zone_require / zone enforcement
Exploit reliabilityHigh with heap spraysबहुत कम, सफल होने के लिए logic bugs या info leaks चाहिए
Large allocations handlingसभी छोटे allocations समान रूप से manage होते थेबड़े allocations zones को bypass कर VM के माध्यम से handle होते हैं

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

हाल के Apple OS वर्ज़न्स (खासकर iOS 17+), Apple ने userland allocator, xzone malloc (XZM) पेश किया। यह kernel के kalloc_type का user-space समकक्ष है, जो type awareness, metadata isolation, और memory tagging safeguards लागू करता है।

Goals & Design Principles

  • Type segregation / type awareness: allocations को type या usage (pointer vs data) के अनुसार group करना ताकि type confusion और cross-type reuse न हो।
  • Metadata isolation: heap metadata (उदा. free lists, size/state bits) को object payloads से अलग रखना ताकि out-of-bounds writes से metadata corrupt न हो।
  • Guard pages / redzones: allocations के चारों ओर unmapped pages या padding डालकर overflows पकड़े जाएँ।
  • Memory tagging (EMTE / MIE): hardware tagging के साथ मिलकर use-after-free, out-of-bounds, और invalid accesses को detect करना।
  • Scalable performance: कम ओवरहेड बनाए रखना, अत्यधिक fragmentation से बचना, और प्रति सेकंड कई allocations को कम latency के साथ सपोर्ट करना।

Architecture & Components

नीचे xzone allocator के मुख्य घटक दिए गए हैं:

Segment Groups & Zones

  • Segment groups address space को usage categories के अनुसार partition करते हैं: उदा. data, pointer_xzones, data_large, pointer_large
  • प्रत्येक segment group में उन categories के allocations host करने वाले segments (VM ranges) होते हैं।
  • हर segment के साथ एक metadata slab (अलग VM क्षेत्र) जुड़ा होता है जो उस segment के लिए metadata (उदा. free/used bits, size classes) रखता है। यह out-of-line (OOL) metadata सुनिश्चित करता है कि metadata object payloads के साथ मिश्रित न हो, जिससे overflows से होने वाली corruption कम हो।
  • Segments को chunks (slices) में बाँटा जाता है जो आगे blocks (allocation units) में subdivide होते हैं। एक chunk किसी विशेष size class और segment group से जुड़ा होता है (यानी एक chunk के सभी blocks एक ही size और category साझा करते हैं)।
  • छोटे/मध्यम allocations के लिए fixed-size chunks उपयोग किए जाते हैं; बड़े/बहुत बड़े allocations के लिए अलग mapping हो सकती है।

Chunks & Blocks

  • एक chunk एक क्षेत्र है (अक्सर कई pages) जो एक group के भीतर एक size class के allocations के लिए समर्पित होता है।
  • एक chunk के अंदर, blocks allocation के लिए उपलब्ध slots होते हैं। Freed blocks metadata slab के माध्यम से ट्रैक किए जाते हैं — जैसे bitmaps या out-of-line रखे गए free lists।
  • chunks के बीच (या भीतर) guard slices / guard pages डाली जा सकती हैं (उदा. unmapped slices) ताकि out-of-bounds writes पकड़े जा सकें।

Type / Type ID

  • हर allocation site (या malloc, calloc, आदि कॉल) एक type identifier (एक malloc_type_id_t) के साथ जुड़ा होता है जो बताता है कि किस प्रकार का object allocate हो रहा है। वह type ID allocator को पास किया जाता है, जो इसे उपयोग करके सही zone / segment चुनता है।
  • इसके कारण, भले ही दो allocations का आकार समान हो, वे पूरी तरह अलग zones में जा सकते हैं यदि उनके types अलग हों।
  • iOS 17 के शुरुआती वर्ज़न्स में, सभी APIs (उदा. CFAllocator) पूरी तरह type-aware नहीं थे; Apple ने iOS 18 में उन कमजोरियों में से कुछ का समाधान किया।

Allocation & Freeing Workflow

यहाँ xzone में allocation और deallocation का एक high-level flow है:

  1. malloc / calloc / realloc / typed alloc को size और type ID के साथ invoke किया जाता है।
  2. Allocator type ID का उपयोग करके सही segment group / zone चुनता है।
  3. उस zone/segment के भीतर, यह उस size के free blocks वाले chunk की तलाश करता है।
  • यह local caches / per-thread pools या metadata से free block lists देख सकता है।
  • यदि कोई free block उपलब्ध नहीं है, तो वह zone में नया chunk allocate कर सकता है।
  1. metadata slab अपडेट किया जाता है (free bit cleared, bookkeeping)।
  2. यदि memory tagging (EMTE) लागू है, तो वापस किया गया block एक tag पाता है, और metadata को इसके “live” state को दर्शाने के लिए अपडेट किया जाता है।
  3. जब free() कॉल किया जाता है:
  • ब्लॉक को metadata में freed के रूप में चिह्नित किया जाता है (OOL slab के जरिए)।
  • ब्लॉक को reuse के लिए free list में रखा जा सकता है या pooled किया जा सकता है।
  • वैकल्पिक रूप से, ब्लॉक की contents को cleared या poisoned किया जा सकता है ताकि data leaks या use-after-free exploitation की संभावना कम हो।
  • ब्लॉक से जुड़े hardware tag को invalidated या re-tagged किया जा सकता है।
  • अगर पूरा chunk free हो गया (सभी blocks freed), तो allocator memory pressure के दौरान उस chunk को reclaim कर सकता है (unmap करना या OS को वापस करना)।

Security Features & Hardening

ये आधुनिक userland xzone में लागू किए गए defenses हैं:

FeaturePurposeNotes
Metadata decouplingOverflow से metadata corrupt होने से रोकनाMetadata अलग VM क्षेत्र (metadata slab) में रहता है
Guard pages / unmapped slicesOut-of-bounds writes पकड़नाBuffer overflows को silent corruption के बजाय पकड़ने में मदद करता है
Type-based segregationCross-type reuse और type confusion रोकनाभले ही size समान हो, अलग types अलग zones में जाते हैं
Memory Tagging (EMTE / MIE)Invalid access, stale references, OOB, UAF पकड़नाxzone hardware EMTE के synchronous mode के साथ काम करता है
Delayed reuse / poisoning / zapUse-after-free exploitability घटानाFreed blocks को poison, zero या quarantine किया जा सकता है before reuse
Chunk reclamation / dynamic unmappingMemory waste और fragmentation घटानाIdle chunks unmapped किए जा सकते हैं
Randomization / placement variationDeterministic adjacency रोकनाChunk और block चयन में randomized पहलू हो सकते हैं
Segregation of “data-only” allocationsउन allocations को अलग करना जिनमें pointers नहीं होतेMetadata या control fields पर attacker का नियंत्रण घटता है

Interaction with Memory Integrity Enforcement (MIE / EMTE)

  • Apple की MIE (Memory Integrity Enforcement) hardware + OS फ्रेमवर्क है जो Enhanced Memory Tagging Extension (EMTE) को major attack surfaces पर always-on, synchronous mode में लाती है।
  • xzone allocator MIE के user space आधार के रूप में काम करता है: xzone के माध्यम से की गई allocations को tags मिलते हैं, और accesses hardware द्वारा चेक किए जाते हैं।
  • MIE में allocator, tag assignment, metadata management, और tag confidentiality enforcement एक साथ integrate होते हैं ताकि memory errors (उदा. stale reads, OOB, UAF) तुरंत पकड़े जाएँ न कि बाद में exploit किए जाएँ।

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 मॉड्यूल

  • Watcher anti-analysis: एक समर्पित watcher बाइनरी डिवाइस की लगातार प्रोफाइलिंग करती है और जब एक research वातावरण का पता चलता है तो kill-chain को रद्द कर देती है। यह security.mac.amfi.developer_mode_status, diagnosticd कंसोल की उपस्थिति, locales US या IL, jailbreak traces जैसे Cydia, bash, tcpdump, frida, sshd, या checkrain जैसे प्रोसेस, mobile AV apps (McAfee, AvastMobileSecurity, NortonMobileSecurity), कस्टम HTTP proxy सेटिंग्स, और कस्टम root CAs की जांच करती है। किसी भी चेक में विफलता आगे की payload डिलीवरी को ब्लॉक कर देती है।
  • Helper surveillance hooks: helper component अन्य स्टेजों से /tmp/helper.sock के माध्यम से संवाद करता है, फिर DMHooker और UMHooker नामक hook sets लोड करता है। ये hooks VOIP audio paths को टैप करते हैं (रिकॉर्डिंग्स /private/var/tmp/l/voip_%lu_%u_PART.m4a में सेव होती हैं), एक system-wide keylogger लागू करते हैं, बिना UI के फोटो कैप्चर करते हैं, और SpringBoard को hook करके उन notifications को दबा देते हैं जो ये क्रियाएँ सामान्यतः उत्पन्न करतीं। इसलिए helper एक छिपा हुआ सत्यापन + हल्की निगरानी परत के रूप में कार्य करता है, इससे पहले कि Predator जैसे heavier implants डाले जाएँ।

iMessage/Media Parser Zero-Click Chains

Imessage Media Parser Zero Click Coreaudio Pac Bypass

संदर्भ

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें