iOS Exploiting
Reading time: 13 minutes
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
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
iOS Exploit Mitigations
- Code Signing iOS'ta çalıştırılabilir her bir kod parçasının (apps, libraries, extensions, vb.) Apple tarafından verilen bir sertifika ile kriptografik olarak imzalanmasını gerektirecek şekilde işler. Kod yüklendiğinde, iOS dijital imzayı Apple’ın güvenilen root’u ile doğrular. İmza geçersiz, eksik veya değiştirilmişse, OS çalıştırmayı reddeder. Bu, saldırganların meşru uygulamalara kötü amaçlı kod enjekte etmesini veya unsigned binary çalıştırmasını engeller; böylece rasgele veya değiştirilmiş kod çalıştırmaya dayanan birçok exploit zinciri durdurulur.
- CoreTrust kod imzasını çalışma zamanında zorlayan iOS alt sistemidir. İmzaları cached trust store'lara güvenmeden doğrudan Apple’ın root sertifikasıyla doğrular; bu da yalnızca Apple tarafından imzalanmış (veya geçerli entitlements'a sahip) binary'lerin çalışabileceği anlamına gelir. CoreTrust, bir uygulama kurulumdan sonra değiştirilse, sistem kütüphaneleri manipüle edilse veya unsigned kod yüklemeye çalışılsa bile çalıştırmayı engeller. Bu sıkı uygulama, eski iOS sürümlerinin daha zayıf veya atlatılabilir imza kontrolleriyle izin verdiği birçok post-exploitation vektörünü kapatır.
- Data Execution Prevention (DEP) bellek bölgelerini açıkça kod içermedikçe non-executable olarak işaretler. Bu, saldırganların stack veya heap gibi veri bölgelerine shellcode enjekte edip çalıştırmasını engeller ve onları ROP gibi daha karmaşık tekniklere zorlar.
- ASLR (Address Space Layout Randomization) kod, kütüphaneler, stack ve heap adreslerini her çalıştırmada rastgeleleştirir. Bu, saldırganların faydalı talimatların veya gadget'ların konumunu tahmin etmesini çok daha zorlaştırır ve sabit bellek düzenine dayanan birçok exploit zincirini kırar.
- KASLR (Kernel ASLR) aynı rastgeleleştirme konseptini iOS kernel'ine uygular. Kernel’in base adresini her bootta karıştırarak, saldırganların kernel fonksiyonlarını veya yapıları güvenilir şekilde bulmasını engeller ve kernel seviyesindeki exploit'lerin zorluğunu artırır.
- Kernel Patch Protection (KPP), iOS'ta AMCC (Apple Mobile File Integrity) olarak da bilinir, kernel’in code page’lerini sürekli izleyerek değiştirilip değiştirilmediklerini kontrol eder. Kernel fonksiyonlarını patchlemeye veya kötü amaçlı kod eklemeye çalışan herhangi bir tespit edildiğinde cihaz hemen panic yapıp reboot eder. Bu koruma, persistent kernel exploit'lerini zorlaştırır; çünkü saldırganlar kernel talimatlarını hook'lamak veya patch'lemek istediklerinde sistem çökmesi tetiklenir.
- Kernel Text Readonly Region (KTRR) iOS cihazlarında tanıtılmış donanım tabanlı bir güvenlik özelliğidir. CPU’nun bellek denetleyicisini kullanarak kernel’in code (text) bölümünü boot sonrası kalıcı olarak read-only olarak işaretler. Bir kez kilitlendiğinde, kernel’in kendisi bile bu bellek bölgesini değiştiremez. Bu, saldırganların — hatta ayrıcalıklı kodun — kernel talimatlarını runtime’da patchlemesini engeller ve kernel kodunu doğrudan değiştirmeye dayanan büyük bir exploit sınıfını kapatır.
- Pointer Authentication Codes (PAC) pointer’ların kullanılmadan önce bütünlüğünü doğrulamak için pointer’ların kullanılmayan bitlerine gömülü kriptografik imzalar kullanır. Bir pointer (ör. return address veya function pointer) oluşturulduğunda, CPU onu gizli bir anahtarla imzalar; dereference edilmeden önce CPU bu imzayı kontrol eder. Pointer manipüle edildiyse kontrol başarısız olur ve yürütme durur. Bu, saldırganların bellekte bozulmuş pointer'ları sahteleyip yeniden kullanmasını önler ve ROP veya JOP gibi teknikleri güvenilir şekilde yapmayı çok daha zorlaştırır.
- Privilege Access never (PAN), kernel (privileged mode) kullanıcı alanı belleğine doğrudan erişimi açıkça etkinleştirmedikçe engelleyen bir donanım özelliğidir. Bu, kernel kodu yürütmesi ele geçirilmiş saldırganların kullanıcı belleğini kolayca okuyup yazmasını, exploit'i yükseltmesini veya hassas verileri çalmasını zorlaştırır. Katı ayrımı zorunlu kılarak PAN, kernel exploit'lerinin etkisini azaltır ve birçok yaygın privilege-escalation tekniğini bloke eder.
- Page Protection Layer (PPL), özellikle code signing ve entitlements ile ilgili önemli kernel taraflı bellek bölgelerini koruyan bir iOS güvenlik mekanizmasıdır. MMU (Memory Management Unit) ve ek kontroller kullanarak sıkı write korumaları uygular; böylece ayrıcalıklı kernel kodu bile hassas sayfaları rastgele değiştiremez. Bu, kernel seviyesinde yürütme elde eden saldırganların security-critical yapılarını manipüle etmesini, persistence sağlamasını ve code-signing atlatmalarını önemli ölçüde zorlaştırır.
Old Kernel Heap (Pre-iOS 15 / Pre-A12 era)
Kernel, sabit boyutlu "zones"lara bölünmüş bir zone allocator (kalloc
) kullanıyordu.
Her zone yalnızca tek bir boyut sınıfına ait allocation'ları saklardı.
From the screenshot:
Zone Name | Element Size | Example Use |
---|---|---|
default.kalloc.16 | 16 bytes | Very small kernel structs, pointers. |
default.kalloc.32 | 32 bytes | Small structs, object headers. |
default.kalloc.64 | 64 bytes | IPC messages, tiny kernel buffers. |
default.kalloc.128 | 128 bytes | Medium objects like parts of OSObject . |
… | … | … |
default.kalloc.1280 | 1280 bytes | Large structures, IOSurface/graphics metadata. |
Nasıl çalışıyordu:
- Her allocation isteği en yakın zone boyutuna yuvarlanır.
(Örn., 50-byte’lık bir istek
kalloc.64
zonuna düşer). - Her zondaki bellek bir freelist içinde tutulurdu — kernel tarafından freed edilen chunk'lar o zone'a geri girerdi.
- Eğer 64-byte bir buffer overflow olursa, aynı zon içindeki sonraki obje'yu ezerdiniz.
Bu yüzden heap spraying / feng shui çok etkiliydi: aynı boyut sınıfında allocation’lar spreylayarak obje komşularını tahmin edebiliyordunuz.
The freelist
Her kalloc zonu içinde, freed edilen objeler doğrudan sisteme geri verilmez — onlar bir freelist'e, kullanılabilir chunk'ların bağlı listesine giderdi.
-
Bir chunk free edildiğinde, kernel o chunk’ın başına bir pointer yazar → aynı zon içindeki bir sonraki free chunk’ın adresi.
-
Zone, ilk free chunk'a işaret eden bir HEAD pointer tutardı.
-
Allocation her zaman mevcut HEAD'i kullanırdı:
-
HEAD'i pop et (o belleği caller'a döndür).
-
HEAD = HEAD->next ile güncelle (freed chunk'ın header'ında saklı).
-
Free işlemi chunk'ları geri iter:
-
freed_chunk->next = HEAD
-
HEAD = freed_chunk
Yani freelist, freed bellek içinde inşa edilen bir bağlı listeydi.
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)
freelist'in istismarı
Çünkü bir free chunk'ın ilk 8 baytı = freelist pointer olduğu için, bir saldırgan bunu bozabilir:
-
Heap overflow ile bitişik freed chunk'a taşma → onun “next” pointer'ını overwrite eder.
-
Use-after-free ile freed edilmiş bir nesneye yazma → onun “next” pointer'ını overwrite eder.
Sonra, aynı boyuttaki bir sonraki allocation sırasında:
- Allocator bozuk chunk'ı pop eder.
- Saldırgan tarafından sağlanan “next” pointer'ını takip eder.
- Rastgele belleğe bir pointer döndürür; bu, fake object primitives veya targeted overwrite'a olanak sağlar.
freelist poisoning'ın görsel örneği:
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.
Bu freelist tasarımı, hardening öncesinde exploit’i son derece etkili hale getirdi: heap sprays’tan 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ı kernel belleği üzerinde keyfi kontrole yükseltmesine izin veriyordu.
Heap Grooming / Feng Shui
Heap grooming’in amacı, bir saldırgan overflow veya use-after-free tetiklediğinde hedef (kurban) nesnenin saldırgan tarafından kontrol edilen bir nesnenin hemen yanında oturmasını sağlayacak şekilde heap düzenini şekillendirmektir.
Böylece bellek bozulması gerçekleştiğinde, saldırgan kurban nesneyi kontrollü verilerle güvenilir biçimde overwrite edebilir.
Adımlar:
- Spray allocations (fill the holes)
- Zamanla kernel heap parçalanır: bazı zonlarda eskiden freed edilmiş nesnelerin bıraktığı boşluklar 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.
- Force new pages
- Boşluklar dolduğunda, sonraki allocation’lar zone’a eklenen yeni sayfalardan gelmek zorunda kalır.
- Yeni sayfalar, nesnelerin eski parçalanmış bellek boyunca dağılmayıp kümeleşmesini sağlar.
- Bu, saldırgana komşular üzerinde çok daha iyi kontrol kazandırır.
- Place attacker objects
- Saldırgan şimdi yeniden spray yapar, o yeni sayfalarda çok sayıda saldırgan-kontrollü nesne oluşturur.
- Bu nesneler boyut ve yerleşim açısından öngörülebilirdir (hepsi aynı zone’a ait oldukları için).
- Free a controlled object (make a gap)
- Saldırgan kasten kendi nesnelerinden birini free eder.
- Bu, allocator’ın daha sonra aynı boyuttaki bir sonraki allocation için yeniden kullanacağı heap’te bir “delik” oluşturur.
- Victim object lands in the hole
- Saldırgan, kernel’i kurban nesneyi (bozmak istediği nesne) allocate etmeye zorlar.
- Delik freelist’teki ilk uygun slot olduğu için, kurban tam olarak saldırganın free ettiği nesnenin yerine yerleştirilir.
- Overflow / UAF into victim
- Artık saldırganın, kurbanın etrafında saldırgan-kontrollü nesneleri vardır.
- Kendi nesnelerinden birinden overflow yaparak (veya freed edilmiş birini reuse ederek), kurbanın bellek alanlarını seçilmiş değerlerle güvenilir biçimde overwrite edebilir.
Neden işe yarar:
- Zone allocator öngörülebilirliği: aynı boyuttaki allocation’lar her zaman aynı zon’dan gelir.
- Freelist davranışı: yeni allocation’lar önce en son freed edilmiş chunk’ı yeniden kullanır.
- Heap sprays: saldırgan belleği öngörülebilir içerikle doldurur ve yerleşimi kontrol eder.
- Sonuç: saldırgan kurban nesnenin nereye yerleşeceğini ve yanında hangi verinin bulunacağı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ı (16, 32, 64, … 1280, vb.) için tek bir
kalloc.<size>
zone’u vardı. O boyuttaki herhangi bir nesne oraya yerleştirilirdi → saldırgan nesneleri ayrıcalıklı kernel nesnelerinin yanında oturabilirdi. - Now:
- Kernel nesneleri typed zones (
kalloc_type
) üzerinden allocate ediliyor. - Her nesne tipi (ör.
ipc_port_t
,task_t
,OSString
,OSData
) kendi özel zon’una sahiptir, aynı boyutta olsalar bile. - Nesne tipi ↔ zone eşlemesi derleme zamanında kalloc_type system tarafından üretilir.
Saldırgan artık kontrollü verinin (OSData
) aynı boyuttaki hassas kernel nesneleriyle (task_t
) komşu geleceğini garanti edemez.
2. Slabs and Per-CPU Caches
- Heap, o zone için sabit boyutlu chunk’lara ayrılmış sayfa grupları olan slab’lara bölünmüştür.
- Her zone’un contention azaltmak için bir per-CPU cache’i vardır.
- Allocation yolu:
- Per-CPU cache’e bak.
- Eğer boşsa, global freelist’ten çek.
- Eğer freelist boşsa, yeni bir slab (bir veya daha fazla sayfa) allocate et.
- Fayda: Bu merkezkaçlaştırma, allocation’ların farklı CPU’ların cache’lerinden karşılanabilmesi nedeniyle heap spray’leri daha az deterministik hale getirir.
3. Randomization inside zones
- Bir zon içinde, freed element’ler basit FIFO/LIFO sırasıyla geri verilmez.
- Modern XNU encoded freelist pointers kullanır (Linux tarzı safe-linking, ~iOS 14 civarında tanıtıldı).
- Her freelist pointer bir per-zone gizli cookie ile XOR-encoded edilir.
- Bu, eğer bir write primitive elde etseniz bile sahte bir freelist pointer oluşturmanızı engeller.
- Bazı allocation’lar slab içinde yerleşim açısından rastgeleleştirilir, bu yüzden spraying adjacency’yi garanti etmez.
4. Guarded Allocations
- Bazı kritik kernel nesneleri (ör. credentials, task yapıları) guarded zones içinde allocate edilir.
- Bu zon’lar slab’lar arasında guard pages (map edilmemiş bellek) ekler veya nesnelerin etrafında redzones kullanır.
- Guard page’e yapılan herhangi bir overflow bir fault tetikler → sessiz bozulma yerine anında panic olur.
5. Page Protection Layer (PPL) and SPTM
- Bir freed nesneyi kontrole alsanız bile, kernel belleğinin tamamını değiştiremezsiniz:
- PPL (Page Protection Layer), belirli bölgelerin (ör. code signing verileri, entitlements) kernel’in kendisine bile sadece-okunur olmasını zorunlu kılar.
- A15/M2+ cihazlarda bu rol SPTM (Secure Page Table Monitor) + TXM (Trusted Execution Monitor) ile değiştirilmiş/güçlendirilmiştir.
- Bu donanım-taraflı katmanlar, saldırganların tek bir heap bozulmasından kritik güvenlik yapılarını keyfi şekilde patch’lemeye yükselmesini engeller.
6. Large Allocations
- Tüm allocation’lar
kalloc_type
üzerinden gitmez. - Çok büyük istekler (yaklaşık ~16KB üzeri) typed zone’ları bypass eder ve doğrudan kernel VM (kmem) üzerinden sayfa allocation’ları ile karşılanır.
- Bunlar daha az öngörülebilir, ama aynı zamanda diğer nesnelerle slab paylaşmadıkları için daha az exploitable’dir.
7. Allocation Patterns Attackers Target
Bu korumalar olsa bile, saldırganlar hâlâ şunları ararlar:
- Reference count objects: retain/release sayaçlarıyla oynayabilirseniz, use-after-free’a yol açabilirsiniz.
- Objects with function pointers (vtables): birini bozmak hâlâ kontrol akışı sağlar.
- Shared memory objects (IOSurface, Mach ports): bunlar user ↔ kernel köprüsü sağladıkları için hâlâ hedef alınır.
Ama — eskisi gibi — sadece OSData
spray yapıp task_t
ile komşu olmasını bekleyemezsiniz. Başarılı olmak için type-specific bug’lar veya info leaks gereklidir.
Example: Allocation Flow in Modern Heap
Varsayalım userspace IOKit’e çağrı yapıp bir OSData
nesnesi allocate ediyor:
- Type lookup →
OSData
kalloc_type_osdata
zone’una (boyut 64 bytes) eşlenir. - Per-CPU cache’te boş element kontrolü.
- Bulunursa → bir tane döndür.
- Boşsa → global freelist’e git.
- Freelist boşsa → yeni bir slab allocate et (4KB sayfa → 64 adet 64 byte chunk).
- Chunk’ı çağırana döndür.
Freelist pointer protection:
- Her freed chunk bir sonraki free chunk’ın adresini saklar, fakat bir gizli anahtarla encode edilmiştir.
- O alanı saldırgan verisiyle overwrite etmek, anahtarı bilmiyorsanız işe yaramaz.
Comparison Table
Feature | Old Heap (Pre-iOS 15) | Modern Heap (iOS 15+ / A12+) |
---|---|---|
Allocation granularity | Fixed size buckets (kalloc.16 , kalloc.32 , etc.) | Size + type-based buckets (kalloc_type ) |
Placement predictability | High (same-size objects side by side) | Low (same-type grouping + randomness) |
Freelist management | Raw pointers in freed chunks (easy to corrupt) | Encoded pointers (safe-linking style) |
Adjacent object control | Easy via sprays/frees (feng shui predictable) | Hard — typed zones separate attacker objects |
Kernel data/code protections | Few hardware protections | PPL / SPTM protect page tables & code pages |
Exploit reliability | High with heap sprays | Much lower, requires logic bugs or info leaks |
(Old) Physical Use-After-Free via IOSurface
Ghidra Install BinDiff
BinDiff DMG’yi https://www.zynamics.com/bindiff/manual adresinden indirin ve yükleyin.
ghidraRun
ile Ghidra’yı açın ve File
--> Install Extensions
yolunu izleyin, add butonuna basın ve yolu /Applications/BinDiff/Extra/Ghidra/BinExport
olarak seçin ve OK’a tıklayıp, sürüm uyumsuzluğu olsa bile yükleyin.
Using BinDiff with Kernel versions
- https://ipsw.me/ sayfasına gidin ve diff’ini almak istediğiniz iOS versiyonlarını indirin. Bunlar
.ipsw
dosyaları olacaktır. - Her iki
.ipsw
dosyasının kernelcache’inin bin formatına ulaşana kadar açın. Bunu nasıl yapacağınızla ilgili bilgi şuradadır:
macOS Kernel Extensions & Debugging
ghidraRun
ile Ghidra’yı açın, yeni bir proje oluşturun ve kernelcache’leri yükleyin.- Her kernelcache’i açın ki Ghidra otomatik olarak analiz etsin.
- Sonra, Ghidra proje penceresinde her kernelcache’e sağ tıklayın,
Export
seçin, format olarakBinary BinExport (v2) for BinDiff
seçin ve export edin. - BinDiff’i açın, yeni bir workspace oluşturun ve bir diff ekleyin; primary file olarak vulnerability içeren kernelcache’i, secondary file olarak patched kernelcache’i gösterin.
Finding the right XNU version
Belirli bir iOS sürümündeki açıkları kontrol etmek istiyorsanız, iOS sürümünün hangi XNU release versiyonunu kullandığını şu adreste kontrol edebilirsiniz: [https://www.theiphonewiki.com/wiki/kernel]https://www.theiphonewiki.com/wiki/kernel).
Örneğin, 15.1 RC
, 15.1
ve 15.1.1
sürümleri Darwin Kernel Version 21.1.0: Wed Oct 13 19:14:48 PDT 2021; root:xnu-8019.43.1~1/RELEASE_ARM64_T8006
versiyonunu kullanır.
iMessage/Media Parser Zero-Click Chains
Imessage Media Parser Zero Click Coreaudio Pac Bypass
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
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.