
Technischer Bericht zur Analyse von CVE-2024-20154, einem stackbasierten Pufferüberlauf in der MediaTek MT6769 NB-IoT-Baseband-Firmware, einschließlich Reverse Engineering und Exploit-Kette.
Klassifizierung: CWE-121 — Stack-basierter Buffer Overflow
Schweregrad: Kritisch (MediaTek-Bulletin) · 8.8 Hoch, Angriffsvektor: Adjacent (CISA-ADP)
Typ: Remote Code Execution — keine Benutzerinteraktion, keine vorherige Assoziation
Offenlegung: MediaTek Security Bulletin, 6. Januar 2025 https://corp.mediatek.com/product-security-bulletin/January-2025
Analysiertes Ziel: Samsung Galaxy A14 SM-A145R — MT6769-Familie (Helio G80), innerhalb der von MediaTek aufgeführten betroffenen Chipsätze - Die Firmware wurde unter sicheren Bedingungen emuliert.
Status: Gepatcht.
Dies war meine erste veröffentlichte Baseband-Forschung. Ich komme aus einem Hintergrund, der weit entfernt ist von Telekommunikationsinfrastruktur, Mediationsschichten für rechtmäßige Überwachung, Stingray- und IMSI-Catcher-Analyse sowie Sicherheit eingebetteter Geräte — ich hatte zuvor kein tiefgehendes Firmware-Reverse-Engineering an einem zellularen Modem durchgeführt. Ich wollte mir selbst beweisen, dass eine strukturierte analytische Methodik sich über verschiedene Ziele hinweg anpassen lässt und dass Vertrautheit mit einer spezifischen Plattform durch rigoroses Chain-Tracing ersetzt werden kann. NB-IoT stach hervor, weil es an einer wirklich gefährlichen Schnittstelle liegt: Das Protokoll ist für ressourcenbeschränkte IoT-Geräte konzipiert, die Angriffsfläche besteht vor der Assoziation, und der Modem-Stack verarbeitet sie unabhängig davon, was der Handset-Nutzer gerade tut.
Als die gepatchte Firmware analysiert und das verwundbare Muster bestätigt als abwesend festgestellt wurde, ordnete das für die Massenanalyse der Firmware vor der gezielten Adressierung spezifischer Funktionen verwendete KI-System
unabhängig die rekonstruierte Fehlerklasse, die Bedingungen und die betroffene Firmware-Familie der Beschreibung von CVE-2024-20154 zu.
Die technischen Schlussfolgerungen sind die des Analysten selbst.
Das Telefon in Ihrer Tasche enthält mindestens zwei separate Computer. Derjenige, mit dem Sie interagieren, führt Android aus. Der andere — das Baseband — läuft völlig unabhängig, verarbeitet die gesamte Funkkommunikation und ist für das darüberliegende Betriebssystem nahezu unsichtbar. Android mag vollständig gepatcht sein. Der Browser mag sandboxed sein. Der Nutzer mag niemals auf einen bösartigen Link tippen. Nichts davon spielt eine Rolle, wenn der verwundbare Code in der Modem-Firmware liegt, die Funksignale verarbeitet, bevor der Anwendungsprozessor überhaupt beteiligt ist.
CVE-2024-20154 ist genau diese Art von Schwachstelle.
Eine fehlerhafte NB-IoT-Systeminformations-Rundsendung veranlasst die MediaTek-Modem-Firmware, eine angreiferkontrollierte Scheduling-Anzahl zu akzeptieren, diese Anzahl durch den RRC-zu-L1-Konfigurationspfad zu tragen, ohne sie jemals zu begrenzen, und sie schließlich als Schleifengrenze für eine stack-schreibende Schleife innerhalb des NB-IoT-Broadcast-Channel- Handlers zu verwenden. Wenn die Anzahl die Kapazität der Ziel-Arrays überschreitet, schreibt die Schleife über sie hinaus, erreicht gespeicherte Register auf dem Stack und überschreibt die gespeicherte Rücksprungadresse. Die Funktion stellt dann den korrumpierten Wert in das Rücksprungadressregister wieder her und springt dorthin.
Was die Schwere ausmacht:
Die Schwachstelle wurde in MediaTeks Security Bulletin vom 6. Januar 2025 mit einer Kritisch-Schweregradbewertung veröffentlicht und betrifft unter anderem die LR12A-Modem- Familie. Samsung integrierte den Fix in sein Security Maintenance Release vom Februar 2025.
Dieser Beitrag veröffentlicht keinen weaponisierten Exploit und ist anhand des hier Veröffentlichten nicht reproduzierbar. Das Ziel ist zu zeigen, wo die Kette bricht, warum jede Schicht versagt hat, sie aufzuhalten, und was nötig ist, um einen Baseband-Bug verantwortungsvoll zu validieren, wenn man keinen Debugger am Live-Modem anbringen kann.
Primäres Ziel: Samsung Galaxy A14 (SM-A145R). Das Funksubsystem wird von einem MediaTek- Baseband-Prozessor aus der MT6769-Chipsatzfamilie (Helio G80) angetrieben. Die MT6769-Familie ist ausdrücklich in MediaTeks Liste der betroffenen Chipsätze für CVE-2024-20154 aufgeführt.``` AP/CP firmware: A145RXXU1AWD1 Modem software: MOLY LR12A.R3.TC10.6M.A14.PR.SP.V1.P5 Build date: 2023-04-18
Die Baseband-Firmware ist kein Android-Code. Sie ist ein separates eingebettetes System
auf dem Funk-Subsystem des SoC mit eigener CPU, eigenem RTOS und eigenem Speicherbereich,
außerhalb der Android-Prozess-Sandbox.
### 2.2 Modem-Architektur
Die Analyse des extrahierten Binaries zeigt, dass der Modem-Prozessor MIPS32 mit MIPS16e2-
komprimierten Instruktionen im Little-Endian-Modus ausführt. MIPS16e2 ist eine 16-Bit-
Kodierungserweiterung zur Reduzierung der Codegröße in eingebetteten Systemen — konsistent
mit MediaTeks Ansatz für Basebands der Helio-Generation, bestätigt durch unabhängige
veröffentlichte Baseband-Forschung zu dieser SoC-Familie.
Das Betriebssystem ist Nucleus RTOS, das Task-Scheduling, IPC-Nachrichtenwarteschlangen und
einen pool-basierten Speicherallokator bereitstellt. Es gibt keine Kernel/User-
Privilegientrennung, keine Durchsetzung einer Speicherschutzeinheit zwischen Tasks und keinen
Hardware-Stack-Guard-Mechanismus.
Alle Adressen in diesem Beitrag sind virtuelle Adressen, wie sie in Ghidra mit Basis
`0x90000000` geladen werden.
### 2.3 Mitigationsmaßnahmen (beobachtet im analysierten Build)
| Mitigation | Status | Wirkung |
|---|---|---|
| ASLR | Fehlt | Firmware-Adressen sind statisch und aus dem Image vorhersagbar |
| Stack Canary | Fehlt | `SAVE`/`RESTORE` speichert callee-saved Register ohne Guard-Wert |
| NX / W^X | Fehlt | Stack-Speicher ist ausführbar |
| CFI | Fehlt | Rücksprungadressen werden gegen keine Policy validiert |
### 2.4 Analyseansatz
Drei parallele Spuren:
**Statische Analyse.** Samsung-Firmware-Paket → CP-Partition-Extraktion → `md1img.img` →
Ghidra (MIPS LE 32-Bit, Basis `0x90000000`) mit MediaTek-Engineering-Symbolen, die aus dem
Firmware-Debug-Bereich mit dem NCC Group `mtk_bp`-Toolset wiederhergestellt wurden.
**Dynamische Validierung.** Unicorn Engine (MIPS32-Emulation) wurde verwendet, um bestimmte
Firmware-Routinen isoliert über zwei Phasen auszuführen. Phase 1 versuchte, die ungeklemmte
Kopie von `si_count` in den Kanal-Kontext durch das native Instruktionspaar zu beweisen.
Phase 2 führte die verwundbare Schleife auf echten Firmware-Bytes aus und bestätigte, dass
die Firmware-eigenen Instruktionen die gespeicherte Rücksprungadresse korrumpieren. Wo Phase 1
nicht vollständig nativ ausgeführt werden konnte — weil die vom CPHY-Dispatch-Pfad benötigte
RTOS-Service-Object-Umgebung nicht rekonstruiert wurde — wurde der Seiteneffekt direkt
modelliert und als solcher in allen Ausgaben gekennzeichnet.
**Funkseitige Validierung.** srsRAN 4G mit einem ZMQ-Loopback — rein softwarebasiert, keine
RF-Emission — bestätigte, dass die Test-Payload die NB-IoT-PHY-Kodierung und Transportblock-
Zustellung übersteht.
---
## 3. Angriffsfläche: NB-IoT und SIB1-NB
### 3.1 Angriffsfläche vor der Assoziierung
NB-IoT (Narrowband Internet of Things) ist 3GPP Release 13 und wurde entwickelt, um
ressourcenbeschränkte IoT-Geräte über vorhandenes lizenziertes LTE-Spektrum zu verbinden. Es
ist in einer breiten Palette moderner zellularer SoCs implementiert, einschließlich solcher in
Consumer-Smartphones.
Während sich ein Gerät im RRC_IDLE befindet, bevor eine RRC-Verbindung aufgebaut wird, wird
ein Gerät, das nach einem Dienst sucht:
1. Mit den Timing-Signalen der Zelle synchronisieren (NPSS/NSSS)
2. Den Master Information Block über NPBCH dekodieren (640 ms Übertragungsfenster)
3. SIB1-NB aus NPDSCH dekodieren (2560 ms Zeitplan)
4. Die Scheduling-Informationen in SIB1-NB verwenden, um zusätzliche Systeminformationsblöcke zu lokalisieren
In Schritt 3 verarbeitet das Modem eine Nachricht von einer Entität, die es nicht
authentifiziert hat, bevor irgendeine Verbindung oder Benutzerinteraktion stattfindet. Ein
bösartiger Sender, der die normalen Zellauswahlbedingungen erfüllt, wird verarbeitet.```
+------------------+ +---------------------+
| 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 ist in 3GPP TS 36.331 definiert. Sein Feld schedulingInfoList enthält, wie viele
System Information-Nachrichten die Zelle aussendet, wobei die Spezifikation auf maximal 8
Einträge begrenzt ist (1..maxSI-Message-NB-r13 = 8). Dies ist eine Einschränkung auf
Protokollebene. Die Speichersicherheits-Einschränkung — dass die Listenlänge die Kapazität der
Ziel-Arrays nicht überschreiten darf — muss separat von der Firmware durchgesetzt werden.
Wurde sie nicht.
Die Firmware wurde aus einem Samsung CP-Paket bezogen und mit dem NCC Group mtk_bp
Toolset extrahiert:```
md1img.img → md1_extract.py → 000_md1rom (17.8 MB code image)
→ 017_md1_dbginfo (XZ-compressed CATI debug symbols)
Der CATI-Debug-Bereich wurde mit `mtk_dbg_extract.py symbols` dekomprimiert und geparst und
anschließend über `ImportSymbolsScript.py` in Ghidra importiert. Das Ergebnis waren vollständige interne Funktions-
namen im gesamten Modem-Stack — ERRC-Schicht, L1-Kanalverwaltung, IPC-Subsystem und die
NB-IoT-BCCH-Handler-Kette — was eine semantikgestützte Kettenrekonstruktion ermöglichte.
Alle Funktionsnamen in diesem Beitrag stammen aus MediaTeks eigenen eingebetteten Debug-Symbolen, die
aus dem Firmware-Image extrahiert wurden.
---
## 5. Schwachstelle
### 5.1 Die anfällige Schleife
`el1_ch_nbcch_resume_req` (`0x90213940`) behandelt das NB-IoT-Broadcast-Channel-Resume-Ereignis.
Sein MIPS16e2-Funktionsprolog:```asm
90213940: save 0xE8, ra, s0-s1
Die SAVE-Instruktion dekrementiert sp um 0xE8 und speichert callee-saved Register abwärts:```
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
Aus der Ghidra-Dekompilierung der tatsächlichen Firmware-Binärdatei:```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] ist ch_ctx[+0x40A] — ein persistentes Byte in der BSS-Struktur des Kanal-Kontexts.
Die Schleifengrenze wird direkt verwendet, ohne vorherigen Vergleich mit den Array-Kapazitäten.
Stream A (Halfword-sh-Schreibvorgänge) beginnt bei new_sp+0x98 und schreitet um 2 Bytes pro Iteration voran.
Er erreicht die gespeicherte RA bei new_sp+0xE4 in Iteration 38:```
new_sp + 0x98 + i×2 = new_sp + 0xE4
i = (0xE4 - 0x98) / 2 = 0x4C / 2 = 38
Stream B (Byte-`sb`-Schreibvorgänge) beginnt bei `new_sp+0x78` und würde Iteration 108 erfordern, um
den RA-Slot zu erreichen:```
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108
Mit si_count = 40 (dem Demonstrator-Wert, gewählt, um den Überlaufschwellenwert von 38 zu überschreiten)
läuft die Schleife 40 Iterationen. Stream B erreicht niemals den RA-Slot. Die RA-Korruption stammt
vollständig aus Stream A.
Nach 40 Iterationen lädt die MIPS16e2-RESTORE-Instruktion den korrumpierten Wert vom
Stack in $ra zurück, und jrc ra überträgt die Kontrolle.
ch_ctx[+0x40A] wird von el1_ch_nbcch_start bei 0x90213444 geschrieben. Zwei aufeinanderfolgende MIPS-
Instruktionen ohne etwas dazwischen:```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 Der ERRC-Builder — Layer A
Der CPHY_CFG_REQ-Puffer wird im ERRC-Layer aus dem dekodierten SIB1-NB aufgebaut. Die Funktion
`errc_chm_l1_set_bcch_si_reception` schreibt `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
}
}
Die Schleifengrenze ist die dekodierte Eintragsanzahl aus SIB1-NB. Der Zähler wird einmal pro dekodiertem Eintrag inkrementiert, für so viele Einträge wie dekodiert wurden, ohne Obergrenze.
Sobald der CPHY_CFG_REQ-Puffer befüllt ist, leitet ERRC ihn mit sap_id = 0x501F
als Routing-Schlüssel an L1 weiter:```
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 Dreischichtiges Fehlen einer Begrenzung
| Ebene | Funktion | Adresse | Begrenzung vorhanden? |
|---|---|---|---|
| A — ERRC-Builder | `errc_chm_l1_set_bcch_si_reception` | ERRC-Bereich | **Keine** |
| B — L1-Kopie | `el1_ch_nbcch_start` | `0x90213444` | **Keine** |
| C — L1-Schleife | `el1_ch_nbcch_resume_req` | `0x90213940` | **Keine** |
Jede einzelne Prüfung auf jeder der Ebenen hätte die Kette unterbrochen.
### 5.7 Grundursache
Eine verletzte Invariante:
> Die Anzahl der SI-Scheduling-Einträge darf niemals die Kapazität des Ziel-Arrays überschreiten.
3GPP gibt die beabsichtigte Protokollgrenze vor (8 Einträge). Die Firmware musste die
Speichersicherheitsgrenze auf jeder Ebene durchsetzen, auf der die Anzahl zu einem Index oder
Schleifenlimit wird. Im verwundbaren Build wanderte die Anzahl vom SIB1-NB-Broadcast-Feld durch den
ERRC-Decoder, in die CPHY_CFG_REQ-Nachricht, über eine IPC-Grenze in die L1-Task, in den
Kanal-Kontext-BSS und in eine stack-schreibende Schleife — ohne dass eine Ebene sie begrenzte.
---
## 6. Die Aufrufkette — Wie sie gefunden wurde
### 6.1 Die Verwechslung der zwei Pfade
Zwei strukturell ähnliche, aber unterschiedliche Pfade können einen 0x760-Byte-Konfigurationspuffer an
`el1_ch_nbcch_main` liefern:
| Pfad | Quelle | `[+0x99]`-Wert | Relevanz |
|---|---|---|---|
| Pfad A (ERRC → L1 IPC) | ERRC baut CPHY_CFG_REQ aus decodiertem SIB1-NB | `schedulingInfoList.count` aus OTA | **Der verwundbare Pfad** |
| Pfad B (L1-intern) | `el1_ch_scs_ind_send` baut internen IPC-Body | Fest codiert `1` | Nicht verwundbar |
Pfad B bestätigte das Nachrichtenformat — Byte `+0x99` ist die SI-Anzahl, die von
`el1_ch_nbcch_start` konsumiert wird. Da seine Anzahl immer fest auf 1 codiert ist, kann er nicht
überlaufen. Der von außen beeinflussbare Pfad ist Pfad A.
### 6.2 Die Suche nach dem Schreiber
Die Mustersuche in der Firmware nach jeglicher Instruktion, die in Offset `+0x99` schreibt, erzeugte Rauschen:
T1 (direktes `sb`, ~100 Treffer), T2 (geteilte Basis, 5 Treffer), T3 (berechneter Offset, 0), T4
(überlappendes `sh`/`sw`, ~465). Die ERRC-Kanalverwaltungsfunktionen fehlten in der
`msg_send6`-Querverweisliste, weil ERRC `errc_com_send_msg` verwendet. Eine Emulationssonde
bestätigte, dass der Schreibvorgang auf der ERRC-Seite erfolgte: Das Ausführen des Unicorn-Harness vom L1-Dispatcher aus und die Überwachung auf Schreibvorgänge in den `+0x99`-Offset des Puffers erfasste nichts von der L1-Seite.```
[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.
Die Verfolgung von sap_id = 0x501F in errc_com_send_msg identifizierte das Routing zu
el1_chmgm_errc_cfg_req_in_idle, welches den CPHY_CFG_REQ-Zeiger bei
L1_ctx[+0x323C] speichert und den nachgelagerten Dispatch beginnt.
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. Validierung
Dieses spezifische SM-A145R-Modell scheint den verwundbaren NB-IoT-Codepfad im normalen Ship-Build-Betrieb nicht zu durchlaufen, weshalb Hybrid-Emulation und statische Analyse anstelle einer direkten Hardware-Reproduktion verwendet wurden.
**Statisch bewiesen.** Die Firmware-Binärdatei enthält das verwundbare Instruktionspaar. Die Aufrufkette wird aus Symbolen, Querverweisen und dekompilierten Funktionskörpern rekonstruiert.
**Nativ in der Emulation ausgeführt.** Die Schleife innerhalb von `el1_ch_nbcch_resume_req` lief auf echten MediaTek-Firmware-Bytes in Unicorn Engine (MIPS32). Die `sh`-Instruktion der Firmware bei `0x90213B02` schrieb in den gespeicherten Rücksprungadress-Slot. Die `RESTORE`-Instruktion lud den korrumpierten Wert in `$ra`, und `jrc ra` übertrug die Kontrolle.
**Explizit modelliert.** Die `lbu`/`sb`-Kopie in `el1_ch_nbcch_start` konnte nicht vollständig nativ ausgeführt werden, da der RTOS-Callback-Table-Dispatch-Pfad innerhalb von `el1_ch_nbcch_cphy_cfg_req_
process` lebende Nucleus-Heap-Objekte erwartete, die der flache Emulator nicht bereitstellte. Der Resume-Handler (`el1_ch_nbcch_resume_req`) in Phase 2 liest nur aus dem BSS-residenten Kanal-Kontext und trifft nicht auf denselben Dispatch-Pfad, weshalb Phase 2 nativ ohne dasselbe Gerüst lief. Der Seiteneffekt von Phase 1 — ein Byte aus `IPC_msg[+0x99]`, geschrieben nach `ch_ctx[+0x40A]` — wurde direkt modelliert und als `[PHASE1-MODEL]` gekennzeichnet.
**Nicht beansprucht.** Eine vollständige End-to-End-Over-the-Air-Hardware-Reproduktion.
### 7.1 Anti-Tamper
Die Harness erzwang eine Regel: Kein Hook durfte den Proof-Marker in den gespeicherten Rücksprungadress-Slot schreiben. Jeder Nicht-Firmware-Speicherschreibvorgang wurde verfolgt.```
[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 ist die sh-Instruktion innerhalb des Schleifenkörpers. Die Firmware platzierte diese Bytes am
vorhergesagten Stack-Offset. In Little-Endian-Speicherung kombinieren die Halbwörter 0xBEEF und 0xDEAD
bei new_sp+0xE4 und new_sp+0xE6 zu [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-Zustellung
Um zu bestätigen, dass die Testnutzlast die NB-IoT-PHY-Codierung und die Transportblock-Zustellung übersteht, wurde srsRAN 4G mit einem ZMQ-Loopback (keine HF-Abstrahlung) verwendet. Die Nutzlast war ein bewusst nicht konformer Vektor — die ASN.1-SIZE-Einschränkung für `schedulingInfoList` wurde gelockert, um 40 Einträge zuzulassen, wobei die pycrate-Round-Trip-Dekodierung das Zählfeld bei Byte 14 bestätigte.```
SIB1 received
SIB2 activated
exit 0
Dies bestätigt die Zustellung auf der Transportschicht. Das ASN.1-Verhalten auf Firmware-Seite wird durch die statische Analyse der Ebene A belegt.
Die Task el1_ch hat einen Stack. Phase 1 und Phase 2 sind zwei separate IPC-Ereignisse, die
sequenziell von derselben Task verarbeitet werden, wobei der Stack zwischen ihnen vollständig abgebaut wird. Der Zähler
bleibt im Kanal-Kontext-BSS erhalten, nicht auf dem 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]` liegt im BSS und behält den Wert des Angreifers, bis das Modem zurückgesetzt wird oder eine nachfolgende Kanalkonfiguration ihn überschreibt.
### 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]
Die Framegröße wurde durch Emulationsmessung bestätigt. Die Array-Positionen wurden durch das Emulationsergebnis bestätigt — RA geschrieben bei Iteration 38, konsistent damit, dass si_sched_arr bei new_sp+0x98 beginnt.
| Build | Modem-Firmware | Build-Datum |
|---|---|---|
| Verwundbar | A145RXXU1AWD1, MOLY LR12A...V1.P5 | 2023-04-18 |
| Gepatcht | A145RXXUDDZC2, MOLY LR12A...V3.P8 |
Build-Daten bestätigt durch Extrahieren der md1_dbginfo-Metadaten aus beiden Images. Patch-ID:
MOLY00720348 · Issue-ID: MSV-2392.
el1_ch_nbcch_start (0x90213444 im verwundbaren Binary): Das lbu/sb-Instruktionspaar
fehlt. Die direkte Kopie von IPC_msg[+0x99] nach ch_ctx[+0x40A] ist verschwunden.
el1_ch_nbcch_resume_req (0x90213940 im verwundbaren Binary): Die stack-schreibende
Schleife über ch_ctx[0x40A] fehlt. Die Architektur, bei der ein nicht vertrauenswürdiges Byte
zu einer Schleifengrenze über Stack-Arrays fester Größe wird, existiert nicht mehr. Der
Funktionskörper ist durch eine andere Dispatch-Struktur ersetzt.
errc_chm_l1_set_bcch_si_reception: Die unbegrenzte Zählerschleife ist durch
validierungsorientierte Hilfsaufrufe ersetzt.
Zwei Funktionen, die im gepatchten Binary vorhanden sind, fehlen im verwundbaren Binary:``` el1_ch_nbcch_param_check el1_ch_scell_param_check
Ein einzeiliger Bounds-Check würde als ein paar zusätzliche Instruktionen innerhalb einer bestehenden Funktion an derselben Adresse erscheinen. Was das gepatchte Binary zeigt, ist eine architektonische Überarbeitung: Der NBCCH-Scheduling-Pfad wurde neu gestaltet, sodass das Muster `si_count`-als-Schleifengrenze nirgendwo im Pfad mehr existiert.
### 10.4 CVE-Zuordnung
Die hier beschriebene Schwachstelle entspricht CVE-2024-20154, veröffentlicht von MediaTek am 6. Januar 2025. Bestätigungsgrundlage:
- Betroffene Firmware-Familie (LR12A) stimmt mit MediaTeks Bulletin überein.
- Schwachstellenklasse — Stack-Overflow, fehlender Bounds-Check, RCE von einer rogue Basisstation, keine Benutzerinteraktion — stimmt mit der CVE-Beschreibung und dem NVD-Eintrag überein.
- Die gepatchte Firmware entfernt genau die als verwundbar identifizierten Codestrukturen.
- Patch-ID MOLY00720348 bestätigt aus MediaTeks Bulletin und dem Android Security Bulletin (A-376809176).
- KI-gestützte Analyse stimmte das rekonstruierte Muster unabhängig mit CVE-2024-20154 ab, bevor die manuelle Bestätigung erfolgte.
---
## 11. Ethik und verantwortungsvolle Offenlegung
### 11.1 Was dieser Beitrag nicht enthält
Kein weaponisierter Exploit. Kein Firmware-Binary-Inhalt. Keine malformed Payload-Bytes. Keine Schritt-für-Schritt-Anleitung zum Auslösen der Schwachstelle gegen ein Live-Gerät. Die Informationen, die zur Reproduktion eines funktionierenden Angriffs benötigt werden — vollständige Payload-Konstruktion für den spezifischen Modem-Decoder, RTOS-Heap-Object-Scaffolding für vollständige Phase-1-Emulation, Over-the-Air-Funkkonfiguration — fehlen bewusst.
### 11.2 Warum ZMQ-Loopback und Emulation der ethische Ansatz sind
ZMQ-Loopback bedeutet, dass niemals ein Signal über die Luft übertragen wurde. Kein reales Gerät wurde angegriffen. Kein Carrier-Netzwerk war beteiligt. Der Proof läuft vollständig in einer abgeschotteten Softwareumgebung auf Hardware, die dem Analysten gehört. Dies ist der korrekte Ansatz zur Validierung einer Pre-Association-Funk-Schwachstelle — die Übertragung eines malformed Broadcast würde jedes Gerät in Reichweite betreffen.
Unicorn-Emulation demonstriert, dass das verwundbare Verhalten im Firmware-Binary selbst liegt, reproduzierbar, unabhängig von einem bestimmten Gerätezustand oder Funkumfeld. Dies ist eine technisch stärkere Aussage als ein einzelner Hardware-Crash, und es vermeidet, irgendetwas über die Luft einzusetzen.
### 11.3 MediaTek geistiges Eigentum
Die gesamte Analyse wurde an Firmware durchgeführt, die rechtmäßig von einem Consumer-Gerät und aus Samsungs öffentlich veröffentlichten Firmware-Paketen bezogen wurde. Es wurde keine proprietäre Dokumentation verwendet. Interne MediaTek-Struct-Definitionen und IPC-Nachrichtenformate werden nur in dem Umfang beschrieben, der zur Erklärung des Memory-Safety-Fehlers erforderlich ist. Sie werden nicht als Spezifikationen veröffentlicht.
---
| Iteration | sh schreibt nach | Auswirkung |
|---|
| 0–33 | si_sched_arr[0..33] | Innerhalb der Grenzen |
| 34–35 | new_sp+0xDC — gespeichertes s0 | s0 korrumpiert |
| 36–37 | new_sp+0xE0 — gespeichertes s1 | s1 korrumpiert |
| 38 | new_sp+0xE4 — gespeichertes ra [15:0] | RA niederes Halbwort |
| 39 | new_sp+0xE6 — gespeichertes ra [31:16] | RA hohes Halbwort |
| Gate | Bedingung | Wo geprüft |
|---|
| NB-IoT aktiver Pfad | cfg_type == 1 | el1_ch_nbcch_cphy_cfg_req_process |
| Kanal nicht abgeschlossen | done_flag == 0 | ch_ctx[0x438] |
Zustandsmaschine 0x0B | NBCCH im Resume-Zustand | el1_ch_nbcch_main Dispatch |
| si_count ungleich null | ch_ctx[0x40A] > 0 | Schleifenbedingung |
| Bandklasse ≤ 2 | Gültiger NB-IoT-Modus | Eintritt von el1_ch_nbcch_resume_req |
el1_chmgm_cell_info_get ungleich null | Zelle in der Service-Tabelle | Aufgerufen in el1_ch_nbcch_start |
| Funktion | Adresse | Rolle | Begrenzung? |
|---|
errc_chm_l1_set_bcch_si_reception | ERRC-Bereich | Schreibt CPHY_CFG_REQ[+0x99] | Keine |
el1_ch_nbcch_cphy_cfg_req_process | 0x90213F80 | Leitet CPHY-Konfiguration in L1 | N/A — liest si_count nicht |
el1_chmgm_cell_info_get | 0x9020E0D0 | Validiert EARFCN/PCI | N/A |
el1_ch_nbcch_start | 0x90213444 | Kopiert Zähler nach BSS | Keine |
el1_ch_nbcch_resume_req | 0x90213940 | Verwendet Zähler als Schleifengrenze | Keine |
| 2025-04-23 |