
Writeup tecnico per CVE-2024-20154
Classificazione: CWE-121 — Buffer overflow basato su stack
Severità: Critica (bollettino MediaTek) · 8.8 Alto, Vettore di attacco: Adiacente (CISA-ADP)
Tipo: Esecuzione di codice remota — nessuna interazione con l'utente, nessuna associazione precedente
Divulgazione: Bollettino di sicurezza MediaTek, 6 gennaio 2025 https://corp.mediatek.com/product-security-bulletin/January-2025
Target analizzato: Samsung Galaxy A14 SM-A145R — famiglia MT6769 (Helio G80), all'interno dell'elenco dei chipset interessati di MediaTek - Il firmware è stato emulato in condizioni sicure.
Stato: Patch applicata.
Questa è stata la mia prima ricerca pubblicata sul baseband. Vengo da un background lontano dalle infrastrutture di telecomunicazione, dai livelli di mediazione per l'intercettazione legale, dall'analisi di stingray e IMSI-catcher, e dalla sicurezza dei dispositivi embedded — non avevo mai fatto prima un reverse engineering approfondito del firmware su un modem cellulare. Volevo dimostrare a me stesso che una metodologia analitica strutturata si adatta a tutti i target, e che la familiarità con una piattaforma specifica può essere sostituita da un rigoroso tracciamento della catena. NB-IoT si è distinto perché si trova a un'intersezione davvero pericolosa: il protocollo è progettato per dispositivi IoT vincolati, la superficie d'attacco è pre-associazione, e lo stack del modem lo elabora indipendentemente da ciò che l'utente del telefono sta facendo.
Quando il firmware con patch è stato analizzato e il pattern vulnerabile confermato assente, il sistema di IA usato per l'analisi di massa del firmware prima di indirizzare funzioni specifiche
ha associato in modo indipendente la classe del bug ricostruita, le condizioni e la famiglia di firmware interessata alla descrizione di CVE-2024-20154.
Le conclusioni tecniche sono dell'analista.
Il telefono nella tua tasca contiene almeno due computer separati. Quello con cui interagisci esegue Android. L'altro — il baseband — funziona in modo completamente indipendente, gestisce tutte le comunicazioni radio, ed è quasi del tutto invisibile al sistema operativo che lo sovrasta. Android potrebbe essere completamente patchato. Il browser potrebbe essere in sandbox. L'utente potrebbe non toccare mai un link malevolo. Nulla di tutto questo ha importanza se il codice vulnerabile si trova nel firmware del modem che elabora i segnali radio prima che il processore dell'applicazione venga coinvolto.
CVE-2024-20154 è esattamente quel tipo di vulnerabilità.
Una trasmissione di system-information NB-IoT malformata porta il firmware del modem MediaTek ad accettare un conteggio di schedulazione controllato dall'attaccante, trasportare quel conteggio attraverso il percorso di configurazione RRC-to-L1 senza mai limitarlo, e infine usarlo come limite del ciclo per un ciclo di scrittura sullo stack all'interno del gestore del canale broadcast NB-IoT. Quando il conteggio supera la capacità degli array di destinazione, il ciclo scrive oltre i loro limiti, raggiunge i registri salvati sullo stack e sovrascrive l'indirizzo di ritorno salvato. La funzione quindi ripristina il valore corrotto nel registro dell'indirizzo di ritorno e salta a esso.
Ciò che rende così grave la vulnerabilità:
La vulnerabilità è stata pubblicata nel bollettino di sicurezza di MediaTek del 6 gennaio 2025 con una valutazione di gravità critica, che colpisce tra le altre la famiglia di modem LR12A. Samsung ha incorporato la correzione nella release di manutenzione della sicurezza di febbraio 2025.
Questo post non pubblica un exploit weaponizzato e non è riproducibile da ciò che è pubblicato qui. L'obiettivo è mostrare dove si rompe la catena, perché ogni livello non è riuscito a fermarla, e cosa serve per validare responsabilmente un bug del baseband quando non è possibile collegare un debugger al modem live.
Target primario: Samsung Galaxy A14 (SM-A145R). Il sottosistema radio è gestito da un processore baseband MediaTek della famiglia di chipset MT6769 (Helio G80). La famiglia MT6769 è esplicitamente elencata nell'elenco dei chipset interessati di MediaTek per CVE-2024-20154.``` AP/CP firmware: A145RXXU1AWD1 Modem software: MOLY LR12A.R3.TC10.6M.A14.PR.SP.V1.P5 Build date: 2023-04-18
Il firmware di baseband non è codice Android. È un sistema embedded separato nel sottosistema radio del SoC, con la propria CPU, il proprio RTOS e il proprio spazio di memoria, al di fuori della sandbox dei processi Android.
### 2.2 Architettura del modem
L'analisi del binario estratto mostra che il processore del modem esegue MIPS32 con istruzioni compresse MIPS16e2 in modalità little-endian. MIPS16e2 è un'estensione di codifica a 16 bit per la riduzione della dimensione del codice negli embedded — in linea con l'approccio di MediaTek per le baseband della generazione Helio, confermato da ricerche indipendenti pubblicate sulla baseband di questa famiglia di SoC.
Il sistema operativo è Nucleus RTOS, che fornisce scheduling dei task, code di messaggi IPC e un allocatore di memoria basato su pool. Non esiste separazione dei privilegi kernel/utente, nessuna applicazione della memory protection unit tra i task e nessun meccanismo hardware di stack guard.
Tutti gli indirizzi in questo post sono indirizzi virtuali, come caricati in Ghidra alla base `0x90000000`.
### 2.3 Mitigazioni (osservate nella build analizzata)
| Mitigazione | Stato | Effetto |
|---|---|---|
| ASLR | Assente | Gli indirizzi del firmware sono statici e prevedibili dall'immagine |
| Stack canary | Assente | `SAVE`/`RESTORE` salva i registri callee-saved senza valore di guardia |
| NX / W^X | Assente | La memoria dello stack è eseguibile |
| CFI | Assente | Gli indirizzi di ritorno non vengono validati rispetto ad alcuna policy |
### 2.4 Approccio di analisi
Tre percorsi paralleli:
**Analisi statica.** Pacchetto firmware Samsung → estrazione della partizione CP → `md1img.img` → Ghidra (MIPS LE 32-bit, base `0x90000000`) con i simboli engineering MediaTek recuperati dalla sezione di debug del firmware utilizzando il toolset NCC Group `mtk_bp`.
**Validazione dinamica.** Unicorn Engine (emulazione MIPS32) è stato utilizzato per eseguire routine specifiche del firmware in isolamento in due fasi. La fase 1 ha tentato di dimostrare la copia non limitata di `si_count` nel contesto del canale tramite la coppia di istruzioni native. La fase 2 ha eseguito il loop vulnerabile su byte reali del firmware e ha confermato che le istruzioni del firmware stesso corrompono l'indirizzo di ritorno salvato. Laddove la fase 1 non poteva essere eseguita completamente in modo nativo — poiché l'ambiente degli oggetti di servizio RTOS richiesto dal percorso di dispatch CPHY non era stato ricostruito — l'effetto collaterale è stato modellato direttamente ed etichettato come tale in tutti gli output.
**Validazione lato radio.** srsRAN 4G con un loopback ZMQ — solo software, nessuna emissione RF — ha confermato che il payload di test sopravvive alla codifica PHY NB-IoT e alla consegna del transport block.
---
## 3. Superficie d'attacco: NB-IoT e SIB1-NB
### 3.1 Superficie d'attacco pre-associazione
NB-IoT (Narrowband Internet of Things) è la Release 13 del 3GPP, progettata per connettere dispositivi IoT vincolati utilizzando lo spettro LTE concesso in licenza esistente. È implementato in un'ampia gamma di SoC cellulari moderni, inclusi quelli negli smartphone consumer.
Mentre è in RRC_IDLE, prima che venga stabilita qualsiasi connessione RRC, un dispositivo in cerca di servizio:
1. Si sincronizza con i segnali di temporizzazione della cella (NPSS/NSSS)
2. Decodifica il Master Information Block su NPBCH (finestra di trasmissione di 640 ms)
3. Decodifica SIB1-NB da NPDSCH (pianificazione di 2560 ms)
4. Usa le informazioni di pianificazione in SIB1-NB per individuare ulteriori blocchi di informazioni di sistema
Al passaggio 3, il modem elabora un messaggio da un'entità che non ha autenticato, prima di qualsiasi connessione o interazione con l'utente. Un trasmettitore rogue che soddisfa le normali condizioni di selezione della cella verrà elaborato.```
+------------------+ +---------------------+
| 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 è definito in 3GPP TS 36.331. Il suo campo schedulingInfoList indica quanti
messaggi di System Information la cella trasmette, vincolato dalla specifica a un massimo di 8
voci (1..maxSI-Message-NB-r13 = 8). Questo è un vincolo a livello di protocollo. Il
vincolo di sicurezza della memoria — che la lunghezza dell'elenco non deve superare la capacità
degli array di destinazione — deve essere applicato separatamente dal firmware.
Non lo era.
Il firmware è stato ottenuto da un pacchetto CP Samsung ed estratto utilizzando il toolset mtk_bp
di NCC Group:```
md1img.img → md1_extract.py → 000_md1rom (17.8 MB code image)
→ 017_md1_dbginfo (XZ-compressed CATI debug symbols)
La sezione di debug CATI è stata decompressa e analizzata con `mtk_dbg_extract.py symbols`, quindi
importata in Ghidra tramite `ImportSymbolsScript.py`. Il risultato è stato un insieme completo di nomi di funzione
interni in tutto lo stack del modem — livello ERRC, gestione canali L1, sottosistema IPC e la
catena di handler BCCH NB-IoT — consentendo una ricostruzione della catena guidata dalla semantica.
Tutti i nomi di funzione in questo post provengono dai simboli di debug embedded di MediaTek estratti
dall'immagine del firmware.
---
## 5. Vulnerabilità
### 5.1 Il loop vulnerabile
`el1_ch_nbcch_resume_req` (`0x90213940`) gestisce l'evento di ripresa del canale broadcast NB-IoT.
Il suo prologo di funzione MIPS16e2:```asm
90213940: save 0xE8, ra, s0-s1
L'istruzione SAVE decrementa sp di 0xE8 e memorizza i registri callee-saved verso il basso:```
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
Dalla decompilazione Ghidra del binario firmware effettivo:```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] — un byte persistente nella struct BSS del contesto del canale.
Il limite del ciclo viene usato direttamente, senza alcun confronto preventivo con le capacità degli array.
Il flusso A (scritture halfword sh) inizia a new_sp+0x98 e avanza di 2 byte per iterazione.
Raggiunge il RA salvato a new_sp+0xE4 all'iterazione 38:```
new_sp + 0x98 + i×2 = new_sp + 0xE4
i = (0xE4 - 0x98) / 2 = 0x4C / 2 = 38
Stream B (scritture del byte `sb`) inizia a `new_sp+0x78` e richiederebbe l'iterazione 108 per raggiungere lo slot RA:```
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108
Con si_count = 40 (il valore dimostrativo, scelto per superare la soglia di overflow di 38)
il ciclo esegue 40 iterazioni. Stream B non raggiunge mai lo slot RA. La corruzione di RA proviene
interamente da Stream A.
Dopo 40 iterazioni, l'istruzione MIPS16e2 RESTORE ricarica il valore corrotto dallo stack
in $ra e jrc ra trasferisce il controllo.
ch_ctx[+0x40A] viene scritto da el1_ch_nbcch_start a 0x90213444. Due istruzioni MIPS consecutive
senza nulla in mezzo:```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 Il builder ERRC — Layer A
Il buffer CPHY_CFG_REQ viene costruito nel layer ERRC a partire dal SIB1-NB decodificato. La funzione
`errc_chm_l1_set_bcch_si_reception` scrive `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
}
}
Il limite del ciclo è il conteggio delle voci decodificate da SIB1-NB. Il contatore viene incrementato una volta per ogni voce decodificata, per tutte le voci decodificate, senza alcun limite massimo.
Una volta che il buffer CPHY_CFG_REQ è popolato, ERRC lo invia a L1 con sap_id = 0x501F come chiave di instradamento:```
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 Assenza di limitazione su tre livelli
| Livello | Funzione | Indirizzo | Limitazione presente? |
|---|---|---|---|
| A — Costruttore ERRC | `errc_chm_l1_set_bcch_si_reception` | Intervallo ERRC | **Nessuna** |
| B — Copia L1 | `el1_ch_nbcch_start` | `0x90213444` | **Nessuna** |
| C — Ciclo L1 | `el1_ch_nbcch_resume_req` | `0x90213940` | **Nessuna** |
Un singolo controllo su uno qualsiasi dei livelli avrebbe spezzato la catena.
### 5.7 Causa principale
Una singola invariante violata:
> Il numero di voci di pianificazione SI non deve mai superare la capacità dell'array di destinazione.
Il 3GPP fornisce il limite di protocollo previsto (8 voci). Il firmware doveva imporre il
limite di sicurezza della memoria a ogni livello in cui il conteggio diventa un indice o un limite di ciclo. Nella
build vulnerabile, il conteggio viaggiava dal campo broadcast SIB1-NB attraverso il
decoder ERRC, nel messaggio CPHY_CFG_REQ, oltre il confine IPC nel task L1, nel
contesto di canale BSS e in un ciclo di scrittura sullo stack — senza alcuna limitazione a nessun livello.
---
## 6. La Catena di Chiamate — Come è stata Trovata
### 6.1 La confusione tra due percorsi
Due percorsi strutturalmente simili ma distinti possono consegnare un buffer di configurazione da 0x760 byte a
`el1_ch_nbcch_main`:
| Percorso | Origine | Valore `[+0x99]` | Rilevanza |
|---|---|---|---|
| Percorso A (ERRC → IPC L1) | ERRC costruisce CPHY_CFG_REQ dal SIB1-NB decodificato | `schedulingInfoList.count` da OTA | **Il percorso vulnerabile** |
| Percorso B (interno L1) | `el1_ch_scs_ind_send` costruisce il corpo IPC interno | `1` hardcoded | Non vulnerabile |
Il percorso B ha confermato il formato del messaggio — il byte `+0x99` è il conteggio SI consumato da
`el1_ch_nbcch_start`. Poiché il suo conteggio è sempre hardcoded a 1, non può causare overflow. Il
percorso influenzato esternamente è il Percorso A.
### 6.2 La ricerca dello scrittore
La ricerca per pattern nel firmware di qualsiasi istruzione che scrivesse all'offset `+0x99` ha prodotto rumore:
T1 (`sb` diretto, ~100 hit), T2 (base suddivisa, 5 hit), T3 (offset calcolato, 0), T4
(`sh`/`sw` sovrapposti, ~465). Le funzioni di gestione del canale ERRC erano assenti dall'elenco dei
cross-reference di `msg_send6` perché ERRC usa `errc_com_send_msg`. Una sonda di emulazione
ha confermato che la scrittura avveniva lato ERRC: eseguendo l'harness Unicorn dal dispatcher L1 e
monitorando le scritture all'offset `+0x99` del buffer non è stato catturato nulla dal lato 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.
Seguendo sap_id = 0x501F in errc_com_send_msg è stata identificata la route verso
el1_chmgm_errc_cfg_req_in_idle, che memorizza il puntatore CPHY_CFG_REQ in
L1_ctx[+0x323C] e avvia la dispatch a valle.
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. Validazione
Questa specifica variante SM-A145R non sembra esercitare il percorso di codice NB-IoT vulnerabile nelle normali operazioni della build di produzione, motivo per cui sono state utilizzate emulazione ibrida e analisi statica anziché riproduzione diretta su hardware.
**Provato staticamente.** Il binario del firmware contiene la coppia di istruzioni vulnerabile. La catena di chiamate è ricostruita da simboli, riferimenti incrociati e corpi di funzioni decompilati.
**Eseguito nativamente in emulazione.** Il ciclo all'interno di `el1_ch_nbcch_resume_req` è stato eseguito su byte reali del firmware MediaTek in Unicorn Engine (MIPS32). L'istruzione `sh` del firmware stesso a `0x90213B02` ha scritto nello slot salvato dell'indirizzo di ritorno. L'istruzione `RESTORE` ha caricato il valore corrotto in `$ra` e `jrc ra` ha trasferito il controllo.
**Modellato esplicitamente.** La copia `lbu`/`sb` in `el1_ch_nbcch_start` non ha potuto essere eseguita completamente in modo nativo perché il percorso di dispatch della tabella di callback RTOS all'interno di `el1_ch_nbcch_cphy_cfg_req_process` si aspettava oggetti heap Nucleus live che l'emulatore piatto non forniva. L'handler di ripresa (`el1_ch_nbcch_resume_req`) nella Fase 2 legge solo dal contesto del canale residente in BSS e non passa attraverso lo stesso percorso di dispatch, motivo per cui la Fase 2 è stata eseguita nativamente senza richiedere lo stesso scaffolding. L'effetto collaterale della Fase 1 — un byte da `IPC_msg[+0x99]` scritto in `ch_ctx[+0x40A]` — è stato modellato direttamente ed etichettato `[PHASE1-MODEL]`.
**Non affermato.** Una riproduzione hardware completa end-to-end over-the-air.
### 7.1 Anti-manomissione
L'harness ha imposto una sola regola: nessun hook era autorizzato a scrivere il marker di prova nello slot salvato dell'indirizzo di ritorno. Ogni scrittura di memoria non appartenente al firmware è stata tracciata.```
[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 è l'istruzione sh all'interno del corpo del ciclo. Il firmware ha posizionato questi byte all'offset di stack previsto. Nella memorizzazione little-endian, le halfword 0xBEEF e 0xDEAD a new_sp+0xE4 e new_sp+0xE6 si combinano in [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 Consegna ZMQ
Per confermare che il payload di test sopravvive alla codifica PHY NB-IoT e alla consegna del transport-block, srsRAN
4G con un loopback ZMQ (nessuna emissione RF) è stato utilizzato. Il payload era un vettore volutamente
non conforme: il vincolo SIZE ASN.1 su `schedulingInfoList` è stato allentato per
consentire 40 voci, con decodifica round-trip di pycrate che conferma il campo contatore al byte 14.```
SIB1 received
SIB2 activated
exit 0
Ciò conferma la consegna a livello di trasporto. Il comportamento ASN.1 lato firmware è definito dall'analisi statica del Layer A.
Il task el1_ch ha uno stack. La Fase 1 e la Fase 2 sono due eventi IPC separati elaborati
sequenzialmente dallo stesso task, con lo stack che si svolge completamente tra di essi. Il contatore
persiste nel BSS del contesto di canale, non sullo stack:```
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]` risiede in BSS e conserva il valore dell'attaccante finché il modem non si riavvia o una successiva configurazione del canale non lo sovrascrive.
### 8.2 Stack frame```
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]
Dimensione del frame confermata tramite misurazione in emulazione. Posizioni dell'array confermate dal risultato dell'emulazione — RA scritto all'iterazione 38, coerente con si_sched_arr che inizia a new_sp+0x98.
| Build | Firmware del modem | Data di build |
|---|---|---|
| Vulnerabile | A145RXXU1AWD1, MOLY LR12A...V1.P5 | 2023-04-18 |
| Patchato | A145RXXUDDZC2, MOLY LR12A...V3.P8 |
Date di build confermate estraendo i metadati md1_dbginfo da entrambe le immagini. Patch ID:
MOLY00720348 · Issue ID: MSV-2392.
el1_ch_nbcch_start (0x90213444 nel binario vulnerabile): La coppia di istruzioni
lbu/sb è assente. La copia diretta di IPC_msg[+0x99] in ch_ctx[+0x40A] non è più presente.
el1_ch_nbcch_resume_req (0x90213940 nel binario vulnerabile): Il loop di scrittura
nello stack basato su ch_ctx[0x40A] è assente. L'architettura in cui un byte non attendibile
diventa un limite del loop su array di stack a dimensione fissa non esiste più. Il corpo della
funzione è sostituito con una diversa
struttura di dispatch.
errc_chm_l1_set_bcch_si_reception: Il loop del contatore senza limiti è sostituito con
chiamate a helper orientati alla validazione.
Due funzioni presenti nel binario patchato sono assenti dal binario vulnerabile:``` el1_ch_nbcch_param_check el1_ch_scell_param_check
Un controllo dei limiti di una sola riga apparirebbe come poche istruzioni aggiunte all'interno di una funzione esistente allo stesso indirizzo. Ciò che mostra il binario corretto è una revisione architetturale: il percorso di pianificazione NBCCH è stato riprogettato in modo che il pattern `si_count`-come-limite-del-ciclo non esista più da nessuna parte nel percorso.
### 10.4 Attribuzione CVE
La vulnerabilità qui descritta corrisponde a CVE-2024-20154 come pubblicato da MediaTek il 6 gennaio 2025. Base di conferma:
- La famiglia di firmware interessata (LR12A) corrisponde al bollettino di MediaTek.
- Classe di vulnerabilità — stack overflow, controllo dei limiti mancante, RCE da stazione base rogue, nessuna interazione dell'utente — corrisponde alla descrizione della CVE e al record NVD.
- Il firmware corretto rimuove esattamente le strutture di codice identificate come vulnerabili.
- L'ID della patch MOLY00720348 è stato confermato dal bollettino di MediaTek e dall'Android Security Bulletin (A-376809176).
- L'analisi assistita da IA ha associato in modo indipendente il pattern ricostruito a CVE-2024-20154 prima della conferma manuale.
---
## 11. Etica e Divulgazione Responsabile
### 11.1 Cosa non contiene questo post
Nessun exploit armato. Nessun contenuto binario del firmware. Nessun byte di payload malformato. Nessuna procedura passo-passo per attivare la vulnerabilità contro un dispositivo reale. Le informazioni necessarie per riprodurre un attacco funzionante — costruzione completa del payload per il decoder modem specifico, scaffolding degli oggetti heap RTOS per la piena emulazione della Fase 1, configurazione radio over-the-air — sono deliberatamente assenti.
### 11.2 Perché il loopback ZMQ e l'emulazione sono l'approccio etico
Il loopback ZMQ significa che nessun segnale è mai stato trasmesso via etere. Nessun dispositivo reale è stato preso di mira. Nessuna rete di operatore è stata coinvolta. La dimostrazione viene eseguita interamente in un ambiente software contenuto su hardware di proprietà dell'analista. Questo è l'approccio corretto per validare una vulnerabilità radio pre-associazione — trasmettere una trasmissione broadcast malformata colpirebbe qualsiasi dispositivo nel raggio d'azione.
L'emulazione Unicorn dimostra che il comportamento vulnerabile è nel binario del firmware stesso, in modo riproducibile, indipendentemente da qualsiasi stato specifico del dispositivo o ambiente radio. Questa è un'affermazione tecnicamente più forte di un singolo crash hardware ed evita di distribuire qualsiasi cosa via etere.
### 11.3 Proprietà intellettuale di MediaTek
Tutte le analisi sono state eseguite su firmware ottenuto legittimamente da un dispositivo consumer e dai pacchetti di firmware rilasciati pubblicamente da Samsung. Nessuna documentazione proprietaria è stata utilizzata. Le definizioni interne delle struct MediaTek e i formati dei messaggi IPC sono descritti solo nella misura necessaria a spiegare il fallimento della memory safety. Non vengono pubblicati come specifiche.
---
| Iterazione | sh scrive in | Effetto |
|---|
| 0–33 | si_sched_arr[0..33] | Nei limiti |
| 34–35 | new_sp+0xDC — s0 salvato | s0 corrotto |
| 36–37 | new_sp+0xE0 — s1 salvato | s1 corrotto |
| 38 | new_sp+0xE4 — ra salvato [15:0] | halfword bassa di RA |
| 39 | new_sp+0xE6 — ra salvato [31:16] | halfword alta di RA |
| Gate | Condizione | Dove controllato |
|---|
| Percorso attivo NB-IoT | cfg_type == 1 | el1_ch_nbcch_cphy_cfg_req_process |
| Canale non completo | done_flag == 0 | ch_ctx[0x438] |
Macchina a stati 0x0B | NBCCH nello stato resume | dispatch di el1_ch_nbcch_main |
| si_count diverso da zero | ch_ctx[0x40A] > 0 | Condizione del loop |
| Classe di banda ≤ 2 | Modalità NB-IoT valida | Ingresso di el1_ch_nbcch_resume_req |
el1_chmgm_cell_info_get diverso da zero | Cella nella tabella di servizio | Chiamata in el1_ch_nbcch_start |
| Funzione | Indirizzo | Ruolo | Limitazione? |
|---|
errc_chm_l1_set_bcch_si_reception | Intervallo ERRC | Scrive CPHY_CFG_REQ[+0x99] | Nessuna |
el1_ch_nbcch_cphy_cfg_req_process | 0x90213F80 | Instrada la configurazione CPHY verso L1 | N/A — non legge si_count |
el1_chmgm_cell_info_get | 0x9020E0D0 | Valida EARFCN/PCI | N/A |
el1_ch_nbcch_start | 0x90213444 | Copia il contatore in BSS | Nessuna |
el1_ch_nbcch_resume_req | 0x90213940 | Usa il contatore come limite del loop | Nessuna |
| 2025-04-23 |