iOSのエクスプロイト

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

iOS のエクスプロイト緩和策

1. Code Signing / ランタイム署名検証

初期(iPhone OS → iOS)から導入 これは基本的な防御の一つです:すべての実行可能コード(アプリ、動的ライブラリ、JIT生成コード、拡張、framework、キャッシュ)は Apple の信頼のルートである証明書チェーンで暗号的に署名されている必要があります。ランタイムでは、バイナリをメモリにロードする前(あるいは特定の境界を越えてジャンプする前)に署名が検査されます。コードが改変(ビット反転、パッチ)されているか、署名がない場合はロードが失敗します。

  • 阻止するもの:エクスプロイトチェーンの「古典的なペイロードドロップ+実行」段階;任意コード注入;既存バイナリを改変して悪意あるロジックを挿入する行為。
  • 仕組みの詳細
  • Mach-O ローダ(と動的リンカ)はコードページ、セグメント、entitlements、team ID、および署名がファイル内容をカバーしているかをチェックする。
  • JIT キャッシュや動的に生成されたコードのようなメモリ領域については、Apple はページが署名されているか特別な API を通じて検証されることを要求する(例:code-sign チェックを伴う mprotect)。
  • 署名には entitlements と識別子が含まれ、OS は特定の API や特権機能が特定の entitlement を必要とすることを強制し、それらは偽造できない。
Example あるエクスプロイトがプロセス内でコード実行を得て、ヒープにシェルコードを書き込みそこへジャンプしようとするとします。iOS では、そのページは実行可能にフラグされるだけでなく code-signature の制約を満たす必要があります。シェルコードは Apple の証明書で署名されていないため、ジャンプは失敗するか、そのメモリ領域を実行可能にする操作はシステムに拒否されます。

2. CoreTrust

iOS 14 以降の時期に導入(あるいは新しいデバイス / 後の iOS で段階的に) CoreTrust はバイナリの ランタイム署名検証 を行うサブシステムで、ローカルのユーザーランドの信頼ストアに頼らず Apple のルート証明書 に対して検証します。

  • 阻止するもの:インストール後のバイナリ改ざん、システムライブラリやユーザアプリを差し替え・パッチして永続性を得ようとする jailbreak 手法、信頼されたバイナリを悪意あるものに置き換えてシステムを騙す行為。
  • 仕組みの詳細
  • CoreTrust はローカルの信頼データベースや証明書キャッシュを信用する代わりに、Apple のルートに照会するか、セキュアなチェーンで中間証明書を検証する。
  • 既存バイナリのファイルシステム上の改変(例:書き換え)を検出して拒否する。
  • entitlements、team ID、コード署名フラグ、その他のメタデータをロード時にバイナリに紐付けて検証する。
Example jailbreak が `SpringBoard` や `libsystem` をパッチ版に置き換えて永続性を得ようとしても、OS のローダや CoreTrust がチェックすると署名不一致(あるいは entitlements の変更)を検出して実行を拒否します。

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

多くの OS で早期に導入;iOS も長らく NX-bit / w^x を採用 DEP は writable(データ用)にマークされたページが実行不可、実行可能にマークされたページが書き込み不可であることを強制します。単純にヒープやスタック領域にシェルコードを書き込んで実行することはできません。

  • 阻止するもの:直接的なシェルコード実行;古典的なバッファオーバーフロー→注入シェルコードへのジャンプ。
  • 仕組みの詳細
  • MMU/ページテーブルの保護フラグが分離を強制する。
  • writable なページを実行可能にしようとするとシステムチェックが行われ(禁止されるかコード署名承認が必要になる)。
  • 多くの場合、ページを実行可能にするには追加の制約やチェックを課す OS API 経由が必要になる。
Example オーバーフローでシェルコードをヒープに書き込み、攻撃者が `mprotect(heap_addr, size, PROT_EXEC)` を試みる。しかしシステムは拒否するか、新しいページが code-sign 制約を満たすことを検証するため、シェルコードは実行できません。

4. Address Space Layout Randomization (ASLR)

iOS の大まかな導入時期:iOS 4–5 あたり ASLR はライブラリ、ヒープ、スタックなど主要なメモリ領域のベースアドレスを各プロセス起動ごとにランダム化します。ガジェットのアドレスは実行ごとに移動します。

  • 阻止するもの:ROP/JOP のガジェットアドレスをハードコードする手法;静的なエクスプロイトチェーン;既知オフセットへの盲目的ジャンプ。
  • 仕組みの詳細
  • 各ロードされたライブラリ/モジュールはランダム化されたオフセットで再配置される。
  • スタックやヒープのベースポインタは(ある程度のエントロピー内で)ランダム化される。
  • 場合によっては他の領域(例えば mmap 割当て)もランダム化される。
  • 情報-leak 緩和策と組み合わせることで、攻撃者はまずランタイムでアドレスやポインタを leak してベースを特定する必要がある。
Example ROP チェーンが `0x….lib + offset` にあるガジェットを期待していても、`lib` は実行ごとに再配置されるためハードコードされたチェーンは失敗します。エクスプロイトはモジュールのベースアドレスを先に leak してからガジェットアドレスを算出しなければなりません。

5. Kernel Address Space Layout Randomization (KASLR)

導入時期:iOS 5 / iOS 6 あたり ユーザ ASLR に相当し、KASLR はブート時に カーネルテキスト やその他カーネル構造のベースをランダム化します。

  • 阻止するもの:カーネルレベルのエクスプロイトで固定されたカーネルコードやデータ位置に依存するもの;静的なカーネルエクスプロイト。
  • 仕組みの詳細
  • 各ブートでカーネルのベースアドレスが(ある範囲内で)ランダム化される。
  • task_structvm_map などのカーネルデータ構造も移動またはオフセットされる可能性がある。
  • 攻撃者はカーネルポインタを leak したり情報開示脆弱性を利用してオフセットを算出する必要がある。
Example ローカル脆弱性が `KERN_BASE + offset` にある vtable の関数ポインタを破壊しようとしても、`KERN_BASE` が不明なため攻撃者はまずそれを leak(例:read primitive を通じて)して正しいアドレスを計算する必要があります。

6. Kernel Patch Protection (KPP / AMCC)

導入時期:新しい iOS / Aシリーズハードウェア(大体 iOS 15–16 以降や新しいチップ) KPP(別名 AMCC)はカーネルテキストページの整合性を継続的に監視します(ハッシュやチェックサムを用いる)。改変(パッチ、インラインフック、コード修正)を検知するとカーネルパニックや再起動を引き起こします。

  • 阻止するもの:永続的なカーネルパッチ(カーネル命令の改変)、インラインフック、静的な関数上書き。
  • 仕組みの詳細
  • ハードウェアまたはファームウェアモジュールがカーネルテキスト領域を監視する。
  • 定期的または要求時にページを再ハッシュし、期待値と比較する。
  • 悪意のある改変が検出され、正当な更新ウィンドウ外で不一致が発生した場合はデバイスをパニックさせる(持続的な悪意あるパッチを避けるため)。
  • 攻撃者は検出ウィンドウを回避するか、正当なパッチ経路を利用する必要がある。
Example エクスプロイトが `memcmp` のプロローグをパッチして呼び出しを傍受しようとしても、KPP はコードページのハッシュが期待値と異なることを検出してカーネルパニックを引き起こし、パッチが安定する前にデバイスをクラッシュさせます。

7. Kernel Text Read‐Only Region (KTRR)

導入時期:近年の SoC(おおむね A12 以降のハードウェア) KTRR はハードウェアで強制される仕組みです:カーネルテキストがブートの早期にロックされると、EL1(カーネル)からの書き込みが不可能になり、その後のコードページへの書き込みを防ぎます。

  • 阻止するもの:ブート後のカーネルコードの改変(EL1 権限でのパッチやインプレースコード注入)。
  • 仕組みの詳細
  • ブート中(secure/bootloader ステージ)にメモリコントローラやセキュアハードウェアユニットがカーネルテキストを含む物理ページを read-only にマークする。
  • エクスプロイトが完全なカーネル権限を得ても、これらページを書き換えることはできない。
  • これらを変更するには、ブートチェーン自体を侵害するか KTRR を破壊する必要がある。
Example 特権昇格エクスプロイトが EL1 にジャンプしてカーネル関数にトランポリンを書き込もうとしても、KTRR によってページが read-only にロックされているため書き込みは失敗するかフォルトが発生し、パッチは適用されません。

8. Pointer Authentication Codes (PAC)

ハードウェアとしては ARMv8.3 で導入、Apple は A12 / iOS ~12+ から採用

  • PAC は ARMv8.3-A で導入されたハードウェア機能で、ポインタ値(リターンアドレス、ファンクションポインタ、一部のデータポインタ)の改竄を検出するため、ポインタの未使用上位ビットに小さな暗号署名(「MAC」)を埋め込みます。
  • 署名(「PAC」)はポインタ値と modifier(コンテキスト値、例:スタックポインタや識別用データ)に基づいて計算されます。これにより同じポインタ値でもコンテキストが異なれば異なる PAC になります。
  • 使用時には、ポインタをデリファレンスしたりブランチする前に authenticate 命令が PAC を検証します。検証が成功すれば PAC は剥がされ純粋なポインタが得られ、無効ならポインタは「poisoned」になるかフォルトが発生します。
  • PAC を生成・検証する鍵は特権レジスタ(EL1、カーネル)に保管され、ユーザモードから直接読み出すことはできません。
  • 多くのシステムで 64 ビット中すべてをアドレスに使っていない(例:48 ビットアドレス空間)ため、上位ビットに PAC を収納しても有効アドレスに影響しない場合があります。

アーキテクチャ的基礎と鍵の種類

  • ARMv8.3 は 5 つの 128-bit 鍵(それぞれが 2 つの 64-bit システムレジスタで実装される)を導入します。

  • APIAKey — instruction pointer 用(ドメイン “I”, key A)

  • APIBKey — instruction pointer の 2 番目の鍵(“I”, key B)

  • APDAKey — data pointer 用(“D”, key A)

  • APDBKey — data pointer 用(“D”, key B)

  • APGAKey — generic(ポインタ以外のデータや汎用用途)用

  • これらの鍵は特権システムレジスタに格納され(EL1/EL2 などでのみアクセス可能)、ユーザモードからはアクセスできません。

  • PAC は暗号関数で計算され(ARM は QARMA を示唆)、次を入力として使います:

  1. ポインタ値(正規化された部分)
  2. modifier(コンテキスト値、例:salt)
  3. 秘密鍵
  4. 内部のチュークロジック もし算出された PAC がポインタ上位ビットに格納されているものと一致すれば、認証は成功します。

命令ファミリ

命名規則は:PAC / AUT / XPAC、続いてドメイン文字です。

  • PACxx 命令はポインタに署名して PAC を挿入します
  • AUTxx 命令は認証して PAC を剥がします(検証+剥離)
  • XPACxx 命令は検証せずに剥がします

ドメイン / サフィックス:

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

(注:上の mnemonic やアセンブリ例はコード命令なので翻訳していません。)

いくつかの短縮 / エイリアス形式があります:

  • PACIASPPACIA X30, SP の省略形(リンクレジスタを SP を modifier にして署名)
  • AUTIASPAUTIA X30, SP(リンクレジスタを SP で認証)
  • RETAA, RETAB(認証して戻る)、BLRAA(認証して分岐)などの組み合わせ命令は ARM 拡張/コンパイラサポートで存在します。
  • 修飾子がゼロのバリアント:PACIZA / PACIZB のように修飾子が暗黙的にゼロになるものもあります。

Modifiers

修飾子の主目的は PAC を特定のコンテキストに結びつけることで、同じアドレスが異なるコンテキストで署名されると異なる PAC になるようにすることです。ハッシュに salt を加えるようなものです。

したがって:

  • modifier はコンテキスト値(別のレジスタ)で、PAC 計算に混ぜられます。典型的選択肢:スタックポインタ(SP)、フレームポインタ、オブジェクト ID など。
  • リターンアドレス署名で SP を modifier に使うのは一般的です:PAC は特定のスタックフレームに結びつくため、異なるフレームで LR を再利用しようとすると modifier が変わり、PAC の検証が失敗します。
  • 同じポインタ値でも異なる modifier で署名すれば異なる PAC になる。
  • modifier は必ずしも秘密である必要はないが、理想的には攻撃者に制御されない値であるべきです。
  • 意味のある modifier が存在しない場合、ゼロや暗黙の定数を使う形式もある。

Apple / iOS / XNU におけるカスタマイズ & 観察

  • Apple の PAC 実装は ブートごとの diversifier を含み、鍵やチュークがブート毎に変わるためブートをまたいだ再利用を防ぐ。
  • クロスドメイン緩和策を含み、user モードで署名された PAC が容易に kernel モードで再利用されないようにしている。
  • Apple Silicon(M1 以降)のリバースで、9 種類の modifier 型や Apple 固有の鍵制御用システムレジスタがあることが示された。
  • Apple は多くのカーネルサブシステムで PAC を使用している:リターンアドレス署名、カーネルデータのポインタ整合性、署名済みスレッドコンテキストなど。
  • Google Project Zero は、強力なメモリ read/write プリミティブがある場合にカーネル PAC を偽造できる可能性(A鍵向け)を A12 世代で示したが、Apple はその多くの経路を修正した。

PAC のバイパス

  1. カーネルモード PAC:理論上と現実のバイパス
  • カーネル PAC の鍵とロジックは厳格に制御されている(特権レジスタ、diversifier、ドメイン分離)ため、任意の署名済みカーネルポインタを偽造するのは非常に困難です。
  • Azad の 2020 年の報告では iOS 12–13 において部分的バイパス(署名ガジェットの利用、署名済み状態の再利用、保護されていない間接分岐など)をいくつか見つけたが、汎用的な完全バイパスはなかったと報告しています。 bazad.github.io
  • Apple のカスタマイズ(“Dark Magic”)は攻撃可能面をさらに狭めている(ドメイン切替、鍵ごとの有効化ビット等)。 i.blackhat.com
  • Apple silicon(M1/M2)上での kernel PAC bypass CVE-2023-32424 のような既知のバイパスもある(Zecao Cai 他報告)。 i.blackhat.com
  • しかしこれらのバイパスは多くの場合非常に特定のガジェットや実装バグに依存しており、一般的な回避策ではない。

したがってカーネル PAC は「非常に堅牢」と見なされていますが、完璧ではありません。

  1. ユーザモード/ランタイム PAC バイパス技術

これらはより一般的で、PAC の適用やランタイムフレームワークの実装不備を突くものです。以下にクラスごとの例を示します。

2.1 Shared Cache / A key の問題

  • dyld shared cache はシステムフレームワークやライブラリが大きな事前リンク済みブロブとしてまとめられたものです。広く共有されるため、shared cache 内の関数ポインタは「事前に署名」され多くのプロセスで使われます。攻撃者はこれらの既に署名されたポインタを「PAC オラクル」として狙います。

  • 一部のバイパス技術は shared cache 内にある A-key 署名済みポインタを抽出・再利用し、ガジェットと組み合わせて PAC を回避します。

  • “No Clicks Required” の講演は shared cache 上にオラクルを構築して相対アドレスを推定し、署名済みポインタと組み合わせて PAC を回避する手法を説明しています。 saelo.github.io

  • またユーザ空間での shared library からの関数ポインタの import が PAC で十分に保護されていない事例があり、攻撃者が関数ポインタを変更せずに取得して利用できる場合がありました(Project Zero のバグエントリ)。 bugs.chromium.org

2.2 dlsym(3) / 動的シンボル解決

  • 既知のバイパスの一つは dlsym() を呼び出して すでに署名された 関数ポインタ(A-key で署名されたもの、diversifier がゼロ)を取得し、それを使用する方法です。dlsym が合法的に署名されたポインタを返すため、これを使うことで PAC を偽造する必要がなくなります。

  • Epsilon のブログはこの種のバイパスを詳述しており、dlsym("someSym") が署名済みポインタを返し間接呼び出しに使える事例を説明しています。 blog.epsilon-sec.com

  • Synacktiv の「iOS 18.4 — dlsym considered harmful」では、iOS 18.4 におけるバグを記述しており、dlsym 経由で解決された一部のシンボルが不正に署名される(あるいは diversifier にバグがある)ことで意図しない PAC バイパスを招く事例を示しています。 Synacktiv

  • dyld のロジックでは、result->isCode のとき返されるポインタを __builtin_ptrauth_sign_unauthenticated(..., key_asia, 0) のようにコンテキストゼロで署名して返す実装がある、という報告があります。 blog.epsilon-sec.com

したがって、dlsym はユーザモード PAC バイパスの頻出ベクタです。

2.3 その他の DYLD / ランタイム再配置

  • DYLD ローダや動的再配置のロジックは複雑で、一時的にページを read/write としてマップして再配置を行い、その後 read-only に戻すようなウィンドウを持つことがあります。攻撃者はこれらの時間窓を悪用します。Synacktiv の発表は、動的再配置に基づくタイミング攻撃で PAC を回避する「Operation Triangulation」を説明しています。 Synacktiv

  • DYLD のページは現在 SPRR / VM_FLAGS_TPRO のような保護で守られていますが、以前のバージョンではガードが弱かった例があります。 Synacktiv

  • WebKit のエクスプロイトチェーンでは、DYLD ローダが PAC バイパスのターゲットになることが多く、再配置やインターポーザフックを利用した攻撃が多く報告されています。 Synacktiv

2.4 NSPredicate / NSExpression / ObjC / SLOP

  • ユーザランドのエクスプロイトチェーンでは、Objective-C ランタイムのメソッド(NSPredicateNSExpressionNSInvocation など)を使って制御フローを巧妙に運ぶことが多いです。

  • PAC 導入前の古い iOS では、fake NSInvocation オブジェクトを使って任意のセレクタを制御メモリ上で呼び出す手法が使われていました。PAC により修正が必要になりましたが、SLOP(SeLector Oriented Programming)技法は PAC 下でも拡張して使われています。 Project Zero

  • 元の SLOP では偽の invocation を作って ObjC 呼び出しを連鎖させることができました;バイパスは ISA やセレクタポインタが常に完全に PAC 保護されているわけではない点を突くことに依存していました。 Project Zero

  • ポインタ認証が部分的にしか適用されていない環境では、メソッド/セレクタ/ターゲットポインタが常に PAC 保護されていない場合があり、バイパスの余地を生みます。

Example Flow

Example Signing & Authenticating ``` ; Example: function prologue / return address protection my_func: stp x29, x30, [sp, #-0x20]! ; push frame pointer + LR mov x29, sp PACIASP ; sign LR (x30) using SP as modifier ; … body … mov sp, x29 ldp x29, x30, [sp], #0x20 ; restore AUTIASP ; authenticate & strip PAC ret

; Example: indirect function pointer stored in a struct ; suppose X1 contains a function pointer PACDA X1, X2 ; sign data pointer X1 with context X2 STR X1, [X0] ; store signed pointer

; later retrieval: LDR X1, [X0] AUTDA X1, X2 ; authenticate & strip BLR X1 ; branch to valid target

; Example: stripping for comparison (unsafe) LDR X1, [X0] XPACI X1 ; strip PAC (instruction domain) CMP X1, #some_label_address BEQ matched_label

</details>

<details>
<summary>例</summary>
バッファオーバーフローはスタック上のリターンアドレスを上書きします。攻撃者はターゲットのgadgetアドレスを書き込みますが、正しいPACを計算できないことがあります。関数が戻ると、CPUの`AUTIA`命令がPACの不一致でフォルトします。チェーンは失敗します。
Project ZeroによるA12 (iPhone XS) の解析は、AppleのPACの使われ方と、攻撃者がメモリの読み書きプリミティブを持つ場合にPACを偽造する手法を示しました。
</details>


### 9. **Branch Target Identification (BTI)**
**Introduced with ARMv8.5 (later hardware)**
BTIは**間接ブランチのターゲット**をチェックするハードウェア機能です: `blr` や間接的なcall/jumpを実行する際、ターゲットは**BTI landing pad**(`BTI j` または `BTI c`)で始まる必要があります。landing pad を持たないgadgetアドレスにジャンプすると例外が発生します。

LLVMの実装メモはBTI命令の三つの変種と、それらがどのブランチ種にマップされるかを示しています。

| BTI Variant | 許可するもの(どのブランチ種か) | 典型的な配置 / ユースケース |
|-------------|----------------------------------------|-------------------------------|
| **BTI C** | *call*スタイルの間接ブランチのターゲット(例: `BLR`, または X16/X17 を使う `BR`) | 間接呼び出しされる可能性のある関数のエントリに置く |
| **BTI J** | *jump*スタイルのブランチのターゲット(例: tail call に使われる `BR`) | ジャンプテーブルやtail-callから到達可能なブロックの先頭に置く |
| **BTI JC** | C と J の両方の役割を持つ | call でも jump でもターゲットにできる |

- branch target enforcement でコンパイルされたコードでは、コンパイラは各有効な間接ブランチターゲット(関数の先頭やジャンプで到達可能なブロック)にBTI命令(C, J, または JC)を挿入し、間接ブランチがそれらの場所にのみ成功するようにします。
- **直接ブランチ / calls**(固定アドレスの `B`, `BL`)はBTIによって制限されません。前提はコードページが信頼されており攻撃者がそれらを変更できないということ(したがって直接ブランチは安全)です。
- また、**RET / return** 命令は通常BTIで制限されません。returnアドレスはPACやリターン署名機構で保護されているためです。

#### メカニズムと強制

- CPUが「guarded / BTI-enabled」とマークされたページ内の**間接ブランチ(`BLR` / `BR`)**をデコードするとき、ターゲットアドレスの最初の命令が許可されたBTI(C, J, または許される場合はJC)かどうかをチェックします。そうでない場合、**Branch Target Exception** が発生します。
- BTI命令のエンコーディングは、以前のARMバージョンでNOP用に予約されていたオペコードを再利用するように設計されています。したがって、BTI対応のバイナリは下位互換性を保ち、BTI非対応ハードウェアではこれらの命令はNOPとして動作します。
- BTIを挿入するコンパイラパスは、必要な場所にのみ挿入します:間接的に呼び出される可能性のある関数や、ジャンプから到達される基本ブロックなど。
- 一部のパッチやLLVMのコードは、BTIがすべての基本ブロックに挿入されるわけではなく、潜在的なブランチターゲット(例: switch / jump table からのターゲット)にのみ挿入されることを示しています。

#### BTI と PAC の相乗効果

PACはポインタ値(ソース)を保護し—間接コール/リターンのチェーンが改ざんされていないことを保証します。

BTIは有効なポインタであっても、正しくマークされたエントリポイントのみをターゲットにできるようにします。

組み合わせると、攻撃者は正しいPACを持つ有効なポインタに加えて、ターゲットがBTIでマークされている必要があります。これによりgadgetを構築する難易度が上がります。

#### 例


<details>
<summary>例</summary>
エクスプロイトが`0xABCDEF`のgadgetにピボットしようとしますが、その先頭が`BTI c`で始まっていません。CPUは`blr x0`を実行するときにターゲットをチェックし、有効なlanding padが含まれていないためフォルトします。したがって、BTIプレフィックスを含まない多くのgadgetは使用不能になります。
</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** で導入された機能で、**特権コード**(EL1 または EL2)が**ユーザがアクセス可能な(EL0)**としてマークされたメモリを**読み書きすることを防ぎます**。ただしPANは明示的に無効化されない限り有効です。
- アイデアは:カーネルが騙されたり侵害された場合でも、カーネルはユーザ空間ポインタを恣意的にデリファレンスできないようにし、`ret2usr` 型のエクスプロイトやユーザ制御バッファの悪用リスクを減らすことです。
- PANが有効なとき(`PSTATE.PAN = 1`)、EL0で「アクセス可能」とされる仮想アドレスに対して特権の load/store 命令がアクセスすると、**permission fault** が発生します。
- カーネルが正当にユーザ空間メモリにアクセスする必要がある場合(例:ユーザバッファへのデータコピー)、カーネルは一時的にPANを**無効化する**か、「アンプリビレッジドな load/store 命令」に切り替えてそのアクセスを許可する必要があります。
- ARM64上のLinuxでは、PANサポートは2015年頃に導入されました:カーネルパッチは機能の検出を追加し、`get_user` / `put_user` 等をPANをクリアするバリアラントに置き換えました。

**重要なニュアンス / 制限 / バグ**
- Siguzaらが指摘したように、ARM設計の仕様バグ(あるいは曖昧な挙動)により、**execute-only user mappings**(`--x`)はPANを**トリガーしない**可能性があります。つまり、ユーザページが実行可能だが読み取り権限を持たない場合、カーネルの読み取り試行がPANを回避するかもしれません。アーキテクチャが「EL0でアクセス可能」を可読権限が必要とみなしており、単に実行可能であるだけでは該当しないためです。これは特定の構成でPANのバイパスに繋がります。
- そのため、iOS / XNUがexecute-only user pagesを許可している場合(JITやコードキャッシュのセットアップなど)、カーネルはPANが有効でもそれらから意図せず読み取ってしまう可能性があります。これはいくつかのARMv8+システムで既知の微妙な脆弱領域です。

#### PXN (Privileged eXecute Never)

- **PXN** はページテーブルフラグ(ページテーブルエントリ、leafまたはblockエントリ)で、そのページが**特権モードで実行不可(EL1で実行不可)**であることを示します。
- PXNはカーネル(または任意の特権コード)がユーザ空間ページから命令を実行するのを防ぎます。これにより、制御が逸らされてもカーネルレベルでユーザメモリに飛ぶことを阻止します。
- PANと組み合わせると次が保証されます:
  1. カーネルは(デフォルトで)ユーザ空間データを読み書きできない(PAN)
  2. カーネルはユーザ空間コードを実行できない(PXN)
- ARMv8のページテーブルフォーマットでは、leafエントリには属性ビットとして `PXN` ビット(および非特権実行不可の `UXN`)があります。

したがって、たとえカーネルがユーザメモリを指す破損した関数ポインタを持っていてそこへ分岐しようとしても、PXNビットがフォルトを引き起こします。

#### メモリ許可モデル & PAN / PXN がページテーブルビットにどのように対応するか

PAN / PXN の動作を理解するには、ARMの翻訳と権限モデル(簡略化)を知る必要があります:

- 各ページまたはブロックエントリには、読み書きや特権/非特権のアクセス許可を示す **AP[2:1]** や、実行不可制限のための **UXN / PXN** ビットなどの属性フィールドがあります。
- `PSTATE.PAN` が 1(有効)であるとき、ハードウェアは修正されたセマンティクスを強制します:EL0により「アクセス可能」とマークされたページへの特権アクセスは拒否され(フォルト)ます。
- 前述のバグのため、読み取り許可を持たない「実行のみ」ページは、ある実装ではEL0で「アクセス可能」と見なされない場合があり、これがPANのバイパスに繋がることがあります。
- ページの `PXN` ビットが設定されている場合、より高い特権レベルからの命令フェッチであっても実行は禁止されます。

#### ハードニングされたOS(例:iOS / XNU)におけるPAN / PXNのカーネル利用

ハードニングされたカーネル設計(Appleが使用する可能性のある設計)では:

- カーネルはデフォルトでPANを有効にします(したがって特権コードは制約されます)。
- ユーザバッファを正当に読み書きする必要がある経路(syscallのバッファコピー、I/O、ユーザポインタの読み書き等)では、カーネルは一時的にPANを**無効化**するか、ユーザメモリアクセスを許可する特殊命令を使います。
- ユーザデータアクセスを終えたら、PANを再び有効にする必要があります。
- PXNはページテーブルを通じて強制されます:ユーザページには `PXN = 1` が設定され(カーネルがそこを実行できないように)、カーネルページには PXN は設定されません(カーネルコードは実行可能)。
- カーネルは、ユーザメモリ領域への実行フローを引き起こす経路がないことを保証しなければなりません(これが守られないとPXNを迂回する可能性があります) — したがって「ユーザ制御のシェルコードにジャンプする」ことを利用するエクスプロイトチェーンはブロックされます。

前述のexecute-onlyページによるPANバイパスのため、実際のシステムではAppleがexecute-only user pagesを無効にするか、仕様上の弱点を回避するパッチを適用する可能性があります。

#### 攻撃面、バイパス、および緩和策

- **execute-onlyページ経由のPANバイパス**: 述べたように仕様の隙間により、読み取り権限を持たない実行専用ユーザページは、一部の実装で「EL0でアクセス可能」と見なされないため、PANがブロックしない可能性があります。これにより攻撃者は「実行専用」セクション経由でデータを供給するという異例の道を得ることがあります。
- **一時的ウィンドウのエクスプロイト**: カーネルがPANを必要以上に長く無効化する場合、そのウィンドウを悪用して意図しないユーザメモリアクセスを行うレースや悪意ある操作が可能になります。
- **再有効化の忘却**: コード経路がPANを再有効化し忘れると、その後のカーネル操作が誤ってユーザメモリにアクセスすることがあります。
- **PXNの誤設定**: ページテーブルがユーザページにPXNを設定していない、またはユーザコードページを誤ってマップしていると、カーネルがユーザ空間コードを実行してしまう可能性があります。
- **投機的実行 / サイドチャネル**: 投機的なバイパスに類似して、PAN / PXNチェックの一時的な違反を引き起こすマイクロアーキテクチャ的副作用があるかもしれません(ただしそのような攻撃はCPU設計に大きく依存します)。
- **複雑な相互作用**: JIT、共有メモリ、just-in-timeコード領域などの高度な機能では、カーネルがユーザマップ領域で特定のメモリアクセスや実行を許可する必要があり、PAN/PXN制約下で安全に設計することは難しいです。

#### 例

<details>
<summary>コード例</summary>
ここに示すのは、ユーザメモリアクセスの前後でPANを有効/無効化する擬似アセンブリのシーケンスと、どのようにフォルトが生じ得るかを示す例です。
</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

If the kernel had **not** set PXN on that user page, then the branch might succeed — which would be insecure.

カーネルがそのユーザページに対してPXNを**設定していなかった**場合、その分岐は成功する可能性があり — それは安全でない挙動になります。

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.

カーネルがユーザメモリアクセス後にPANを再有効化するのを忘れると、その間にカーネルの他の処理が誤って任意のユーザメモリを読み書きしてしまう余地が生じます。

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.

ユーザポインタが実行専用ページ(実行のみ許可、読み/書き不可)を指している場合、PAN仕様のバグにより、実装によってはPANが有効でも `ldr W2, [X1]` が**フォルトしない**ことがあり、バイパスエクスプロイトを可能にし得ます。

</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 means the top byte (most-significant byte) of a 64-bit pointer is ignored by address translation. This lets OS or hardware embed **tag bits** in the pointer’s top byte without affecting the actual address.

- TBI stands for **Top Byte Ignore** (sometimes called *Address Tagging*). It is a hardware feature (available in many ARMv8+ implementations) that **ignores the top 8 bits** (bits 63:56) of a 64-bit pointer when performing **address translation / load/store / instruction fetch**.
- In effect, the CPU treats a pointer `0xTTxxxx_xxxx_xxxx` (where `TT` = top byte) as `0x00xxxx_xxxx_xxxx` for the purposes of address translation, ignoring (masking off) the top byte. The top byte can be used by software to store **metadata / tag bits**.
- This gives software “free” in-band space to embed a byte of tag in each pointer without altering which memory location it refers to.
- The architecture ensures that loads, stores, and instruction fetch treat the pointer with its top byte masked (i.e. tag stripped off) before performing the actual memory access.

Thus TBI decouples the **logical pointer** (pointer + tag) from the **physical address** used for memory operations.

#### Why TBI: Use cases and motivation

- **Pointer tagging / metadata**: You can store extra metadata (e.g. object type, version, bounds, integrity tags) in that top byte. When you later use the pointer, the tag is ignored at hardware level, so you don’t need to strip manually for the memory access.
- **Memory tagging / MTE (Memory Tagging Extension)**: TBI is the base hardware mechanism that MTE builds on. In ARMv8.5, the **Memory Tagging Extension** uses bits 59:56 of the pointer as a **logical tag** and checks it against an **allocation tag** stored in memory.
- **Enhanced security & integrity**: By combining TBI with pointer authentication (PAC) or runtime checks, you can force not just the pointer value but also the tag to be correct. An attacker overwriting a pointer without the correct tag will produce a mismatched tag.
- **Compatibility**: Because TBI is optional and tag bits are ignored by hardware, existing untagged code continues to operate normally. The tag bits effectively become “don’t care” bits for legacy code.

#### Example
<details>
<summary>Example</summary>
A function pointer included a tag in its top byte (say `0xAA`). An exploit overwrites the pointer low bits but neglects the tag, so when the kernel verifies or sanitizes, the pointer fails or is rejected.
</details>

---

### 12. **Page Protection Layer (PPL)**
**Introduced in late iOS / modern hardware (iOS ~17 / Apple silicon / high-end models)** (some reports show PPL circa macOS / Apple silicon, but Apple is bringing analogous protections to iOS)

- PPL is designed as an **intra-kernel protection boundary**: even if the kernel (EL1) is compromised and has read/write capabilities, **it should not be able to freely modify** certain **sensitive pages** (especially page tables, code-signing metadata, kernel code pages, entitlements, trust caches, etc.).
- It effectively creates a **“kernel within the kernel”** — a smaller trusted component (PPL) with **elevated privileges** that alone can modify protected pages. Other kernel code must call into PPL routines to effect changes.
- This reduces the attack surface for kernel exploits: even with full arbitrary R/W/execute in kernel mode, exploit code must also somehow get into the PPL domain (or bypass PPL) to modify critical structures.
- On newer Apple silicon (A15+ / M2+), Apple is transitioning to **SPTM (Secure Page Table Monitor)**, which in many cases replaces PPL for page-table protection on those platforms.

Here’s how PPL is believed to operate, based on public analysis:

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

- Apple hardware uses a mechanism called **APRR (Access Permission ReRouting)**, which allows page table entries (PTEs) to contain small indices, rather than full permission bits. Those indices are mapped via APRR registers to actual permissions. This allows dynamic remapping of permissions per domain.
- PPL leverages APRR to segregate privilege within kernel context: only the PPL domain is permitted to update the mapping between indices and effective permissions. That is, when non-PPL kernel code writes a PTE or tries to flip permission bits, the APRR logic disallows it (or enforces read-only mapping).
- PPL code itself runs in a restricted region (e.g. `__PPLTEXT`) which is normally non-executable or non-writable until entry gates temporarily allow it. The kernel calls PPL entry points (“PPL routines”) to perform sensitive operations.

#### Gate / Entry & Exit

- When the kernel needs to modify a protected page (e.g. change permissions of a kernel code page, or modify page tables), it calls into a **PPL wrapper** routine, which does validation and then transitions into the PPL domain. Outside that domain, the protected pages are effectively read-only or non-modifiable by the main kernel.
- During PPL entry, the APRR mappings are adjusted so that memory pages in the PPL region are set to **executable & writable** within PPL. Upon exit, they are returned to read-only / non-writable. This ensures that only well-audited PPL routines can write to protected pages.
- Outside PPL, attempts by kernel code to write to those protected pages will fault (permission denied) because the APRR mapping for that code domain doesn’t permit writing.

#### Protected page categories

The pages that PPL typically protects include:

- Page table structures (translation table entries, mapping metadata)
- Kernel code pages, especially those containing critical logic
- Code-sign metadata (trust caches, signature blobs)
- Entitlement tables, signature enforcement tables
- Other high-value kernel structures where a patch would allow bypassing signature checks or credentials manipulation

The idea is that even if the kernel memory is fully controlled, the attacker cannot simply patch or rewrite these pages, unless they also compromise PPL routines or bypass PPL.


#### Known Bypasses & Vulnerabilities

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

- A public writeup by Project Zero describes a bypass involving **stale TLB entries**.
- The idea:

1. Allocate two physical pages A and B, mark them as PPL pages (so they are protected).
2. Map two virtual addresses P and Q whose L3 translation table pages come from A and B.
3. Spin a thread to continuously access Q, keeping its TLB entry alive.
4. Call `pmap_remove_options()` to remove mappings starting at P; due to a bug, the code mistakenly removes the TTEs for both P and Q, but only invalidates the TLB entry for P, leaving Q’s stale entry live.
5. Reuse B (page Q’s table) to map arbitrary memory (e.g. PPL-protected pages). Because the stale TLB entry still maps Q’s old mapping, that mapping remains valid for that context.
6. Through this, the attacker can put writable mapping of PPL-protected pages in place without going through PPL interface.

- This exploit required fine control of physical mapping and TLB behavior. It demonstrates that a security boundary relying on TLB / mapping correctness must be extremely careful about TLB invalidations and mapping consistency.

- Project Zero commented that bypasses like this are subtle and rare, but possible in complex systems. Still, they regard PPL as a solid mitigation.

2. **Other potential hazards & constraints**

- If a kernel exploit can directly enter PPL routines (via calling the PPL wrappers), it might bypass restrictions. Thus argument validation is critical.
- Bugs in the PPL code itself (e.g. arithmetic overflow, boundary checks) can allow out-of-bounds modifications inside PPL. Project Zero observed that such a bug in `pmap_remove_options_internal()` was exploited in their bypass.
- The PPL boundary is irrevocably tied to hardware enforcement (APRR, memory controller), so it's only as strong as the hardware implementation.



#### Example
<details>
<summary>Code Example</summary>
Here’s a simplified pseudocode / logic showing how a kernel might call into PPL to modify protected pages:
```c
// In kernel (outside PPL domain)
function kernel_modify_pptable(pt_addr, new_entry) {
// validate arguments, etc.
return ppl_call_modify(pt_addr, new_entry)  // call PPL wrapper
}

// In PPL (trusted domain)
function ppl_call_modify(pt_addr, new_entry) {
// temporarily enable write access to protected pages (via APRR adjustments)
aprr_set_index_for_write(PPL_INDEX)
// perform the modification
*pt_addr = new_entry
// restore permissions (make pages read-only again)
aprr_restore_default()
return success
}

// If kernel code outside PPL does:
*pt_addr = new_entry  // a direct write
// It will fault because APRR mapping for non-PPL domain disallows write to that page

The kernel 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:

  1. Tag assignment
  • When memory is allocated (e.g. in kernel or user space via secure allocators), a secret tag is assigned to that block.
  • The pointer returned to the user or kernel includes that tag in its high bits (using TBI / top byte ignore mechanisms).
  1. Tag checking on access
  • Whenever a load or store is executed using a pointer, the hardware checks that the pointer’s tag matches the memory block’s tag (allocation tag). If mismatch, it faults immediately (since synchronous).
  • Because it’s synchronous, there is no “delayed detection” window.
  1. Retagging on free / reuse
  • When memory is freed, the allocator changes the block’s tag (so older pointers with old tags no longer match).
  • A use-after-free pointer would therefore have a stale tag and mismatch when accessed.
  1. Neighbor-tag differentiation to catch overflows
  • Adjacent allocations are given distinct tags. If a buffer overflow spills into neighbor’s memory, tag mismatch causes a fault.
  • This is especially powerful in catching small overflows that cross boundary.
  1. Tag confidentiality enforcement
  • Apple must prevent tag values being leaked (because if attacker learns the tag, they could craft pointers with correct tags).
  • They include protections (microarchitectural / speculative controls) to avoid side-channel leakage of tag bits.
  1. Kernel and user-space integration
  • Apple uses EMTE not just in user-space but also in kernel / OS-critical components (to guard kernel against memory corruption).
  • The hardware/OS ensures tag rules apply even when kernel is executing on behalf of 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>

#### 制限と課題

- **Intrablock overflows**: オーバーフローが同じ割り当て内に留まり(境界を越えない)タグが同じままの場合、tag mismatch は検出できないことがある。
- **Tag width limitation**: タグに利用できるビット数は限られている(例: 4ビットなど、小さなドメイン)— 名前空間が制限される。
- **Side-channel leaks**: タグビットが(cache / speculative execution 経由で)leaked 可能性がある場合、攻撃者は有効なタグを学習して回避できる。Apple の tag confidentiality enforcement はこれを緩和することを目的としている。
- **Performance overhead**: 各 load/store でのタグチェックはコストを追加するため、Apple はオーバーヘッドを低く抑えるためにハードウェア最適化を行う必要がある。
- **Compatibility & fallback**: 古いハードウェアや EMTE をサポートしない部分ではフォールバックが必要。Apple は MIE がサポートあるデバイスのみで有効になると主張している。
- **Complex allocator logic**: アロケータはタグ管理、retagging、境界のアライン、タグ衝突の回避を扱う必要がある。アロケータロジックのバグは脆弱性を生む可能性がある。
- **Mixed memory / hybrid areas**: 一部のメモリは未タグ(レガシー)のまま残る可能性があり、相互運用性が難しくなる。
- **Speculative / transient attacks**: 多くのマイクロアーキテクチャ保護と同様に、speculative execution や micro-op fusion により一時的にチェックを回避したりタグビットを漏洩させたりする可能性がある。
- **Limited to supported regions**: Apple は EMTE をカーネルやセキュリティクリティカルなサブシステムといった選択的で高リスクな領域にのみ強制する可能性があり、全域にわたって有効とは限らない。



---

## Key enhancements / differences compared to standard MTE

Here are the improvements and changes Apple emphasizes:

| Feature | Original MTE | EMTE (Apple’s enhanced) / MIE |
|---|---|---|
| **Check mode** | Supports synchronous and asynchronous modes. In async, tag mismatches are reported later (delayed)| Apple insists on **synchronous mode** by default—tag mismatches are caught immediately, no delay/race windows allowed.|
| **Coverage of non-tagged memory** | Accesses to non-tagged memory (e.g. globals) may bypass checks in some implementations | EMTE requires that accesses from a tagged region to non-tagged memory also validate tag knowledge, making it harder to bypass by mixing allocations.|
| **Tag confidentiality / secrecy** | Tags might be observable or leaked via side channels | Apple adds **Tag Confidentiality Enforcement**, which attempts to prevent leakage of tag values (via speculative side-channels etc.).|
| **Allocator integration & retagging** | MTE leaves much of allocator logic to software | Apple’s secure typed allocators (kalloc_type, xzone malloc, etc.) integrate with EMTE: when memory is allocated or freed, tags are managed at fine granularity.|
| **Always-on by default** | In many platforms, MTE is optional or off by default | Apple enables EMTE / MIE by default on supported hardware (e.g. iPhone 17 / A19) for kernel and many user processes.|

Apple はハードウェアとソフトウェアスタックの両方を制御しているため、EMTE を厳密に強制し、パフォーマンスの問題を回避し、side-channel holes を塞ぐことが可能である。

---

## How EMTE works in practice (Apple / MIE)

Here’s a higher-level description of how EMTE operates under Apple’s MIE setup:

1. **Tag assignment**
- When memory is allocated (e.g. in kernel or user space via secure allocators), a **secret tag** is assigned to that block.
- The pointer returned to the user or kernel includes that tag in its high bits (using TBI / top byte ignore mechanisms).

2. **Tag checking on access**
- Whenever a load or store is executed using a pointer, the hardware checks that the pointer’s tag matches the memory block’s tag (allocation tag). If mismatch, it faults immediately (since synchronous).
- Because it's synchronous, there is no “delayed detection” window.

3. **Retagging on free / reuse**
- When memory is freed, the allocator changes the block’s tag (so older pointers with old tags no longer match).
- A use-after-free pointer would therefore have a stale tag and mismatch when accessed.

4. **Neighbor-tag differentiation to catch overflows**
- Adjacent allocations are given distinct tags. If a buffer overflow spills into neighbor’s memory, tag mismatch causes a fault.
- This is especially powerful in catching small overflows that cross boundary.

5. **Tag confidentiality enforcement**
- Apple must prevent tag values being leaked (because if attacker learns the tag, they could craft pointers with correct tags).
- They include protections (microarchitectural / speculative controls) to avoid side-channel leakage of tag bits.

6. **Kernel and user-space integration**
- Apple uses EMTE not just in user-space but also in kernel / OS-critical components (to guard kernel against memory corruption).
- The hardware/OS ensures tag rules apply even when kernel is executing on behalf of user space.

Because EMTE is built into MIE, Apple uses EMTE in synchronous mode across key attack surfaces, not as opt-in or debugging mode.



---

## Exception handling in XNU

When an **exception** occurs (e.g., `EXC_BAD_ACCESS`, `EXC_BAD_INSTRUCTION`, `EXC_CRASH`, `EXC_ARM_PAC`, etc.), the **Mach layer** of the XNU kernel is responsible for intercepting it before it becomes a UNIX-style **signal** (like `SIGSEGV`, `SIGBUS`, `SIGILL`, ...).

This process involves multiple layers of exception propagation and handling before reaching user space or being converted to a BSD signal.


### Exception Flow (High-Level)

1.  **CPU triggers a synchronous exception** (e.g., invalid pointer dereference, PAC failure, illegal instruction, etc.).

2.  **Low-level trap handler** runs (`trap.c`, `exception.c` in XNU source).

3.  The trap handler calls **`exception_triage()`**, the core of the Mach exception handling.

4.  `exception_triage()` decides how to route the exception:

-   First to the **thread's exception port**.

-   Then to the **task's exception port**.

-   Then to the **host's exception port** (often `launchd` or `ReportCrash`).

If none of these ports handle the exception, the kernel may:

-   **Convert it into a BSD signal** (for user-space processes).

-   **Panic** (for kernel-space exceptions).


### Core Function: `exception_triage()`

The function `exception_triage()` routes Mach exceptions up the chain of possible handlers until one handles it or until it's finally fatal. It's defined in `osfmk/kern/exception.c`.
```c
void exception_triage(exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt);

典型的な呼び出しフロー:

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

すべて失敗した場合 → bsd_exception() によって処理され → SIGSEGV のようなシグナルに変換される。

例外ポート

各 Mach オブジェクト (thread, task, host) は、例外メッセージが送られる 例外ポート を登録できる。

それらは API によって定義されている:

task_set_exception_ports()
thread_set_exception_ports()
host_set_exception_ports()

Each exception port has:

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

Debuggers and Exception Handling

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

When an exception occurs:

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

Flow of EXC_BAD_ACCESS

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

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

  3. Message sent to:

  • Thread port → (debugger can intercept breakpoint).

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

  • If ignored → Host port (usually ReportCrash).

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

PAC Exceptions

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

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

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

Software Breakpoints

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

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

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

Conversion to BSD Signals

If no handler accepts the exception:

  • Kernel calls task_exception_notify() → bsd_exception().

  • This maps Mach exceptions to signals:

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

### Key Files in XNU Source

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

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

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

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

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


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

カーネルは固定サイズの「zones」に分かれたゾーンアロケータ(kalloc)を使用していました。各ゾーンは単一のサイズクラスの割り当てのみを保持します。

From the screenshot:

Zone NameElement SizeExample Use
default.kalloc.1616 bytes非常に小さなカーネル構造体、ポインタ。
default.kalloc.3232 bytes小さな構造体、オブジェクトヘッダ。
default.kalloc.6464 bytesIPCメッセージ、小さなカーネルバッファ。
default.kalloc.128128 bytesOSObject の一部のような中程度のオブジェクト。
default.kalloc.12801280 bytes大きな構造体、IOSurface/グラフィックスメタデータ。

動作の仕組み:

  • 各割り当て要求は最も近いゾーンサイズに切り上げられる。 (例: 50バイトの要求は kalloc.64 ゾーンに入る)
  • 各ゾーンのメモリはfreelistで管理され、カーネルが解放したチャンクはそのゾーンに戻された。
  • 64バイトバッファをオーバーフローすると、同じゾーン内の次のオブジェクトを上書きしてしまう。

このため、同じサイズクラスの割り当てを大量に行う「heap spraying / feng shui」が非常に効果的でした。スプレーによりオブジェクトの隣接関係を予測できたからです。

The freelist

各 kalloc ゾーンの中で、解放されたオブジェクトはシステムに直接返却されず、freelist(利用可能チャンクのリンクリスト)に入れられていました。

  • チャンクが解放されると、カーネルはそのチャンクの先頭にポインタを書き込む → 同じゾーン内の次の空きチャンクのアドレス。

  • ゾーンは最初の空きチャンクへの HEAD ポインタを保持していた。

  • 割り当ては常に現在の HEAD を使う:

  1. HEAD をポップ(そのメモリを呼び出し元へ返す)。

  2. HEAD = HEAD->next に更新(解放チャンクのヘッダに保存されている)。

  • 解放はチャンクをプッシュする:

  • freed_chunk->next = HEAD

  • HEAD = freed_chunk

つまり freelist は解放されたメモリ自体の中に構築された単なるリンクリストでした。

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 を悪用する

free chunk の最初の 8 バイトが freelist pointer に等しいため、攻撃者はそれを破損させることができる:

  1. Heap overflow で隣接する解放済みチャンクに侵入 → その “next” pointer を上書き。
  2. Use-after-free で解放済みオブジェクトに書き込み → その “next” pointer を上書き。

次に、そのサイズの次回の割り当てで:

  • アロケータは破損したチャンクをポップする。
  • 攻撃者が供給した “next” pointer をたどる。
  • 任意のメモリへのポインタを返し、fake object primitives や targeted overwrite を可能にする。

Visual example of freelist poisoning:

Before corruption:
HEAD ──► [ F1 ] ──► [ F2 ] ──► [ F3 ] ──► NULL

After attacker overwrite of F1->next:
HEAD ──► [ F1 ]
(next) ──► 0xDEAD_BEEF_CAFE_BABE  (attacker-chosen)

Next alloc of this zone → kernel hands out memory at attacker-controlled address.

This freelist design made exploitation highly effective pre-hardening: predictable neighbors from heap sprays, raw pointer freelist links, and no type separation allowed attackers to escalate UAF/overflow bugs into arbitrary kernel memory control.

Heap Grooming / Feng Shui

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

Steps:

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

Why it works:

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

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

Apple hardened the allocator and made heap grooming much harder:

1. From Classic kalloc to kalloc_type

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

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

2. Slabs and Per-CPU Caches

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

3. Randomization inside zones

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

4. Guarded Allocations

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

5. Page Protection Layer (PPL) and SPTM

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

6. Large Allocations

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

7. Allocation Patterns Attackers Target

Even with these protections, attackers still look for:

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

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

Example: Allocation Flow in Modern Heap

Suppose userspace calls into IOKit to allocate an OSData object:

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

Freelist pointer protection:

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

Comparison Table

FeatureOld Heap (Pre-iOS 15)Modern Heap (iOS 15+ / A12+)
Allocation granularityFixed size buckets (kalloc.16, kalloc.32, etc.)Size + type-based buckets (kalloc_type)
Placement predictabilityHigh (same-size objects side by side)Low (same-type grouping + randomness)
Freelist managementRaw pointers in freed chunks (easy to corrupt)Encoded pointers (safe-linking style)
Adjacent object controlEasy via sprays/frees (feng shui predictable)Hard — typed zones separate attacker objects
Kernel data/code protectionsFew hardware protectionsPPL / SPTM protect page tables & code pages, and PAC protects pointers
Allocation reuse validationNone (freelist pointers raw)zone_require / zone enforcement
Exploit reliabilityHigh with heap spraysMuch lower, requires logic bugs or info leaks
Large allocations handlingAll small allocations managed equallyLarge ones bypass zones → handled via VM

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

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

Goals & Design Principles

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

Architecture & Components

Below are the main elements in the xzone allocator:

Segment Groups & Zones

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

Chunks & Blocks

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

Type / Type ID

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

Allocation & Freeing Workflow

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

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

Security Features & Hardening

These are the defenses built into modern userland xzone:

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

Interaction with Memory Integrity Enforcement (MIE / EMTE)

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

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

(Old) Physical Use-After-Free via IOSurface

ios Physical UAF - IOSurface


Ghidra Install BinDiff

Download BinDiff DMG from https://www.zynamics.com/bindiff/manual and install it.

Open Ghidra with ghidraRun and go to File –> Install Extensions, press the add button and select the path /Applications/BinDiff/Extra/Ghidra/BinExport and click OK and isntall it even if there is a version mismatch.

Using BinDiff with Kernel versions

  1. Go to the page https://ipsw.me/ and download the iOS versions you want to diff. These will be .ipsw files.
  2. Decompress until you get the bin format of the kernelcache of both .ipsw files. You have information on how to do this on:

macOS Kernel Extensions & Kernelcache

  1. Open Ghidra with ghidraRun, create a new project and load the kernelcaches.
  2. Open each kernelcache so they are automatically analyzed by Ghidra.
  3. Then, on the project Window of Ghidra, right click each kernelcache, select Export, select format Binary BinExport (v2) for BinDiff and export them.
  4. Open BinDiff, create a new workspace and add a new diff indicating as primary file the kernelcache that contains the vulnerability and as secondary file the patched kernelcache.

Finding the right XNU version

If you want to check for vulnerabilities in a specific version of iOS, you can check which XNU release version the iOS version uses at [https://www.theiphonewiki.com/wiki/kernel]https://www.theiphonewiki.com/wiki/kernel).

For example, the versions 15.1 RC, 15.1 and 15.1.1 use the version Darwin Kernel Version 21.1.0: Wed Oct 13 19:14:48 PDT 2021; root:xnu-8019.43.1~1/RELEASE_ARM64_T8006.

JSKit-Based Safari Chains and PREYHUNTER Stagers

Renderer RCE abstraction with JSKit

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

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

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

PREYHUNTER helper & watcher modules

  • Watcher anti-analysis: 専用の watcher バイナリがデバイスを継続的にプロファイルし、研究用環境が検出された場合は kill-chain を中断します。security.mac.amfi.developer_mode_statusdiagnosticd コンソールの存在、ロケール US または ILCydia のような jailbreak の痕跡、bashtcpdumpfridasshdcheckrain といったプロセス、モバイル AV アプリ(McAfee、AvastMobileSecurity、NortonMobileSecurity)、カスタム HTTP プロキシ設定、およびカスタムルート CA を検査します。いずれかのチェックが失敗すると、さらなるペイロード配信はブロックされます。
  • Helper surveillance hooks: helper コンポーネントは /tmp/helper.sock を通じて他のステージと通信し、その後 DMHookerUMHooker という hook セットをロードします。これらのフックは VOIP オーディオ経路にタップし(録音は /private/var/tmp/l/voip_%lu_%u_PART.m4a に保存される)、システム全体の keylogger を実装し、UI なしで写真を撮影し、SpringBoard をフックして通常ならこれらの動作が引き起こす通知を抑制します。したがって helper は、Predator のようなより重いインプラントが投入される前のステルスな検証 + 軽度の監視レイヤとして機能します。

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

References

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする