
Analisi tecnica di CVE-2024-20154, un buffer overflow basato su stack nel firmware del baseband NB-IoT MediaTek MT6769, che copre il reverse engineering e la catena di exploit.
Classificazione: CWE-121 — Stack-based Buffer Overflow
Gravità: Critica (bollettino MediaTek) · 8.8 Alta, Attack Vector: Adjacent (CISA-ADP)
Tipo: Remote Code Execution — nessuna interazione utente, nessuna associazione preventiva
Divulgazione: MediaTek Security Bulletin, 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 della lista di chipset interessati di MediaTek - Il firmware è stato emulato in condizioni sicure.
Stato: Corretto.
Questa è stata la mia prima ricerca pubblicata sul baseband. Provengo da un background molto distante 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 in precedenza reverse engineering approfondito del firmware di un modem cellulare. Volevo dimostrare a me stesso che una metodologia analitica strutturata si adatta a target diversi, e che la familiarità con una piattaforma specifica può essere sostituita da un rigoroso chain-tracing. NB-IoT si è distinto perché si trova in un'intersezione genuinamente pericolosa: il protocollo è progettato per dispositivi IoT con risorse limitate, 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 corretto è stato analizzato e il pattern vulnerabile confermato assente, il sistema AI utilizzato per l'analisi di massa del firmware prima di prendere di mira funzioni specifiche
ha associato in modo indipendente la classe di 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 sovrastante. Android può essere completamente aggiornato. Il browser può essere in sandbox. L'utente può non toccare mai un link malevolo. Niente di tutto ciò conta se il codice vulnerabile si trova nel firmware del modem che elabora i segnali radio prima che l'application processor sia coinvolto.
CVE-2024-20154 è esattamente questo tipo di vulnerabilità.
Una trasmissione di system-information NB-IoT malformata causa al firmware del modem MediaTek di accettare un conteggio di scheduling controllato dall'attaccante, di trasportare quel conteggio attraverso il percorso di configurazione RRC-to-L1 senza mai limitarlo, e infine di usarlo come limite di ciclo per un ciclo di scrittura sullo stack all'interno dell'handler del canale broadcast NB-IoT. Quando il conteggio supera la capacità degli array di destinazione, il ciclo scrive oltre essi, 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 ad esso.
Ciò che rende la gravità quella che è:
La vulnerabilità è stata pubblicata nel Security Bulletin di MediaTek del 6 gennaio 2025 con una valutazione di gravità Critica, che interessa tra gli altri la famiglia di modem LR12A. Samsung ha incorporato la correzione nella sua Security Maintenance Release di febbraio 2025.
Questo post non pubblica un exploit weaponizzato e non è riproducibile da ciò che è pubblicato qui. L'obiettivo è mostrare dove la catena si rompe, perché ogni livello ha fallito nel fermarla, e cosa serve per validare responsabilmente un bug del baseband quando non puoi collegare un debugger al modem live.
Target primario: Samsung Galaxy A14 (SM-A145R). Il sottosistema radio è pilotato da un processore baseband MediaTek della famiglia di chipset MT6769 (Helio G80). La famiglia MT6769 è esplicitamente elencata nella lista di 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 del baseband non è codice Android. È un sistema embedded separato sul sottosistema radio del SoC con la propria CPU, il proprio RTOS e il proprio spazio di memoria, al di fuori del 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 embedded — coerente con l'approccio di MediaTek per i baseband della generazione Helio, confermato da ricerche indipendenti pubblicate sui 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/user, né applicazione della memory protection unit tra i task, né 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 sono validati rispetto ad alcuna policy |
### 2.4 Approccio di analisi
Tre percorsi paralleli:
**Analisi statica.** Pacchetto firmware Samsung → estrazione partizione CP → `md1img.img` →
Ghidra (MIPS LE 32-bit, base `0x90000000`) con simboli di engineering MediaTek recuperati dalla
sezione di debug del firmware usando il toolset `mtk_bp` di NCC Group.
**Validazione dinamica.** Unicorn Engine (emulazione MIPS32) è stato usato per eseguire specifiche
routine del firmware in isolamento attraverso due fasi. La Fase 1 ha tentato di dimostrare la copia
non limitata di `si_count` nel contesto del canale attraverso 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. Dove la Fase 1 non ha potuto essere eseguita completamente in modo nativo — perché
l'ambiente degli oggetti di servizio RTOS richiesto dal percorso di dispatch CPHY non è stato ricostruito —
l'effetto collaterale è stato modellato direttamente ed etichettato come tale in tutto l'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 di attacco: NB-IoT e SIB1-NB
### 3.1 Superficie di attacco pre-associazione
NB-IoT (Narrowband Internet of Things) è 3GPP Release 13, progettato per connettere dispositivi
IoT vincolati usando lo spettro LTE concesso esistente. È implementato in un'ampia gamma di SoC
cellulari moderni, inclusi quelli degli smartphone di consumo.
Mentre è in RRC_IDLE, prima che qualsiasi connessione RRC sia stabilita, un dispositivo in ricerca del servizio:
1. Si sincronizza con i segnali di timing 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 scheduling in SIB1-NB per localizzare ulteriori system information block
Al passo 3, il modem elabora un messaggio da un'entità che non ha autenticato, prima di qualsiasi
connessione o interazione utente. Un trasmettitore malevolo 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 nella specifica 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 memory safety — ovvero che la lunghezza della lista non deve superare la capacità degli
array di destinazione — deve essere imposto separatamente dal firmware.
Non lo era.
Il firmware è stato ottenuto da un pacchetto Samsung CP 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`, poi
importata in Ghidra tramite `ImportSymbolsScript.py`. Il risultato è stato la completa
denominazione delle funzioni interne in tutto lo stack del modem — livello ERRC, gestione dei canali L1, sottosistema IPC e la
catena di gestione NB-IoT BCCH — consentendo la ricostruzione della catena guidata dalla semantica.
Tutti i nomi delle funzioni in questo post provengono dai simboli di debug incorporati di MediaTek estratti
dall'immagine del firmware.
---
## 5. Vulnerabilità
### 5.1 Il ciclo 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 utilizzato direttamente, senza alcun confronto preventivo con le capacità dell'array.
Lo stream 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 di 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. Lo Stream B non raggiunge mai lo slot RA. La corruzione del RA
proviene interamente dallo 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 tra di esse:```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 — Livello A
Il buffer CPHY_CFG_REQ viene costruito nel livello ERRC 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 numero di voci decodificate da SIB1-NB. Il contatore viene incrementato una volta per ogni voce decodificata, per tutte le voci che sono state decodificate, senza alcuna protezione sul 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 clamping su tre livelli
| Livello | Funzione | Indirizzo | Clamp presente? |
|---|---|---|---|
| A — builder ERRC | `errc_chm_l1_set_bcch_si_reception` | range ERRC | **Nessuno** |
| B — copia L1 | `el1_ch_nbcch_start` | `0x90213444` | **Nessuno** |
| C — loop L1 | `el1_ch_nbcch_resume_req` | `0x90213940` | **Nessuno** |
Un singolo controllo su uno qualsiasi dei livelli avrebbe interrotto la catena.
### 5.7 Causa radice
Un invariante violato:
> Il numero di voci di scheduling SI non deve mai superare la capacità dell'array di destinazione.
3GPP fornisce il limite di protocollo previsto (8 voci). Il firmware doveva far rispettare il
limite di memory-safety a ogni livello in cui il conteggio diventa un indice o un limite di
ciclo. Nella build vulnerabile, il conteggio viaggiava dal campo di broadcast SIB1-NB attraverso
il decoder ERRC, nel messaggio CPHY_CFG_REQ, oltre un confine IPC nel task L1, nel contesto
canale BSS, e in un ciclo di scrittura sullo stack — senza che alcun livello lo limitasse.
---
## 6. La Catena di Chiamate — Come È Stato Trovato
### 6.1 La confusione tra i due percorsi
Due percorsi strutturalmente simili ma distinti possono consegnare un buffer di configurazione
da 0x760 byte a `el1_ch_nbcch_main`:
| Percorso | Sorgente | Valore `[+0x99]` | Rilevanza |
|---|---|---|---|
| Percorso A (ERRC → L1 IPC) | ERRC costruisce CPHY_CFG_REQ dal SIB1-NB decodificato | `schedulingInfoList.count` da OTA | **Il percorso vulnerabile** |
| Percorso B (L1 interno) | `el1_ch_scs_ind_send` costruisce il corpo IPC interno | Hardcoded `1` | 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ò andare in overflow. Il
percorso influenzato esternamente è il Percorso A.
### 6.2 La ricerca del writer
La ricerca per pattern nel firmware di qualsiasi istruzione che scrivesse all'offset `+0x99` ha prodotto rumore:
T1 (`sb` diretto, ~100 hit), T2 (base divisa, 5 hit), T3 (offset calcolato, 0), T4
(`sh`/`sw` sovrapposti, ~465). Le funzioni di gestione del canale ERRC erano assenti dalla
lista di cross-reference di `msg_send6` perché ERRC usa `errc_com_send_msg`. Una sonda di emulazione
ha confermato che la scrittura era lato ERRC: eseguendo l'harness Unicorn dal dispatcher L1 e
monitorando le scritture all'offset `+0x99` del buffer non ha 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 è stato identificato il routing 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
Questo specifico modello SM-A145R non sembra percorrere il codice NB-IoT vulnerabile durante
il normale funzionamento di ship-build, motivo per cui sono state utilizzate l'emulazione ibrida
e l'analisi statica anziché la riproduzione diretta su hardware.
**Dimostrato staticamente.** Il binario del firmware contiene la coppia di istruzioni vulnerabile. La catena
di chiamate è ricostruita da simboli, riferimenti incrociati e corpi di funzioni decompilate.
**Eseguito nativamente in emulazione.** Il loop 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 dell'indirizzo di ritorno salvato. 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 attivi che l'emulatore flat non forniva. Il gestore
di resume (`el1_ch_nbcch_resume_req`) nella Fase 2 legge solo dal contesto di canale residente in BSS
e non incontra 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 rivendicato.** Una riproduzione hardware over-the-air completa end-to-end.
### 7.1 Anti-manomissione
L'harness ha imposto una regola: nessun hook era autorizzato a scrivere il marcatore di prova nello slot
dell'indirizzo di ritorno salvato. Ogni scrittura in memoria non proveniente dal 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 loop. Il firmware ha posizionato questi byte
all'offset dello 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, è stato utilizzato srsRAN 4G con un loopback ZMQ (nessuna emissione RF). Il payload era un vettore deliberatamente non conforme — il vincolo ASN.1 SIZE su `schedulingInfoList` è stato allentato per consentire 40 voci, con la decodifica round-trip di pycrate che conferma il campo count al byte 14.```
SIB1 received
SIB2 activated
exit 0
Questo conferma la consegna a livello di trasporto. Il comportamento ASN.1 lato firmware è stabilito dall'analisi statica del Livello A.
Il task el1_ch ha un solo stack. La Fase 1 e la Fase 2 sono due eventi IPC separati elaborati sequenzialmente dallo stesso task, con lo stack che si svuota completamente tra di essi. Il conteggio persiste nel BSS del contesto del 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 mantiene il valore dell'attaccante fino al riavvio del modem o finché 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]
La dimensione del frame è confermata dalla misurazione dell'emulazione. Le posizioni nell'array sono 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 |
| Corretta | A145RXXUDDZC2, MOLY LR12A...V3.P8 |
Date di build confermate estraendo i metadati md1_dbginfo da entrambe le immagini. ID patch:
MOLY00720348 · ID issue: 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] è scomparsa.
el1_ch_nbcch_resume_req (0x90213940 nel binario vulnerabile): Il ciclo che scrive
sullo stack su ch_ctx[0x40A] è assente. L'architettura in cui un byte non attendibile diventa
un limite di ciclo su array a dimensione fissa sullo stack non esiste più. Il corpo della
funzione è sostituito con una diversa struttura di dispatch.
errc_chm_l1_set_bcch_si_reception: Il ciclo con contatore non limitato è sostituito con
chiamate a helper orientate alla validazione.
Due funzioni presenti nel binario corretto sono assenti dal binario vulnerabile:``` el1_ch_nbcch_param_check el1_ch_scell_param_check
Un semplice controllo dei limiti su una singola riga apparirebbe come poche istruzioni aggiunte all'interno di una funzione esistente allo stesso indirizzo. Ciò che il binario corretto mostra è una revisione architetturale: il percorso di scheduling NBCCH è stato riprogettato in modo che il pattern `si_count`-come-limite-di-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 della conferma:
- La famiglia di firmware interessata (LR12A) corrisponde al bollettino di MediaTek.
- La classe di vulnerabilità — stack overflow, controllo dei limiti mancante, RCE da stazione base malevola, nessuna interazione utente — corrisponde alla descrizione della CVE e al record NVD.
- Il firmware corretto rimuove esattamente le strutture di codice identificate come vulnerabili.
- Patch ID MOLY00720348 confermato dal bollettino di MediaTek e dall'Android Security Bulletin (A-376809176).
- L'analisi assistita da AI ha autonomamente associato 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 weaponizzato. 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 — la costruzione completa del payload per lo specifico decoder del modem, l'impalcatura degli oggetti heap RTOS per l'emulazione completa della Fase 1, la 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 prova 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 un broadcast malformato influenzerebbe 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ù solida rispetto a un singolo crash hardware, ed evita di distribuire qualsiasi cosa via etere.
### 11.3 Proprietà intellettuale di MediaTek
Tutta l'analisi è stata eseguita su firmware ottenuto legittimamente da un dispositivo di consumo e dai pacchetti firmware rilasciati pubblicamente da Samsung. Nessuna documentazione proprietaria è stata utilizzata. Le definizioni interne delle struct di MediaTek e i formati dei messaggi IPC sono descritti solo nella misura necessaria a spiegare il fallimento della sicurezza della memoria. Non sono pubblicati come specifiche.
---
| Iterazione | sh scrive in | Effetto |
|---|
| 0–33 | si_sched_arr[0..33] | Entro i 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] | Metà inferiore del RA |
| 39 | new_sp+0xE6 — ra salvato [31:16] | Metà superiore del RA |
| Gate | Condizione | Dove viene verificato |
|---|
| 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 in stato resume | dispatch di el1_ch_nbcch_main |
| si_count diverso da zero | ch_ctx[0x40A] > 0 | Condizione del ciclo |
| Band class ≤ 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 | Chiamato in el1_ch_nbcch_start |
| Funzione | Indirizzo | Ruolo | Clamp? |
|---|
errc_chm_l1_set_bcch_si_reception | Intervallo ERRC | Scrive CPHY_CFG_REQ[+0x99] | Nessuno |
el1_ch_nbcch_cphy_cfg_req_process | 0x90213F80 | Instrada la configurazione CPHY in L1 | N/D — non legge si_count |
el1_chmgm_cell_info_get | 0x9020E0D0 | Valida EARFCN/PCI | N/D |
el1_ch_nbcch_start | 0x90213444 | Copia il conteggio in BSS | Nessuno |
el1_ch_nbcch_resume_req | 0x90213940 | Usa il conteggio come limite del ciclo | Nessuno |
| 2025-04-23 |