
Technischer Bericht zu CVE-2024-20154
Classification: CWE-121 — Stack-basierter Pufferüberlauf
Severity: Kritisch (MediaTek Bulletin) · 8.8 Hoch, Angriffsvektor: Angrenzend (CISA-ADP)
Type: Remote Code Execution — keine Benutzerinteraktion, keine vorherige Verbindung
Disclosure: 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 betroffenen Chipsatzliste von MediaTek - Firmware wurde unter sicheren Bedingungen emuliert.
Status: Behoben.
Dies war meine erste veröffentlichte Basisbandforschung. Ich komme aus einem Bereich, der weit entfernt ist von Telekommunikationsinfrastruktur, lawful interception Vermittlungsschichten, Stingray- und IMSI-Catcher-Analyse sowie eingebetteter Gerätesicherheit — ich hatte zuvor keine tiefgreifende Firmware-Rückentwicklung an einem Mobilfunkmodem durchgeführt. Ich wollte mir selbst beweisen, dass eine strukturierte Analysemethodik sich an unterschiedliche Ziele anpassen lässt und dass Vertrautheit mit einer bestimmten Plattform durch rigides Chain-Tracing ersetzt werden kann. NB-IoT stach hervor, weil es an einer wirklich gefährlichen Schnittstelle liegt: Das Protokoll ist für eingeschränkte IoT-Geräte ausgelegt, die Angriffsfläche liegt vor der Assoziation, und der Modem-Stack verarbeitet es unabhängig davon, was der Handy-Nutzer gerade tut.
Als die gepatchte Firmware analysiert und das anfällige Muster als nicht vorhanden bestätigt wurde, ordnete das KI-System, das für die Massenanalyse der Firmware vor der gezielten Untersuchung bestimmter Funktionen verwendet wurde, 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.
Das Telefon in Ihrer Tasche enthält mindestens zwei separate Computer. Der, mit dem Sie interagieren, läuft unter Android. Der andere — das Basisband — läuft völlig unabhängig, kümmert sich um die gesamte Funkkommunikation und ist für das darüberliegende Betriebssystem nahezu unsichtbar. Android kann vollständig gepatcht sein. Der Browser kann in einer Sandbox laufen. Der Benutzer tippt nie auf einen bösartigen Link. Nichts davon spielt eine Rolle, wenn der anfällige Code in der Modem-Firmware liegt, die Funksignale verarbeitet, bevor der Anwendungsprozessor einbezogen wird.
CVE-2024-20154 ist genau diese Art von Schwachstelle.
Eine fehlerhafte NB-IoT Systeminformation-Sendung führt dazu, dass die MediaTek-Modem-Firmware eine vom Angreifer kontrollierte Scheduling-Anzahl akzeptiert, diese Anzahl ohne jede Begrenzung durch den RRC-zu-L1-Konfigurationspfad trägt und sie schließlich als Schleifenbegrenzung für eine stapelschreibende Schleife innerhalb des NB-IoT Broadcast-Kanal-Handlers verwendet. Wenn die Anzahl die Kapazität der Zielarrays überschreitet, schreibt die Schleife über diese 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 im MediaTek Security Bulletin vom 6. Januar 2025 mit einer kritischen Schweregradbewertung veröffentlicht, die unter anderem die LR12A-Modem-Familie betrifft. Samsung hat den Fix in ihr Security Maintenance Release vom Februar 2025 integriert.
Dieser Beitrag veröffentlicht keinen ausnutzbaren Exploit und ist anhand des hier Veröffentlichten nicht reproduzierbar. Das Ziel ist es zu zeigen, wo die Kette bricht, warum jede Schicht versagt hat, sie zu stoppen, und was es braucht, um einen Basisband-Fehler verantwortungsvoll zu validieren, wenn man keinen Debugger an das laufende Modem anschließen kann.
Primäres Ziel: Samsung Galaxy A14 (SM-A145R). Das Funk-Subsystem wird von einem MediaTek-Basisbandprozessor der MT6769-Chipsatzfamilie (Helio G80) angetrieben. Die MT6769-Familie ist explizit in der Liste der betroffenen Chipsätze von MediaTek 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 Basisband-Firmware ist kein Android-Code. Es ist ein separates eingebettetes System im Funk-Subsystem des SoC mit eigener CPU, eigenem RTOS und eigenem Speicherbereich, außerhalb der Android-Prozess-Sandbox.
### 2.2 Modem-Architektur
Die Analyse der extrahierten Binärdatei zeigt, dass der Modem-Prozessor im Little-Endian-Modus MIPS32 mit MIPS16e2-komprimierten Befehlen ausführt. MIPS16e2 ist eine 16-Bit-Codierungserweiterung zur Reduzierung der Codegröße in eingebetteten Systemen – konsistent mit MediaTeks Ansatz für Basisbänder der Helio-Generation, bestätigt durch unabhängige veröffentlichte Basisband-Forschung zu dieser SoC-Familie.
Das Betriebssystem ist Nucleus RTOS, das Task-Scheduling, IPC-Nachrichtenwarteschlangen und einen Pool-basierten Speicherzuweiser bereitstellt. Es gibt keine Kernel/Benutzer-Privilegientrennung, keine Durchsetzung von Speicherschutzeinheiten zwischen Tasks und keinen Hardware-Stack-Guard-Mechanismus.
Alle Adressen in diesem Beitrag sind virtuelle Adressen, wie sie in Ghidra mit der Basis `0x90000000` geladen werden.
### 2.3 Gegenmaßnahmen (in der analysierten Build beobachtet)
| Gegenmaßnahme | Status | Auswirkung |
|---|---|---|
| ASLR | Nicht vorhanden | Firmware-Adressen sind statisch und aus dem Image vorhersagbar |
| Stack Canary | Nicht vorhanden | `SAVE`/`RESTORE` speichert Callee-saved Register ohne Schutz-Wert |
| NX / W^X | Nicht vorhanden | Stack-Speicher ist ausführbar |
| CFI | Nicht vorhanden | Rücksprungadressen werden nicht gegen eine Richtlinie validiert |
### 2.4 Analyseansatz
Drei parallele Pfade:
**Statische Analyse.** Samsung Firmware-Paket → CP-Partition extrahieren → `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 in zwei Phasen auszuführen. Phase 1 versuchte, die ungeklemmte Kopie von `si_count` in den Kanal-Kontext durch das native Befehlspaar nachzuweisen. Phase 2 führte die anfällige Schleife mit echten Firmware-Bytes aus und bestätigte, dass die eigenen Befehle der Firmware die gespeicherte Rücksprungadresse korrumpieren. Wo Phase 1 nicht vollständig nativ ausgeführt werden konnte – weil die RTOS-Service-Objekt-Umgebung, die vom CPHY-Dispatch-Pfad benötigt wurde, nicht rekonstruiert wurde – wurde der Nebeneffekt direkt modelliert und in allen Ausgaben als solcher gekennzeichnet.
**Funkseitige Validierung.** srsRAN 4G mit einer ZMQ-Schleife – rein softwarebasiert, keine HF-Abstrahlung – bestätigte, dass die Test-Nutzlast die NB-IoT-PHY-Codierung und den Transport-Block-Versand übersteht.
---
## 3. Angriffsfläche: NB-IoT und SIB1-NB
### 3.1 Angriffsfläche vor der Assoziation
NB-IoT (Schmalband-Internet der Dinge) ist 3GPP Release 13, entwickelt um eingeschränkte IoT-Geräte mit vorhandenem lizenziertem LTE-Spektrum zu verbinden. Es wird in einer Vielzahl moderner Mobilfunk-SoCs implementiert, darunter auch in denen von Verbraucher-Smartphones.
Während sich das Gerät im RRC_IDLE befindet, bevor eine RRC-Verbindung hergestellt ist, wird ein Gerät, das nach Dienst sucht, folgendes tun:
1. Mit den Zeitsignalen der Zelle synchronisieren (NPSS/NSSS)
2. Den Master Information Block über NPBCH decodieren (640 ms Sendefenster)
3. SIB1-NB von NPDSCH decodieren (2560 ms Zeitplan)
4. Die Planungsinformationen 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 eine Verbindung oder Benutzerinteraktion stattfindet. Ein unechter 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 trägt die Anzahl der System Information Messages, die die Zelle ausstrahlt, begrenzt durch die Spezifikation auf maximal 8 Einträge (1..maxSI-Message-NB-r13 = 8). Dies ist eine Einschränkung auf Protokollebene. Die Speichersicherheitseinschränkung – dass die Listenlänge die Kapazität der Ziel-Arrays nicht überschreiten darf – muss von der Firmware separat durchgesetzt werden.
Dies wurde nicht beachtet.
Die Firmware wurde aus einem Samsung-CP-Paket bezogen und mit dem NCC Group mtk_bp-Werkzeugsatz extrahiert:```
md1img.img → md1_extract.py → 000_md1rom (17.8 MB code image)
→ 017_md1_dbginfo (XZ-compressed CATI debug symbols)
Der CATI-Debug-Abschnitt wurde mit `mtk_dbg_extract.py symbols` dekomprimiert und geparst, dann über `ImportSymbolsScript.py` in Ghidra importiert. Das Ergebnis waren vollständige interne Funktionsnamen im gesamten Modem-Stack – ERRC-Schicht, L1-Kanalmanagement, IPC-Subsystem und die NB-IoT-BCCH-Handler-Kette – was eine semantikgesteuerte Kettenrekonstruktion ermöglichte.
Alle Funktionsnamen in diesem Beitrag stammen aus MediaTeks eigenen eingebetteten Debug-Symbolen, die aus dem Firmware-Image extrahiert wurden.
---
## 5. Sicherheitslücke
### 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
Der SAVE-Befehl verringert 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] is ch_ctx[+0x40A] — ein persistentes Byte im BSS-Struct des Kanal-Kontexts.
Die Schleifenbegrenzung wird direkt verwendet, ohne vorherigen Vergleich mit den Array-Kapazitäten.
Stream A (Halfword sh schreibt) beginnt bei new_sp+0x98 und rückt pro Iteration um 2 Bytes vor.
Er erreicht das 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` writes) beginnt bei `new_sp+0x78` und würde Iteration 108 benötigen, um den RA-Slot zu erreichen:```
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108
With si_count = 40 (dem Demonstratorwert, gewählt um den Überlaufschwellenwert von 38 zu überschreiten) führt die Schleife 40 Iterationen aus. Stream B erreicht nie den RA-Slot. Die RA-Korruption stammt vollständig von Stream A.
Nach 40 Iterationen lädt die MIPS16e2 RESTORE-Instruktion den beschädigten Wert vom Stack in $ra, und jrc ra übergibt die Kontrolle.
ch_ctx[+0x40A] wird von el1_ch_nbcch_start bei 0x90213444 geschrieben. Zwei aufeinanderfolgende MIPS-Befehle 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 — Schicht A
Der CPHY_CFG_REQ-Puffer wird in der ERRC-Schicht aus dem decodierten SIB1-NB erstellt. 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 Anzahl der decodierten Einträge aus SIB1-NB. Der Zähler erhöht sich um eins pro decodiertem Eintrag, für so viele Einträge, wie decodiert wurden, ohne maximale Begrenzung.
Sobald der CPHY_CFG_REQ-Puffer gefüllt ist, sendet ERRC ihn an L1 mit sap_id = 0x501F als Routing-Schlüssel:```
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 Fehlende Begrenzung auf drei Ebenen
| 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** |
Eine einzige Prüfung auf einer beliebigen Ebene hätte die Kette unterbrochen.
### 5.7 Grundursache
Eine verletzte Invariante:
> Die Anzahl der SI-Planungseinträge darf niemals die Kapazität des Ziel-Arrays überschreiten.
3GPP liefert die vorgesehene Protokollgrenze (8 Einträge). Die Firmware musste die Speichersicherheitsgrenze auf jeder Ebene durchsetzen, auf der die Anzahl zu einem Index oder einer Schleifenbegrenzung wird. In der anfälligen Version wanderte die Anzahl vom SIB1-NB-Rundfunkfeld durch den ERRC-Decoder, in die CPHY_CFG_REQ-Nachricht, über eine IPC-Grenze hinweg in die L1-Aufgabe, in den Kanal-Kontext-BSS und in eine Stack-Schreibschleife — ohne dass eine Ebene sie begrenzte.
---
## 6. Die Aufrufkette — Wie sie gefunden wurde
### 6.1 Die Zwei-Pfad-Verwirrung
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 erstellt CPHY_CFG_REQ aus dekodiertem SIB1-NB | `schedulingInfoList.count` from OTA | **Der anfällige Pfad** |
| Pfad B (L1-intern) | `el1_ch_scs_ind_send` erstellt internen IPC body | Hartcodiert `1` | Nicht anfällig |
Pfad B bestätigte das Nachrichtenformat — Byte `+0x99` ist die SI-Anzahl, die von `el1_ch_nbcch_start` konsumiert wird. Da seine Anzahl immer auf 1 hartcodiert ist, kann es nicht überlaufen. Der extern beeinflusste Pfad ist Pfad A.
### 6.2 Die Suche nach der Schreibinstruktion
Die Mustersuche in der Firmware nach Anweisungen, die auf Offset `+0x99` schreiben, ergab 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 die Schreiboperation auf der ERRC-Seite stattfand: Das Ausführen des Unicorn-Harness vom L1-Dispatcher und das Überwachen auf Schreibvorgänge auf den Puffer-Offset `+0x99` 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.
Nach sap_id = 0x501F in errc_com_send_msg wurde das Routing zu
el1_chmgm_errc_cfg_req_in_idle identifiziert, welches den CPHY_CFG_REQ-Zeiger an
L1_ctx[+0x323C] speichert und mit der nachgelagerten Verteilung 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 im normalen Betrieb des ausgelieferten Geräts den anfälligen NB-IoT-Codepfad nicht zu durchlaufen, weshalb anstelle einer direkten Hardware-Reproduktion hybride Emulation und statische Analyse eingesetzt wurden.
**Statisch nachgewiesen.** Das Firmware-Binary enthält das anfällige Instruktionspaar. Die Aufrufkette wird aus Symbolen, Querverweisen und dekompilierten Funktionskörpern rekonstruiert.
**Nativ in Emulation ausgeführt.** Die Schleife innerhalb von `el1_ch_nbcch_resume_req` lief mit echten MediaTek-Firmware-Bytes in der Unicorn Engine (MIPS32). Die eigene `sh`-Instruktion der Firmware an Adresse `0x90213B02` schrieb in den Slot der gesicherten Rücksprungadresse. Die Instruktion `RESTORE` lud den korrupten Wert in `$ra` und `jrc ra` übergab 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-Tabellen-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 ohne die gleiche Gerüststruktur nativ lief. Der Nebeneffekt von Phase 1 – ein Byte von `IPC_msg[+0x99]` geschrieben nach `ch_ctx[+0x40A]` – wurde direkt modelliert und als `[PHASE1-MODEL]` gekennzeichnet.
**Nicht beansprucht.** Eine vollständige End-to-End-Hardware-Reproduktion über die Luftschnittstelle.
### 7.1 Anti-Manipulation
Die Testumgebung setzte eine Regel durch: Kein Hook durfte den Proof-Marker in den Slot der gesicherten Rücksprungadresse schreiben. Jeder Nicht-Firmware-Speicherschreibzugriff 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 der sh-Befehl innerhalb des Schleifenkörpers. Die Firmware platzierte diese Bytes an
dem vorhergesagten Stack-Offset. In Little-Endian-Speicherung kombinieren sich 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 der Test-Payload die NB-IoT-PHY-Kodierung und die Transportblock-Zustellung übersteht, wurde srsRAN
4G mit einer ZMQ-Rückkopplung (keine HF-Emission) verwendet. Der Payload war ein bewusst
nicht konformer Vektor — die ASN.1-SIZE-Einschränkung auf `schedulingInfoList` wurde gelockert, um
40 Einträge zu erlauben, wobei die pycrate-Round-Trip-Dekodierung das Zählerfeld bei Byte 14 bestätigte.```
SIB1 received
SIB2 activated
exit 0
Dies bestätigt die Zustellung auf Transportschicht. Das ASN.1-Verhalten auf Firmware-Seite wird durch die Layer-A-Statikanalyse festgelegt.
Die el1_ch-Aufgabe hat einen Stack. Phase 1 und Phase 2 sind zwei separate IPC-Ereignisse, die nacheinander von derselben Aufgabe verarbeitet werden, wobei der Stack zwischen ihnen vollständig abgewickelt wird. Der Zähler bleibt im Kanal-Kontext-BSS bestehen, 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]` lives in BSS and behält den Wert des Angreifers, bis das Modem zurückgesetzt wird oder eine
nachfolgende Kanal-Konfiguration ihn überschreibt.
### 8.2 Stackrahmen```
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]
Rahmengröße durch Emulationsmessung bestätigt. Array-Positionen durch das Emulationsergebnis bestätigt — RA geschrieben bei Iteration 38, konsistent mit si_sched_arr, beginnend bei new_sp+0x98.
| Build | Modem-Firmware | Bau-Datum |
|---|---|---|
| Anfällig | A145RXXU1AWD1, MOLY LR12A...V1.P5 | 2023-04-18 |
| Gepatched | A145RXXUDDZC2, MOLY LR12A...V3.P8 |
Baudaten bestätigt durch Extrahieren der md1_dbginfo-Metadaten aus beiden Images. Patch-ID: MOLY00720348 · Issue-ID: MSV-2392.
el1_ch_nbcch_start (0x90213444 im anfälligen Binary): Das lbu/sb-Befehlspaar fehlt. Die direkte Kopie von IPC_msg[+0x99] in ch_ctx[+0x40A] ist weg.
el1_ch_nbcch_resume_req (0x90213940 im anfälligen 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 wird durch eine andere Dispatch-Struktur ersetzt.
errc_chm_l1_set_bcch_si_reception: Die unbegrenzte Zählerschleife wird durch validierungsorientierte Hilfsaufrufe ersetzt.
Zwei Funktionen, die im gepatachten Binary vorhanden sind, fehlen im anfälligen Binary:``` el1_ch_nbcch_param_check el1_ch_scell_param_check
Eine einzeilige Grenzwertprüfung würde als einige wenige hinzugefügte Instruktionen innerhalb einer vorhandenen Funktion an derselben Adresse erscheinen. Was die gepatchte Binärdatei zeigt, ist eine architektonische Überarbeitung: Der NBCCH-Scheduling-Pfad wurde so umgestaltet, dass das Muster `si_count`-als-Schleifengrenze nirgendwo mehr im Pfad existiert.
### 10.4 CVE-Zuordnung
Die hier beschriebene Schwachstelle entspricht CVE-2024-20154, veröffentlicht von MediaTek am 6. Januar 2025. Bestätigungsbasis:
- Die betroffene Firmware-Familie (LR12A) stimmt mit dem MediaTek-Bulletin überein.
- Die Schwachstellenklasse – Stack-Überlauf, fehlende Grenzwertprüfung, RCE von einer unechten Basisstation, keine Benutzerinteraktion – entspricht der CVE-Beschreibung und dem NVD-Eintrag.
- Die gepatchte Firmware entfernt genau die Code-Strukturen, die als anfällig identifiziert wurden.
- Patch-ID MOLY00720348, bestätigt durch das MediaTek-Bulletin und das Android Security Bulletin (A-376809176).
- KI-gestützte Analyse hat das rekonstruierte Muster unabhängig mit CVE-2024-20154 abgeglichen, bevor eine manuelle Bestätigung erfolgte.
---
## 11. Ethik und verantwortungsvolle Offenlegung
### 11.1 Was dieser Beitrag nicht enthält
Kein einsatzfähiger Exploit. Kein Firmware-Binärinhalt. Keine fehlerhaften Payload-Bytes. Keine Schritt-für-Schritt-Anleitung zum Auslösen der Schwachstelle gegen ein Live-Gerät. Die Informationen, die zur Reproduktion eines funktionsfähigen Angriffs benötigt werden – vollständiger Payload-Aufbau für den spezifischen Modem-Decoder, RTOS-Heap-Objektgerüst für vollständige Phase-1-Emulation, Over-the-Air-Funkkonfiguration – sind bewusst weggelassen.
### 11.2 Warum ZMQ-Loopback und Emulation der ethische Ansatz sind
ZMQ-Loopback bedeutet, dass nie ein Signal über die Luft gesendet wurde. Kein echtes Gerät wurde angegriffen. Kein Betreibernetz war involviert. Der Beweis läuft vollständig in einer eingeschlossenen Softwareumgebung auf Hardware, die dem Analysten gehört. Dies ist der richtige Ansatz zur Validierung einer Pre-Association-Funkschwachstelle – das Senden einer fehlerhaften Broadcast-Nachricht würde jedes Gerät in Reichweite betreffen.
Unicorn-Emulation zeigt, dass das anfällige Verhalten in der Firmware-Binärdatei selbst liegt, reproduzierbar, unabhängig von einem bestimmten Gerätezustand oder einer Funkumgebung. Dies ist eine technisch stärkere Behauptung als ein einzelner Hardware-Absturz und vermeidet die Auslieferung von etwas über die Luft.
### 11.3 MediaTek-Geistiges Eigentum
Sämtliche Analysen wurden an Firmware durchgeführt, die rechtmäßig von einem Verbrauchergerät und aus den öffentlich veröffentlichten Firmware-Paketen von Samsung bezogen wurde. Es wurde keine proprietäre Dokumentation verwendet. Interne MediaTek-Strukturdefinitionen und IPC-Nachrichtenformate werden nur in dem Umfang beschrieben, der zur Erklärung des Speichersicherheitsfehlers erforderlich ist. Sie werden nicht als Spezifikationen veröffentlicht.
| Iteration | sh schreibt in | Effekt |
|---|
| 0–33 | si_sched_arr[0..33] | In Grenzen |
| 34–35 | new_sp+0xDC — gespeichertes s0 | s0 beschädigt |
| 36–37 | new_sp+0xE0 — gespeichertes s1 | s1 beschädigt |
| 38 | new_sp+0xE4 — gespeichertes ra [15:0] | Niedriges Halbwort von RA |
| 39 | new_sp+0xE6 — gespeichertes ra [31:16] | Hohes Halbwort von RA |
| Sperre | 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 Wiederaufnahmezustand | 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 Servicetabelle | 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 an L1 weiter | 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 in BSS | Keine |
el1_ch_nbcch_resume_req | 0x90213940 | Verwendet Zähler als Schleifengrenze | Keine |
| 2025-04-23 |