iOS Exploiting
Reading time: 54 minutes
tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
iOS Exploit Mitigations
1. Code Signing / Verifikacija potpisa za vreme izvršavanja
Introduced early (iPhone OS → iOS) Ovo je jedna od osnovnih zaštita: all executable code (apps, dynamic libraries, JIT-ed code, extensions, frameworks, caches) mora biti kriptografski potpisan sertifikacionim lancem koji se root-uje u Apple-ov trust. U runtime-u, pre nego što se binarni fajl učita u memoriju (ili pre izvršavanja skokova preko određenih granica), sistem proverava njegov potpis. Ako je kod izmenjen (bit-flipped, patched) ili unsigned, učitavanje ne uspeva.
- Sprečava: the “classic payload drop + execute” stage in exploit chains; arbitrary code injection; modifying an existing binary to insert malicious logic.
- Detalji mehanizma:
- Mach-O loader (and dynamic linker) proverava code pages, segmente, entitlements, team IDs, i da li potpis pokriva sadržaj fajla.
- Za regionе memorije poput JIT cache-ova ili dinamički generisanog koda, Apple zahteva da stranice budu potpisane ili validirane putem specijalnih API-ja (npr.
mprotectsa proverama code-sign). - Potpis uključuje entitlements i identifikatore; OS obezbeđuje da određeni API-ji ili privilegovane capability zahtevaju specifična entitlements koja se ne mogu lažno prikazati.
Example
Pretpostavimo da exploit dobije code execution u procesu i pokuša da upiše shellcode na heap i skoči na njega. Na iOS-u, ta stranica bi morala biti označena kao executable **i** zadovoljiti code-signature ograničenja. Pošto shellcode nije potpisan Apple-ovim sertifikatom, skok ne uspeva ili sistem odbija da učini taj region memorije izvršivim.2. CoreTrust
Introduced around iOS 14+ era (or gradually in newer devices / later iOS) CoreTrust je subsistem koji vrši runtime signature validation binarnih fajlova (uključujući sistemske i korisničke binarne) protiv Apple’s root certificate umesto oslanjanja na keširane userland trust store-ove.
- Sprečava: post-install tampering of binaries, jailbreaking techniques that try to swap or patch system libraries or user apps; tricking the system by replacing trusted binaries with malicious counterparts.
- Detalji mehanizma:
- Umesto oslanjanja na lokalnu trust bazu ili keš sertifikata, CoreTrust referiše Apple-ov root direktno ili proverava intermediate sertifikate u sigurnom lancu.
- Obezbeđuje da se izmene (npr. u filesystem-u) postojećih binarnih fajlova detektuju i odbace.
- Povezuje entitlements, team IDs, code signing flagove i drugu metadata sa binarnim fajlom u vreme učitavanja.
Example
Jailbreak bi mogao pokušati da zameni `SpringBoard` ili `libsystem` patched verzijom da bi stekao persistenciju. Ali kada loader OS-a ili CoreTrust proveri, primećuje mismatch potpisa (ili izmenjene entitlements) i odbija da izvrši.3. Data Execution Prevention (DEP / NX / W^X)
Introduced in many OSes earlier; iOS had NX-bit / w^x for a long time DEP nalaže da stranice označene kao writable (za podatke) budu non-executable, i stranice označene kao executable budu non-writable. Ne može se jednostavno upisati shellcode u heap ili stack region i izvršiti ga.
- Sprečava: direct shellcode execution; classic buffer-overflow → jump to injected shellcode.
- Detalji mehanizma:
- MMU / memory protection flagovi (putem page table-a) primenjuju razdvajanje.
- Bilo koji pokušaj da se writable stranici dodeli executable prava pokreće sistemsku proveru (i ili je zabranjen ili zahteva code-sign odobrenje).
- U mnogim slučajevima, da bi stranice postale executable moraju se koristiti OS API-ji koji nameću dodatna ograničenja ili provere.
Example
Overflow upisuje shellcode na heap. Napadač pokušava `mprotect(heap_addr, size, PROT_EXEC)` da bi ga označio kao izvršiv. Ali sistem odbija ili validira da nova stranica mora proći code-sign constraint-e (što shellcode ne može).4. Address Space Layout Randomization (ASLR)
Introduced in iOS ~4–5 era (roughly iOS 4–5 timeframe) ASLR randomizuje baze ključnih memorijskih regiona: libraries, heap, stack, itd., pri svakom pokretanju procesa. Adrese gadget-a se menjaju između pokretanja.
- Sprečava: hardcoding gadget addresses for ROP/JOP; static exploit chains; blind jumping to known offsets.
- Detalji mehanizma:
- Svaka učitana biblioteka / dynamic module se rebazuje na randomizovani offset.
- Stack i heap base pointeri se randomizuju (u okviru određenih nivoa entropije).
- Ponekad su i drugi regioni (npr. mmap alokacije) randomizovani.
- U kombinaciji sa information-leak mitigacijama, primorava napadača da prvo leak an address or pointer da bi otkrio baze adresa u runtime-u.
Example
ROP chain očekuje gadget na `0x….lib + offset`. Ali pošto je `lib` relociran drugačije pri svakom run-u, hardkodovani chain ne uspeva. Exploit mora prvo da leak base address modula pre nego što izračuna ispravne gadget adrese.5. Kernel Address Space Layout Randomization (KASLR)
Introduced in iOS ~ (iOS 5 / iOS 6 timeframe) Analogno korisničkom ASLR-u, KASLR randomizuje bazu kernel text i druge kernel strukture pri boot-u.
- Sprečava: kernel-level exploits that rely on fixed location of kernel code or data; static kernel exploits.
- Detalji mehanizma:
- Pri svakom boot-u kernel base adresa se randomizuje (u okviru opsega).
- Kernel data strukture (kao
task_structs,vm_map, itd.) mogu biti relocirane ili ofsetovane. - Napadači moraju prvo da leak kernel pointers ili iskoriste information disclosure ranjivosti da bi izračunali offset-e pre nego što hijack-uju kernel strukture ili kod.
Example
Lokalna ranjivost cilja da korumpira kernel function pointer (npr. u `vtable`) na `KERN_BASE + offset`. Ali pošto je `KERN_BASE` nepoznat, napadač mora prvo da leak-uje (npr. preko read primitive) pre nego što izračuna ispravnu adresu za korupciju.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) kontinuirano nadgleda integritet kernel text stranica (preko hash-a ili checksum-a). Ako detektuje tampering (patch-e, inline hooks, izmene koda) van dozvoljenih window-a, izaziva kernel panic ili reboot.
- Sprečava: persistent kernel patching (modifying kernel instructions), inline hooks, static function overwrites.
- Detalji mehanizma:
- Hardverski ili firmware modul nadgleda kernel text region.
- Periodično ili na zahtev re-hash-uje stranice i upoređuje sa očekivanim vrednostima.
- Ako se pojave mismatch-e van benignih update window-a, device se panici (da bi se izbegla persistenta maliciozna izmena).
- Napadači moraju ili izbeći detekcione window-e ili koristiti legitimne putanje za patch.
Example
Exploit pokušava da patch-uje kernel funkciju prologue-a (npr. `memcmp`) da bi presreo pozive. Ali KPP primeti da hash code stranice više ne odgovara očekivanoj vrednosti i izazove kernel panic, rušeći uređaj pre nego što patch postane stabilan.7. Kernel Text Read‐Only Region (KTRR)
Introduced in modern SoCs (post ~A12 / newer hardware) KTRR je hardverski sproveden mehanizam: kada se kernel text zaključа ranim tokom boot-a, postaje read-only iz EL1 (kernel), sprečavajući dalje upise u code stranice.
- Sprečava: bilo kakve izmene kernel koda posle boot-a (npr. patching, in-place code injection) na EL1 privilege nivou.
- Detalji mehanizma:
- Tokom boot-a (u secure/bootloader fazi), memory controller (ili secure hardware unit) označava fizičke stranice koje sadrže kernel text kao read-only.
- Čak i ako exploit dobije pune kernel privilegije, ne može da piše u te stranice da bi patch-ovao instrukcije.
- Da bi ih menjao, napadač mora prvo kompromitovati boot chain ili subvert-ovati KTRR.
Example
Privilege-escalation exploit skače u EL1 i upisuje trampoline u kernel funkciju (npr. u `syscall` handler). Ali zato što su stranice zaključane kao read-only od strane KTRR, upis ne uspeva (ili izaziva fault), te patch-evi nisu primenjeni.8. Pointer Authentication Codes (PAC)
Introduced with ARMv8.3 (hardware), Apple beginning with A12 / iOS ~12+
- PAC je hardverska funkcija uvedena u ARMv8.3-A za detekciju tamperinga pointer vrednosti (return addresses, function pointers, certain data pointers) tako što ubacuje mali kriptografski signature („MAC“) u neiskorišćene visoke bitove pointera.
- Potpis („PAC“) se računa preko pointer vrednosti plus modifier (kontekst vrednost, npr. stack pointer ili neki distinguishing data). Tako ista pointer vrednost u različitim kontekstima dobija drugačiji PAC.
- Pri korišćenju, instrukcija za authenticate proverava PAC. Ako je validan, PAC se skida i dobija se čisti pointer; ako nije, pointer postaje „poisoned“ (ili se podiže fault).
- Ključevi koji se koriste za proizvodnju/validaciju PAC-a žive u privilegovanim registrima (EL1, kernel) i nisu direktno čitljivi iz user mode-a.
- Pošto ne koriste svi sistemi svih 64 bita pointera (npr. 48-bit address space), gornji bitovi su „spare“ i mogu držati PAC bez menjanja efektivne adrese.
Architectural Basis & Key Types
-
ARMv8.3 uvodi pet 128-bit ključeva (svaki implementiran kao dva 64-bit sistema registra) za pointer authentication.
-
APIAKey — za instruction pointers (domen “I”, key A)
-
APIBKey — drugi instruction pointer key (domen “I”, key B)
-
APDAKey — za data pointers (domen “D”, key A)
-
APDBKey — za data pointers (domen “D”, key B)
-
APGAKey — “generic” key, za potpisivanje non-pointer podataka ili druge generic upotrebe
-
Ovi ključevi se čuvaju u privilegovanim sistemskim registrima (pristup samo na EL1/EL2 itd.), nisu dostupni iz user mode-a.
-
PAC se računa putem kriptografske funkcije (ARM preporučuje QARMA kao algoritam) koristeći:
- Pointer vrednost (canonical portion)
- Modifier (kontekst vrednost, poput soli)
- Tajni ključ
- Neki interni tweak mehanizam Ako dobijeni PAC odgovara onome što je smešteno u gornjim bitovima pointera, autentikacija uspeva.
Instruction Families
Konvencija imenovanja je: PAC / AUT / XPAC, zatim sufiksi domena.
PACxxinstrukcije potpisuju pointer i ubacuju PACAUTxxinstrukcije autentikuju + skidaju (validiraju i uklanjaju PAC)XPACxxinstrukcije skidaju bez validacije
Domains / sufiksi:
| Mnemonic | Meaning / Domain | Key / Domain | Example Usage in Assembly |
|---|---|---|---|
| PACIA | Sign instruction pointer with APIAKey | “I, A” | PACIA X0, X1 — sign pointer in X0 using APIAKey with modifier X1 |
| PACIB | Sign instruction pointer with APIBKey | “I, B” | PACIB X2, X3 |
| PACDA | Sign data pointer with APDAKey | “D, A” | PACDA X4, X5 |
| PACDB | Sign data pointer with APDBKey | “D, B” | PACDB X6, X7 |
| PACG / PACGA | Generic (non-pointer) signing with APGAKey | “G” | PACGA X8, X9, X10 (sign X9 with modifier X10 into X8) |
| AUTIA | Authenticate APIA-signed instruction pointer & strip PAC | “I, A” | AUTIA X0, X1 — check PAC on X0 using modifier X1, then strip |
| AUTIB | Authenticate APIB domain | “I, B” | AUTIB X2, X3 |
| AUTDA | Authenticate APDA-signed data pointer | “D, A” | AUTDA X4, X5 |
| AUTDB | Authenticate APDB-signed data pointer | “D, B” | AUTDB X6, X7 |
| AUTGA | Authenticate generic / blob (APGA) | “G” | AUTGA X8, X9, X10 (validate generic) |
| XPACI | Strip PAC (instruction pointer, no validation) | “I” | XPACI X0 — remove PAC from X0 (instruction domain) |
| XPACD | Strip PAC (data pointer, no validation) | “D” | XPACD X4 — remove PAC from data pointer in X4 |
Postoje specijalizovane / alias forme:
PACIASPje skraćeno zaPACIA X30, SP(potpiši link register koristeći SP kao modifier)AUTIASPjeAUTIA X30, SP(autentikuj link register sa SP)- Kombinovane forme poput
RETAA,RETAB(authenticate-and-return) iliBLRAA(authenticate & branch) postoje u ARM ekstenzijama / podršci kompajlera. - Takođe postoje varijante sa implicitnim nul-modifierom:
PACIZA/PACIZBgde je modifier implictno zero, itd.
Modifiers
Glavni cilj modifier-a je da veže PAC za specifičan kontekst tako da ista adresa potpisana u različitim kontekstima daje različite PAC-ove. To sprečava jednostavnu ponovnu upotrebu pointera između frame-ova ili objekata. To je kao dodavanje soli u hash.
Dakle:
- modifier je kontekst vrednost (drugi registar) koja se meša u PAC računanje. Tipični izbori: stack pointer (
SP), frame pointer, ili neki object ID. - Korišćenje SP kao modifier-a je uobičajeno za potpisivanje return adresa: PAC je vezan za specifičan stack frame. Ako pokušaš da ponovo iskoristiš LR u drugom frame-u, modifier se menja i PAC validacija ne uspe.
- Ista pointer vrednost potpisana pod različitim modifier-ima daje različite PAC-ove.
- Modifier ne mora biti tajan, ali idealno nije attacker-controlled.
- Za instrukcije koje potpisuju ili proveravaju pointere gde nema smislenog modifier-a, neke forme koriste zero ili implicitnu konstantu.
Apple / iOS / XNU Customizations & Observations
- Apple-ova PAC implementacija uključuje per-boot diversifiers tako da ključevi ili tweak-ovi menjaju svaki boot, što onemogućava reuse across boots.
- Takođe imaju cross-domain mitigations tako da PAC potpisani u user mode-u ne mogu lako biti re-used u kernel mode-u, itd.
- Na Apple M1 / Apple Silicon, reverse engineering je pokazao da postoje nine modifier types i Apple-specifični sistem registari za kontrolu ključeva.
- Apple koristi PAC u mnogim kernel subsistemima: potpisivanje return adresa, pointer integriteta u kernel podacima, potpisani thread context-i, itd.
- Google Project Zero je pokazao kako pod moćnim memory read/write primitive u kernel-u, može se forge-ovati kernel PAC-ove (za A keys) na A12-era uređajima, ali Apple je zakrpio mnoge od tih puteva.
- U Apple-ovom sistemu, neki ključevi su globalni za kernel, dok procesi u korisničkom prostoru mogu dobiti per-process key randomness.
PAC Bypasses
- Kernel-mode PAC: theoretical vs real bypasses
- Pošto su kernel PAC ključevi i logika strogo kontrolisani (privileged registri, diversifiers, domain isolation), forging arbitrary signed kernel pointers je veoma teško.
- Azad-ov 2020 "iOS Kernel PAC, One Year Later" izveštava da je u iOS 12-13 pronađeno nekoliko partial bypass-ova (signing gadgets, reuse of signed states, unprotected indirect branches) ali ne i potpuni generički bypass. bazad.github.io
- Apple-ov "Dark Magic" customizacije dodatno su suzile exploitable surface-e (domain switching, per-key enabling bits). i.blackhat.com
- Postoji poznat kernel PAC bypass CVE-2023-32424 na Apple silicon (M1/M2) prijavljen od strane Zecao Cai et al. i.blackhat.com
- Ali ovi bypass-ovi često zavise od vrlo specifičnih gadget-a ili implementacionih bug-ova; nisu general-purpose bypass.
Dakle kernel PAC se smatra visoko robusnim, iako nije savršen.
- User-mode / runtime PAC bypass techniques
Ovi su češći i iskorišćavaju nesavršenosti u primeni PAC-a ili upotrebi u dynamic linking / runtime framework-ovima. Ispod su klase sa primerima.
2.1 Shared Cache / A key issues
-
dyld shared cache je veliki pre-linked blob sistemskih framework-a i biblioteka. Pošto se tako široko deli, function pointers unutar shared cache-a su "pre-signed" i onda korišćeni od strane mnogih procesa. Napadači ciljaju te već potpisane pointer-e kao "PAC oracles".
-
Neki bypass pristupi pokušavaju da izvuku ili re-use A-key signed pointer-e prisutne u shared cache-u i re-upotrebe ih u gadget lancima.
-
Predavanje "No Clicks Required" opisuje izgradnju oracle-a preko shared cache-a da se infer-uju relativne adrese i kombinuju sa signed pointer-ima da se zaobiđe PAC. saelo.github.io
-
Takođe, import-i function pointer-a iz shared libraries u userspace-u su nađeni kao nedovoljno zaštićeni od strane PAC-a, dopuštajući napadaču da dobije function pointers bez menjanja njihovog potpisa. (Project Zero bug entry) bugs.chromium.org
2.2 dlsym(3) / dynamic symbol resolution
-
Jedan poznat bypass je pozivanje
dlsym()da bi se dobio already signed function pointer (signed with A-key, diversifier zero) i zatim njegovo korišćenje. Poštodlsymvraća legitimno signed pointer, njegovo korišćenje zaobilazi potrebu za forging PAC-a. -
Epsilon-ov blog objašnjava kako neki bypass-ovi iskorišćavaju ovo: poziv
dlsym("someSym")vraća signed pointer i može se koristiti za indirektne pozive. blog.epsilon-sec.com -
Synacktiv-ov "iOS 18.4 --- dlsym considered harmful" opisuje bug: neki simboli rešeni putem
dlsymna iOS 18.4 vraćaju pointer-e koji su netačno potpisani (ili sa buggy diversifiers), omogućavajući nepredviđeni PAC bypass. Synacktiv -
Logika u dyld za dlsym uključuje: kada
result->isCode, oni sign-uju vraćeni pointer sa__builtin_ptrauth_sign_unauthenticated(..., key_asia, 0), tj. context zero. blog.epsilon-sec.com
Dakle, dlsym je čest vektor u user-mode PAC bypass-ovima.
2.3 Other DYLD / runtime relocations
-
DYLD loader i dynamic relocation logika su kompleksni i ponekad privremeno mapiraju stranice kao read/write da bi obavili relocations, a potom ih vraćaju na read-only. Napadači iskorišćavaju te prozore. Synacktiv-ovo predavanje opisuje "Operation Triangulation", timing-based PAC bypass kroz dynamic relocations. Synacktiv
-
DYLD stranice su sada zaštićene sa SPRR / VM_FLAGS_TPRO (neke protection flags za dyld). Ali ranije verzije su imale slabije garde. Synacktiv
-
U WebKit exploit lancima, DYLD loader je često cilj za PAC bypass. Slides navode da su mnogi PAC bypass-ovi ciljali DYLD loader (preko relocacija, interposer hook-ova). Synacktiv
2.4 NSPredicate / NSExpression / ObjC / SLOP
-
U userland exploit lancima, Objective-C runtime metode poput
NSPredicate,NSExpressioniliNSInvocationse koriste da se izmanipulišu kontrolni pozivi bez očiglednog pointer forging-a. -
Na starijem iOS-u (pre PAC), exploit je koristio fake NSInvocation objekte da pozove arbitrary selectors na kontrolisanoj memoriji. Sa PAC, potrebne su izmene. Ali tehnika SLOP (SeLector Oriented Programming) je proširena i pod PAC-om. Project Zero
-
Originalna SLOP tehnika je dozvoljavala chain-ovanje ObjC poziva kreiranjem fake invocation-a; bypass se oslanja na to da ISA ili selector pointer-i ponekad nisu potpuno PAC-protected. Project Zero
-
U okruženjima gde je pointer authentication delimično primenjen, metode / selector-i / target pointer-i možda nisu uvek PAC-zastupljeni, dajući prostor za bypass.
Example Flow
Example Signing & Authenticating
``` ; Example: function prologue / return address protection my_func: stp x29, x30, [sp, #-0x20]! ; push frame pointer + LR mov x29, sp PACIASP ; sign LR (x30) using SP as modifier ; … body … mov sp, x29 ldp x29, x30, [sp], #0x20 ; restore AUTIASP ; authenticate & strip PAC ret; Example: indirect function pointer stored in a struct ; suppose X1 contains a function pointer PACDA X1, X2 ; sign data pointer X1 with context X2 STR X1, [X0] ; store signed pointer
; later retrieval: LDR X1, [X0] AUTDA X1, X2 ; authenticate & strip BLR X1 ; branch to valid target
; Example: stripping for comparison (unsafe) LDR X1, [X0] XPACI X1 ; strip PAC (instruction domain) CMP X1, #some_label_address BEQ matched_label
</details>
<details>
<summary>Primer</summary>
A buffer overflow prepisuje return address na steku. Napadač upisuje ciljnu adresu gadgeta ali ne može izračunati ispravan PAC. Kada funkcija vraća kontrolu, CPU-ova `AUTIA` instrukcija izaziva grešku zbog neusaglašenosti PAC-a. Lanac ne uspeva.
Project Zero analiza na A12 (iPhone XS) je pokazala kako Apple koristi PAC i metode falsifikovanja PAC-ova ako napadač poseduje primitive za čitanje/pisanje memorije.
</details>
### 9. **Branch Target Identification (BTI)**
**Introduced with ARMv8.5 (later hardware)**
BTI je hardverska funkcija koja proverava **indirektne ciljeve grananja**: pri izvršavanju `blr` ili indirektnih poziva/skokova, cilj mora da počne sa **BTI landing pad** (`BTI j` ili `BTI c`). Skočenje na adrese gadgeta koje nemaju landing pad pokreće izuzetak.
LLVM-ova implementacija navodi tri varijante BTI instrukcija i kako se one mapiraju na tipove grananja.
| 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 |
- U kodu kompajliranom sa branch target enforcement, kompajleri umeću BTI instrukciju (C, J ili JC) na svako važeće indirektno-branch odredište (početci funkcija ili blokovi dostupni skokovima) tako da indirektna grananja uspevaju samo na tim mestima.
- **Direktna grananja / pozivi** (tj. fiksno-adresni `B`, `BL`) **nisu ograničeni** od strane BTI. Pretpostavka je da su code page-ovi pouzdani i da napadač ne može da ih menja (tako da su direktna grananja bezbedna).
- Takođe, **RET / return** instrukcije generalno nisu ograničene BTI zato što su return adrese zaštićene preko PAC ili mehanizama potpisivanja povratka.
#### Mechanism and enforcement
- Kada CPU dekodira **indirektno grananje (BLR / BR)** u stranici označenoj kao “guarded / BTI-enabled,” proverava da li prva instrukcija ciljne adrese predstavlja važeći BTI (C, J ili JC kako je dozvoljeno). Ako nije, nastaje **Branch Target Exception**.
- Kodiranje BTI instrukcije je dizajnirano da ponovo iskoristi opkodove ranije rezervisane za NOP-ove (u starijim ARM verzijama). Tako BTI-om omogućeni binarni fajlovi ostaju kompatibilni unazad: na hardveru bez BTI podrške te instrukcije se ponašaju kao NOP.
- Compiler pass-ovi koji dodaju BTI umeću ih samo gde je potrebno: funkcije koje mogu biti pozvane indirektno, ili osnovni blokovi koji su ciljevi skokova.
- Neki patch-evi i LLVM kod pokazuju da BTI nije umetnut za *sve* osnovne blokove — samo za one koji su potencijalni branch ciljevi (npr. iz switch / jump tabela).
#### BTI + PAC synergy
PAC štiti vrednost pokazivača (izvor) — osigurava da lanac indirektnih poziva / return-ova nije promenjen.
BTI osigurava da čak i važeći pokazivač može ciljati samo pravilno obeležene ulazne tačke.
Zajedno, napadaču su potrebni i važeći pokazivač sa ispravnim PAC-om i da cilj sadrži BTI. To povećava težinu konstruisanja exploit gadgeta.
#### Primer
<details>
<summary>Primer</summary>
Exploit pokušava da pivotira na gadget na `0xABCDEF` koji ne počinje sa `BTI c`. CPU, pri izvršavanju `blr x0`, proverava cilj i izaziva grešku zato što instrukcija ne sadrži validan landing pad. Dakle, mnogi gadgeti postaju neupotrebljivi osim ako nemaju BTI prefiks.
</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** je funkcija uvedena u **ARMv8.1-A** koja sprečava da **privilegovan kod** (EL1 ili EL2) **čita ili piše** memoriju koja je označena kao **user-accessible (EL0)**, osim ako PAN nije eksplicitno onemogućen.
- Ideja: čak i ako je kernel prevaren ili kompromitovan, on ne može proizvoljno dereferencirati user-space pokazivače bez prethodnog *isključivanja* PAN-a, čime se smanjuju rizici od eksploitacija tipa **`ret2usr`** ili zloupotrebe bafera kontrolisanih od strane korisnika.
- Kada je PAN omogućen (PSTATE.PAN = 1), svaka privilegiovana load/store instrukcija koja pristupa virtuelnoj adresi koja je “accessible at EL0” izaziva **permission fault**.
- Kernel, kada legitimno mora da pristupi user-space memoriji (npr. kopiranje podataka do/iz korisničkih bafera), mora **privremeno da isključi PAN** (ili da koristi “unprivileged load/store” instrukcije) da bi omogućio taj pristup.
- U Linux-u na ARM64, podrška za PAN je uvedena oko 2015: kernel patch-evi su dodali detekciju feature-a i zamenili `get_user` / `put_user` itd. varijantama koje brišu PAN oko pristupa korisničkoj memoriji.
**Ključna nijansa / ograničenje / bug**
- Kao što su primetili Siguza i drugi, specifikaciona greška (ili dvosmisleno ponašanje) u ARM dizajnu znači da **execute-only user mappings** (`--x`) možda **neće pokrenuti PAN**. Drugim rečima, ako je user stranica označena kao izvršna ali bez prava čitanja, kernelov pokušaj čitanja možda zaobiđe PAN jer arhitektura smatra da “accessible at EL0” zahteva pravo čitanja, a ne samo izvršenje. Ovo dovodi do PAN bypass-a u određenim konfiguracijama.
- Zbog toga, ako iOS / XNU dozvoljava execute-only user stranice (kao što to neki JIT ili code-cache setup-i mogu), kernel bi mogao nenamerno da čita iz njih čak i sa uključenim PAN-om. Ovo je poznato i suptilno eksploatabilno područje u nekim ARMv8+ sistemima.
#### PXN (Privileged eXecute Never)
- **PXN** je flag u page table-u (u page table entry-ima, leaf ili block entry-ima) koji označava da stranica **nije izvršna kada se pokreće u privilegovanom režimu** (tj. kada EL1 izvršava).
- PXN sprečava kernel (ili bilo koji privilegiovan kod) da skoči u ili izvršava instrukcije iz user-space stranica čak i ako se kontrola preusmeri. U praksi, to zaustavlja kernel-level preusmeravanje kontrole toka u user memoriju.
- U kombinaciji sa PAN, ovo osigurava da:
1. Kernel ne može (po defaultu) da čita ili piše user-space podatke (PAN)
2. Kernel ne može da izvršava user-space kod (PXN)
- U ARMv8 formatu page table-a, leaf entry-i imaju `PXN` bit (i takođe `UXN` za unprivileged execute-never) u svojim atributnim bitovima.
Dakle, čak i ako kernel ima korumpiran pokazivač funkcije koji pokazuje na user memoriju i pokuša da skoči tamo, PXN bit bi izazvao grešku.
#### Memory-permission model & how PAN and PXN map to page table bits
Da biste razumeli kako PAN / PXN rade, treba da vidite kako ARM-ov model translacije i dozvola radi (pojednostavljeno):
- Svaka stranica ili block entry ima polja atributa uključujući **AP[2:1]** za pristupna dopuštenja (read/write, privileged vs unprivileged) i **UXN / PXN** bitove za zabranu izvršenja.
- Kada je PSTATE.PAN = 1 (uključen), hardver primenjuje izmenjene semantike: privilegovani pristupi stranicama označenim kao “accessible by EL0” (tj. user-accessible) su zabranjeni (fault).
- Zbog pomenutog buga, stranice koje su označene samo kao izvršne (bez prava čitanja) možda se ne računaju kao “accessible by EL0” kod određenih implementacija, čime se PAN može zaobići.
- Kada je PXN bit postavljen na stranici, čak i ako je fetch instrukcije došao sa višeg privilegionog nivoa, izvršenje je zabranjeno.
#### Kernel usage of PAN / PXN in a hardened OS (e.g. iOS / XNU)
U dizajnu ojačanog kernela (kao što Apple može koristiti):
- Kernel podrazumevano uključuje PAN (tako da je privilegiovani kod ograničen).
- U putevima koji legitimno moraju da čitaju ili pišu korisničke bafer-e (npr. syscall buffer copy, I/O, read/write user pointer), kernel privremeno **isključuje PAN** ili koristi specijalne instrukcije da to zaobiđe.
- Nakon završetka pristupa korisničkim podacima, mora ponovo da uključi PAN.
- PXN se sprovedi preko page table-a: user stranice imaju PXN = 1 (tako da kernel ne može da ih izvršava), kernel stranice nemaju PXN (tako da kernel kod može da se izvršava).
- Kernel mora da osigura da nijedan kodni put ne dovodi do izvršenja u user memorijskim regionima (što bi zaobišlo PXN) — tako exploit lanci koji se oslanjaju na “skoči u user-controlled shellcode” su blokirani.
Zbog pomenutog PAN bypass-a putem execute-only stranica, u realnom sistemu Apple može onemogućiti ili zabraniti execute-only user stranice, ili ispraviti specifikacionu slabost.
#### Attack surfaces, bypasses, and mitigations
- **PAN bypass via execute-only pages**: kao što je diskutovano, specifikacija ostavlja prazninu: user stranice sa execute-only (bez read perm) možda ne računaju kao “accessible at EL0,” tako da PAN neće blokirati kernel čitanja iz takvih stranica kod nekih implementacija. Ovo napadaču daje neuobičajen put da ubaci podatke putem “execute-only” sekcija.
- **Temporal window exploit**: ako kernel isključi PAN za vremenski prozor duži nego što je potrebno, race ili zlonameran put može iskoristiti taj prozor za nepredviđeni pristup korisničkoj memoriji.
- **Forgotten re-enable**: ako kod zaboravi da ponovo uključi PAN, naknadne kernel operacije mogu pogrešno pristupati korisničkoj memoriji.
- **Misconfiguration of PXN**: ako page table-i ne postave PXN na user stranicama ili pogrešno mapiraju user code stranice, kernel može biti prevaren da izvrši user-space kod.
- **Speculation / side-channels**: analogno spekulativnim zaobilaženjima, mogu postojati mikroarhitekturni sporedni efekti koji izazovu tranzijentne kršenja PAN / PXN provera (iako su takvi napadi jako zavisni od dizajna CPU-a).
- **Complex interactions**: U naprednijim feature-ima (npr. JIT, shared memory, just-in-time code regions), kernel može zahtevati fino upravljanje da dozvoli određene memorijske pristupe ili izvršenje u user-mapiranim regionima; dizajniranje tih mehanizama bezbedno pod PAN/PXN ograničenjima nije trivijalno.
#### Primer
<details>
<summary>Primer koda</summary>
Here are illustrative pseudo-assembly sequences showing enabling/disabling PAN around user memory access, and how a fault might occur.
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs"> </span></div>
// Suppose kernel entry point, PAN is enabled (privileged code cannot access user memory by default)
; Kernel receives a syscall with user pointer in X0 ; wants to read an integer from user space mov X1, X0 ; X1 = user pointer
; disable PAN to allow privileged access to user memory MSR PSTATE.PAN, #0 ; clear PAN bit, disabling the restriction
ldr W2, [X1] ; now allowed load from user address
; re-enable PAN before doing other kernel logic MSR PSTATE.PAN, #1 ; set PAN
; ... further kernel work ...
; Later, suppose an exploit corrupts a pointer to a user-space code page and jumps there BR X3 ; branch to X3 (which points into user memory)
; Because the target page is marked PXN = 1 for privileged execution, ; the CPU throws an exception (fault) and rejects execution
If the kernel had **not** set PXN on that user page, then the branch might succeed — which would be insecure.
If the kernel forgets to re-enable PAN after user memory access, it opens a window where further kernel logic might accidentally read/write arbitrary user memory.
If the user pointer is into an execute-only page (user page with only execute permission, no read/write), under the PAN spec bug, `ldr W2, [X1]` might **not** fault even with PAN enabled, enabling a bypass exploit, depending on implementation.
</details>
<details>
<summary>Example</summary>
A kernel vulnerability tries to take a user-provided function pointer and call it in kernel context (i.e. `call user_buffer`). Under PAN/PXN, that operation is disallowed or faults.
</details>
---
### 11. **Top Byte Ignore (TBI) / Pointer Tagging**
**Introduced in ARMv8.5 / newer (or optional extension)**
TBI znači da se gornji bajt (najznačajniji bajt) 64-bitnog pokazivača ignoriše pri address translation. Ovo dopušta OS-u ili hardveru da ugradi **tag bits** u gornji bajt pokazivača bez uticaja na stvarnu adresu.
- TBI znači **Top Byte Ignore** (ponekad nazivan *Address Tagging*). To je hardverska funkcija (dostupna u mnogim ARMv8+ implementacijama) koja **ignoriše gornjih 8 bitova** (bitovi 63:56) 64-bitnog pokazivača pri obavljanju **address translation / load/store / instruction fetch**.
- U praksi, CPU tretira pokazivač `0xTTxxxx_xxxx_xxxx` (gde je `TT` = top byte) kao `0x00xxxx_xxxx_xxxx` za potrebe address translation, ignorišući (maskirajući) gornji bajt. Gornji bajt može koristiti softver za čuvanje **metadata / tag bits**.
- Ovo daje softveru “besplatan” in-band prostor da ugradi bajt taga u svaki pokazivač bez menjanja koje memorijsko mesto pokazivač zapravo referencira.
- Arhitektura obezbeđuje da loads, stores i instruction fetch tretiraju pokazivač sa maskiranim gornjim bajtom (tj. tag uklonjenim) pre nego što izvrše stvarni memory access.
Dakle, TBI razdvaja **logički pokazivač** (pokazivač + tag) od **fizičke adrese** korišćene za memorijske operacije.
#### Why TBI: Use cases and motivation
- **Pointer tagging / metadata**: Možete skladištiti dodatne metapodatke (npr. tip objekta, verziju, bounds, integrity tags) u tom gornjem bajtu. Kada kasnije koristite pokazivač, tag se na hardverskom nivou ignoriše, pa ne morate ručno da ga skidate za memory access.
- **Memory tagging / MTE (Memory Tagging Extension)**: TBI je osnovni hardverski mehanizam na kojem MTE gradi. U ARMv8.5, **Memory Tagging Extension** koristi bitove 59:56 pokazivača kao **logički tag** i upoređuje ga sa **allocation tag** koji je pohranjen u memoriji.
- **Enhanced security & integrity**: Kombinovanjem TBI sa pointer authentication (PAC) ili runtime proverama, možete zahtevati da ne bude ispravan samo vrednost pokazivača već i tag. Napadač koji prepiše pokazivač bez pravilnog taga će izazvati mismatch taga.
- **Compatibility**: Pošto je TBI opcion, a tag bitovi se ignorišu na hardveru, postojeći netagovani kod nastavlja da radi normalno. Tag bitovi efektivno postaju “don't care” bitovi za legacy kod.
#### Example
<details>
<summary>Example</summary>
A function pointer included a tag in its top byte (say `0xAA`). An exploit overwrites the pointer low bits but neglects the tag, so when the kernel verifies or sanitizes, the pointer fails or is rejected.
</details>
---
### 12. **Page Protection Layer (PPL)**
**Introduced in late iOS / modern hardware (iOS ~17 / Apple silicon / high-end models)** (some reports show PPL circa macOS / Apple silicon, but Apple is bringing analogous protections to iOS)
- PPL je dizajniran kao **intra-kernel protection boundary**: čak i ako je kernel (EL1) kompromitovan i ima read/write mogućnosti, **ne bi trebalo da može slobodno da menja** određene **osetljive strane** (posebno page tables, code-signing metadata, kernel code pages, entitlements, trust caches, itd.).
- Efektivno stvara **“kernel unutar kernela”** — manju poverenu komponentu (PPL) sa **povišenim privilegijama** koja samo ona može da menja zaštićene strane. Ostali kernel kod mora da pozove PPL rutine da bi napravio izmene.
- Ovo smanjuje attack surface za kernel exploite: čak i sa potpunim arbitrary R/W/execute u kernel modu, exploit kod mora na neki način da uđe u PPL domen (ili da zaobiđe PPL) da bi modifikovao kritične strukture.
- Na novijem Apple silicon-u (A15+ / M2+), Apple prelazi na **SPTM (Secure Page Table Monitor)**, koji u mnogim slučajevima zamenjuje PPL za zaštitu page-table-a na tim platformama.
Evo kako se veruje da PPL radi, na osnovu javnih analiza:
#### Use of APRR / permission routing (APRR = Access Permission ReRouting)
- Apple hardver koristi mehanizam nazvan **APRR (Access Permission ReRouting)**, koji dozvoljava da page table entries (PTEs) sadrže male indekse, umesto punih permission bitova. Ti indeksi se mapiraju pomoću APRR registara na stvarne dozvole. To omogućava dinamičko remapiranje dozvola po domenu.
- PPL koristi APRR da segregira privilegije unutar kernel konteksta: samo PPL domen ima dozvolu da ažurira mapiranje između indeksa i efektivnih dozvola. To jest, kada non-PPL kernel kod upiše PTE ili pokuša da promeni permission bitove, APRR logika to zabranjuje (ili nameće read-only mapiranje).
- PPL kod sam radi u ograničenom regionu (npr. `__PPLTEXT`) koji je obično non-executable ili non-writable dok entry gates privremeno ne dozvole pristup. Kernel zove PPL entry points (“PPL routines”) da izvrši osetljive operacije.
#### Gate / Entry & Exit
- Kada kernel treba da modifikuje zaštićenu stranicu (npr. promeni permisije kernel code stranice, ili modifikuje page tables), poziva se u **PPL wrapper** rutinu, koja radi validaciju, a zatim prelazi u PPL domen. Van tog domena, zaštićene strane su efektivno read-only ili nemodifikabilne od glavnog kernela.
- Tokom PPL entry, APRR mapiranja se podešavaju tako da su memorijske stranice u PPL regionu postavljene kao **executable & writable** unutar PPL. Nakon izlaza, one se vraćaju na read-only / non-writable. Ovo osigurava da samo dobro revidirane PPL rutine mogu da pisu u zaštićene strane.
- Van PPL-a, pokušaji kernel koda da pišu u te zaštićene strane će izazvati fault (permission denied) jer APRR mapiranje za taj kod domen ne dozvoljava pisanje.
#### Protected page categories
Stranice koje PPL obično štiti uključuju:
- Page table strukture (translation table entries, mapping metadata)
- Kernel code pages, naročito one koje sadrže kritičnu logiku
- Code-sign metadata (trust caches, signature blobs)
- Entitlement tables, signature enforcement tables
- Druge visokovredne kernel strukture gde bi patch omogućio zaobilaženje signature provera ili manipulaciju kredencijalima
Ideja je da čak i ako je kernel mem potpuno kontrolisan, napadač ne može jednostavno da patch-uje ili prepiše ove stranice, osim ako ne kompromituje i PPL rutine ili ne zaobiđe PPL.
#### Known Bypasses & Vulnerabilities
1. **Project Zero’s PPL bypass (stale TLB trick)**
- Javna objava od Project Zero opisuje bypass koji uključuje **stale TLB entries**.
- Ideja:
1. Allocate two physical pages A and B, mark them as PPL pages (so they are protected).
2. Map two virtual addresses P and Q whose L3 translation table pages come from A and B.
3. Spin a thread to continuously access Q, keeping its TLB entry alive.
4. Call `pmap_remove_options()` to remove mappings starting at P; due to a bug, the code mistakenly removes the TTEs for both P and Q, but only invalidates the TLB entry for P, leaving Q’s stale entry live.
5. Reuse B (page Q’s table) to map arbitrary memory (e.g. PPL-protected pages). Because the stale TLB entry still maps Q’s old mapping, that mapping remains valid for that context.
6. Through this, the attacker can put writable mapping of PPL-protected pages in place without going through PPL interface.
- Ovaj exploit je zahtevao fino upravljanje fizičkim mapiranjem i TLB ponašanjem. Pokazuje da bezbednosna granica koja zavisi od ispravnosti TLB / mapping konzistentnosti mora biti izuzetno pažljiva oko TLB invalidacija i konzistentnosti mapiranja.
- Project Zero je komentarisao da su bypass-ovi ovakve prirode suptilni i retki, ali mogući u kompleksnim sistemima. Ipak, smatraju PPL solidnom mitigacijom.
2. **Other potential hazards & constraints**
- Ako kernel exploit može direktno da uđe u PPL rutine (pozivanjem PPL wrapper-a), može zaobići restrikcije. Zato je validacija argumenata kritična.
- Bagovi u samom PPL kodu (npr. arithmetic overflow, provere granica) mogu omogućiti out-of-bounds modifikacije unutar PPL. Project Zero je uočio da je takav bag u `pmap_remove_options_internal()` iskorišćen u njihovom bypass-u.
- PPL granica je čvrsto vezana za hardversko sprovođenje (APRR, memory controller), tako da je tek toliko jaka koliko je hardverna implementacija.
#### Example
<details>
<summary>Code Example</summary>
Here’s a simplified pseudocode / logic showing how a kernel might call into PPL to modify protected pages:
</details>
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">c</span></div>
```c
// In kernel (outside PPL domain)
function kernel_modify_pptable(pt_addr, new_entry) {
// validate arguments, etc.
return ppl_call_modify(pt_addr, new_entry) // call PPL wrapper
}
// In PPL (trusted domain)
function ppl_call_modify(pt_addr, new_entry) {
// temporarily enable write access to protected pages (via APRR adjustments)
aprr_set_index_for_write(PPL_INDEX)
// perform the modification
*pt_addr = new_entry
// restore permissions (make pages read-only again)
aprr_restore_default()
return success
}
// If kernel code outside PPL does:
*pt_addr = new_entry // a direct write
// It will fault because APRR mapping for non-PPL domain disallows write to that page
The kernel can do many normal operations, but only through ppl_call_* routines can it change protected mappings or patch code.
Example
A kernel exploit tries to overwrite the entitlement table, or disable code-sign enforcement by modifying a kernel signature blob. Because that page is PPL-protected, the write is blocked unless going through the PPL interface. So even with kernel code execution, you cannot bypass code-sign constraints or modify credential data arbitrarily. On iOS 17+ certain devices use SPTM to further isolate PPL-managed pages.PPL → SPTM / Replacements / Future
- On Apple’s modern SoCs (A15 or later, M2 or later), Apple supports SPTM (Secure Page Table Monitor), which replaces PPL for page table protections.
- Apple calls out in documentation: “Page Protection Layer (PPL) and Secure Page Table Monitor (SPTM) enforce execution of signed and trusted code … PPL manages the page table permission overrides … Secure Page Table Monitor replaces PPL on supported platforms.”
- The SPTM architecture likely shifts more policy enforcement into a higher-privileged monitor outside kernel control, further reducing the trust boundary.
MTE | EMTE | MIE
Here’s a higher-level description of how EMTE operates under Apple’s MIE setup:
- Tag assignment
- Kada se memorija dodeli (npr. u kernel ili user space putem secure allocators), tom bloku se dodeljuje secret tag.
- Pointer koji se vrati korisniku ili kernelu uključuje taj tag u svojim visokim bitovima (koristeći TBI / top byte ignore mechanisms).
- Tag checking on access
- Kad god se izvrši load ili store koristeći pointer, hardware proverava da li tag pointera odgovara tagu memorijskog bloka (allocation tag). Ako se ne poklapaju, nastaje fault odmah (pošto je synchronous).
- Pošto je synchronous, nema „delayed detection“ prozora.
- Retagging on free / reuse
- Kada se memorija oslobodi, allocator menja tag bloka (tako da stariji pointeri sa old tagovima više ne odgovaraju).
- Use-after-free pointer će zato imati stale tag i mismatch pri pristupu.
- Neighbor-tag differentiation to catch overflows
- Susedne alokacije dobijaju različite tagove. Ako buffer overflow prelije u memoriju suseda, tag mismatch izaziva fault.
- Ovo je posebno efikasno za hvatanje malih overflows koji prelaze granicu.
- Tag confidentiality enforcement
- Apple mora sprečiti da vrednosti taga budu leaked (jer, ako attacker sazna tag, mogao bi da sastavi pointere sa ispravnim tagovima).
- Uvode zaštite (microarchitectural / speculative controls) da bi izbegli side-channel leakage of tag bits.
- Kernel and user-space integration
- Apple koristi EMTE ne samo u user-space već i u kernel / OS-critical komponentama (da bi zaštitio kernel od memory corruption).
- Hardware/OS osigurava da se tag rules primenjuju čak i kada kernel izvršava u ime user space.
Example
``` Allocate A = 0x1000, assign tag T1 Allocate B = 0x2000, assign tag T2// pointer P points into A with tag T1 P = (T1 << 56) | 0x1000
// Valid store *(P + offset) = value // tag T1 matches allocation → allowed
// Overflow attempt: P’ = P + size_of_A (into B region) *(P' + delta) = value → pointer includes tag T1 but memory block has tag T2 → mismatch → fault
// Free A, allocator retags it to T3 free(A)
// Use-after-free: *(P) = value → pointer still has old tag T1, memory region is now T3 → mismatch → fault
</details>
#### Ograničenja i izazovi
- **Intrablock overflows**: Ako overflow ostane unutar iste alokacije (ne pređe granicu) i tag ostane isti, tag mismatch ga neće detektovati.
- **Tag width limitation**: Dostupno je samo nekoliko bitova (npr. 4 bita, ili mali domen) za tag—ograničen namespace.
- **Side-channel leaks**: Ako se tag bits mogu leak-ovati (putem cache / speculative execution), napadač može saznati validne tage i zaobići zaštitu. Apple-ovo Tag Confidentiality Enforcement ima za cilj da ovo umanji.
- **Performance overhead**: Provere taga pri svakom load/store dodaju trošak; Apple mora optimizovati hardver da taj overhead bude mali.
- **Compatibility & fallback**: Na starijem hardveru ili delovima koji ne podržavaju EMTE mora postojati fallback. Apple navodi da je MIE omogućen samo na uređajima koji imaju podršku.
- **Complex allocator logic**: Allocator mora da upravlja tagovima, retagging-om, poravnavanjem granica i da izbegne sudare tag-ova. Bagovi u logici allocator-a mogu uvesti ranjivosti.
- **Mixed memory / hybrid areas**: Neki delovi memorije mogu ostati untagged (legacy), što čini interoperabilnost komplikovanijom.
- **Speculative / transient attacks**: Kao i sa mnogim mikroarhitekturnim zaštitama, speculative execution ili micro-op fuzije mogu privremeno zaobići provere ili leak-ovati tag bits.
- **Limited to supported regions**: Apple može primenjivati EMTE selektivno, u rizičnijim zonama (kernel, security-critical subsistemi), a ne univerzalno.
---
## Ključna poboljšanja / razlike u odnosu na standardni MTE
Evo poboljšanja i izmena koje Apple naglašava:
| 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 zahteva da pristupi iz tagged regiona ka non-tagged memoriji takođe validiraju znanje o tagu, što otežava zaobilaženje mešanim alokacijama.|
| **Tag confidentiality / secrecy** | Tags might be observable or leaked via side channels | Apple dodaje **Tag Confidentiality Enforcement**, koja pokušava da spreči leak-ovanje vrednosti tag-ova (putem speculative side-channels itd.).|
| **Allocator integration & retagging** | MTE leaves much of allocator logic to software | Apple-ovi secure typed allocators (kalloc_type, xzone malloc, itd.) integrišu se sa EMTE: kada se memorija alocira ili oslobodi, tagovi se upravljaju na finom nivou.|
| **Always-on by default** | In many platforms, MTE is optional or off by default | Apple omogućava EMTE / MIE po defaultu na podržanom hardveru (npr. iPhone 17 / A19) za kernel i mnoge user processes.|
Zbog toga što Apple kontroliše i hardver i softverski stack, može strogo da primeni EMTE, izbegne performansne zamke i zatvori side-channel rupe.
---
## Kako EMTE radi u praksi (Apple / MIE)
Evo opisa visokog nivoa kako EMTE radi u Apple-ovom MIE setup-u:
1. **Tag assignment**
- Kada se memorija alocira (npr. u kernelu ili user space preko secure allocators), dodeljuje se **secret tag** bloku.
- Pointer koji se vraća korisniku ili kernelu sadrži taj tag u visokim bitovima (koristeći TBI / top byte ignore mehanizme).
2. **Tag checking on access**
- Kad se izvrši load ili store koristeći pointer, hardver proverava da li tag u pointeru odgovara tagu memorijskog bloka (allocation tag). Ako se ne poklapa, odmah se javi fault (pošto je sync).
- Pošto je synchronous, ne postoji prozor za “delayed detection”.
3. **Retagging on free / reuse**
- Kada se memorija oslobodi, allocator menja tag bloka (tako da stariji pointeri sa starim tagovima više ne odgovaraju).
- Use-after-free pointer će zbog toga imati stale tag i dovesti do mismatch-a pri pristupu.
4. **Neighbor-tag differentiation to catch overflows**
- Susedne alokacije dobijaju različite tagove. Ako buffer overflow pređe u memoriju suseda, tag mismatch uzrokuje fault.
- Ovo je naročito efikasno za detekciju malih overflow-a koji prelaze granicu.
5. **Tag confidentiality enforcement**
- Apple mora sprečiti leak-ovanje vrednosti tag-ova (jer ako napadač sazna tag, može konstruisati pointere sa ispravnim tagom).
- Uključuje zaštite (mikroarhitekturne / speculative kontrole) da se izbegne leak-ovanje tag bits.
6. **Kernel and user-space integration**
- Apple koristi EMTE ne samo u user-space već i u kernel / OS-critical komponentama (da zaštiti kernel od memory corruption).
- Hardver/OS osiguravaju da se pravila o tagovima primenjuju čak i kada kernel radi u ime user-space procesa.
Pošto je EMTE ugrađen u MIE, Apple koristi EMTE u synchronous modu preko ključnih attack površina, a ne kao opcioni ili debug mod.
---
## Exception handling in XNU
Kada se dogodi **exception** (npr. `EXC_BAD_ACCESS`, `EXC_BAD_INSTRUCTION`, `EXC_CRASH`, `EXC_ARM_PAC`, itd.), **Mach layer** XNU kernela je zadužen da je presretne pre nego što se konvertuje u UNIX-style **signal** (kao `SIGSEGV`, `SIGBUS`, `SIGILL`, ...).
Ovaj proces uključuje više nivoa propagacije i rukovanja exception-om pre nego što stigne do user space-a ili bude pretvoren u BSD signal.
### Exception Flow (High-Level)
1. **CPU triggers a synchronous exception** (npr. nevalidan pointer dereference, PAC failure, illegal instruction, itd.).
2. **Low-level trap handler** se izvršava (`trap.c`, `exception.c` u XNU source).
3. Trap handler poziva **`exception_triage()`**, jezgro Mach exception handling-a.
4. `exception_triage()` odlučuje kako da rutira exception:
- Prvo ka **thread's exception port**.
- Zatim ka **task's exception port**.
- Zatim ka **host's exception port** (često `launchd` ili `ReportCrash`).
Ako nijedan od ovih portova ne obradi exception, kernel može:
- **Konvertovati ga u BSD signal** (za user-space procese).
- **Panic** (za kernel-space exception-e).
### Core Function: `exception_triage()`
Funkcija `exception_triage()` routuje Mach exception-e kroz lanac mogućih handler-a dok jedan ne obradi exception ili dok on ne postane fatalan. Definisana je u `osfmk/kern/exception.c`.
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">c</span></div>
```c
void exception_triage(exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt);
Tipičan tok poziva:
exception_triage() └── exception_deliver() ├── exception_deliver_thread() ├── exception_deliver_task() └── exception_deliver_host()
Ako svi zakažu → obrađuje se pomoću bsd_exception() → prevedeno u signal kao što je SIGSEGV.
Exception Ports
Svaki Mach objekat (thread, task, host) može da registruje exception ports, na koje se šalju exception messages.
Definisani su API-jem:
task_set_exception_ports()
thread_set_exception_ports()
host_set_exception_ports()
Svaki exception port ima:
- mask (koje izuzetke želi da primi)
- port name (Mach port koji prima poruke)
- behavior (kako kernel šalje poruku)
- flavor (koji thread state uključiti)
Debuggeri i rukovanje izuzecima
Debugger (npr. LLDB) postavlja exception port na ciljni task ili thread, obično koristeći task_set_exception_ports().
Kada se desi izuzetak:
- Mach poruka se šalje debugger procesu.
- Debugger može odlučiti da obradi (resume, modifikuje registre, preskoči instrukciju) ili ne obradi izuzetak.
- Ako debugger ne obradi izuzetak, on se propagira na sledeći nivo (task → host).
Tok EXC_BAD_ACCESS
-
Thread dereferencira nevažeći pokazivač → CPU podiže Data Abort.
-
Kernel trap handler poziva
exception_triage(EXC_BAD_ACCESS, ...). -
Poruka se šalje na:
-
Thread port → (debugger može presresti breakpoint).
-
Ako debugger ignoriše → Task port → (process-level handler).
-
Ako se ignoriše → Host port (obično ReportCrash).
- Ako niko ne obradi →
bsd_exception()prevodi uSIGSEGV.
PAC Exceptions
Kada Pointer Authentication (PAC) zakaže (neslaganje potpisa), podiže se poseban Mach izuzetak:
EXC_ARM_PAC(tip)- Codes mogu sadržati detalje (npr. tip ključa, tip pokazivača).
Ako binar ima flag TFRO_PAC_EXC_FATAL, kernel tretira PAC greške kao fatalne, zaobilazeći presretanje od strane debugger-a. Ovo služi da spreči napadače da koriste debuggere za zaobilaženje PAC provera i omogućeno je za platform binaries.
Software Breakpoints
Software breakpoint (int3 na x86, brk na ARM64) se implementira tako što se namerno izazove greška.
Debugger to presreće preko exception porta:
- Modifikuje instrukcioni pokazivač ili memoriju.
- Vraća originalnu instrukciju.
- Nastavlja izvršavanje.
Isti mehanizam omogućava da „uhvatite“ PAC izuzetak — osim ako nije postavljen TFRO_PAC_EXC_FATAL, u kom slučaju nikada ne doseže debugger.
Konverzija u BSD signale
Ako nijedan handler ne prihvati izuzetak:
-
Kernel poziva
task_exception_notify() → bsd_exception(). -
Ovo mapira Mach izuzetke na signale:
| Mach Exception | Signal |
|---|---|
| EXC_BAD_ACCESS | SIGSEGV or SIGBUS |
| EXC_BAD_INSTRUCTION | SIGILL |
| EXC_ARITHMETIC | SIGFPE |
| EXC_SOFTWARE | SIGTRAP |
| EXC_BREAKPOINT | SIGTRAP |
| EXC_CRASH | SIGKILL |
| EXC_ARM_PAC | SIGILL (on non-fatal) |
Ključni fajlovi u XNU source
-
osfmk/kern/exception.c→ Core ofexception_triage(),exception_deliver_*(). -
bsd/kern/kern_sig.c→ Signal delivery logic. -
osfmk/arm64/trap.c→ Low-level trap handlers. -
osfmk/mach/exc.h→ Exception codes and structures. -
osfmk/kern/task.c→ Task exception port setup.
Old Kernel Heap (Pre-iOS 15 / Pre-A12 era)
Kernel je koristio zone allocator (kalloc) podeljen na fiksne "zone."
Svaka zona čuva alokacije samo jedne veličine (size class).
Iz screenshot-a:
| Zone Name | Element Size | Example Use |
|---|---|---|
default.kalloc.16 | 16 bytes | Veoma male kernel strukture, pokazivači. |
default.kalloc.32 | 32 bytes | Male strukture, zaglavlja objekata. |
default.kalloc.64 | 64 bytes | IPC poruke, sitni kernel buffer-i. |
default.kalloc.128 | 128 bytes | Srednji objekti kao delovi OSObject. |
| … | … | … |
default.kalloc.1280 | 1280 bytes | Velike strukture, IOSurface/graphics metadata. |
Kako je radilo:
- Svaki zahtev za alokacijom se zaokruži nagore na najbližu veličinu zone.
(Npr. zahtev od 50 bajtova ide u zonu
kalloc.64). - Memorija u svakoj zoni se čuvala u freelist-u — chunk-ovi koji su oslobođeni od strane kernela vraćali su se u tu zonu.
- Ako bi prelio 64-bajtni buffer, prepisali biste sledeći objekat u istoj zoni.
Zbog toga su bile veoma efikasne tehnike kao što su heap spraying / feng shui: mogli ste predvideti susedne objekte tako što biste prskali alokacije iste veličine.
Freelist
Unutar svake kalloc zone, oslobođeni objekti se nisu vraćali direktno sistemu — odlazili su u freelist, linked list dostupnih chunk-ova.
-
Kada bi chunk bio oslobođen, kernel bi upisao pokazivač na početku tog chunka → adresu sledećeg slobodnog chunka u istoj zoni.
-
Zona je čuvala HEAD pokazivač na prvi slobodan chunk.
-
Alokacija je uvek koristila trenutni HEAD:
-
Pop HEAD (vrati tu memoriju pozivaocu).
-
Ažuriraj HEAD = HEAD->next (smešteno u header-u oslobođenog chunka).
-
Oslobađanje je guralo chunk-ove nazad:
-
freed_chunk->next = HEAD -
HEAD = freed_chunk
Dakle, freelist je bila samo linked lista izgrađena unutar same oslobođene memorije.
Normalno stanje:
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)
Eksploatacija freelist-a
Pošto prvih 8 bajtova free chunk-a = freelist pointer, napadač bi mogao da ga korumpira:
-
Heap overflow u susedni freed chunk → overwrite its “next” pointer.
-
Use-after-free write into a freed object → overwrite its “next” pointer.
Zatim, pri sledećoj alokaciji te veličine:
-
Alokator izbacuje korumpirani chunk.
-
Prati “next” pointer koji je obezbedio napadač.
-
Vraća pointer na proizvoljnu memoriju, omogućavajući fake object primitives ili targeted overwrite.
Vizuelni primer 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 dizajn je pre hardening-a omogućavao veoma efektivnu eksploataciju: predvidivi susedi iz heap sprays, raw pointer freelist links, i nedostatak razdvajanja tipova dozvoljavao je napadačima da eskaliraju UAF/overflow bagove u kontrolu proizvoljne kernel memorije.
Heap Grooming / Feng Shui
Cilj heap grooming-a je da oblikuje raspored heap-a tako da kad napadač pokrene overflow ili use-after-free, meta (victim) objekat bude odmah pored objekta koji kontroliše napadač.
Na taj način, kad dođe do korupcije memorije, napadač može pouzdano prepisati victim objekat kontrolisanim podacima.
Koraci:
- Spray allocations (fill the holes)
- Vremenom se kernel heap fragmentira: neke zone imaju rupe gde su stari objekti bili oslobođeni.
- Napadač prvo pravi mnogo dummy alokacija da popuni te praznine, tako da heap postane „zgusnut“ i predvidiv.
- Force new pages
- Kad su rupe popunjene, sledeće alokacije moraju doći iz novih stranica dodatih u zonu.
- Sveže stranice znače da će objekti biti grupisani zajedno, a ne rasuti po staroj fragmentiranoj memoriji.
- Ovo daje napadaču bolju kontrolu nad susedstvom.
- Place attacker objects
- Napadač ponovo pravi spray, kreirajući mnogo attacker-controlled objekata u tim novim stranicama.
- Ti objekti su predvidivi po veličini i poziciji (pošto svi pripadaju istoj zoni).
- Free a controlled object (make a gap)
- Napadač namerno oslobađa jedan od svojih objekata.
- To pravi „rupu“ u heap-u koju će allocator kasnije ponovo iskoristiti za sledeću alokaciju te veličine.
- Victim object lands in the hole
- Napadač izaziva kernel da alocira victim objekat (onaj koji želi da korumpira).
- Pošto je rupa prvi dostupan slot u freelist-u, victim se postavlja tačno na mesto koje je napadač oslobodio.
- Overflow / UAF into victim
- Sada napadač ima attacker-controlled objekte oko victima.
- Prelivanjem iz jednog od svojih objekata (ili ponovnim korišćenjem freed objekta), može pouzdano prepisati polja victim objekta sa izabranim vrednostima.
Zašto ovo radi:
- Zone allocator predictability: alokacije iste veličine uvek dolaze iz iste zone.
- Freelist behavior: nove alokacije ponovo koriste najnovije oslobođeni chunk prvo.
- Heap sprays: napadač popunjava memoriju predvidivim sadržajem i kontroliše raspored.
- Krajnji rezultat: napadač kontroliše gde victim objekat završi i koji podaci se nalaze pored njega.
Modern Kernel Heap (iOS 15+/A12+ SoCs)
Apple je ojačao allocator i učinio heap grooming mnogo težim:
1. From Classic kalloc to kalloc_type
- Pre: postojala je jedna zona
kalloc.<size>za svaku veličinsku klasu (16, 32, 64, … 1280, itd.). Bilo koji objekat te veličine stavljen je tamo → attacker objekti su mogli sedeti pored privilegovanih kernel objekata. - Sada:
- Kernel objekti se alociraju iz typed zones (
kalloc_type). - Svaki tip objekta (npr.
ipc_port_t,task_t,OSString,OSData) ima svoju namensku zonu, čak i ako su iste veličine. - Mapiranje između tipa objekta ↔ zone se generiše iz kalloc_type system pri kompajliranju.
Napadač više ne može garantovati da će kontrolisani podaci (OSData) završiti pored osetljivih kernel objekata (task_t) iste veličine.
2. Slabs and Per-CPU Caches
- Heap je podeljen na slabs (stranice memorije podeljene na fiksne chunk-ove za tu zonu).
- Svaka zona ima per-CPU cache da smanji contentiju.
- Putanja alokacije:
- Pokušaj iz per-CPU cache.
- Ako je prazno, uzmi iz global freelist-a.
- Ako je freelist prazan, alociraj novi slab (jedna ili više stranica).
- Prednost: ova decentralizacija čini heap sprays manje determinističkim, pošto alokacije mogu biti zadovoljene iz cache-a različitih CPU-ova.
3. Randomization inside zones
- Unutar zone, oslobođeni elementi se ne vraćaju u prost FIFO/LIFO redu.
- Modern XNU koristi encoded freelist pointers (safe-linking stil, uvedeno oko iOS 14).
- Svaki freelist pointer je XOR-enkodiran sa per-zone secret cookie.
- Ovo sprečava napadače da falsifikuju lažni freelist pointer ako dobiju write primitive.
- Neke alokacije su randomizovane u pozicioniranju unutar slaba, tako da spray ne garantuje susedstvo.
4. Guarded Allocations
- Određeni kritični kernel objekti (npr. credentials, task strukture) se alociraju u guarded zones.
- Te zone ubacuju guard pages (ne-mapirane stranice) između slab-ova ili koriste redzones oko objekata.
- Bilo koji overflow u guard page izaziva fault → trenutni panic umesto tihi korupcije.
5. Page Protection Layer (PPL) and SPTM
- Čak i ako kontrolišeš freed objekat, ne možeš modifikovati čitavu kernel memoriju:
- PPL (Page Protection Layer) nameće da određene regije (npr. code signing data, entitlements) budu read-only čak i za sam kernel.
- Na A15/M2+ uređajima, ovu ulogu zamenjuju/pojačavaju SPTM (Secure Page Table Monitor) + TXM (Trusted Execution Monitor).
- Ovi hardware-primorani slojevi znače da napadači ne mogu da eskaliraju iz jedne heap korupcije u proizvoljno patch-ovanje kritičnih sigurnosnih struktura.
- (Dodato / Pojačano): takođe se koristi PAC (Pointer Authentication Codes) u kernelu za zaštitu pokazivača (posebno funkcijskih pointera, vtable-ova) tako da njihovo falsifikovanje ili korupcija postaju teži.
- (Dodato / Pojačano): zone mogu primenjivati zone_require / zone enforcement, tj. da objekat koji je oslobođen može biti vraćen samo kroz ispravnu typed zonu; nevažeći cross-zone frees mogu izazvati panic ili biti odbijeni. (Apple nagoveštava ovo u svojim postovima o memory safety)
6. Large Allocations
- Neće sve alokacije ići kroz
kalloc_type. - Veći zahtevi (iznad ~16 KB) zaobilaze typed zone i služe se direktno iz kernel VM (kmem) putem page alokacija.
- Oni su manje predvidivi, ali i manje eksploatabilni, pošto ne dele slab-ove sa drugim objektima.
7. Allocation Patterns Attackers Target
Čak i uz ove zaštite, napadači i dalje traže:
- Reference count objects: ako možeš menjati retain/release brojače, možeš izazvati use-after-free.
- Objects with function pointers (vtables): korumpovanje jednog i dalje daje kontrolu toka izvršavanja.
- Shared memory objects (IOSurface, Mach ports): i dalje su mete jer predstavljaju most user ↔ kernel.
Međutim — za razliku od ranije — ne možeš samo spray-ovati OSData i očekivati da će biti pored task_t. Potreban ti je type-specific bugs ili info leaks da bi uspeo.
Example: Allocation Flow in Modern Heap
Pretpostavimo da userspace pozove IOKit da alocira OSData objekat:
- Type lookup →
OSDatamapira na zonukalloc_type_osdata(veličina 64 bajta). - Proveri per-CPU cache za slobodne elemente.
- Ako pronađeno → vrati jedan.
- Ako je prazno → idi na global freelist.
- Ako je freelist prazan → alociraj novi slab (stranica od 4KB → 64 chunka od 64 bajta).
- Vrati chunk pozivaocu.
Freelist pointer protection:
- Svaki oslobođeni chunk čuva adresu narednog slobodnog chunka, ali enkodiranu sa secret key.
- Prepisivanje tog polja attacker podacima neće raditi osim ako ne poznaješ ključ.
Comparison Table
| Feature | Old Heap (Pre-iOS 15) | Modern Heap (iOS 15+ / A12+) |
|---|---|---|
| Allocation granularity | Fixed size buckets (kalloc.16, kalloc.32, etc.) | Size + type-based buckets (kalloc_type) |
| Placement predictability | High (same-size objects side by side) | Low (same-type grouping + randomness) |
| Freelist management | Raw pointers in freed chunks (easy to corrupt) | Encoded pointers (safe-linking style) |
| Adjacent object control | Easy via sprays/frees (feng shui predictable) | Hard — typed zones separate attacker objects |
| Kernel data/code protections | Few hardware protections | PPL / SPTM protect page tables & code pages, and PAC protects pointers |
| Allocation reuse validation | None (freelist pointers raw) | zone_require / zone enforcement |
| Exploit reliability | High with heap sprays | Much lower, requires logic bugs or info leaks |
| Large allocations handling | All small allocations managed equally | Large ones bypass zones → handled via VM |
Modern Userland Heap (iOS, macOS — type-aware / xzone malloc)
U novijim Apple OS verzijama (posebno iOS 17+), Apple je uvodio sigurniji userland allocator, xzone malloc (XZM). Ovo je user-space analog kernel-ovog kalloc_type, primenjujući type awareness, izolaciju metadata i memory tagging zaštite.
Goals & Design Principles
- Type segregation / type awareness: grupisati alokacije po tipu ili upotrebi (pointer vs data) da se spreči type confusion i cross-type reuse.
- Metadata isolation: odvojiti heap metadata (npr. free lists, size/state bita) od payload-a objekata tako da out-of-bounds write manje verovatno korumpira metadata.
- Guard pages / redzones: ubaciti ne-mapirane stranice ili padding oko alokacija da bi se uhvatili overflows.
- Memory tagging (EMTE / MIE): raditi u kombinaciji sa hardware tagging-om da se detektuju use-after-free, out-of-bounds i nevalidni pristupi.
- Scalable performance: održavati nizak overhead, izbegavati preveliku fragmentaciju i podržati mnogobrojne alokacije u sekundi sa niskom latencijom.
Architecture & Components
Ispod su glavni elementi xzone allocatora:
Segment Groups & Zones
- Segment groups particionišu address space po kategorijama upotrebe: npr.
data,pointer_xzones,data_large,pointer_large. - Svaka segment group sadrži segments (VM opsege) koji hostuju alokacije za tu kategoriju.
- Povezan sa svakim segmentom je metadata slab (odvojen VM area) koji čuva metadata (npr. free/used bitove, size klase) za taj segment. Ova out-of-line (OOL) metadata osigurava da metadata nije pomešana sa payload-om objekata, smanjujući šansu za korupciju usled overflows.
- Segmenti se seciraju u chunks (slice-ove) koji dalje bivaju podeljeni u blocks (alokacione jedinice). Chunk je vezan za specifičnu size klasu i segment group (tj. svi block-ovi u chunk-u dele istu veličinu i kategoriju).
- Za male / srednje alokacije koristiće se fiksno-veličinski chunks; za velike/ogromne, moguće je mapiranje posebno.
Chunks & Blocks
- Chunk je region (često nekoliko stranica) posvećen alokacijama jedne size klase unutar grupe.
- Unutar chunk-a, blocks su slotovi dostupni za alokacije. Oslobođeni block-ovi su praćeni kroz metadata slab — npr. putem bitmap-a ili free list-ova koji su pohranjeni out-of-line.
- Između chunk-ova (ili unutar njih) mogu biti ubačeni guard slices / guard pages (npr. ne-mapirani slice-ovi) da se detektuju out-of-bounds write.
Type / Type ID
- Svaka lokacija alokacije (ili poziv na malloc, calloc, itd.) je povezana sa type identifier-om (tipa
malloc_type_id_t) koji enkodira koji tip objekta se alocira. Taj type ID se prosleđuje allocator-u, koji ga koristi da izabere zonu / segment za alokaciju. - Zbog toga, čak i ako dve alokacije imaju istu veličinu, mogu ići u potpuno različite zone ako su tipovi različiti.
- U ranim iOS 17 verzijama, ne svi API-ji (npr. CFAllocator) su bili potpuno type-aware; Apple je adresirao neke od tih slabosti u iOS 18.
Allocation & Freeing Workflow
Evo visokog nivo toka kako alokacija i oslobađanje rade u xzone:
- Poziva se malloc / calloc / realloc / typed alloc sa veličinom i type ID.
- Allocator koristi type ID da izabere odgovarajući segment group / zonu.
- Unutar te zone/segmenta traži chunk koji ima slobodne block-ove tražene veličine.
- Može konsultovati local caches / per-thread pools ili free block lists iz metadata.
- Ako nema slobodnog block-a, može alocirati novi chunk u toj zoni.
- Metadata slab se ažurira (free bit se briše, bookkeeping).
- Ako je memory tagging (EMTE) uključen, vraćenom block-u se dodeljuje tag, a metadata se ažurira da reflektuje njegov „live“ status.
- Kada se pozove
free():
- Block se označava kao oslobođen u metadata (putem OOL slab-a).
- Block može biti stavljen u free list ili pooled za ponovnu upotrebu.
- Opcionalno, sadržaj block-a može biti očišćen ili poison-ovan da se smanji curenje podataka ili exploatacija use-after-free.
- Hardware tag povezan sa block-om može biti invalidiran ili re-tag-ovan.
- Ako ceo chunk postane slobodan (svi block-ovi oslobođeni), allocator može reclaim taj chunk (unmap-ovati ga ili vratiti OS-u) pod pritiskom memorije.
Security Features & Hardening
Ovo su odbrane ugrađene u moderni userland xzone:
| Feature | Purpose | Notes |
|---|---|---|
| Metadata decoupling | Prevent overflow from corrupting metadata | Metadata resides in separate VM region (metadata slab) |
| Guard pages / unmapped slices | Catch out-of-bounds writes | Pomaže detekciji buffer overflows umesto tihog korumpiranja susednih blokova |
| Type-based segregation | Prevent cross-type reuse & type confusion | Čak i iste-size alokacije iz različitih tipova idu u različite zone |
| Memory Tagging (EMTE / MIE) | Detect invalid access, stale references, OOB, UAF | xzone radi u dogovoru sa hardware EMTE u synchronous modu (“Memory Integrity Enforcement”) |
| Delayed reuse / poisoning / zap | Reduce chance of use-after-free exploitation | Freed blocks mogu biti poison-ovani, zero-ovani ili stavljeni u karantin pre ponovne upotrebe |
| Chunk reclamation / dynamic unmapping | Reduce memory waste and fragmentation | Celokupni chunk-ovi mogu biti unmap-ovani kada su neiskorišćeni |
| Randomization / placement variation | Prevent deterministic adjacency | Block-ovi u chunk-u i izbor chunk-a mogu imati randomizovane aspekte |
| Segregation of “data-only” allocations | Separate allocations that don’t store pointers | Smanjuje kontrolu napadača nad metadata ili kontrolnim poljima |
Interaction with Memory Integrity Enforcement (MIE / EMTE)
- Apple-ov MIE (Memory Integrity Enforcement) je hardware + OS okvir koji unosi Enhanced Memory Tagging Extension (EMTE) u uvek-uključen, sinhroni režim preko glavnih napadnih površina.
- xzone allocator je fundamentalna osnova MIE u user space: alokacije urađene preko xzone dobijaju tagove, a pristupi se proveravaju od strane hardware-a.
- U MIE, allocator, dodela tagova, upravljanje metadata i enforcement konfidencijalnosti tagova su integrisani da osiguraju da se greške u memoriji (npr. stale reads, OOB, UAF) odmah detektuju, a ne iskorišćavaju naknadno.
Ako želiš, mogu takođe da generišem cheat-sheet ili dijagram xzone internals za tvoju knjigu. Želiš li da to uradim sledeće? ::contentReference[oai:20]{index=20}
(Old) Physical Use-After-Free via IOSurface
Ghidra Install BinDiff
Preuzmi BinDiff DMG sa https://www.zynamics.com/bindiff/manual i instaliraj ga.
Otvori Ghidra sa ghidraRun i idi na File --> Install Extensions, pritisni add dugme i selektuj path /Applications/BinDiff/Extra/Ghidra/BinExport i klikni OK i instaliraj ga čak i ako postoji mismatch verzije.
Using BinDiff with Kernel versions
- Idi na stranicu https://ipsw.me/ i preuzmi iOS verzije koje želiš da diff-uješ. To će biti
.ipswfajlovi. - Decompress-uj dok ne dobiješ bin format kernelcache-a obe
.ipswdatoteke. Imaš informacije kako to da uradiš u:
macOS Kernel Extensions & Kernelcache
- Otvori Ghidra sa
ghidraRun, kreiraj novi projekat i učitaj kernelcache-ove. - Otvori svaki kernelcache tako da budu automatski analizirani od strane Ghidra.
- Zatim, u project Window-u Ghidra, desni klik na svaki kernelcache, izaberi
Export, izaberi formatBinary BinExport (v2) for BinDiffi eksportuj ih. - Otvori BinDiff, kreiraj novi workspace i dodaj novi diff označivši kao primary fajl kernelcache koji sadrži ranjivost i kao secondary fajl patched kernelcache.
Finding the right XNU version
Ako želiš da proveriš ranjivosti u određenoj verziji iOS-a, možeš proveriti koja XNU release verzija taj iOS koristi na [https://www.theiphonewiki.com/wiki/kernel]https://www.theiphonewiki.com/wiki/kernel).
Na primer, verzije 15.1 RC, 15.1 i 15.1.1 koriste verziju Darwin Kernel Version 21.1.0: Wed Oct 13 19:14:48 PDT 2021; root:xnu-8019.43.1~1/RELEASE_ARM64_T8006.
iMessage/Media Parser Zero-Click Chains
Imessage Media Parser Zero Click Coreaudio Pac Bypass
tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
HackTricks