Files
revkit/docs/spec/capture_decode_status.md
T
tkgstratorandClaude Opus 4.6 7eb39fabfd docs: Netflix仕様書の再構成とiOS解析ドキュメント追加
- 旧ドキュメント (docs/netflix/, docs/instructions/ 等) を削除
- docs/spec/: appboot ピンニング解析、iOS再生フロー、
  MSL CBOR鍵交換解析、キャプチャ復号状況、暗号化フロー図を追加
- docs/netflix_client_spec.md, platform_flow_comparison.md を追加
- iOS認証・マニフェスト・ライセンス取得フロー詳細を追加

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 02:06:14 +00:00

105 lines
5.6 KiB
Markdown

# キャプチャデータ復号状況
キャプチャ日: 2026-04-06
デバイス: iPhone 9, Argo 15.48.1
## エンドポイント別復号状況
| エンドポイント | 総ファイル数 | JSON 平文 | CBOR 暗号化 | CBOR 平文 | CBOR 鍵交換 | 復号不可 | 復号不可の理由 |
|--------------|-----------|----------|-----------|---------|-----------|---------|-------------|
| appboot | 2 | 0 | 1 | 1 | 0 | **1** | MSL セッション鍵なし (AES-128-CBC 暗号化) |
| iosui | 11 | 5 | 0 | 0 | 0 | **0** | — (全て平文 JSON) |
| graphql (FTL) | 23 (JSON) | 23 | 0 | 0 | 0 | **0** | — (全て平文 JSON) |
| graphql (Cloud/NGP) | 22 (CBOR) | 0 | 16 | 4 | 0 | **16** | MSL セッション鍵なし |
| pbo_license | 40 | 0 | 27 | 12 | 1 | **27** | MSL セッション鍵なし |
| ios_manifest | ~20 | 0 | ~15 | ~5 | 0 | **~15** | MSL セッション鍵なし |
| ios_logblob | ~15 | 0 | ~10 | ~5 | 0 | **~10** | MSL セッション鍵なし |
| msl (event 等) | 51 | 23 | 18 | 10 | 0 | **18** | MSL セッション鍵なし |
| other (speedtest) | 3 | 0 | 0 | 0 | 0 | **0** | OCA プローブ (バイナリ、復号不要) |
| other (残り) | 41 | 28 | 3 | 0 | 0 | **3** | MSL セッション鍵なし |
## 復号可能 / 復号不可の分類
### 復号済み (平文で取得できている)
| カテゴリ | 内容 | 形式 |
|---------|------|------|
| iosui API | healthcheck, user, warmer | HTTP/JSON (平文) |
| graphql (FTL) | FTL ホスト経由の GraphQL | HTTP/JSON (平文) |
| appboot (ヘッダー部) | MSL ヘッダー、entity auth、鍵交換パラメータ | CBOR (構造は見える) |
| CBOR メタデータ | MSL ヘッダー、sequence number、capabilities | CBOR (構造は見える) |
| Cookie | nfvdid, NetflixId, SecureNetflixId 等 | テキスト |
| HTTP ヘッダー | 全リクエスト/レスポンスの全ヘッダー | JSON |
### 復号不可 (暗号化されたペイロード)
| カテゴリ | 内容 | 暗号化方式 | 復号に必要なもの |
|---------|------|----------|---------------|
| appboot レスポンスペイロード | サーバー設定、trust store データ | AES-128-CBC + HMAC-SHA256 | MSL セッション鍵 (鍵交換で導出) |
| graphql (Cloud/NGP) | カタログ、SSO トークン等 | AES-128-CBC + HMAC-SHA256 | MSL セッション鍵 |
| pbo_license リクエスト | FairPlay SPC ペイロード | AES-128-CBC + HMAC-SHA256 | MSL セッション鍵 |
| pbo_license レスポンス | FairPlay ライセンス応答 | AES-128-CBC + HMAC-SHA256 | MSL セッション鍵 |
| ios_manifest リクエスト | マニフェスト要求パラメータ | AES-128-CBC + HMAC-SHA256 | MSL セッション鍵 |
| ios_manifest レスポンス | ストリーム URL、コーデック情報 | AES-128-CBC + HMAC-SHA256 | MSL セッション鍵 |
| ios_logblob | テレメトリデータ | AES-128-CBC + HMAC-SHA256 | MSL セッション鍵 |
| msl (event 等) | イベントデータ | AES-128-CBC + HMAC-SHA256 | MSL セッション鍵 |
## MSL セッション鍵の取得方法
暗号化ペイロードの復号には **MSL セッション鍵** (encryption key + HMAC key) が必要。
### 方法 1: Frida でセッション鍵をフック
MslClient / NFWebCrypto 内の鍵導出関数をフックして鍵を抽出:
- `IosMslClient` の鍵交換完了時にセッション鍵がメモリに保持される
- `NFWebCrypto::aesCbc` の引数から AES 鍵と IV を取得
- `NFWebCrypto::dhDerive` / `HKDF` の出力を取得
### 方法 2: Python MSL クライアントで鍵交換を再現
`src/netflix_msl/` の既存実装を拡張:
1. appboot CBOR リクエストを再現 (FAIRPLAY_MGK_APPID は iOS 固有のため困難)
2. ASYMMETRIC_WRAPPED (RSA) で鍵交換 (Chrome/Android 向けなら可能)
3. セッション鍵を取得して、キャプチャ済みデータを復号
### 方法 3: Frida で平文を直接キャプチャ
暗号化前/復号後のデータを Frida フックで取得:
- `SSL_write` / `SSL_read` — HTTP レベルの平文
- MSL の暗号化関数 (`aesCbc`) の入出力をフック
## 結論
| 項目 | 状態 |
|------|------|
| HTTP ヘッダー・Cookie | ✓ 全て取得済み |
| 平文 JSON レスポンス (iosui, FTL graphql) | ✓ 全て取得済み |
| MSL CBOR 構造 (ヘッダー、entity auth) | ✓ デコード済み |
| MSL 暗号化ペイロード | ✗ **セッション鍵がないため復号不可** |
| OCA スピードテスト | — 復号不要 (バイナリプローブ) |
**ボトルネック**: MSL セッション鍵の取得。ただし鍵交換データはキャプチャ済み。
## 補足: FairPlay と MSL 鍵交換は独立
FairPlay (`FAIRPLAY_MGK_APPID`) は **entity auth** (認証スキーム) であり、**MSL の鍵交換とは無関係**。
- Entity Auth (key 34): `FAIRPLAY_MGK_APPID` → デバイス認証 (apphmac, devicetoken, ESN)
- Key Exchange (key 33): スキーム ID `3` → セッション鍵の導出 (DH or RSA ラッピング)
鍵交換データは appboot の CBOR に含まれており:
- **リクエスト key 33.6**: 464 bytes (クライアント鍵交換データ)
- **レスポンス key 33.6**: 96 bytes (サーバー鍵交換レスポンス = ラップされたセッション鍵)
- **key 33.8**: ESN + suffix (identity)
- **key 33.9**: 16 bytes nonce
Python MSL クライアント (`src/netflix_msl/`) で ASYMMETRIC_WRAPPED 鍵交換を再現すれば、
FairPlay に依存せずセッション鍵を取得し、暗号化ペイロードを復号できる可能性がある。
iOS の CBOR スキーム ID `3` が JSON 形式の `ASYMMETRIC_WRAPPED` に対応するか、
別のスキーム (DIFFIE_HELLMAN 等) かは要調査。