iOS Exploiting

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

iOS Exploit Mitigations

1. Code Signing / Runtime Signature Verification

Introduced early (iPhone OS → iOS) Bu temel korumalardan biridir: tüm yürütülebilir kod (uygulamalar, dynamic libraries, JIT-ed code, extensions, frameworks, caches) Apple’ın trust köküne dayanan bir sertifika zinciri ile kriptografik olarak imzalanmış olmalıdır. Çalışma zamanında, bir ikili belleğe yüklenmeden önce (veya bazı sınırlar arası atlamalar yapılmadan önce) sistem imzayı doğrular. Kod değiştirilmiş (bit-flip, patch) veya imzasız ise yükleme başarısız olur.

  • Önler: exploit zincirlerindeki “klasik payload drop + execute” aşamasını; arbitrary code injection; mevcut bir ikiliyi kötü amaçlı mantık eklemek için değiştirmeyi.
  • Mekanizma detayı:
  • Mach-O loader (ve dynamic linker) kod sayfalarını, segmentleri, entitlements, team ID’leri ve imzanın dosya içeriğini kapsayıp kapsamadığını kontrol eder.
  • JIT cache’leri veya dinamik üretilen kod gibi bellek bölgeleri için Apple, sayfaların imzalanmasını veya özel API’ler aracılığıyla doğrulanmasını zorunlu kılar (örn. code-sign kontrolleriyle mprotect).
  • İmza entitlements ve kimlikleri içerir; OS belirli API’lerin veya ayrıcalıklı yeteneklerin belirli entitlements gerektirdiğini zorunlu kılar ve bunlar taklit edilemez.
Example Bir exploit bir süreçte kod yürütmesi elde edip shellcode’u heap’e yazıp oraya atlamayı denesin. iOS’ta o sayfanın executable olarak işaretlenmesi ve ayrıca code-signature kısıtlamalarını sağlaması gerekir. Shellcode Apple’ın sertifikasıyla imzalanmadığından atlama başarısız olur veya sistem o bellek bölgesini executable hale getirmeyi reddeder.

2. CoreTrust

Introduced around iOS 14+ era (or gradually in newer devices / later iOS) CoreTrust, ikililerin (sistem ve kullanıcı ikilileri dahil) çalışma zamanı imza doğrulamasını Apple’ın root sertifikası karşısında yapan alt sistemdir; yerel kullanıcı alanı trust store’larına güvenmek yerine.

  • Önler: ikililerin kurulum sonrası tahrifatını, SpringBoard/libsystem gibi sistem kütüphanelerini veya kullanıcı uygulamalarını swap/patch etmeye çalışan jailbreaking tekniklerini; güvenilen ikililerin kötü amaçlı muadilleriyle değiştirilerek sistemi kandırmayı.
  • Mekanizma detayı:
  • Yerel bir trust veritabanına veya sertifika cache’ine güvenmek yerine CoreTrust doğrudan Apple’ın root’una referans verir veya güvenli bir zincirde ara sertifikaları doğrular.
  • Mevcut ikililerin dosya sistemindeki değişikliklerin (ör. modifikasyonlar) tespit edilip reddedilmesini sağlar.
  • İmzalama sırasında entitlements, team ID’leri, code signing bayrakları ve diğer metadataları ikiliye bağlar ve bunları yükleme zamanında uygular.
Example Bir jailbreak `SpringBoard` veya `libsystem`’i yama içeren bir sürümle değiştirmeye çalışabilir. Ancak OS loader veya CoreTrust doğrulaması yaparken imza uyuşmazlığını (veya değiştirilmiş entitlements’ı) fark eder ve çalıştırmayı reddeder.

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

Introduced in many OSes earlier; iOS had NX-bit / w^x for a long time DEP, yazılabilir (data için) olarak işaretlenen sayfaların non-executable, executable olarak işaretlenen sayfaların ise non-writable olmasını zorunlu kılar. Basitçe heap veya stack bölgesine shellcode yazıp onu çalıştıramazsınız.

  • Önler: doğrudan shellcode yürütmeyi; klasik buffer-overflow → inject edilen shellcode’a atlamayı.
  • Mekanizma detayı:
  • MMU / bellek koruma bayrakları (page table’lar aracılığıyla) ayrımı uygular.
  • Bir yazılabilir sayfayı executable yapmak için yapılan herhangi bir deneme sistem kontrolünü tetikler (veya yasaklanır ya da code-sign onayı gerektirir).
  • Birçok durumda sayfaları executable yapmak OS API’leri üzerinden yapılmalı ve ek kısıtlamalar/controllar uygulanır.
Example Bir overflow shellcode’u heap’e yazar. Saldırgan `mprotect(heap_addr, size, PROT_EXEC)` yaparak sayfayı executable hale getirmeye çalışır. Ancak sistem bunu reddeder ya da yeni sayfanın code-sign kısıtlamalarını sağlamasını doğrular (ki shellcode sağlayamaz).

4. Address Space Layout Randomization (ASLR)

Introduced in iOS ~4–5 era (roughly iOS 4–5 timeframe) ASLR, kütüphaneler, heap, stack vb. ana bellek bölgelerinin base adreslerini her süreç başlatıldığında rastgeleleştirir. Gadget adresleri her çalıştırmada değişir.

  • Önler: ROP/JOP için gadget adreslerinin hardcode edilmesini; statik exploit zincirlerini; bilinen offset’lere kör atlamayı.
  • Mekanizma detayı:
  • Yüklenen her kütüphane / dynamic module rastgele bir offset ile rebase edilir.
  • Stack ve heap base pointer’ları rastgeleleştirilir (belirli entropi sınırları içinde).
  • Bazen diğer bölgeler (örn. mmap ile ayrılanlar) de rastgeleleştirilir.
  • information-leak mitigations ile kombine edildiğinde, saldırganın önce bir adres veya pointer leak etmesi gerekir ki base adreslerini çalışma zamanında hesaplayabilsin.
Example Bir ROP zinciri `0x….lib + offset`’deki gadget’ı bekler. Ancak `lib` her çalıştırmada farklı bir yere rebase edildiği için hardcoded zincir başarısız olur. Bir exploit, gadget adreslerini hesaplamadan önce modülün base adresini leak etmelidir.

5. Kernel Address Space Layout Randomization (KASLR)

Introduced in iOS ~ (iOS 5 / iOS 6 timeframe) Kullanıcı ASLR’sine benzer şekilde, KASLR önyükleme sırasında kernel text ve diğer kernel yapılarının base’ini rastgeleleştirir.

  • Önler: kernel seviyesindeki exploitlerin sabit kernel kodu veya verisinin konumuna dayanmasını; statik kernel exploitlerini.
  • Mekanizma detayı:
  • Her boot’ta kernel’in base adresi bir aralık içinde rastgele belirlenir.
  • Kernel veri yapıları (task_structs, vm_map vb.) da yeniden yerleştirilebilir veya offsetlenebilir.
  • Saldırganların önce kernel pointer’ları leak etmesi veya bilgi açıklama (information disclosure) açıklarını kullanması gerekir ki offsetleri hesaplayıp kernel yapıları/ kodu üzerinde kaçırma yapabilsinler.
Example Bir local zafiyet kernel fonksiyon işaretçisini (ör. `vtable` içindeki) `KERN_BASE + offset` adresinde bozmayı hedefler. Ancak `KERN_BASE` bilinmediği için saldırgan önce bunu leak etmelidir (örn. bir read primitive ile) ve doğru adresi hesapladıktan sonra bozar.

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 sayfalarının bütünlüğünü sürekli izler (hash veya checksum yoluyla). Eğer allowed window’lar dışında bir tahrifat (patch, inline hook, code modification) tespit edilirse kernel panic veya reboot tetikler.

  • Önler: persistent kernel patching (kernel talimatlarını değiştirme), inline hook’lar, statik fonksiyon overwrite’ları.
  • Mekanizma detayı:
  • Bir donanım veya firmware modülü kernel text bölgesini izler.
  • Periyodik veya talep üzerine sayfaları yeniden hash’ler ve beklenen değerlerle karşılaştırır.
  • Eğer uyumsuzluklar benign update pencereleri dışında görülürse cihazı panic’ler (kalıcı kötü amaçlı patch’i önlemek için).
  • Saldırganların ya tespit dışı pencerelerden kaçınması ya da meşru patch yollarını kullanması gerekir.
Example Bir exploit bir kernel fonksiyon prologunu (örn. `memcmp`) patch’lemeye çalışır ki çağrıları yakalasın. Ancak KPP kod sayfasının hash’inin beklenenle uyuşmadığını görür ve kernel panic tetikleyerek cihazı çökertir; böylece patch kalıcı hale gelemez.

7. Kernel Text Read‐Only Region (KTRR)

Introduced in modern SoCs (post ~A12 / newer hardware) KTRR donanım tarafından zorlanan bir mekanizmadır: kernel text önyükleme sırasında kilitlenip EL1’den (kernel) yazılamaz hale getirilir, böylece code sayfalarına daha sonra yazma engellenir.

  • Önler: boot sonrası kernel kodunun herhangi bir şekilde değiştirilmesini (örn. patching, in-place code injection) EL1 ayrıcalık düzeyinde.
  • Mekanizma detayı:
  • Boot sırasında (secure/bootloader aşamasında) memory controller veya güvenli bir donanım ünitesi kernel text’i içeren fiziksel sayfaları read-only olarak işaretler.
  • Bir exploit tam kernel ayrıcalıkları elde etse bile o sayfalara yazamaz.
  • Bunları değiştirmek için saldırgan önce boot zincirini bozmalı veya KTRR’yi subvert etmelidir.
Example Bir privilege-escalation exploit EL1’e geçip kernel fonksiyonuna (örn. syscall handler) bir trampoline yazmayı dener. Ancak sayfalar KTRR tarafından read-only olarak kilitlendiği için yazma başarısız olur veya fault verir; dolayısıyla patch uygulanamaz.

8. Pointer Authentication Codes (PAC)

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

  • PAC, pointer değerlerinin (return adresleri, function pointer’ları, belirli data pointer’ları) tahrifatını tespit etmek için ARMv8.3-A ile gelen bir donanım özelliğidir; pointer’ın kullanılmayan üst bitlerine küçük bir kriptografik imza (bir “MAC”) yerleştirilir.
  • İmza (“PAC”), pointer değeri ile bir modifier (bağlam değeri; ör. stack pointer veya ayırt edici bir veri) üzerinde hesaplanır. Böylece aynı pointer değeri farklı bağlamlarda farklı PAC üretir.
  • Kullanım zamanında, o pointer’ı dereference etmeden veya branch yapmadan önce bir authenticate talimatı PAC’ı kontrol eder. Geçerliyse PAC çıkarılır ve saf pointer elde edilir; geçersizse pointer “poisoned” olur veya bir fault tetiklenir.
  • PAC üretme/doğrulama için kullanılan anahtarlar ayrıcalıklı register’larda (EL1, kernel) bulunur ve user moddan doğrudan okunamaz.
  • Birçok sistemde tüm 64 bit’ler adres için kullanılmadığından (örn. 48-bit adres alanı), üst bitler “boş”tur ve PAC bu bitlere yerleştirilebilir.

Architectural Basis & Key Types

  • ARMv8.3 beş adet 128-bit anahtar tanıtır (her biri iki 64-bit sistem register’ı ile uygulanır).

  • APIAKey — instruction pointers için (domain “I”, key A)

  • APIBKey — ikinci instruction pointer anahtarı (domain “I”, key B)

  • APDAKey — data pointer’lar için (domain “D”, key A)

  • APDBKey — data pointer’lar için ikinci anahtar (domain “D”, key B)

  • APGAKey — generic anahtar, pointer olmayan veriler veya diğer genel kullanımlar için

  • Bu anahtarlar ayrıcalıklı sistem register’larında saklanır (yalnızca EL1/EL2 vb. erişebilir), user mod tarafından erişilemez.

  • PAC bir kriptografik fonksiyonla hesaplanır (ARM QARMA’yı önermektedir) ve şunları kullanır:

  1. Pointer değeri (canonical portion)
  2. Bir modifier (bağlam değeri, ör. salt)
  3. Gizli anahtar
  4. İçsel tweak mantığı Eğer ortaya çıkan PAC pointer’ın üst bitlerinde saklananla eşleşirse authentication başarılı olur.

Instruction Families

İsimlendirme kuralı: PAC / AUT / XPAC, ardından domain harfleri.

  • PACxx talimatları bir pointer’ı sign eder ve PAC ekler
  • AUTxx talimatları authenticate + strip yapar (doğrula ve PAC’ı çıkar)
  • XPACxx talimatları doğrulama yapmadan strip eder

Domain / suffix örnekleri:

MnemonicAnlam / DomainAnahtar / AlanAssembly’de Örnek Kullanım
PACIAInstruction pointer’ı APIAKey ile imzalar“I, A”PACIA X0, X1 — X0 içindeki pointer’ı X1 modifier ile APIAKey kullanarak imzalar
PACIBInstruction pointer’ı APIBKey ile imzalar“I, B”PACIB X2, X3
PACDAData pointer’ı APDAKey ile imzalar“D, A”PACDA X4, X5
PACDBData pointer’ı APDBKey ile imzalar“D, B”PACDB X6, X7
PACG / PACGAGeneric (pointer olmayan) imzalama APGAKey ile“G”PACGA X8, X9, X10 (X9’u X10 modifier ile X8’e imzalar)
AUTIAAPIA ile imzalanmış instruction pointer’ı doğrula & PAC’ı çıkar“I, A”AUTIA X0, X1 — X0’daki PAC’ı X1 modifier ile kontrol eder, sonra çıkar
AUTIBAPIB domain doğrulama“I, B”AUTIB X2, X3
AUTDAAPDA ile imzalanmış data pointer’ı doğrula“D, A”AUTDA X4, X5
AUTDBAPDB ile imzalanmış data pointer’ı doğrula“D, B”AUTDB X6, X7
AUTGAGeneric / blob doğrulama (APGA)“G”AUTGA X8, X9, X10 (generic doğrulama)
XPACIPAC’ı çıkar (instruction pointer, doğrulama yok)“I”XPACI X0 — X0’taki PAC’ı çıkar (instruction domain)
XPACDPAC’ı çıkar (data pointer, doğrulama yok)“D”XPACD X4 — X4’teki data pointer’ın PAC’ını çıkar

Bazı özel / alias formlar:

  • PACIASP PACIA X30, SP için kısadır (link register’ı SP modifier ile imzala)
  • AUTIASP AUTIA X30, SP’dir (link register’ı SP ile doğrula)
  • RETAA, RETAB (authenticate-and-return) veya BLRAA (authenticate & branch) gibi combined formlar ARM uzantılarında / compiler desteğinde bulunur.
  • Ayrıca modifier’ın sıfır olduğu formlar da vardır: PACIZA / PACIZB gibi, modifier implicit olarak sıfırdır.

Modifiers

Modifier’ın ana amacı PAC’ı belirli bir bağlama bağlamaktır, böylece aynı adres farklı bağlamlarda yeniden kullanılamaz — bir hash’e salt eklemeye benzer.

Buna göre:

  • Modifier bir bağlam değeridir (başka bir register) ve PAC hesaplamasına karıştırılır. Tipik seçimler: stack pointer (SP), frame pointer veya bir nesne ID’si.
  • SP modifier olarak kullanıldığında return address signing için yaygındır: PAC spesifik stack frame’e bağlanır. LR’ı farklı bir framede yeniden kullanmaya çalışırsanız modifier değişir ve PAC doğrulaması başarısız olur.
  • Aynı pointer değeri farklı modifier’larla imzalandığında farklı PAC’lar üretir.
  • Modifier gizli olmak zorunda değildir, ancak ideal olarak saldırgan tarafından kontrol edilmemelidir.
  • Anlamsız modifier’ın olduğu durumlarda bazı form’lar implicit sıfır veya sabit bir değer kullanır.

Apple / iOS / XNU Customizations & Observations

  • Apple’ın PAC uygulaması her boot için diversifier içerir; böylece anahtarlar veya tweak’ler her boot’ta değişir ve boots arasında yeniden kullanım önlenir.
  • Ayrıca cross-domain mitigations içerir, böylece user modda imzalanan PAC’lar kolayca kernel modda yeniden kullanılamaz.
  • Apple Silicon (M1) üzerinde tersine mühendislik, dokuz modifier tipi ve Apple’a özgü anahtar kontrol sistem register’ları olduğunu gösterdi.
  • Apple PAC’ı birçok kernel alt sisteminde kullanır: return address signing, kernel verilerinde pointer bütünlüğü, imzalı thread context’leri vb.
  • Google Project Zero, güçlü bir read/write primitive ile kernel’da kernel PAC’larını (A anahtarları için) taklit etmenin mümkün olduğuna dair bulgular gösterdi (A12 dönemi), ancak Apple bu yolların birçoğunu yamadı.
  • Apple’ın sisteminde bazı anahtarlar kernel çapında global iken, kullanıcı süreçleri için per-process key randomness sağlanabilir.

PAC Bypasses

  1. Kernel-mode PAC: theoretical vs real bypasses
  • Çünkü kernel PAC anahtarları ve mantığı sıkı şekilde kontrol edilir (ayrıcalıklı register’lar, diversifier’lar, domain izolasyonu), arbitrary signed kernel pointer’ları forge etmek çok zordur.
  • Azad’ın 2020 “iOS Kernel PAC, One Year Later” raporu iOS 12-13’te birkaç kısmi bypass (signing gadget’ları, signed state reuse, korunmasız indirect branch’ler) bulduğunu bildirir ama genel amaçlı bir bypass yoktu. bazad.github.io
  • Apple’ın “Dark Magic” özelleştirmeleri exploit yüzeylerini daha da daralttı (domain switching, per-key enabling bit’leri). i.blackhat.com
  • Apple silicon (M1/M2) üzerinde bilinen kernel PAC bypass CVE-2023-32424 Zecao Cai ve ekibi tarafından raporlandı. i.blackhat.com
  • Ancak bu bypass’lar genellikle çok özel gadget’lara veya implementasyon hatalarına dayanır; genel amaçlı değildir.

Bu nedenle kernel PAC yüksek derecede sağlam kabul edilir, fakat kusursuz değildir.

  1. User-mode / runtime PAC bypass techniques

Bunlar daha yaygındır ve PAC’ın runtime/dynamic linking kullanımındaki eksiklikleri suistimal eder. Aşağıda sınıflar ve örnekler verilmiştir.

2.1 Shared Cache / A key issues

  • dyld shared cache sistem framework’lerinin ve kütüphanelerinin büyük, ön-linklenmiş bir blob’udur. Bu kadar yaygın paylaşıldığı için shared cache içindeki fonksiyon pointer’ları “önceden imzalanmış” olur ve birçok süreç tarafından kullanılır. Saldırganlar bu zaten-imzalanmış pointer’ları “PAC oracles” olarak hedef alır.
  • Bazı bypass teknikleri shared cache’deki A-key ile imzalanmış pointer’ları çıkarmayı veya yeniden kullanmayı dener.
  • “No Clicks Required” konuşması shared cache üzerinde bir oracle inşa ederek relatif adresleri çıkarma ve imzalı pointer’larla PAC’ı bypass etme örneğini açıklar. saelo.github.io
  • Ayrıca kullanıcı alanındaki shared library import edilen fonksiyon pointer’larının PAC ile yeterince korunmadığı bulunmuş; bu saldırganın fonksiyon pointer’larını değiştirmeden elde etmesine izin vermiştir. (Project Zero bug kaydı) bugs.chromium.org

2.2 dlsym(3) / dynamic symbol resolution

  • Bilinen bir bypass, dlsym() çağırıp zaten imzalanmış bir fonksiyon pointer’ı (A-key ile, diversifier sıfır) almak ve bunu kullanmaktır. dlsym meşru şekilde imzalanmış bir pointer döndüğünden, onun kullanımı PAC taklidi gerektirmez.
  • Epsilon’ın blog’u bazı bypass’ların bunu nasıl suistimal ettiğini detaylandırır: dlsym("someSym") çağrısı imzalı bir pointer döndürür ve dolayısıyla indirect call’larda kullanılabilir. blog.epsilon-sec.com
  • Synacktiv’in “iOS 18.4 — dlsym considered harmful” yazısı bir bugı tarif eder: iOS 18.4’te dlsym ile çözümlenen bazı semboller yanlış imzalanmış (veya hatalı diversifier ile) pointer’lar döndürüyor, bu da istenmeyen PAC bypass’a izin veriyor. Synacktiv
  • dyld içindeki logic: result->isCode olduğunda döndürülen pointer’ı __builtin_ptrauth_sign_unauthenticated(..., key_asia, 0) ile imzalar, yani context sıfır ile. blog.epsilon-sec.com

Böylece dlsym user-mode PAC bypass’larında sık kullanılan bir vektördür.

2.3 Other DYLD / runtime relocations

  • DYLD loader ve dynamic relocation mantığı karmaşıktır ve bazen relocasyon yapmak için sayfaları geçici olarak read/write map’ler, sonra tekrar read-only yapar. Saldırganlar bu zaman pencerelerini suistimal eder. Synacktiv’in sunumu “Operation Triangulation” olarak adlandırılan, dynamic relocations ile zamanlama bazlı bir PAC bypass’ı tarif eder. Synacktiv
  • DYLD sayfaları artık SPRR / VM_FLAGS_TPRO ile korunur (dyld için bazı koruma bayrakları). Ancak daha eski sürümlerde zayıf korumalar vardı. Synacktiv
  • WebKit exploit zincirlerinde, DYLD loader genellikle PAC bypass hedefidir. Sunumlarda birçok PAC bypass’ının DYLD loader’ını (relocation, interposer hook’lar üzerinden) hedef aldığı belirtiliyor. Synacktiv

2.4 NSPredicate / NSExpression / ObjC / SLOP

  • Userland exploit zincirlerinde, Objective-C runtime metodları (NSPredicate, NSExpression, NSInvocation) kontrol çağrılarını belli belirsiz şekilde smuggle etmek için kullanılır.
  • PAC öncesi eski iOS sürümlerinde exploit’ler fake NSInvocation objeleriyle kontrollü bellekteki selector’ları çağırabiliyordu. PAC ile bu teknikler güncellenmelidir. Ancak SLOP (SeLector Oriented Programming) tekniği PAC altında da genişletildi. Project Zero
  • Orijinal SLOP tekniği, sahte invocation’lar yaratarak ObjC çağrılarının zincirlenmesine izin veriyordu; bypass, ISA veya selector pointer’larının bazen tam olarak PAC ile korunmamasına dayanıyordu. Project Zero
  • Pointer authentication kısmen uygulandığı ortamlarda, methodlar / selector’lar / hedef pointer’lar her zaman PAC korumalı olmayabilir; bu da bypass için bir açıklık sağlar.

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>
Bir buffer overflow, stack üzerindeki return adresini taşır. Saldırgan hedef gadget adresini yazar ama doğru PAC'ı hesaplayamaz. Fonksiyon döndüğünde, CPU’nun `AUTIA` talimatı PAC uyumsuzluğu nedeniyle hata verir. Zincir başarısız olur.
Project Zero’nun A12 (iPhone XS) analizleri, Apple’ın PAC kullanımını ve bir saldırganın bellek okuma/yazma primitive’ine sahip olması durumunda PAC sahteleme yöntemlerini gösterdi.
</details>


### 9. **Branch Target Identification (BTI)**
**Introduced with ARMv8.5 (later hardware)**
BTI, **dolaylı branch hedeflerini** kontrol eden bir donanım özelliğidir: `blr` veya dolaylı call/jump’lar çalıştırılırken, hedefin bir **BTI landing pad** ile başlaması gerekir (`BTI j` veya `BTI c`). Landing pad içermeyen gadget adreslerine atlama bir istisna tetikler.

LLVM’nin uygulama notları BTI talimatlarının üç varyantını ve bunların branch tiplerine nasıl eşlendiğini belirtir.

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

- Branch target enforcement ile derlenen kodda, compiler her geçerli dolaylı-branch hedefine (dolaylı çağrılabilecek fonksiyon başlangıçları veya jump’larla erişilebilen bloklar) bir BTI talimatı (C, J veya JC) ekler; böylece dolaylı branch’ler yalnızca bu yerlere başarılı olurlar.
- **Direct branches / calls** (ör. sabit-adresli `B`, `BL`) BTI tarafından **kısıtlanmaz**. Varsayım, kod sayfalarının güvenilir olduğu ve saldırganın bunları değiştiremeyeceğidir (dolayısıyla direct branch’ler güvenlidir).
- Ayrıca, **RET / return** talimatları genellikle BTI ile kısıtlanmaz çünkü return adresleri PAC veya return signing mekanizmalarıyla korunur.

#### Mechanism and enforcement

- CPU, bir sayfa “guarded / BTI-enabled” olarak işaretlendiğinde bir **dolaylı branch (BLR / BR)** decode ettiğinde, hedef adresin ilk talimatının izin verilen bir BTI (C, J veya JC) olup olmadığını kontrol eder. Değilse, bir **Branch Target Exception** oluşur.
- BTI talimatının encoding’i daha önce NOP için ayrılmış opcode’ları yeniden kullanacak şekilde tasarlanmıştır (eski ARM sürümlerinde). Bu yüzden BTI-enabled ikili dosyalar geriye dönük uyumludur: BTI desteği olmayan donanımda bu talimatlar NOP gibi davranır.
- BTI ekleyen compiler pass’ları yalnızca gerekli yerlere BTI ekler: dolaylı çağrılabilecek fonksiyonlar veya jump’larla hedeflenen basic block’lar.
- Bazı yamalar ve LLVM kodu, BTI’nin *tüm* basic block’lara eklenmediğini — sadece potansiyel branch hedeflerine (ör. switch / jump tablolarından) eklendiğini gösterir.

#### BTI + PAC synergy

PAC, pointer değerini (kaynağı) korur — dolaylı çağrı/return zincirinin değiştirilmediğinden emin olunmasını sağlar.

BTI, geçerli bir pointer olsa bile yalnızca doğru işaretlenmiş giriş noktalarını hedeflemesini garanti eder.

Birlikte, bir saldırganın hem doğru PAC ile işaretlenmiş geçerli bir pointer’a hem de hedefin orada BTI içermesine ihtiyaç duyması gerekir. Bu, exploit gadget’ları oluşturma zorluğunu artırır.

#### Example


<details>
<summary>Example</summary>
Bir exploit, `0xABCDEF` adresindeki ve `BTI c` ile başlamayan bir gadget’a pivot etmeye çalışır. CPU, `blr x0` çalıştırıldığında hedefi kontrol eder ve talimat hizalaması geçerli bir landing pad içermediği için hata verir. Bu nedenle birçok gadget, BTI öneki içermedikçe kullanılamaz.
</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** ile tanıtılan bir özellik olup **ayrıcalıklı kodun** (EL1 veya EL2) **user-accessible (EL0)** olarak işaretlenmiş belleği **okumasını veya yazmasını** engeller; PAN açık olmadığı sürece erişime izin verilmez.
- Fikir: kernel kandırılsa veya ele geçirilse bile, user-space pointer’larını keyfi olarak dereference edememeli — PAN önce temizlenmeden bu yapılmamalı; böylece `ret2usr` tarzı exploit’ler veya kullanıcı kontrollü buffer’ların kötüye kullanımı azalır.
- PAN etkin olduğunda (PSTATE.PAN = 1), “EL0 tarafından erişilebilir” olarak işaretlenmiş sanal adrese yapılan ayrıcalıklı load/store talimatları bir **permission fault** tetikler.
- Kernel, meşru olarak user-space belleğine erişmesi gerektiğinde (ör. kullanıcı buffer’larına veri kopyalama), PAN’ı **geçici olarak devre dışı bırakmalı** (veya “unprivileged load/store” talimatları kullanmalı) ki erişim mümkün olsun.
- Linux’ta ARM64 üzerinde PAN desteği yaklaşık 2015 civarında geldi: kernel yamaları özelliğin tespiti için eklendi ve `get_user` / `put_user` gibi fonksiyonlar PAN’ı temizleyen varyantlarla değiştirildi.

**Önemli nüans / sınırlama / bug**
- Siguza ve diğerlerinin belirttiği gibi, ARM spesifikasyonundaki bir bug (veya belirsiz davranış) nedeniyle **execute-only user mapping** (`--x`) PAN’ı **tetiklemeyebilir**. Başka bir deyişle, bir user sayfası yürütülebilir olarak işaretlenip okumaya izin verilmiyorsa, kernel’in okuma girişimi PAN tarafından engellenmeyebilir çünkü mimari “EL0 tarafından erişilebilir” tanımını yalnızca okunabilir izin gerektirecek şekilde değerlendiriyor olabilir. Bu, belirli konfigürasyonlarda PAN bypass’ına yol açar.
- Bu yüzden eğer iOS / XNU execute-only user sayfalarına izin veriyorsa (ör. bazı JIT veya code-cache ayarlarında olduğu gibi), kernel PAN etkin olsa bile bu sayfalardan kazara okuyabilir. Bu, ARMv8+ sistemlerde bilinen ve ince istismar edilebilen bir ikincil durumdur.

#### PXN (Privileged eXecute Never)

- **PXN**, sayfa tablosu girdilerinde (leaf veya block entry’lerde) bulunan bir bayraktır ve sayfanın **ayrıcalıklı modda yürütülemeyeceğini** (yani EL1 tarafından yürütülemeyeceğini) gösterir.
- PXN, kernel’in (veya herhangi ayrıcalıklı kodun) user-space sayfalarından talimatları yürütmesini engeller; böylece kontrol kernel’e kayarsa user belleğine atlama engellenir.
- PAN ile birleştiğinde:
1. Kernel varsayılan olarak user verisini okuyup yazamaz (PAN)
2. Kernel user-space kodunu yürütemez (PXN)
- ARMv8 sayfa tablosu formatında, leaf girdilerin attribute bitleri arasında `PXN` biti (ve ayrıca unprivileged için `UXN`) bulunur.

Dolayısıyla kernel’in bozulmuş bir function pointer’ı user belleğine işaret etse bile ve oraya branch etmeye çalışsa, PXN biti bir hata oluşturur.

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

PAN / PXN’in nasıl çalıştığını anlamak için ARM’ın translation ve izin modeline bakmak gerekir (basitleştirilmiş):

- Her sayfa veya block girdisinin, erişim izinleri (read/write, privileged vs unprivileged) için **AP[2:1]** ve yürütme-kısıtlamaları için **UXN / PXN** gibi attribute alanları vardır.
- PSTATE.PAN = 1 olduğunda, donanım değiştirilmiş semantikleri uygular: “EL0 tarafından erişilebilir” olarak işaretlenen sayfalara ayrıcalıklı erişimler engellenir (fault).
- Bahsedilen bug nedeniyle, sadece yürütülebilir olarak işaretlenmiş (okunamaz) sayfalar bazı uygulamalarda “EL0 tarafından erişilebilir” sayılmayabilir ve böylece PAN atlanabilir.
- Bir sayfanın PXN biti setliyse, instruction fetch yüksek ayrıcalık seviyesinden gelse bile yürütme yasaktır.

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

Sertleştirilmiş bir kernel tasarımında (Apple’ın kullanabileceği gibi):

- Kernel varsayılan olarak PAN’ı etkinleştirir (yani ayrıcalıklı kod kısıtlanır).
- Kullanıcı buffer’larını meşru olarak okumak/yazmak gereken yollar (ör. syscall buffer kopyası, I/O) PAN’ı geçici olarak **devre dışı bırakır** veya override eden özel talimatlar kullanır.
- Kullanıcı verisine erişim bitince PAN yeniden etkinleştirilmelidir.
- PXN sayfa tabloları aracılığıyla uygulanır: user sayfalarda PXN = 1 (böylece kernel bunları çalıştıramaz), kernel sayfalarında PXN yoktur.
- Kernel, yürütme akışının user bellek bölgelerine yönelmesine neden olabilecek yol olmamasını sağlamalıdır — aksi takdirde “kullanıcı kontrollü shellcode’a atlama” temelli exploit zincirleri engellenmiş olur.

Execute-only sayfalar vasıtasıyla PAN bypass’ı olduğu düşünüldüğünde, gerçek bir sistemde Apple muhtemelen execute-only user sayfalarını devre dışı bırakır veya spesifikasyon zayıflığına karşı yamalar uygular.

#### Attack surfaces, bypasses, and mitigations

- **PAN bypass via execute-only pages**: daha önce tartışıldığı gibi, spesifikasyon bir boşluk sağlar: execute-only (okunamaz) user sayfaları bazı uygulamalarda “EL0 tarafından erişilebilir” sayılmayabilir, bu yüzden PAN kernel okumalarını engellemez. Bu, saldırganın execute-only bölümler aracılığıyla veri beslemesine izin verebilir.
- **Temporal window exploit**: kernel PAN’ı gerekli olandan daha uzun süre devre dışı bırakırsa, bir yarış durumu veya kötü amaçlı yol bu pencereyi kullanarak istenmeyen user bellek erişimleri gerçekleştirebilir.
- **Forgotten re-enable**: PAN’ı yeniden etkinleştirmeyi unutmak, sonraki kernel operasyonlarının yanlışlıkla user belleğine erişmesine neden olabilir.
- **Misconfiguration of PXN**: sayfa tabloları user sayfalarda PXN’ı setlemezse veya yanlış map’lerse, kernel user-space kodunu çalıştıracak şekilde kandırılabilir.
- **Speculation / side-channels**: spekülatif atlamalara benzer şekilde, mikro-mimari yan-etkiler PAN / PXN kontrollerinin geçici olarak ihlal edilmesine neden olabilir (bu tür saldırılar CPU tasarımına çok bağımlıdır).
- **Complex interactions**: JIT, shared memory, just-in-time code regions gibi gelişmiş özelliklerde kernel belirli memory erişimlerine veya user-mapped bölgelerde yürütmeye izin vermek zorunda kalabilir; PAN/PXN kısıtları altında bunları güvenli tasarlamak zordur.

#### Example

<details>
<summary>Code Example</summary>
Burada, user bellek erişimi etrafında PAN’ın etkinleştirilmesi/devre dışı bırakılmasını ve bir hatanın nasıl oluşabileceğini gösteren örnek pseudo-assembly dizileri bulunmaktadır.
</details>

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

Eğer kernel o kullanıcı sayfasında PXN’i ayarlamamış olsaydı, o branch başarılı olabilirdi — bu güvensiz olurdu.

Kernel kullanıcı belleğine erişimden sonra PAN’ı yeniden etkinleştirmeyi unutursa, ilerideki kernel mantığının kazara rastgele kullanıcı belleğini okuyup/yazabileceği bir pencere açılır.

Eğer kullanıcı işaretçisi yalnızca yürütme iznine sahip bir sayfaya işaret ediyorsa (kullanıcı sayfası sadece execute izni, okuma/yazma yok), PAN spec hatası altında `ldr W2, [X1]` PAN etkin olsa bile fault vermeyebilir; bu, uygulamaya bağlı olarak bir bypass exploit’ine yol açabilir.

</details>

<details>
<summary>Example</summary>
Bir kernel açığı, kullanıcı tarafından sağlanan bir fonksiyon işaretçisini alıp kernel bağlamında çağırmaya çalışır (ör. `call user_buffer`). PAN/PXN altında bu işlem yasaklanır veya fault verir.
</details>

---

### 11. **Top Byte Ignore (TBI) / Pointer Tagging**
**ARMv8.5 / daha yeni sürümlerde (veya isteğe bağlı genişletme) tanıtıldı**
TBI, 64-bit bir işaretçinin en üst baytının adres çevirisi sırasında yoksayılmasını sağlar. Bu, OS veya donanımın işaretçinin üst baytına **tag bitleri** gömme imkanı verir.

- TBI, **Top Byte Ignore** anlamına gelir (bazen *Address Tagging* olarak anılır). Bu, birçok ARMv8+ uygulamasında bulunan bir donanım özelliğidir ve adres çevirisi / load/store / instruction fetch yapılırken 64-bit bir işaretçinin en üst 8 bitini (bits 63:56) **yoksayar**.
- Pratikte CPU, adres çevirisi açısından `0xTTxxxx_xxxx_xxxx` (burada `TT` = üst bayt) işaretçisini `0x00xxxx_xxxx_xxxx` olarak ele alır; üst bayt maskelenir (çıkarılır). Üst bayt yazılım tarafından **metadata / tag bitleri** depolamak için kullanılabilir.
- Bu, her işaretçiye bir baytlık tag gömmek için yazılıma “ücretsiz” bir in-band alan sağlar; hangi bellek konumuna işaret ettiğini değiştirmez.
- Mimari, yükleme, saklama ve instruction fetch işlemlerinin gerçek bellek erişimini gerçekleştirmeden önce işaretçinin üst baytını maskelendiğini (yani etiketi ayıkladığını) garanti eder.

Böylece TBI, **mantıksal işaretçi**yi (işaretçi + tag) bellek işlemlerinde kullanılan **fiziksel adres**den ayırır.

#### Why TBI: Use cases and motivation

- **Pointer tagging / metadata**: Üst baytta ek metadata (ör. obje türü, sürüm, bounds, bütünlük etiketleri) depolayabilirsiniz. Daha sonra işaretçiyi kullandığınızda, donanım düzeyinde etiket yoksayıldığı için belleğe erişim için manuel ayıklama yapmanıza gerek kalmaz.
- **Memory tagging / MTE (Memory Tagging Extension)**: TBI, MTE’nin üzerine inşa edildiği temel donanım mekanizmasıdır. ARMv8.5’te Memory Tagging Extension, işaretçinin bits 59:56’sını bir **mantıksal etiket** olarak kullanır ve bunu bellekte saklanan bir **allocation tag** ile kontrol eder.
- **Geliştirilmiş güvenlik ve bütünlük**: TBI’yi pointer authentication (PAC) veya çalışma zamanı kontrolleriyle birleştirerek yalnızca işaretçi değerinin değil aynı zamanda etiketin de doğru olmasını zorlayabilirsiniz. Etiketi doğru olmayan bir şekilde üzerine yazılan bir işaretçi, etiket uyuşmazlığına yol açar.
- **Uyumluluk**: TBI isteğe bağlı olduğu ve etiket bitleri donanım tarafından yoksayıldığı için mevcut etiketsiz kod normal şekilde çalışmaya devam eder. Etiket bitleri geri uyumluluk için pratikte “umursanmaz” bitler haline gelir.

#### Example
<details>
<summary>Example</summary>
Bir fonksiyon işaretçisi üst baytında bir etiket içeriyordu (ör. `0xAA`). Bir exploit, işaretçinin düşük bitlerini üzerine yazar fakat etiketi ihmal eder; kernel doğrulama veya sanitizasyon yaptığında işaretçi başarısız olur veya reddedilir.
</details>

---

### 12. **Page Protection Layer (PPL)**
**Geç iOS / modern donanımda tanıtıldı (iOS ~17 / Apple silicon / üst seviye modeller)** (bazı raporlar PPL’in macOS / Apple silicon civarında olduğunu gösteriyor, ancak Apple benzer korumaları iOS’a getiriyor)

- PPL, bir **intra-kernel koruma sınırı** olarak tasarlanmıştır: kernel (EL1) ele geçirilmiş ve okuma/yazma yetkisine sahip olsa bile, belirli **hassas sayfaları** (özellikle page table’lar, code-sign metadata, kernel kod sayfaları, entitlements, trust cache’leri vb.) serbestçe değiştirememelidir.
- Bu, fiilen bir “kernel içinde kernel” yaratır — yalnızca korunan sayfaları değiştirebilen **yüksek ayrıcalıklı** daha küçük güvenilir bir bileşen (PPL). Diğer kernel kodu değişiklik yapmak için PPL rutinlerini çağırmak zorundadır.
- Bu, kernel exploit’leri için saldırı yüzeyini azaltır: kernel modunda tam keyfi R/W/execute sağlansa bile, exploit kodunun kritik yapıları değiştirebilmesi için ya PPL alanına erişmesi ya da PPL’i atlatması gerekir.
- Yeni Apple silicon’larda (A15+ / M2+), Apple birçok durumda sayfa-tablosu koruması için PPL yerine **SPTM (Secure Page Table Monitor)**’a geçiş yapmaktadır.

Aşağıda, kamuya açık analizlere dayanarak PPL’in nasıl çalıştığına dair inançlar verilmiştir:

#### Use of APRR / permission routing (APRR = Access Permission ReRouting)

- Apple donanımı, PTE’lerin tam izin bitleri yerine küçük indeksler içerebilmesine izin veren **APRR (Access Permission ReRouting)** adlı bir mekanizma kullanır. Bu indeksler APRR kayıtları aracılığıyla gerçek izinlere eşlenir. Bu, etki alanına göre izinlerin dinamik olarak yeniden haritalanmasına olanak tanır.
- PPL, kernel bağlamı içinde ayrıcalıkları ayırmak için APRR’den yararlanır: yalnızca PPL alanı indeks ile efektif izinler arasındaki eşlemeyi güncelleme yetkisine sahiptir. Yani, non-PPL kernel kodu bir PTE yazdığında veya izin bitlerini değiştirmeye çalıştığında APRR mantığı bunu engeller (veya salt okunur eşleme uygular).
- PPL kodu kendisi kısıtlı bir bölgede çalışır (ör. `__PPLTEXT`) ve giriş kapıları geçici olarak izin verene kadar normalde yürütülebilir veya yazılabilir değildir. Kernel, hassas işlemleri gerçekleştirmek için PPL giriş noktalarını (“PPL rutinleri”) çağırır.

#### Gate / Entry & Exit

- Kernelin korunan bir sayfayı değiştirmesi gerektiğinde (ör. bir kernel kod sayfasının izinlerini değiştirmek veya page table’ları düzenlemek), bir **PPL wrapper** rutinini çağırır; bu rutin doğrulama yapar ve ardından PPL alanına geçiş yapar. Bu alanın dışında korunan sayfalar esasen main kernel tarafından salt okunur veya değiştirilemez durumdadır.
- PPL girişinde, APRR eşlemeleri PPL bölgesindeki bellek sayfalarının PPL içinde **yürütülebilir & yazılabilir** olacak şekilde ayarlanır. Çıkışta ise tekrar salt okunur / yazılamaz hale getirilir. Bu, yalnızca denetlenmiş PPL rutinlerinin korunan sayfalara yazabilmesini sağlar.
- PPL dışında, kernel kodunun bu korunan sayfalara yazma girişimleri (izin verilmemiş olduğu için) fault üretecektir.

#### Protected page categories

PPL’in tipik olarak koruduğu sayfalar şunlardır:

- Page table yapıları (translation table entries, mapping metadata)
- Kernel kod sayfaları, özellikle kritik mantığı içerenler
- Code-sign metadata (trust cache’ler, signature blob’lar)
- Entitlement tabloları, imza denetimi tabloları
- Bir yama ile imza kontrollerinin veya kimlik bilgisi manipülasyonunun atlatılmasına izin verecek diğer yüksek değerli kernel yapıları

Fikir şudur: kernel belleği tamamen kontrol altında olsa bile, saldırgan bu sayfaları basitçe patch’leyemez veya yeniden yazamaz; PPL rutinlerini ya da PPL’i atlatmadıkça değişiklik yapamaz.

#### Known Bypasses & Vulnerabilities

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

- Project Zero tarafından yayımlanan bir yazıda **stale TLB entry’leri** içeren bir bypass anlatılmaktadır.
- Fikir:

1. Fiziksel olarak iki sayfa A ve B ayırın; bunları PPL sayfaları olarak işaretleyin (yani korunmuş olsun).
2. A ve B’den gelen L3 çeviri tablo sayfalarını kullanan iki sanal adres P ve Q haritalayın.
3. Bir thread’i Q’ya sürekli erişecek şekilde döndürün; böylece Q’nun TLB girdisi canlı kalsın.
4. `pmap_remove_options()` çağırarak P’den başlayan eşlemeleri kaldırın; bir hatadan dolayı kod yanlışlıkla hem P hem de Q için TTE’leri kaldırır, fakat yalnızca P için TLB girdisini invalid eder, Q’nun stale girdisini canlı bırakır.
5. B’yi (Q’nun tablosu olan sayfayı) yeniden kullanarak rastgele belleği (ör. PPL korumalı sayfaları) map edin. Çünkü stale TLB girdisi hâlâ Q’nun eski eşlemesini map ediyor, bu bağlamda o eşleme geçerli kalır.
6. Bunun aracılığıyla saldırgan PPL korumalı sayfaların yazılabilir eşlemesini PPL arayüzüne gitmeden yerleştirebilir.

- Bu exploit, fiziksel eşleme ve TLB davranışı üzerinde hassas kontrol gerektirdi. Bu, TLB invalidasyonları ve eşleme tutarlılığı hakkında son derece dikkatli olunması gerektiğini gösterir.

- Project Zero, bu tür bypass’ların ince ve nadir olduğunu ancak karmaşık sistemlerde mümkün olduğunu belirtti. Yine de PPL’i sağlam bir mitigasyon olarak görüyorlar.

2. **Other potential hazards & constraints**

- Eğer bir kernel exploit’i doğrudan PPL rutinlerine girebiliyorsa (PPL wrapper’larını çağırarak), kısıtlamaları atlayabilir. Bu yüzden argüman doğrulama kritik önemdedir.
- PPL kodunda (ör. arithmetic overflow, sınır kontrolleri) bulunan hatalar PPL içinde out-of-bounds değişikliklere izin verebilir. Project Zero, `pmap_remove_options_internal()` içindeki böyle bir hatanın atlatmada kullanıldığını gözlemledi.
- PPL sınırı donanım uygulamasına (APRR, bellek denetleyicisi) sıkı sıkıya bağlıdır, bu yüzden yalnızca donanım uygulamasının sağlamlığı kadar güçlüdür.

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

Kernel birçok normal işlemi gerçekleştirebilir, ancak korumalı mappingleri değiştirmek veya kod yamalamak yalnızca ppl_call_* rutinleri aracılığıyla mümkündür.

Örnek Bir kernel exploit'i entitlement table'ı overwrite etmeye veya bir kernel signature blob'unu değiştirerek code-sign enforcement'ı devre dışı bırakmaya çalışır. Çünkü o sayfa PPL-korumalı olduğundan, yazma PPL arayüzü üzerinden yapılmadıkça engellenir. Bu yüzden kernel code execution olsa bile code-sign kısıtlamalarını atlatamaz veya credential verilerini keyfi olarak değiştiremezsiniz. iOS 17+'te bazı cihazlar PPL tarafından yönetilen sayfaları daha da izole etmek için SPTM kullanır.

PPL → SPTM / Değişimler / Gelecek

  • On Apple’ın modern SoC’larında (A15 veya sonrası, M2 veya sonrası), Apple page table korumaları için SPTM (Secure Page Table Monitor) destekler; bu PPL’in yerini alır.
  • Apple belgelerinde şunu belirtir: “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.”
  • SPTM mimarisi muhtemelen policy uygulamalarının kernel kontrolü dışında, daha yüksek ayrıcalıklı bir monitöre kaymasını sağlayarak trust boundary’yi daha da azaltır.

MTE | EMTE | MIE

İşte Apple’ın MIE kurulumu altında EMTE’nin nasıl çalıştığına dair daha yüksek seviyede bir açıklama:

  1. Etiket ataması
  • Bellek allocate edildiğinde (ör. kernel veya user space içinde secure allocator’lar aracılığıyla), o blok için bir secret tag atanır.
  • Kullanıcıya veya kernela döndürülen pointer, yüksek bitlerinde o tag’i içerir (TBI / top byte ignore mechanisms kullanılarak).
  1. Erişim sırasında etiket kontrolü
  • Bir pointer kullanılarak her load veya store çalıştırıldığında, donanım pointer’ın tag’inin bellek bloğunun tag’i (allocation tag) ile eşleşip eşleşmediğini kontrol eder. Eğer uyuşmazlık varsa, hemen fault olur (çünkü synchronous).
  • Synchronous olduğundan “delayed detection” penceresi yoktur.
  1. Free / reuse sırasında retagging
  • Bellek free edildiğinde, allocator bloğun tag’ini değiştirir (böylece eski tag’lere sahip pointer’lar artık eşleşmez).
  • Bu nedenle bir use-after-free pointer erişildiğinde stale bir tag’e sahip olur ve uyuşmazlık oluşur.
  1. Taşmaları yakalamak için komşu-etiket farklılaştırması
  • Bitişik allocation’lara farklı tag’ler verilir. Eğer bir buffer overflow komşunun belleğine taşarsa, tag uyuşmazlığı fault’a neden olur.
  • Bu, sınırı geçen küçük overflow’ları yakalamada özellikle etkilidir.
  1. Etiket gizliliğinin uygulanması
  • Apple, tag değerlerinin leaked olmasını önlemelidir (çünkü attacker tag’i öğrenirse doğru tag’lere sahip pointer’lar oluşturabilir).
  • Tag bitlerinin side-channel leakage’ini önlemek için microarchitectural / speculative kontroller gibi korumalar eklerler.
  1. Kernel ve user-space entegrasyonu
  • Apple EMTE’yi yalnızca user-space’te değil, aynı zamanda kernel / OS-kritik bileşenlerde de kullanır (kernel’i memory corruption’a karşı korumak için).
  • Donanım/OS, kernel user space adına çalışırken bile tag kurallarının uygulanmasını garanti eder.
Örnek
``` 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>

#### Sınırlamalar ve zorluklar

- **Intrablock overflows**: Taşma aynı tahsis içinde kalırsa (sınırı aşmaz) ve tag aynı kalırsa, tag mismatch bunu yakalayamaz.
- **Tag width limitation**: Tag için sadece birkaç bit (ör. 4 bit veya küçük bir domain) mevcuttur — sınırlı isim alanı.
- **Side-channel leaks**: Eğer tag bitleri (cache / speculative execution yoluyla) leak olabiliyorsa, saldırgan geçerli tagleri öğrenip atlatabilir. Apple’ın tag confidentiality enforcement bunu hafifletmeyi amaçlar.
- **Performance overhead**: Her load/store üzerindeki tag kontrolleri maliyet katar; Apple donanımı optimize ederek overhead'i düşük tutmalı.
- **Compatibility & fallback**: Eski donanımda veya EMTE desteklemeyen parçalar için fallback bulunmalı. Apple, MIE'nin yalnızca destekleyen cihazlarda etkinleştirildiğini iddia ediyor.
- **Complex allocator logic**: Allocator tagleri yönetmeli, retagging, hizalama sınırlarını ayarlamalı ve yanlış-tag çakışmalarından kaçınmalı. Allocator mantığındaki hatalar yeni zafiyetler getirebilir.
- **Mixed memory / hybrid areas**: Bazı bellek bölgeleri untagged (legacy) kalabilir, bu da birlikte çalışmayı zorlaştırır.
- **Speculative / transient attacks**: Birçok mikro-mimari korumada olduğu gibi, speculative execution veya micro-op fusion türü durumlar kontrolleri geçici olarak atlayabilir veya tag bitlerini leak edebilir.
- **Limited to supported regions**: Apple EMTE'yi yalnızca seçili, yüksek riskli alanlarda (kernel, güvenlik-kritik alt sistemler) uygulayabilir, tümü için değil.



---

## Standart MTE ile karşılaştırıldığında kilit iyileştirmeler / farklar

Apple’ın vurguladığı geliştirmeler ve değişiklikler şunlardır:

| 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 hem donanım hem yazılım yığını kontrol ettiği için EMTE'yi sıkı şekilde uygulayabilir, performans tuzaklarından kaçınabilir ve side-channel açıklıklarını kapatabilir.

---

## EMTE pratikte nasıl çalışır (Apple / MIE)

Aşağıda Apple’ın MIE konfigürasyonu altında EMTE’nin nasıl işlediğine dair üst düzey bir açıklama var:

1. **Tag assignment**
- Bellek tahsis edildiğinde (ör. kernel veya user space'te secure allocators aracılığıyla), o blok için bir **secret tag** atanır.
- Kullanıcıya veya kernela döndürülen pointer, yüksek bitlerinde o tagi içerir (TBI / top byte ignore mechanisms kullanılarak).

2. **Tag checking on access**
- Bir pointer ile load veya store yürütüldüğünde, donanım pointer’ın tagi ile bellek bloğunun tagi (allocation tag) eşleşiyor mu diye kontrol eder. Eğer mismatch varsa, hemen fault oluşur (çünkü eşzamanlı).
- Eşzamanlı olduğu için “gecikmeli tespit” penceresi yoktur.

3. **Retagging on free / reuse**
- Bellek free edildiğinde, allocator bloğun tagini değiştirir (eski tage sahip pointerlar artık eşleşmez).
- Use-after-free pointer bu yüzden stale bir tage sahip olur ve erişildiğinde mismatch verir.

4. **Neighbor-tag differentiation to catch overflows**
- Komşu tahsisler farklı taglerle verilir. Eğer bir buffer overflow komşu belleğe taşarsa, tag mismatch fault oluşturur.
- Bu, sınırı geçen küçük taşmaları yakalamada özellikle etkilidir.

5. **Tag confidentiality enforcement**
- Apple, tag değerlerinin leak olmasını engellemek zorundadır (çünkü saldırgan tagi öğrenirse doğru tage sahip pointer’lar oluşturabilir).
- Speculative side-channel gibi yollarla tag bitlerinin leak olmasını önlemeye yönelik korumalar içerir.

6. **Kernel and user-space integration**
- Apple EMTE'yi sadece user-space'te değil, kernel / OS-kritik bileşenlerde de kullanır (kernel'i bellek bozulmalarından korumak için).
- Donanım/OS, kernel çalışırken bile tag kurallarının uygulanmasını sağlar.

EMTE, MIE içine gömülü olduğundan Apple EMTE'yi eşzamanlı modda ana saldırı yüzeylerinde etkin olarak kullanır; isteğe bağlı veya yalnızca hata ayıklama modu olarak bırakmaz.



---

## XNU'da istisna (exception) işleme

Bir **exception** oluştuğunda (ör. `EXC_BAD_ACCESS`, `EXC_BAD_INSTRUCTION`, `EXC_CRASH`, `EXC_ARM_PAC`, vb.), XNU kernelinin **Mach katmanı** bunun UNIX tarzı bir **signal**e (ör. `SIGSEGV`, `SIGBUS`, `SIGILL`, ...) dönüşmeden önce yakalanmasından sorumludur.

Bu süreç, kullanıcı alanına ulaşmadan veya BSD signal'e çevrilmeden önce birden fazla exception yayılımı ve işleme katmanını içerir.


### Exception Akışı (Yüksek Seviye)

1.  **CPU eşzamanlı bir exception tetikler** (ör. geçersiz pointer erişimi, PAC hatası, illegal instruction, vb.).

2.  **Düşük seviye trap handler** çalışır (`trap.c`, `exception.c` kaynak dosyalarında).

3.  Trap handler **`exception_triage()`** çağrısını yapar; bu Mach exception işleyişinin çekirdeğidir.

4.  `exception_triage()` exception'ı nasıl yönlendireceğine karar verir:

-   Önce **thread'in exception port'una** gider.

-   Ardından **task'in exception port'una**.

-   Sonra **host'un exception port'una** (genellikle `launchd` veya `ReportCrash`).

Eğer bu portların hiçbiri exception'ı ele almazsa, kernel şunları yapabilir:

-   **Bunu bir BSD signal'e çevirir** (kullanıcı alanı süreçleri için).

-   **Panic** (kernel-space exceptionları için).


### Temel Fonksiyon: `exception_triage()`

`exception_triage()` Mach exception'larını zincirdeki olası handler'lara kadar yönlendirir; bunlardan biri ele alana kadar veya nihai olarak fatal olana kadar devam eder. Fonksiyon `osfmk/kern/exception.c` içinde tanımlıdır.
```c
void exception_triage(exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt);

Tipik Çağrı Akışı:

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

Eğer hepsi başarısız olursa → bsd_exception() tarafından işlenir → SIGSEGV gibi bir sinyale çevrilir.

İstisna Portları

Her Mach nesnesi (thread, task, host), istisna mesajlarının gönderildiği istisna portları kaydedebilir.

Bunlar API tarafından tanımlanır:

task_set_exception_ports()
thread_set_exception_ports()
host_set_exception_ports()

Her exception port şunlara sahiptir:

  • Bir maske (hangi istisnaları almak istediği)
  • Bir port name (mesajları almak için Mach port)
  • Bir behavior (çekirdeğin mesajı nasıl gönderdiği)
  • Bir flavor (hangi thread state’in dahil edileceği)

Debuggers and Exception Handling

Bir debugger (ör. LLDB), hedef task veya thread üzerinde genellikle task_set_exception_ports() kullanarak bir exception port ayarlar.

Bir istisna oluştuğunda:

  • Mach mesajı debugger prosesine gönderilir.
  • Debugger, istisnayı işleme (resume, register’ları değiştirme, komutu atlama) veya işlememe kararı verebilir.
  • Eğer debugger işleme almazsa, istisna bir sonraki seviyeye yayılır (task → host).

Flow of EXC_BAD_ACCESS

  1. Thread geçersiz bir pointer’a erişir (dereference) → CPU Data Abort raise eder.

  2. Çekirdek trap handler’ı exception_triage(EXC_BAD_ACCESS, ...) çağırır.

  3. Mesaj gönderilir:

  • Thread port → (debugger breakpoint’i yakalayabilir).

  • Eğer debugger yok sayarsa → Task port → (process-seviyesindeki handler).

  • Eğer yine yok sayılırsa → Host port (genellikle ReportCrash).

  1. Eğer kimse işleme almazsa → bsd_exception() bunu SIGSEGV’ye çevirir.

PAC Exceptions

Pointer Authentication (PAC) başarısız olduğunda (imza uyuşmazlığı), özel bir Mach istisnası yükseltilir:

  • EXC_ARM_PAC (tür)
  • Kodlar detaylar içerebilir (ör., anahtar türü, pointer türü).

Eğer ikili dosyada TFRO_PAC_EXC_FATAL bayrağı varsa, çekirdek PAC hatalarını fatal olarak ele alır ve debugger yakalamasını atlar. Bu, saldırganların debugger kullanarak PAC kontrollerini atlamasını önlemek içindir ve platform ikilileri için aktiftir.

Software Breakpoints

Yazılım breakpoint’i (int3 on x86, brk on ARM64) kasıtlı bir hataya sebep olarak uygulanır.
Debugger bunu exception port aracılığıyla yakalar:

  • Instruction pointer veya belleği değiştirir.
  • Orijinal instruksyonu geri yükler.
  • Çalışmaya devam eder.

Aynı mekanizma bir PAC istisnasını “yakalamanıza” olanak verir — TFRO_PAC_EXC_FATAL ayarlı değilse. Bu bayrak setliyse, istisna hiç debugger’a ulaşmaz.

Conversion to BSD Signals

Eğer hiçbir handler istisnayı kabul etmezse:

  • Çekirdek task_exception_notify() → bsd_exception() çağırır.

  • Bu, Mach istisnalarını sinyallere eşler:

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.cexception_triage(), exception_deliver_*() çekirdeğinin çekirdeği.

  • bsd/kern/kern_sig.c → Sinyal teslimat mantığı.

  • osfmk/arm64/trap.c → Düşük seviyeli trap handler’ları.

  • osfmk/mach/exc.h → Exception kodları ve yapıları.

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


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

Çekirdek, sabit boyutlu “zone“lara bölünmüş bir zone allocator (kalloc) kullanıyordu. Her zone yalnızca tek bir boyut sınıfındaki tahsisleri tutardı.

Ekran görüntüsünden:

Zone NameElement SizeExample Use
default.kalloc.1616 bytesÇok küçük kernel struct’ları, pointer’lar.
default.kalloc.3232 bytesKüçük struct’lar, obje başlıkları.
default.kalloc.6464 bytesIPC mesajları, küçük kernel buffer’ları.
default.kalloc.128128 bytesOSObject gibi orta büyüklükte objelerin parçaları.
default.kalloc.12801280 bytesBüyük yapılar, IOSurface/graphics metadata.

Nasıl çalışıyordu:

  • Her tahsis isteği en yakın zone boyutuna yukarı yuvarlanır. (Örn., 50 baytlık bir istek kalloc.64 zonuna düşer).
  • Her zone içindeki bellek bir freelist içinde tutulurdu — çekirdek tarafından serbest bırakılan parçalar o zone’a geri giderdi.
  • Eğer 64 baytlık bir buffer’ı taşırdıysanız, aynı zone’daki sonraki objeyi ezerdiniz.

Bu yüzden heap spraying / feng shui çok etkiliydi: aynı boyut sınıfında tahsisler spray yaparak obje komşularını tahmin edebiliyordunuz.

The freelist

Her kalloc zone içinde, serbest bırakılan objeler doğrudan sisteme geri verilmez — bir freelist’e, kullanılabilir parçaların bağlı listesine giderdi.

  • Bir parça serbest bırakıldığında, çekirdek o parçanın başına bir pointer yazar → aynı zone’daki bir sonraki boş parçanın adresi.

  • Zone, ilk boş parçaya işaret eden bir HEAD pointer tutardı.

  • Tahsis her zaman mevcut HEAD kullanılarak yapılırdı:

  1. HEAD pop edilir (o bellek çağırana döndürülür).

  2. HEAD = HEAD->next olarak güncellenir (serbest bırakılan parçanın header’ında saklıdır).

  • Serbest bırakma parçaları geri iter:

  • freed_chunk->next = HEAD

  • HEAD = freed_chunk

Yani freelist, serbest bırakılan belleğin kendisi içinde inşa edilen bir bağlı listedendi.

Normal durum:

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)

Freelist’i istismar etme

Bir free chunk’ın ilk 8 baytı freelist pointer olduğu için, bir saldırgan bunu bozabilir:

  1. Heap overflow ile bitişik bir freed chunk’a taşma → onun “next” pointer’ını overwrite etmek.

  2. Use-after-free ile freed object içine yazma → onun “next” pointer’ını overwrite etmek.

Sonra, o boyuttaki bir sonraki allocation sırasında:

  • Allocator bozulmuş chunk’ı poplar.

  • Saldırgan tarafından sağlanan “next” pointer’ını takip eder.

  • Rastgele bir belleğe işaret eden bir pointer döner; bu da fake object primitives veya targeted overwrite yapılmasını sağlar.

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 tasarımı, hardening öncesi istismarı son derece etkili kıldı: heap sprays’dan gelen öngörülebilir komşular, raw pointer freelist bağlantıları ve tip ayrımının olmaması, saldırganların UAF/overflow hatalarını rastgele kernel bellek kontrolüne yükseltmesine izin veriyordu.

Heap Grooming / Feng Shui

Heap grooming’in amacı, bir saldırgan overflow veya use-after-free tetiklediğinde hedef (kurban) objenin saldırgan-kontrollü bir obje ile bitişik olacak şekilde heap düzenini şekillendirmekdir.
Böylece bellek bozulması gerçekleştiğinde, saldırgan kurban objeyi kontrollü verilerle güvenilir şekilde overwrite edebilir.

Adımlar:

  1. Spray allocations (fill the holes)
  • Zamanla, kernel heap parçalanır: bazı zonlarda eski objelerin free edildiği delikler oluşur.
  • Saldırgan önce bu boşlukları doldurmak için çok sayıda dummy allocation yapar, böylece heap “packed” ve öngörülebilir hale gelir.
  1. Force new pages
  • Delikler dolduğunda, sonraki allocation’lar zon’a eklenen yeni sayfalardan gelmek zorunda kalır.
  • Yeni sayfalar, objelerin dağıtılmak yerine kümelenmesini sağlar.
  • Bu saldırgana komşular üzerinde çok daha iyi kontrol verir.
  1. Place attacker objects
  • Saldırgan şimdi tekrar spray yapar ve bu yeni sayfalarda çok sayıda saldırgan-kontrollü obje oluşturur.
  • Bu objeler boyut ve yerleşim açısından öngörülebilirdir (hepsi aynı zone’a ait oldukları için).
  1. Free a controlled object (make a gap)
  • Saldırgan kasten kendi objelerinden birini free eder.
  • Bu, allocator’un sonraki aynı boyuttaki allocation için yeniden kullanacağı bir “delik” oluşturur.
  1. Victim object lands in the hole
  • Saldırgan kernel’i hedef (korumak istedikleri) objeyi allocate etmeye zorlar.
  • Delik freelist’teki ilk kullanılabilir slot olduğundan, victim tam olarak saldırganın free ettiği objenin yerine yerleşir.
  1. Overflow / UAF into victim
  • Artık saldırganın çevresinde saldırgan-kontrollü objeler vardır.
  • Kendi objelerinden birinden overflow yaparak (veya freed birini yeniden kullanarak), kurbanın bellek alanlarını seçilen değerlerle güvenilir biçimde overwrite edebilir.

Neden çalışır:

  • Zone allocator öngörülebilirliği: aynı boyuttaki allocation’lar her zaman aynı zon’dan gelir.
  • Freelist davranışı: yeni allocation’lar en son free edilmiş chunk’ı önce yeniden kullanır.
  • Heap sprays: saldırgan belleği öngörülebilir içerikle doldurur ve düzeni kontrol eder.
  • Sonuç: saldırgan kurban objenin nereye yerleşeceğini ve yanında hangi verinin olacağını kontrol eder.

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

Apple allocator’ı sertleştirdi ve heap grooming çok daha zor hale geldi:

1. From Classic kalloc to kalloc_type

  • Before: her boyut sınıfı için bir kalloc.<size> zone vardı (16, 32, 64, … 1280, vb.). O boyuttaki herhangi bir obje oraya yerleştirilirdi → saldırgan objeleri ayrıcalıklı kernel objelerinin yanına oturabilirdi.
  • Now:
  • Kernel objeler typed zones (kalloc_type)’dan allocate ediliyor.
  • Her obje türünün (ör. ipc_port_t, task_t, OSString, OSData) kendi adanmış zon’u var, aynı boyutta olsalar bile.
  • Obje türü ↔ zone eşlemesi derleme zamanında kalloc_type system tarafından üretilir.

Bir saldırgan artık kontrollü verinin (OSData) aynı boyuttaki hassas kernel objeleri (task_t) ile bitişik geleceğini garanti edemez.

2. Slabs and Per-CPU Caches

  • Heap, o zone için sabit boyutlu parçalara ayrılmış slabs (bellek sayfaları) halinde bölünür.
  • Her zon’un per-CPU cache’i vardır, bu da contention’ı azaltır.
  • Allocation yolu:
  1. Per-CPU cache’e bak.
  2. Boşsa, global freelist’ten çek.
  3. Eğer freelist boşsa, yeni bir slab (bir veya daha fazla sayfa) allocate et.
  • Fayda: Bu merkeziyetsizlik, allocation’ların farklı CPU’ların cache’lerinden karşılanabilmesi nedeniyle heap sprays’i daha az deterministik yapar.

3. Randomization inside zones

  • Bir zon içinde, freed element’ler basit FIFO/LIFO sırayla geri verilmez.
  • Modern XNU, encoded freelist pointers kullanır (Linux’taki safe-linking’e benzer, ~iOS 14 civarında tanıtıldı).
  • Her freelist pointer, bir zon’a özel gizli cookie ile XOR-encoded edilmiştir.
  • Bu, bir yazma primiti elde edilse bile saldırganın sahte freelist pointer oluşturmasını engeller.
  • Bazı allocation’ların slab içindeki yerleşimleri randomize edilir, bu yüzden spraying bitişiklik garantisi vermez.

4. Guarded Allocations

  • Bazı kritik kernel objeleri (ör. credentials, task yapıları) guarded zones içinde allocate edilir.
  • Bu zon’lar slab’lar arasında guard pages (maplenmemiş bellek) ekler veya objelerin çevresine redzones koyar.
  • Guard page’e yapılan herhangi bir overflow hata tetikler → sessiz bozulma yerine anında panic olur.

5. Page Protection Layer (PPL) and SPTM

  • Bir freed objeyi kontrol etseniz bile, kernel belleğinin tamamını değiştiremezsiniz:
  • PPL (Page Protection Layer), belirli bölgelerin (ör. code signing verisi, entitlements) kernel’e bile read-only olmasını zorunlu kılar.
  • A15/M2+ cihazlarda bu rol SPTM (Secure Page Table Monitor) + TXM (Trusted Execution Monitor) ile değiştirilmiş/geliştirilmiştir.
  • Bu donanım destekli katmanlar, saldırganların tek bir heap bozulmasından kritik güvenlik yapılarını rastgele patch’lemeye yükseltmesini engeller.
  • (Added / Enhanced): ayrıca kernel’de pointer’ları (özellikle function pointers, vtables) korumak için PAC (Pointer Authentication Codes) kullanılır; bu, onları taklit etmeyi veya bozmayı zorlaştırır.
  • (Added / Enhanced): zon’lar zone_require / zone enforcement uygulayabilir; yani free edilen bir objenin yalnızca doğru typed zone üzerinden iade edilmesini zorunlu kılabilir; geçersiz cross-zone free’lar panic’e veya reddedilmeye yol açabilir. (Apple, bellek güvenliği yazılarında buna değiniyor)

6. Large Allocations

  • Tüm allocation’lar kalloc_type üzerinden gitmez.
  • Çok büyük istekler (~16 KB üzeri) typed zon’ları bypass eder ve doğrudan kernel VM (kmem) üzerinden sayfa allocation ile servis edilir.
  • Bunlar daha az öngörülebilir, ancak aynı zamanda daha az exploitable’dır çünkü diğer objelerle slab paylaşmazlar.

7. Allocation Patterns Attackers Target

Bu korumalara rağmen, saldırganlar hala şunları hedef alır:

  • Reference count objects: retain/release sayaçlarına müdahale edilebilirse, use-after-free oluşabilir.
  • Objects with function pointers (vtables): bunları bozmak hâlâ kontrol akışı sağlar.
  • Shared memory objects (IOSurface, Mach ports): bunlar user ↔ kernel köprüsü oldukları için hâlâ hedef alınırlar.

Ama — eskisi gibi — sadece OSData spray yapıp bunun bir task_t ile komşu olmasını bekleyemezsiniz. Başarmak için type-specific bugs veya info leaks gerekir.

Example: Allocation Flow in Modern Heap

Userspace IOKit’e bir OSData objesi allocate etmek için çağrı yapsın:

  1. Type lookupOSData kalloc_type_osdata zone’una (boyut 64 byte) eşlenir.
  2. Per-CPU cache’te free element kontrolü.
  • Bulunursa → bir tane döndürülür.
  • Boşsa → global freelist’e bakılır.
  • Freelist boşsa → yeni bir slab allocate edilir (4KB sayfa → 64 adet 64 byte chunk).
  1. Chunk caller’a geri döndürülür.

Freelist pointer protection:

  • Her freed chunk, bir sonraki free chunk’ın adresini saklar, ancak zon’a özel bir gizli anahtarla kodlanmıştır.
  • Bu alanı saldırgan verisiyle overwrite etmek, anahtarı bilmiyorsanız işe yaramaz.

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)

Recent Apple OS sürümlerinde (özellikle iOS 17+), Apple daha güvenli bir userland allocator olan xzone malloc (XZM) tanıttı. Bu, kernel’in kalloc_type’ına karşılık gelen user-space muadili olup type awareness, metadata isolation ve memory tagging korumalarını uyguluyor.

Goals & Design Principles

  • Type segregation / type awareness: type veya kullanım (pointer vs data) bazında allocation’ları gruplayarak type confusion ve cross-type reuse’u önlemek.
  • Metadata isolation: heap metadata’sını (örn. free list’ler, size/state bitleri) obje payload’larından ayrı tutmak; böylece out-of-bounds yazımların metadata’yı bozma olasılığı azalır.
  • Guard pages / redzones: overflow’ları yakalamak için allocation’ların etrafına unmapped sayfalar veya padding koyma.
  • Memory tagging (EMTE / MIE): hardware tagging ile birlikte çalışarak use-after-free, out-of-bounds ve geçersiz erişimleri tespit etme.
  • Scalable performance: düşük overhead, aşırı parçalanmayı önleme ve yüksek throughput ile düşük gecikme sağlama.

Architecture & Components

Aşağıda xzone allocator’ın ana elemanları verilmiştir:

Segment Groups & Zones

  • Segment groups adres uzayını kullanım kategorilerine göre böler: ör. data, pointer_xzones, data_large, pointer_large.
  • Her segment group, ilgili kategori için allocation’ları barındıran segments (VM aralıkları) içerir.
  • Her segment ile ilişkili bir metadata slab (ayrı bir VM alanı) vardır; bu slab segment için metadata’yı (örn. free/used bitleri, size class’lar) depolar. Bu out-of-line (OOL) metadata, metadata’nın obje payload’larıyla karışmamasını sağlar ve overflow ile bozulmayı hafifletir.
  • Segmentler chunks (dilimler) hâlinde parçalanır; chunk’lar da blocks (allocation birimleri) olarak alt bölümlere ayrılır. Bir chunk belirli bir size class ve segment group’a bağlıdır (yani bir chunk’taki tüm block’lar aynı boyut ve kategoriye aittir).
  • Küçük/orta boy allocation’lar için sabit boyutlu chunk’lar kullanılır; büyük/çok büyükler ayrı map edilebilir.

Chunks & Blocks

  • Bir chunk, genellikle birkaç sayfa olan ve bir size class için ayrılmış bir bölgedir.
  • Bir chunk içinde, blocks allocation için kullanılabilir slotlardır. Freed block’lar metadata slab üzerinden takip edilir — ör. bitmap’ler veya out-of-line stored free list’ler ile.
  • Chunk’lar arasında (veya içinde) guard slices / guard pages (ör. maplenmemiş dilimler) insert edilebilir; bu OOB yazımları yakalar.

Type / Type ID

  • Her allocation sitesi (veya malloc, calloc vb. çağrısı) bir type identifier (bir malloc_type_id_t) ile ilişkilendirilir; bu type ID allocator’a hangi zone/segment’in seçileceğini söyler.
  • Bu nedenle, iki allocation aynı boyutta olsa bile türleri farklıysa tamamen farklı zon’lara gidebilir.
  • iOS 17’nin erken sürümlerinde bazı API’ler (örn. CFAllocator) tam olarak type-aware değildi; Apple bu zayıflıkları iOS 18’de ele aldı.

Allocation & Freeing Workflow

xzone’da allocation ve deallocation’ın yüksek seviye akışı:

  1. malloc / calloc / realloc / typed alloc bir boyut ve type ID ile çağrılır.
  2. Allocator type ID’yi kullanarak doğru segment group / zone’u seçer.
  3. Seçilen zone/segment içinde, istenen boyutta free block’ı olan bir chunk aranır.
  • local caches / per-thread pools veya metadata’daki free block list’e bakılabilir.
  • Eğer boş block yoksa, zone’da yeni bir chunk allocate edilebilir.
  1. Metadata slab güncellenir (free biti temizlenir, bookkeeping yapılır).
  2. Eğer memory tagging (EMTE) uygulanıyorsa, döndürülen block’a bir tag atanır ve metadata “live” durumunu yansıtacak şekilde güncellenir.
  3. free() çağrıldığında:
  • Block metadata’da freed olarak işaretlenir (OOL slab üzerinden).
  • Block bir free list’e veya reuse için pool’a konulabilir.
  • Opsiyonel olarak, block içeriği data leak veya use-after-free exploitation riskini azaltmak için temizlenebilir veya poison edilebilir.
  • Bloka ait donanım tag’i invalidated veya re-tagged edilebilir.
  • Bir chunk tamamen boşalırsa, allocator memory pressure altında o chunk’ı reclaim edebilir (unmap etmek veya OS’e geri vermek).

Security Features & Hardening

Modern userland xzone’da yerleşik savunmalar:

FeaturePurposeNotes
Metadata decouplingPrevent overflow from corrupting metadataMetadata ayrı bir VM bölgesinde (metadata slab) saklanır
Guard pages / unmapped slicesCatch out-of-bounds writesBuffer overflow’ları sessizce bitişik block’ları bozmak yerine yakalamaya yardımcı olur
Type-based segregationPrevent cross-type reuse & type confusionAynı boyuttaki allocation’lar bile farklı type’lar için farklı zon’lara gider
Memory Tagging (EMTE / MIE)Detect invalid access, stale references, OOB, UAFxzone, donanım EMTE ile senkron modda (“Memory Integrity Enforcement”) birlikte çalışır
Delayed reuse / poisoning / zapReduce chance of use-after-free exploitationFreed block’lar reuse öncesi poison, zero veya quarantine edilebilir
Chunk reclamation / dynamic unmappingReduce memory waste and fragmentationTüm chunk’lar kullanılmazsa unmap edilebilir
Randomization / placement variationPrevent deterministic adjacencyChunk içindeki block’lar ve chunk seçimi rastgeleleştirilebilir
Segregation of “data-only” allocationsSeparate allocations that don’t store pointersPointer içermeyen allocation’ları ayırmak metadata veya kontrol alanları üzerindeki saldırgan kontrolünü azaltır

Interaction with Memory Integrity Enforcement (MIE / EMTE)

  • Apple’ın MIE (Memory Integrity Enforcement), Enhanced Memory Tagging Extension (EMTE)’yi major attack surface’larda her zaman açık, senkron modda getirerek donanım + OS çerçevesidir.
  • xzone allocator, user space’de MIE’nin temel taşlarından biridir: xzone üzerinden yapılan allocation’lar tag alır ve erişimler donanım tarafından kontrol edilir.
  • MIE’de allocator, tag atama, metadata yönetimi ve tag gizliliği zorlaması, bellek hatalarının (stale reads, OOB, UAF vb.) hemen yakalanmasını ve daha sonra exploit edilmelerini engelleyecek şekilde entegre edilmiştir.

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 modülleri

  • Watcher anti-analysis: Cihazi sürekli profilleyen ve araştırma ortamı tespit edildiğinde kill-chain’i sonlandıran özel bir watcher binary’si vardır. security.mac.amfi.developer_mode_status, bir diagnosticd konsolunun varlığı, US veya IL lokalleri, Cydia gibi jailbreak izleri, bash, tcpdump, frida, sshd veya checkrain gibi prosesler, mobil AV uygulamaları (McAfee, AvastMobileSecurity, NortonMobileSecurity), özel HTTP proxy ayarları ve özel root CA’lar denetlenir. Herhangi bir kontrolde başarısız olunması sonraki payload teslimatını engeller.

  • Helper surveillance hooks: Helper bileşeni diğer aşamalarla /tmp/helper.sock üzerinden konuşur, sonra DMHooker ve UMHooker adlı hook setlerini yükler. Bu hooklar VOIP ses yollarına girer (kayıtlar /private/var/tmp/l/voip_%lu_%u_PART.m4a altında saklanır), sistem genelinde bir keylogger uygular, UI olmadan fotoğraf çeker ve SpringBoard’u hooklayarak bu eylemlerin normalde tetikleyeceği bildirimleri bastırır. Bu yüzden helper, Predator gibi daha ağır implantlar düşürülmeden önce gizli bir doğrulama + hafif gözetim katmanı olarak davranır.

  • HiddenDot indicator suppression in SpringBoard: Kernel seviyesinde kod enjeksiyonu ile Predator SBSensorActivityDataProvider._handleNewDomainData:’yı (sensör etkinliğinin toplama noktası) hooklar. Hook, Objective-C self işaretçisini (x0) sıfırlar; böylece çağrı [nil _handleNewDomainData:newData] olur, kamera/mikrofon güncellemelerini iptal eder ve hem yeşil hem turuncu noktaları bastırır.

  • Mach exception-based hooking flow (DMHooker): Hooklar EXC_BREAKPOINT + exception portları aracılığıyla uygulanır, sonra thread_set_state registerları değiştirir ve yürütme devam eder. Dönen kod 2 ise “değiştirilmiş thread state ile devam et” anlamına gelir.

  • PAC-aware redirection for camera access checks: mediaserverd içinde, bir pattern-scan (ör. memmem) FigVideoCaptureSourceCreateWithSourceInfo yakınındaki özel bir rutini CMCapture.framework içinde bulur. Hook, PAC’ı tatmin ederken kontrolü atlamak için, önceden imzalanmış PAC önbelleğe alınmış bir return adresini kullanmak üzere 3 döndürür.

  • VoIP capture pipeline in mediaserverd: AudioConverterNew ve AudioConverterConvertComplexBuffer+52 hooklanarak buffer’lara girilir, buffer boyutlarından örnekleme hızı çıkarılır, float32 PCM → int16 dönüşümü NEON ile yapılır, 4-kanal stereo’ya downmix edilir ve ExtAudioFileWrite() ile kalıcı hale getirilir. VoIP modülü kendisi göstergeleri bastırmaz; bu yüzden operatörlerin HiddenDot’u ayrı olarak etkinleştirmesi gerekir.

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

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin