
CVE-2024-20154 の技術解説
分類: CWE-121 — スタックベースのバッファオーバーフロー
重大度: Critical(MediaTek セキュリティ情報)· 8.8 High、攻撃ベクトル: Adjacent(CISA-ADP)
種別: リモートコード実行 — ユーザー操作不要、事前の関連付け不要
開示: MediaTek セキュリティ情報、2025年1月6日 https://corp.mediatek.com/product-security-bulletin/January-2025
分析対象: Samsung Galaxy A14 SM-A145R — MT6769 ファミリー(Helio G80)、MediaTek の影響を受けるチップセットリストに含まれる — ファームウェアは安全な条件下でエミュレートされました。
ステータス: パッチ適用済み。
これは私にとって初めての公開ベースバンド研究でした。私は、通信インフラ、合法的傍受の媒介層、スティングレイや IMSIキャッチャーの分析、組み込みデバイスセキュリティからは程遠い経歴の持ち主であり、これまでセルラーモデムのファームウェアを深くリバースエンジニアリングしたことはありませんでした。構造化された分析手法がターゲットを問わず適用でき、特定のプラットフォームへの精通は厳密なチェーン追跡で代替できることを、自分自身に証明したいと考えました。NB-IoT が際立っていたのは、それが真に危険な接点に位置しているからです。このプロトコルはリソース制約のある IoT デバイス向けに設計されており、攻撃面はアソシエーション前にあり、モデムスタックはハンドセットのユーザーが何をしていようとこのプロトコルを処理します。
パッチ適用済みファームウェアを分析し、脆弱なパターンが存在しないことを確認した際、特定の関数を対象とする前にファームウェアの大量分析に使用された AI システムは、再構築されたバグクラス、条件、影響を受けるファームウェアファミリーを、CVE-2024-20154 の説明と独立に一致させました。技術的な結論はアナリスト自身のものです。
あなたのポケットの中のスマートフォンには、少なくとも 2 つの独立したコンピュータが搭載されています。あなたが操作するのは Android を実行するものです。もう一つ — ベースバンド — は完全に独立して動作し、すべての無線通信を処理し、その上のオペレーティングシステムからはほぼ完全に見えません。Android が完全にパッチ適用されていても構いません。ブラウザがサンドボックス化されていても構いません。ユーザーが悪意のあるリンクをタップすることは決してないかもしれません。アプリケーションプロセッサが関与する前に無線信号を処理するモデムファームウェアに脆弱なコードがあるなら、それらはすべて無意味です。
CVE-2024-20154 はまさにその種の脆弱性です。
不正な NB-IoT システム情報ブロードキャストにより、MediaTek モデムファームウェアは攻撃者が制御するスケジューリングカウントを受け入れ、そのカウントをクランプ(上限抑止)することなく RRC から L1 への設定経路を通し、最終的に NB-IoT ブロードキャストチャネルハンドラ内のスタック書き込みループのループ境界として使用します。カウントが宛先配列の容量を超えると、ループは配列を越えて書き込み、スタック上の保存されたレジスタに達し、保存されたリターンアドレスを上書きします。その後、関数は破損した値をリターンアドレスレジスタに復元し、そこへジャンプします。
重大度をこれほど高くしている要因は次のとおりです:
この脆弱性は、MediaTek の 2025 年 1 月 6 日付セキュリティ情報で Critical の重大度評価とともに公開され、とりわけ LR12A モデムファミリーに影響を与えました。Samsung はこの修正を 2025 年 2 月のセキュリティメンテナンスリリースに組み込みました。
この投稿は武器化されたエクスプロイトを公開するものではなく、ここで公開されている内容から再現可能でもありません。 目的は、チェーンがどこで途切れるのか、なぜ各層がそれを防げなかったのか、そして稼働中のモデムにデバッガを接続できない場合にベースバンドのバグを責任を持って検証するために何が必要かを示すことです。
主ターゲット:Samsung Galaxy A14 (SM-A145R)。無線サブシステムは、MT6769 チップセットファミリー(Helio G80)の MediaTek ベースバンドプロセッサによって駆動されます。MT6769 ファミリーは、CVE-2024-20154 に関する MediaTek の影響を受けるチップセットリストに明示的に記載されています。``` AP/CP firmware: A145RXXU1AWD1 Modem software: MOLY LR12A.R3.TC10.6M.A14.PR.SP.V1.P5 Build date: 2023-04-18
ベースバンドファームウェアはAndroidコードではありません。これはSoCの無線
サブシステム上にある独立した組み込みシステムであり、独自のCPU、独自のRTOS、独自のメモリ空間を持ち、
Androidのプロセスサンドボックスの外側にあります。
### 2.2 モデムアーキテクチャ
抽出したバイナリの解析により、モデムプロセッサはリトルエンディアンモードでMIPS32とMIPS16e2
圧縮命令を実行することがわかります。MIPS16e2は、組み込みコードサイズ削減のための16ビット符号化拡張であり、
MediaTekがHelio世代ベースバンドで採用しているアプローチと一致しています。
これは、このSoCファミリに関する独立した公開ベースバンド研究によっても確認されています。
オペレーティングシステムはNucleus RTOSで、タスクスケジューリング、IPCメッセージキュー、
プールベースのメモリアロケータを提供します。カーネルとユーザーの特権分離はなく、
タスク間のメモリ保護ユニットによる強制もなく、ハードウェアのスタックガード機構もありません。
この記事のすべてのアドレスは、Ghidraでベース`0x90000000`としてロードされた仮想アドレスです。
### 2.3 緩和策(解析したビルドで確認)
| 緩和策 | 状態 | 影響 |
|---|---|---|
| ASLR | なし | ファームウェアのアドレスは静的であり、イメージから予測可能 |
| スタックカナリア | なし | `SAVE`/`RESTORE`はガード値なしで呼び出し先保存レジスタを保存する |
| NX / W^X | なし | スタックメモリは実行可能 |
| CFI | なし | 戻りアドレスはポリシーに対して検証されない |
### 2.4 解析アプローチ
3つの並行トラック:
**静的解析。** Samsungファームウェアパッケージ → CPパーティション抽出 → `md1img.img` →
Ghidra(MIPS LE 32ビット、ベース`0x90000000`)、NCC Groupの`mtk_bp`ツールセットを使用して
ファームウェアのデバッグセクションから復元したMediaTekエンジニアリングシンボルを使用。
**動的検証。** Unicorn Engine(MIPS32エミュレーション)を使用して、特定のファームウェアルーチンを
2つのフェーズに分けて単独で実行しました。フェーズ1では、ネイティブの命令ペアを通じて
チャネルコンテキストへの`si_count`のクランプされていないコピーを証明しようとしました。
フェーズ2では、実際のファームウェアバイト上で脆弱なループを実行し、ファームウェア自身の命令が
保存された戻りアドレスを破壊することを確認しました。フェーズ1を完全にネイティブで実行できなかった場合 —
CPHYディスパッチパスが必要とするRTOSサービスオブジェクト環境が再構築されなかったため —
副作用は直接モデル化され、すべての出力でそのようにラベル付けされました。
**無線側の検証。** ZMQループバックを備えたsrsRAN 4G — ソフトウェアのみでRF放射なし — により、
テストペイロードがNB-IoT PHYエンコーディングとトランスポートブロック配信を
正しく通過することを確認しました。
---
## 3. 攻撃面:NB-IoTとSIB1-NB
### 3.1 アソシエーション前の攻撃面
NB-IoT(Narrowband Internet of Things)は3GPP Release 13であり、既存のライセンス済みLTEスペクトルを使用して
制約のあるIoTデバイスを接続するように設計されています。これは、コンシューマ向けスマートフォンを
含む幅広い最新のセルラーSoCに実装されています。
RRC_IDLE中、RRC接続が確立される前に、サービスを探しているデバイスは
次のことを行います:
1. セルのタイミング信号(NPSS/NSSS)と同期する
2. NPBCH(640 ms送信ウィンドウ)でマスタ情報ブロックをデコードする
3. NPDSCH(2560 msスケジュール)からSIB1-NBをデコードする
4. SIB1-NBのスケジューリング情報を使用して追加のシステム情報ブロックを特定する
ステップ3で、モデムは認証していないエンティティからのメッセージを、接続やユーザー操作の前に処理します。
通常のセル選択条件を満たす不正な送信機は処理されます。```
+------------------+ +---------------------+
| Rogue Base Stn | | Target UE (Modem) |
+--------+---------+ +----------+----------+
| |
| NPSS/NSSS sync |
|--------------------------------------->|
| MIB-NB (640 ms cycle) |
|--------------------------------------->|
| SIB1-NB (malformed, si_count > 8) |
|--------------------------------------->| ← vulnerability triggered
| [no RRC connection established] |
SIB1-NB は 3GPP TS 36.331 で定義されている。その schedulingInfoList フィールドは、セルがブロードキャストする
System Information メッセージの数を保持し、仕様により最大8エントリ(1..maxSI-Message-NB-r13 = 8)に
制約されている。これはプロトコル層の制約である。メモリ安全性の制約、すなわちリスト長が
宛先配列の容量を超えてはならないという制約は、ファームウェアが別途
強制しなければならない。
しかし、それは強制されていなかった。
ファームウェアは Samsung CPパッケージから取得され、NCC Group の mtk_bp
ツールセットを用いて抽出された:```
md1img.img → md1_extract.py → 000_md1rom (17.8 MB code image)
→ 017_md1_dbginfo (XZ-compressed CATI debug symbols)
CATIデバッグセクションは、`mtk_dbg_extract.py symbols` で解凍・解析され、その後
`ImportSymbolsScript.py` を介してGhidraにインポートされた。その結果、モデムスタック全体 —
ERRCレイヤ、L1チャネル管理、IPCサブシステム、およびNB-IoT BCCHハンドラチェーン —
にわたる完全な内部関数名が得られ、意味論に基づくチェーン再構築が可能になった。
この記事内のすべての関数名は、ファームウェアイメージから抽出されたMediaTek独自の組み込み
デバッグシンボルに由来する。
---
## 5. 脆弱性
### 5.1 脆弱なループ
`el1_ch_nbcch_resume_req` (`0x90213940`) は、NB-IoTブロードキャストチャネルの再開イベントを処理する。
そのMIPS16e2関数プロローグ:```asm
90213940: save 0xE8, ra, s0-s1
SAVE 命令は sp を 0xE8 だけデクリメントし、呼び出し先保存レジスタを下方向に格納します:```
old_sp (= new_sp + 0xE8)
new_sp + 0xE4 saved ra ← overflow target
new_sp + 0xE0 saved s1
new_sp + 0xDC saved s0
new_sp + 0x98 si_sched_arr [34 halfwords = 68 bytes]
new_sp + 0x78 si_type_arr [32 bytes]
new_sp + 0x00 ← stack pointer after SAVE
実際のファームウェアバイナリのGhidra逆コンパイルから:```c
for (uVar6 = 0; uVar6 < (byte)param_2[0x40a]; uVar6 = uVar6 + 1) {
si_type_arr[uVar6] = /* SI type byte */; // 1 byte/iter, base new_sp+0x78
si_sched_arr[uVar6] = /* SI schedule halfword */; // 2 bytes/iter, base new_sp+0x98
}
param_2[0x40a] は ch_ctx[+0x40A] — チャネルコンテキストBSS構造体内の永続的なバイトである。
ループ境界は、配列容量に対する事前の比較なしに直接使用される。
ストリームA(半語 sh 書き込み)は new_sp+0x98 から始まり、反復ごとに2バイト進む。
それは反復38で new_sp+0xE4 にある保存済みRAに到達する:```
new_sp + 0x98 + i×2 = new_sp + 0xE4
i = (0xE4 - 0x98) / 2 = 0x4C / 2 = 38
ストリームB(バイト `sb` を書き込む)は `new_sp+0x78` から始まり、108回目の反復を必要とし
RAスロットに到達する:```
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108
si_count = 40(デモ用の値。オーバーフロー閾値38を超えるように選択)の場合、
ループは40回実行される。ストリームBがRAスロットに到達することはない。RA破壊は
完全にストリームAに由来する。
40回の反復後、MIPS16e2のRESTORE命令がスタックから破壊された値を$raへ再ロードし、
jrc raが制御を移す。
ch_ctx[+0x40A] は、0x90213444 の el1_ch_nbcch_start によって書き込まれる。間に何もない2つの連続するMIPS命令:```asm
; el1_ch_nbcch_start @ 0x90213444
lbu v0, 0x99(s0) ; read IPC_msg[+0x99] = si_count from CPHY_CFG_REQ
sb v0, 0x40A(s1) ; write to ch_ctx[+0x40A] — no clamp, no mask, no compare
### 5.4 ERRCビルダー — レイヤA
CPHY_CFG_REQバッファは、デコードされたSIB1-NBからERRCレイヤで構築されます。関数 `errc_chm_l1_set_bcch_si_reception` は `IPC_msg[+0x99]` を書き込みます:```c
// errc_chm_l1_set_bcch_si_reception — Layer A
// Loop bound: decoded schedulingInfoList entry count from SIB1-NB
while (bVar3 < *(byte *)(param_3 + 0x44) && (param_2 != 0)) {
bVar3++;
if (uVar2 != param_2) {
*param_5 = *param_5 + 1; // CPHY_CFG_REQ[+0x99]++ — no upper bound check
}
}
The loop bound is the decoded entry count from SIB1-NB. The counter increments once per decoded entry, for as many entries as were decoded, with no maximum guard.
Once the CPHY_CFG_REQ buffer is populated, ERRC dispatches it to L1 with sap_id = 0x501F
as the routing key:```
el1_ch_rcv_ilm (sap 0x501F)
→ el1_chmgm_errc_cfg_req_in_idle ← stores CPHY_CFG_REQ @ L1_ctx[+0x323C]
→ el1_chmgm_nbcch_handler
→ el1_ch_nbcch_main
→ el1_ch_nbcch_cphy_cfg_req_process ← validates cell identity, no si_count check
→ el1_ch_nbcch_start @ 0x90213444 ← Layer B: lbu + sb, no clamp
### 5.6 3層にわたるクランプ(制限処理)の欠如
| レイヤ | 機能 | アドレス | クランプの有無 |
|---|---|---|---|
| A — ERRCビルダー | `errc_chm_l1_set_bcch_si_reception` | ERRC範囲 | **なし** |
| B — L1コピー | `el1_ch_nbcch_start` | `0x90213444` | **なし** |
| C — L1ループ | `el1_ch_nbcch_resume_req` | `0x90213940` | **なし** |
いずれかのレイヤで1回でもチェックがあれば、この連鎖は断ち切れていた。
### 5.7 根本原因
1つの不変条件(インバリアント)が破られていた:
> SIスケジューリングエントリの数は、宛先配列の容量を決して超えてはならない。
3GPPは意図されたプロトコル上の上限(8エントリ)を定めている。ファームウェアは、そのカウントがインデックスやループ上限となるすべてのレイヤにおいて、メモリ安全性の上限を強制する必要があった。脆弱性のあるビルドでは、そのカウントはSIB1-NBのブロードキャストフィールドからERRCデコーダー、CPHY_CFG_REQメッセージ、IPC境界を越えてL1タスク、チャネルコンテキストBSS、そしてスタック書き込みループへと伝搬したが、どのレイヤでもクランプされることはなかった。
---
## 6. コールチェーン — 発見に至る経緯
### 6.1 2つの経路による混乱
構造的に類似しているが異なる2つの経路が、`el1_ch_nbcch_main` に0x760バイトの構成バッファを渡すことができる:
| 経路 | ソース | `[+0x99]` の値 | 関連性 |
|---|---|---|---|
| 経路A(ERRC → L1 IPC) | ERRCがデコード済みSIB1-NBからCPHY_CFG_REQを構築 | OTA由来の `schedulingInfoList.count` | **脆弱な経路** |
| 経路B(L1内部) | `el1_ch_scs_ind_send` が内部IPCボディを構築 | ハードコードされた `1` | 脆弱ではない |
経路Bはメッセージ形式を裏付けた — バイト `+0x99` は `el1_ch_nbcch_start` が消費するSIカウントである。そのカウントは常に1にハードコードされているため、オーバーフローは発生しない。外部から影響を受け得る経路は経路Aである。
### 6.2 書き込み箇所の探索
オフセット `+0x99` に書き込む命令をファームウェアからパターン検索すると、ノイズが生じた:T1(直接 `sb`、約100ヒット)、T2(ベース分割、5ヒット)、T3(計算オフセット、0)、T4(重複する `sh`/`sw`、約465)。`msg_send6` の相互参照リストにERRCのチャネル管理機能が含まれていなかったのは、ERRCが `errc_com_send_msg` を使用しているためである。エミュレーションプローブにより、書き込みがERRC側であることが確認された:L1ディスパッチャからUnicornハーネスを実行し、バッファの `+0x99` オフセットへの書き込みを監視しても、L1側からは何も捕捉されなかった。```
[RUN] dispatcher=0x90214418 watching IPC_msg+0x99
NO writes to IPC_msg+0x99 caught from dispatcher.
Write happened before el1_ch_nbcch_main — confirmed ERRC-side.
errc_com_send_msg 内の sap_id = 0x501F に続いて、el1_chmgm_errc_cfg_req_in_idle へのルーティングが特定され、そこが CPHY_CFG_REQ ポインタを L1_ctx[+0x323C] に格納し、下流へのディスパッチを開始する。
SIB1-NB schedulingInfoList.count (demonstrator: 40) │ ▼ [ERRC task] errc_chm_ch_ctrl_req_hdlr → errc_chm_call_ctrl → errc_chm_l1_main → errc_chm_l1_call_ctrl → errc_chm_l1_snd_cphy_cfg_req ← allocates 0x760-byte CPHY_CFG_REQ → errc_chm_l1_set_cphy_req_nbcch_cfg → errc_chm_l1_set_bcch_inf → errc_chm_l1_set_bcch_si_reception ← Layer A: CPHY_CFG_REQ[+0x99] = 40 → errc_com_send_msg(sap=0x501F) ← IPC to L1 │ ▼ [L1 task] el1_ch_rcv_ilm (sap 0x501F) → el1_chmgm_errc_cfg_req_in_idle ← stores CPHY_CFG_REQ @ L1_ctx[+0x323C] → el1_chmgm_nbcch_handler → el1_ch_nbcch_main → el1_ch_nbcch_cphy_cfg_req_process ← no si_count validation → el1_ch_nbcch_start @ 0x90213444 ← Layer B: lbu + sb, no clamp │ ▼ ch_ctx[0x40A] = 40 (persists in BSS) │ ▼ [state machine advances to 0x0B, event 0x2C] el1_ch_nbcch_resume_req @ 0x90213940 ← Layer C: loop bound from ch_ctx[0x40A] │ ▼ stack overflow → jrc ra → PC = attacker-controlled
---
## 7. 検証
この特定のSM-A145Rモデルは、通常の出荷ビルド動作では
脆弱なNB-IoTコードパスを実行しないように見えるため、直接のハードウェア再現ではなく、ハイブリッド
エミュレーションと静的解析が使用された。
**静的解析で証明された。** ファームウェアバイナリには脆弱な命令ペアが含まれている。呼び出し
チェーンは、シンボル、相互参照、逆コンパイルされた関数本体から再構築される。
**エミュレーション内でネイティブ実行された。** `el1_ch_nbcch_resume_req` 内のループは、実際の
MediaTekファームウェアのバイト列上でUnicorn Engine(MIPS32)内で実行された。ファームウェア自身の`sh`命令は
`0x90213B02` で保存済み戻りアドレススロットに書き込んだ。`RESTORE`命令は
破損した値を`$ra`にロードし、`jrc ra`が制御を移した。
**明示的にモデル化された。** `el1_ch_nbcch_start` 内の`lbu`/`sb`コピーは、完全には
ネイティブ実行できなかった。なぜなら `el1_ch_nbcch_cphy_cfg_req_
process` 内のRTOSコールバックテーブルディスパッチパスが、フラットエミュレータが提供しなかったライブなNucleusヒープオブジェクトを期待していたためである。フェーズ2の再開ハンドラ(`el1_ch_nbcch_resume_req`)はBSS常駐チャネルコンテキストからのみ読み取り、
同じディスパッチパスには該当しない。そのためフェーズ2は
同じ足場を必要とせずにネイティブ実行された。フェーズ1の副作用 — `IPC_msg[+0x99]` からの1バイトが
`ch_ctx[+0x40A]` に書き込まれる — は直接モデル化され、`[PHASE1-MODEL]` とラベル付けされた。
**主張しない。** 完全なエンドツーエンドの無線(over-the-air)ハードウェア再現。
### 7.1 改ざん防止
ハーネスは1つのルールを強制した。保存済み戻りアドレススロットに証明マーカーを書き込むフックは許可されなかった。
ファームウェア以外のメモリ書き込みはすべて追跡された。```
[PROOF-W] saved_RA write: pc=0x90213b02 addr=new_sp+0xE4 value=0xbeef
[PROOF-W] saved_RA write: pc=0x90213b02 addr=new_sp+0xE6 value=0xdead
[ANTI-TAMPER] no hook wrote RA=0xDEADBEEF — firmware only
anti_tamper_fail = False
0x90213B02 はループ本体内部の sh 命令です。ファームウェアはこれらのバイトを
予測されたスタックオフセットに配置しました。リトルエンディアンのストレージでは、ハーフワード 0xBEEF と 0xDEAD は
new_sp+0xE4 と new_sp+0xE6 にあり、結合されて [ef be ad de] = 0xDEADBEEF になります。
[REGS] RA = 0xdeadbeef ← firmware wrote this; decisive proof PC = 0x00000000 ← Unicorn unmapped-fetch artifact, not a hardware exception vector
[STACK] new_sp+0xE4: [ef be ad de] ← little-endian 0xDEADBEEF
[PC-EXPLAIN] PC=0 is an unmapped-fetch artifact; decisive proof is RA=0xDEADBEEF + stack bytes [ef be ad de] + [PROOF-JRC] CONFIRMED: saved RA = 0xDEADBEEF
### 7.3 ZMQ配信
テストペイロードがNB-IoT PHYエンコーディングとトランスポートブロック配信を経ても損なわれないことを確認するため、srsRAN
4G(ZMQループバック、RF放射なし)が使用された。ペイロードは意図的に
非準拠のベクターであり、`schedulingInfoList` のASN.1 SIZE制約は40エントリを許可するよう緩和され、
pycrateのラウンドトリップデコードによってバイト14のカウントフィールドが確認された。```
SIB1 received
SIB2 activated
exit 0
これにより、トランスポート層での配信が確認される。ファームウェア側のASN.1動作は、 Layer Aの静的解析によって確立される。
el1_ch タスクはスタックを1つ持つ。Phase 1 と Phase 2 は、同じタスクによって順次処理される2つの別々のIPCイベントであり、
その間にスタックは完全に巻き戻される。カウントはスタック上ではなく、
チャネルコンテキストのBSSに保持される。```
EVENT: CPHY_CFG_REQ (Phase 1)
el1_ch_nbcch_start
lbu v0, 0x99(s0)
sb v0, 0x40A(s1) ← ch_ctx[0x40A] = attacker value, written to BSS
returns — stack fully unwound
EVENT: resume (state 0x0B, msg 0x2C) (Phase 2) el1_ch_nbcch_resume_req ← frame 0xE8, reads ch_ctx[0x40A] as loop bound loop × 40 → saved RA corrupted jrc ra → attacker-controlled PC
`ch_ctx[0x40A]` はBSSセクションに存在し、モデムがリセットされるか、後続のチャネル設定によって上書きされるまで、攻撃者の値を保持します。
### 8.2 スタックフレーム```
old_sp (= new_sp + 0xE8)
new_sp + 0xE4 saved ra
new_sp + 0xE0 saved s1
new_sp + 0xDC saved s0
new_sp + 0x98 si_sched_arr [34 halfwords = 68 bytes]
new_sp + 0x78 si_type_arr [32 bytes]
Frame size confirmed by emulation measurement. Array positions confirmed by the emulation
result — RA written at iteration 38, consistent with si_sched_arr starting at new_sp+0x98.
| ビルド | モデムファームウェア | ビルド日 |
|---|---|---|
| 脆弱 | A145RXXU1AWD1, MOLY LR12A...V1.P5 | 2023-04-18 |
| パッチ適用済み | A145RXXUDDZC2, MOLY LR12A...V3.P8 | 2025-04-23 |
ビルド日は、両イメージから md1_dbginfo メタデータを抽出することで確認した。パッチ ID: MOLY00720348 · イシュー ID: MSV-2392。
el1_ch_nbcch_start(脆弱なバイナリでは 0x90213444): lbu/sb 命令ペアは存在しない。IPC_msg[+0x99] から ch_ctx[+0x40A] への直接コピーは削除された。
el1_ch_nbcch_resume_req(脆弱なバイナリでは 0x90213940): ch_ctx[0x40A] に対するスタック書き込みループは存在しない。信頼できないバイトが固定サイズのスタック配列のループ境界になるという構造はもはや存在しない。関数本体は別のディスパッチ構造に置き換えられている。
errc_chm_l1_set_bcch_si_reception: 無制限のカウンタループは、検証指向のヘルパー呼び出しに置き換えられている。
パッチ適用済みバイナリに存在し、脆弱なバイナリには存在しない関数が 2 つあります。``` el1_ch_nbcch_param_check el1_ch_scell_param_check
### 10.4 CVE 帰属
ここで説明する脆弱性は、MediaTek が2025年1月6日に公開した CVE-2024-20154 に一致します。確認の根拠は以下のとおりです。
- 影響を受けるファームウェアファミリー (LR12A) が MediaTek のセキュリティ情報と一致する。
- 脆弱性の分類(スタックオーバーフロー、境界チェック欠如、不正基地局からの RCE、ユーザー操作不要)が CVE の説明および NVD の記録と一致する。
- パッチ適用済みファームウェアは、脆弱性が特定されたコード構造を正確に削除している。
- パッチ ID MOLY00720348 が MediaTek のセキュリティ情報および Android セキュリティ情報 (A-376809176) から確認される。
- AI 支援による解析は、手動での確認前に、再構築されたパターンを独立して CVE-2024-20154 に照合した。
---
## 11. 倫理と責任ある開示
### 11.1 この投稿に含まれないもの
兵器化されたエクスプロイトは含まれません。ファームウェアバイナリの内容も含まれません。不正なペイロードバイトも含まれません。実機に対して脆弱性を発動させる手順書も含まれません。動作する攻撃を再現するために必要な情報(特定のモデムデコーダ向けの完全なペイロード構築、完全な Phase 1 エミュレーションのための RTOS ヒープオブジェクトの足場、無線のオーバー・ジ・エア構成)は、意図的に省かれています。
### 11.2 ZMQ ループバックとエミュレーションが倫理的なアプローチである理由
ZMQ ループバックは、電波として信号が一切送信されていないことを意味します。実機は標的にされていません。キャリアネットワークも関与していません。この実証は、解析者が所有するハードウェア上の隔離されたソフトウェア環境でのみ実行されます。これは、関連付け前の無線脆弱性を検証するための正しいアプローチです。不正なブロードキャストを送信すると、電波範囲内のすべてのデバイスに影響を及ぼすからです。
Unicorn エミュレーションは、脆弱な動作がファームウェアバイナリ自体に存在し、特定のデバイス状態や無線環境に依存せずに再現可能であることを示します。これは単一のハードウェアクラッシュよりも技術的に強力な主張であり、電波として何かを展開することも回避します。
### 11.3 MediaTek の知的財産
すべての解析は、一般消費者向けデバイスおよび Samsung が公開しているファームウェアパッケージから正当に入手したファームウェアに対して実施されました。プロプライエタリな文書は使用されていません。MediaTek 内部の構造体定義と IPC メッセージ形式は、メモリ安全性の障害を説明するために必要な範囲でのみ記述されています。これらは仕様として公開されるものではありません。
---
| 反復 | shの書き込み先 | 影響 |
|---|
| 0–33 | si_sched_arr[0..33] | 範囲内 |
| 34–35 | new_sp+0xDC — 保存済みs0 | s0破壊 |
| 36–37 | new_sp+0xE0 — 保存済みs1 | s1破壊 |
| 38 | new_sp+0xE4 — 保存済みra [15:0] | RA下位ハーフワード |
| 39 | new_sp+0xE6 — 保存済みra [31:16] | RA上位ハーフワード |
| ゲート | 条件 | 確認箇所 |
|---|
| NB-IoT アクティブパス | cfg_type == 1 | el1_ch_nbcch_cphy_cfg_req_process |
| チャネル未完了 | done_flag == 0 | ch_ctx[0x438] |
ステートマシン 0x0B | NBCCH がレジューム状態 | el1_ch_nbcch_main ディスパッチ |
| si_count が非ゼロ | ch_ctx[0x40A] > 0 | ループ条件 |
| バンドクラス ≤ 2 | 有効な NB-IoT モード | el1_ch_nbcch_resume_req の入口 |
el1_chmgm_cell_info_get が非ゼロ | サービス表内のセル | el1_ch_nbcch_start で呼び出し |
| 関数 | アドレス | 役割 | クランプ? |
|---|
errc_chm_l1_set_bcch_si_reception | ERRC 範囲 | CPHY_CFG_REQ[+0x99] に書き込む | なし |
el1_ch_nbcch_cphy_cfg_req_process | 0x90213F80 | CPHY 設定を L1 にルーティングする | N/A — si_count を読み取らない |
el1_chmgm_cell_info_get | 0x9020E0D0 | EARFCN/PCI を検証する | N/A |
el1_ch_nbcch_start | 0x90213444 | カウントを BSS にコピーする | なし |
el1_ch_nbcch_resume_req | 0x90213940 | カウントをループ境界として使用する | なし |