Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Outils/GitHubGitHub/harbingerse7en/cve-2024-20154
Sécurité des Systèmes EmbarquésSécurité IoTCriminalistique MémoireAnalyse des VulnérabilitésRétro-ingénierieSécurité MobileSécurité Matériel et IoTAnalyse de BinairesArticles et Recherche

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
Apprentissage et Éducation
Analyse de Micrologiciel
GitHubharbingerse7en/cve-2024-20154

CVE-2024-20154

Analyse technique de CVE-2024-20154, un débordement de tampon basé sur la pile dans le firmware de bande de base NB-IoT MediaTek MT6769, couvrant l'ingénierie inverse et la chaîne d'exploitation.

Voir le dépôt
il y a 3 moisPas encore vérifié

CVE-2024-20154 : Débordement de pile SIB1-NB NB-IoT dans la bande de base MediaTek MT6769

Classification : CWE-121 — Débordement de tampon basé sur la pile
Sévérité : Critique (bulletin MediaTek) · 8.8 Élevée, Vecteur d'attaque : Adjacent (CISA-ADP)
Type : Exécution de code à distance — aucune interaction utilisateur, aucune association préalable
Divulgation : Bulletin de sécurité MediaTek, 6 janvier 2025 https://corp.mediatek.com/product-security-bulletin/January-2025 Cible analysée : Samsung Galaxy A14 SM-A145R — famille MT6769 (Helio G80), figurant dans la liste des chipsets affectés de MediaTek - Le firmware a été émulé dans des conditions sûres. Statut : Corrigé.


Contexte et motivation

Il s'agissait de ma première recherche publiée sur les bandes de base. Je viens d'un milieu très éloigné des infrastructures de télécommunications, des couches de médiation pour l'interception légale, de l'analyse des stingrays et des IMSI-catchers, et de la sécurité des dispositifs embarqués — je n'avais jamais effectué auparavant de rétro-ingénierie approfondie de firmware sur un modem cellulaire. Je voulais me prouver qu'une méthodologie analytique structurée s'adapte à différents types de cibles, et que la familiarité avec une plateforme spécifique peut être remplacée par un traçage rigoureux des chaînes. Le NB-IoT s'est démarqué parce qu'il se situe à une intersection véritablement dangereuse : le protocole est conçu pour des dispositifs IoT à ressources limitées, la surface d'attaque est pré-association, et la pile du modem le traite indépendamment de ce que fait l'utilisateur du téléphone.

Lorsque le firmware corrigé a été analysé et que le motif vulnérable a été confirmé absent, le système d'IA utilisé pour l'analyse de masse du firmware avant de cibler des fonctions spécifiques

a indépendamment fait correspondre la classe de bug reconstruite, les conditions et la famille de firmware affectée à la description de CVE-2024-20154.

Les conclusions techniques sont celles de l'analyste.


1. Introduction

Le téléphone dans votre poche contient au moins deux ordinateurs distincts. Celui avec lequel vous interagissez exécute Android. L'autre — la bande de base — fonctionne de manière totalement indépendante, gère toute la communication radio, et est presque entièrement invisible pour le système d'exploitation au-dessus. Android peut être entièrement corrigé. Le navigateur peut être isolé. L'utilisateur peut ne jamais cliquer sur un lien malveillant. Rien de tout cela n'a d'importance si le code vulnérable se trouve dans le firmware du modem qui traite les signaux radio avant que le processeur applicatif ne soit impliqué.

CVE-2024-20154 est exactement ce type de vulnérabilité.

Une diffusion d'informations système NB-IoT malformée amène le firmware du modem MediaTek à accepter un compteur d'ordonnancement contrôlé par l'attaquant, à faire transiter ce compteur par le chemin de configuration RRC-vers-L1 sans jamais le borner, et finalement à l'utiliser comme borne de boucle pour une boucle d'écriture sur la pile à l'intérieur du gestionnaire de canal de diffusion NB-IoT. Lorsque le compteur dépasse la capacité des tableaux de destination, la boucle écrit au-delà de ceux-ci, atteint les registres sauvegardés sur la pile, et écrase l'adresse de retour sauvegardée. La fonction restaure alors la valeur corrompue dans le registre d'adresse de retour et saute vers celle-ci.

Ce qui rend la sévérité telle qu'elle est :

  • Le chemin de code vulnérable est exercé pendant le campement sur une cellule — après synchronisation sur une cellule mais avant toute connexion RRC, toute authentification, toute interaction utilisateur.
  • L'entrée est une diffusion radio. Le téléphone ne peut pas authentifier la source.
  • Le firmware de la bande de base dans la version analysée s'exécute sans ASLR, sans canaris de pile, sans pile non exécutable, et sans intégrité du flux de contrôle. Un écrasement d'adresse de retour sauvegardée se traduit directement par un contrôle du compteur de programme.

La vulnérabilité a été publiée dans le bulletin de sécurité MediaTek du 6 janvier 2025 avec une évaluation de sévérité Critique, affectant entre autres la famille de modems LR12A. Samsung a intégré le correctif dans sa version de maintenance de sécurité de février 2025.

Cet article ne publie pas d'exploit weaponisé et n'est pas reproductible à partir de ce qui est publié ici. L'objectif est de montrer où la chaîne se brise, pourquoi chaque couche a échoué à l'arrêter, et ce qu'il faut pour valider un bug de bande de base de manière responsable lorsque vous ne pouvez pas attacher un débogueur au modem en direct.


2. Cible et environnement

2.1 Appareil et firmware

Cible principale : Samsung Galaxy A14 (SM-A145R). Le sous-système radio est piloté par un processeur de bande de base MediaTek de la famille de chipsets MT6769 (Helio G80). La famille MT6769 est explicitement listée dans la liste des chipsets affectés de MediaTek pour CVE-2024-20154.``` AP/CP firmware: A145RXXU1AWD1 Modem software: MOLY LR12A.R3.TC10.6M.A14.PR.SP.V1.P5 Build date: 2023-04-18

root@kitploit:~
Le firmware de la bande de base n'est pas du code Android. Il s'agit d'un système embarqué distinct sur le sous-système radio du SoC, avec son propre CPU, son propre RTOS et son propre espace mémoire, en dehors du bac à sable des processus Android.

### 2.2 Architecture du modem

L'analyse du binaire extrait montre que le processeur du modem fonctionne en MIPS32 avec des instructions compressées MIPS16e2 en mode petit-boutiste. MIPS16e2 est une extension d'encodage 16 bits pour la réduction de la taille du code embarqué — cohérente avec l'approche de MediaTek pour les bandes de base de la génération Helio, confirmée par des recherches indépendantes publiées sur les bandes de base de cette famille de SoC.

Le système d'exploitation est Nucleus RTOS, fournissant l'ordonnancement des tâches, des files de messages IPC et un allocateur de mémoire basé sur des pools. Il n'y a pas de séparation des privilèges noyau/utilisateur, pas d'application d'unité de protection mémoire entre les tâches, et pas de mécanisme matériel de protection de pile.

Toutes les adresses dans cet article sont des adresses virtuelles, telles que chargées dans Ghidra à la base `0x90000000`.

### 2.3 Atténuations (observées dans la build analysée)

| Atténuation | Statut | Effet |
|---|---|---|
| ASLR | Absent | Les adresses du firmware sont statiques et prévisibles à partir de l'image |
| Canari de pile | Absent | `SAVE`/`RESTORE` stocke les registres sauvegardés par l'appelé sans valeur de garde |
| NX / W^X | Absent | La mémoire de pile est exécutable |
| CFI | Absent | Les adresses de retour ne sont validées par aucune politique |

### 2.4 Approche d'analyse

Trois axes parallèles :

**Analyse statique.** Package firmware Samsung → extraction de la partition CP → `md1img.img` →
Ghidra (MIPS LE 32 bits, base `0x90000000`) avec les symboles d'ingénierie MediaTek récupérés
depuis la section de débogage du firmware à l'aide de l'outillage `mtk_bp` de NCC Group.

**Validation dynamique.** Unicorn Engine (émulation MIPS32) a été utilisé pour exécuter des
routines spécifiques du firmware en isolation sur deux phases. La phase 1 a tenté de prouver la
copie non bornée de `si_count` dans le contexte de canal via la paire d'instructions native. La
phase 2 a exécuté la boucle vulnérable sur les octets réels du firmware et a confirmé que les
instructions propres au firmware corrompent l'adresse de retour sauvegardée. Là où la phase 1
n'a pas pu s'exécuter entièrement en natif — parce que l'environnement d'objets de service RTOS
requis par le chemin de dispatch CPHY n'a pas été reconstruit — l'effet de bord a été modélisé
directement et étiqueté comme tel dans toutes les sorties.

**Validation côté radio.** srsRAN 4G avec une boucle locale ZMQ — logiciel uniquement, sans
émission RF — a confirmé que la charge utile de test survit à l'encodage PHY NB-IoT et à la
livraison du bloc de transport.

---

## 3. Surface d'attaque : NB-IoT et SIB1-NB

### 3.1 Surface d'attaque pré-association

NB-IoT (Narrowband Internet of Things) est la version 3GPP Release 13, conçue pour connecter des
appareils IoT contraints en utilisant le spectre LTE sous licence existant. Il est implémenté
dans une large gamme de SoC cellulaires modernes, y compris ceux des smartphones grand public.

En état RRC_IDLE, avant qu'une connexion RRC ne soit établie, un appareil recherchant un service
va :

1. Se synchroniser avec les signaux de timing de la cellule (NPSS/NSSS)
2. Décoder le Master Information Block sur NPBCH (fenêtre de transmission de 640 ms)
3. Décoder SIB1-NB depuis NPDSCH (planification de 2560 ms)
4. Utiliser les informations de planification dans SIB1-NB pour localiser des blocs d'informations système supplémentaires

À l'étape 3, le modem traite un message provenant d'une entité qu'il n'a pas authentifiée, avant
toute connexion ou interaction utilisateur. Un émetteur malveillant satisfaisant les conditions
normales de sélection de cellule sera traité.```
+------------------+                   +---------------------+
|  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]      |

3.2 Le champ de comptage de planification

SIB1-NB est défini dans la spécification 3GPP TS 36.331. Son champ schedulingInfoList indique combien de messages d'informations système la cellule diffuse, limité par la spécification à un maximum de 8 entrées (1..maxSI-Message-NB-r13 = 8). Il s'agit d'une contrainte de couche protocolaire. La contrainte de sécurité mémoire — à savoir que la longueur de la liste ne doit pas dépasser la capacité des tableaux de destination — doit être appliquée séparément par le firmware.

Elle ne l'était pas.


4. Extraction du firmware et récupération des symboles

Le firmware a été obtenu à partir d'un paquet CP Samsung et extrait à l'aide de l'ensemble d'outils mtk_bp de NCC Group :``` md1img.img → md1_extract.py → 000_md1rom (17.8 MB code image) → 017_md1_dbginfo (XZ-compressed CATI debug symbols)

root@kitploit:~
La section de débogage CATI a été décompressée et analysée avec `mtk_dbg_extract.py symbols`, puis
importée dans Ghidra via `ImportSymbolsScript.py`. Le résultat a été des noms de fonctions internes
complets dans toute la pile du modem — couche ERRC, gestion des canaux L1, sous-système IPC, et la
chaîne de gestionnaires NB-IoT BCCH — permettant une reconstruction de chaîne guidée par la sémantique.

Tous les noms de fonctions dans cet article proviennent des propres symboles de débogage intégrés de MediaTek extraits
de l'image du firmware.

---

## 5. Vulnérabilité

### 5.1 La boucle vulnérable

`el1_ch_nbcch_resume_req` (`0x90213940`) gère l'événement de reprise du canal de diffusion NB-IoT.
Son prologue de fonction MIPS16e2 :```asm
90213940:  save  0xE8, ra, s0-s1

L'instruction SAVE décrémente sp de 0xE8 et stocke les registres sauvegardés par l'appelé vers le bas :``` 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

root@kitploit:~
À partir de la décompilation Ghidra du binaire du firmware réel :```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] est ch_ctx[+0x40A] — un octet persistant dans la structure BSS du contexte de canal. La borne de boucle est utilisée directement, sans comparaison préalable avec les capacités du tableau.

5.2 L'arithmétique du débordement

Le flux A (écritures de demi-mots sh) commence à new_sp+0x98 et avance de 2 octets par itération. Il atteint l'adresse de retour sauvegardée à new_sp+0xE4 à l'itération 38 :``` new_sp + 0x98 + i×2 = new_sp + 0xE4 i = (0xE4 - 0x98) / 2 = 0x4C / 2 = 38

root@kitploit:~
Le flux B (écritures d'octets `sb`) commence à `new_sp+0x78` et nécessiterait l'itération 108 pour atteindre
l'emplacement RA :```
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108

Avec si_count = 40 (la valeur du démonstrateur, choisie pour dépasser le seuil de dépassement de 38) la boucle effectue 40 itérations. Le flux B n'atteint jamais l'emplacement RA. La corruption du RA provient entièrement du flux A.

Après 40 itérations, l'instruction MIPS16e2 RESTORE recharge la valeur corrompue depuis la pile dans $ra, et jrc ra transfère le contrôle.

5.3 La copie non bornée — Couche B

ch_ctx[+0x40A] est écrit par el1_ch_nbcch_start à 0x90213444. Deux instructions MIPS consécutives sans rien entre elles :```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

root@kitploit:~
### 5.4 Le constructeur ERRC — Couche A

Le tampon CPHY_CFG_REQ est construit dans la couche ERRC à partir du SIB1-NB décodé. La fonction
`errc_chm_l1_set_bcch_si_reception` écrit `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
    }
}

La borne de boucle est le nombre d'entrées décodées de SIB1-NB. Le compteur s'incrémente une fois par entrée décodée, pour autant d'entrées que décodées, sans garde maximale.

5.5 Le chemin IPC

Une fois le tampon CPHY_CFG_REQ rempli, ERRC le distribue à L1 avec sap_id = 0x501F comme clé de routage :``` 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

root@kitploit:~
### 5.6 Absence de clamping à trois couches

| Couche | Fonction | Adresse | Clamp présent ? |
|---|---|---|---|
| A — constructeur ERRC | `errc_chm_l1_set_bcch_si_reception` | plage ERRC | **Aucun** |
| B — copie L1 | `el1_ch_nbcch_start` | `0x90213444` | **Aucun** |
| C — boucle L1 | `el1_ch_nbcch_resume_req` | `0x90213940` | **Aucun** |

N'importe quelle vérification unique à n'importe laquelle de ces couches aurait brisé la chaîne.

### 5.7 Cause racine

Un invariant violé :

> Le nombre d'entrées de planification SI ne doit jamais dépasser la capacité du tableau de destination.

La 3GPP fournit la borne protocolaire prévue (8 entrées). Le firmware devait faire respecter la
borne de sûreté mémoire à chaque couche où le compteur devient un index ou une limite de boucle. Dans la
version vulnérable, le compteur voyageait depuis le champ de diffusion SIB1-NB à travers le décodeur
ERRC, dans le message CPHY_CFG_REQ, à travers une frontière IPC dans la tâche L1, dans
le contexte de canal BSS, et dans une boucle d'écriture sur la pile — sans qu'aucune couche ne le clampe.

---

## 6. La chaîne d'appel — Comment elle a été trouvée

### 6.1 La confusion des deux chemins

Deux chemins structurellement similaires mais distincts peuvent livrer un tampon de configuration de 0x760 octets à
`el1_ch_nbcch_main` :

| Chemin | Source | Valeur `[+0x99]` | Pertinence |
|---|---|---|---|
| Chemin A (ERRC → L1 IPC) | ERRC construit CPHY_CFG_REQ à partir du SIB1-NB décodé | `schedulingInfoList.count` depuis l'OTA | **Le chemin vulnérable** |
| Chemin B (interne L1) | `el1_ch_scs_ind_send` construit le corps IPC interne | `1` codé en dur | Non vulnérable |

Le chemin B a confirmé le format du message — l'octet `+0x99` est le compteur SI consommé par
`el1_ch_nbcch_start`. Comme son compteur est toujours codé en dur à 1, il ne peut pas déborder. Le
chemin influencé de l'extérieur est le chemin A.

### 6.2 La recherche de l'écrivain

La recherche par motif dans le firmware de toute instruction écrivant à l'offset `+0x99` a produit du bruit :
T1 (`sb` direct, ~100 résultats), T2 (base scindée, 5 résultats), T3 (offset calculé, 0), T4
(`sh`/`sw` chevauchants, ~465). Les fonctions de gestion de canal ERRC étaient absentes de la
liste de références croisées `msg_send6` parce qu'ERRC utilise `errc_com_send_msg`. Une sonde d'émulation
a confirmé que l'écriture était côté ERRC : exécuter le harnais Unicorn depuis le dispatcheur L1 et
surveiller les écritures à l'offset `+0x99` du tampon n'a rien capturé du côté 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.

6.3 Résolution via la clé de routage IPC

Le suivi de sap_id = 0x501F dans errc_com_send_msg a identifié le routage vers el1_chmgm_errc_cfg_req_in_idle, qui stocke le pointeur CPHY_CFG_REQ à L1_ctx[+0x323C] et commence la répartition en aval.

6.4 Chaîne d'appels confirmée```

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

root@kitploit:~
---

## 7. Validation

Ce modèle spécifique SM-A145R ne semble pas emprunter le chemin de code NB-IoT vulnérable lors d'un fonctionnement normal en configuration de série, ce qui explique pourquoi l'émulation hybride et l'analyse statique ont été utilisées plutôt qu'une reproduction directe sur matériel.

**Prouvé statiquement.** Le binaire du firmware contient la paire d'instructions vulnérable. La chaîne d'appel est reconstruite à partir des symboles, des références croisées et des corps de fonctions décompilés.

**Exécuté nativement en émulation.** La boucle à l'intérieur de `el1_ch_nbcch_resume_req` s'est exécutée sur de véritables octets de firmware MediaTek dans Unicorn Engine (MIPS32). L'instruction `sh` du firmware à l'adresse `0x90213B02` a écrit dans l'emplacement de l'adresse de retour sauvegardée. L'instruction `RESTORE` a chargé la valeur corrompue dans `$ra`, et `jrc ra` a transféré le contrôle.

**Modélisé explicitement.** La copie `lbu`/`sb` dans `el1_ch_nbcch_start` n'a pas pu être exécutée entièrement nativement car le chemin de dispatch de la table de rappel RTOS au sein de `el1_ch_nbcch_cphy_cfg_req_
process` attendait des objets de tas Nucleus actifs que l'émulateur plat ne fournissait pas. Le gestionnaire de reprise (`el1_ch_nbcch_resume_req`) en Phase 2 lit uniquement depuis le contexte de canal résidant en BSS et n'emprunte pas ce même chemin de dispatch, ce qui explique pourquoi la Phase 2 s'est exécutée nativement sans nécessiter le même échafaudage. L'effet de bord de la Phase 1 — un octet de `IPC_msg[+0x99]` écrit dans `ch_ctx[+0x40A]` — a été modélisé directement et étiqueté `[PHASE1-MODEL]`.

**Non revendiqué.** Une reproduction matérielle complète de bout en bout par liaison radio.

### 7.1 Anti-falsification

Le harnais a appliqué une règle : aucun hook n'était autorisé à écrire le marqueur de preuve dans l'emplacement de l'adresse de retour sauvegardée. Chaque écriture mémoire non liée au firmware a été tracée.```
[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 est l'instruction sh à l'intérieur du corps de la boucle. Le firmware a placé ces octets à l'offset de pile prédit. En stockage little-endian, les demi-mots 0xBEEF et 0xDEAD à new_sp+0xE4 et new_sp+0xE6 se combinent en [ef be ad de] = 0xDEADBEEF.

7.2 Résultat de l'émulation```

[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

root@kitploit:~
### 7.3 Livraison ZMQ

Pour confirmer que la charge utile de test survit à l'encodage PHY NB-IoT et à la livraison du bloc de transport, srsRAN 4G avec une boucle locale ZMQ (sans émission RF) a été utilisé. La charge utile était un vecteur délibérément non conforme — la contrainte ASN.1 SIZE sur `schedulingInfoList` a été assouplie pour autoriser 40 entrées, avec un décodage aller-retour pycrate confirmant le champ de comptage à l'octet 14.```
SIB1 received
SIB2 activated
exit 0

Cela confirme la livraison au niveau de la couche transport. Le comportement ASN.1 côté firmware est établi par l'analyse statique de la couche A.


8. Mécanismes de flux de contrôle

8.1 Deux phases, une tâche, état persistant

La tâche el1_ch dispose d'une seule pile. La phase 1 et la phase 2 sont deux événements IPC distincts traités séquentiellement par la même tâche, la pile se déroulant entièrement entre eux. Le compteur persiste dans le BSS du contexte de canal, et non sur la pile :``` 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

root@kitploit:~
`ch_ctx[0x40A]` réside dans la BSS et conserve la valeur de l'attaquant jusqu'à ce que le modem redémarre ou qu'une configuration de canal ultérieure l'écrase.

### 8.2 Pile d'appels```
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 taille de trame est confirmée par la mesure d'émulation. Les positions dans le tableau sont confirmées par le résultat de l'émulation — RA écrit à l'itération 38, ce qui est cohérent avec si_sched_arr commençant à new_sp+0x98.


9. Preuves

9.1 Conditions préalables à la boucle vulnérable

9.2 Fonctions confirmées comme ne bornant pas si_count


10. Analyse du correctif

10.1 Versions

BuildFirmware du modemDate de build
VulnérableA145RXXU1AWD1, MOLY LR12A...V1.P52023-04-18
CorrigéA145RXXUDDZC2, MOLY LR12A...V3.P8

Dates de build confirmées par l'extraction des métadonnées md1_dbginfo des deux images. ID du correctif : MOLY00720348 · ID du problème : MSV-2392.

10.2 Ce qui a changé

el1_ch_nbcch_start (0x90213444 dans le binaire vulnérable) : La paire d'instructions lbu/sb est absente. La copie directe de IPC_msg[+0x99] dans ch_ctx[+0x40A] a disparu.

el1_ch_nbcch_resume_req (0x90213940 dans le binaire vulnérable) : La boucle d'écriture sur la pile parcourant ch_ctx[0x40A] est absente. L'architecture où un octet non fiable devient une borne de boucle sur des tableaux de pile de taille fixe n'existe plus. Le corps de la fonction est remplacé par une structure de répartition différente.

errc_chm_l1_set_bcch_si_reception : La boucle à compteur non borné est remplacée par des appels à des fonctions auxiliaires orientées validation.

10.3 Nouvelles fonctions de validation

Deux fonctions présentes dans le binaire corrigé sont absentes du binaire vulnérable :``` el1_ch_nbcch_param_check el1_ch_scell_param_check

root@kitploit:~
Une vérification de limites sur une seule ligne apparaîtrait comme quelques instructions ajoutées à l'intérieur d'une fonction existante à la même adresse. Ce que le binaire corrigé montre est une révision architecturale : le chemin de planification NBCCH a été repensé de sorte que le motif `si_count`-comme-borne-de-boucle n'existe plus nulle part dans le chemin.

### 10.4 Attribution CVE

La vulnérabilité décrite ici correspond à CVE-2024-20154 telle que publiée par MediaTek le 6 janvier 2025. Base de confirmation :

- La famille de firmware affectée (LR12A) correspond au bulletin de MediaTek.
- La classe de vulnérabilité — débordement de pile, vérification de limites manquante, RCE depuis une station de base malveillante, aucune interaction utilisateur — correspond à la description de la CVE et à l'enregistrement NVD.
- Le firmware corrigé supprime exactement les structures de code identifiées comme vulnérables.
- L'ID de correctif MOLY00720348 confirmé à partir du bulletin de MediaTek et du Android Security Bulletin (A-376809176).
- L'analyse assistée par IA a indépendamment fait correspondre le motif reconstruit à CVE-2024-20154 avant confirmation manuelle.

---

## 11. Éthique et divulgation responsable

### 11.1 Ce que ce billet ne contient pas

Aucun exploit weaponisé. Aucun contenu binaire de firmware. Aucun octet de charge utile malformée. Aucune procédure étape par étape pour déclencher la vulnérabilité contre un appareil en fonctionnement. Les informations nécessaires pour reproduire une attaque fonctionnelle — construction complète de la charge utile pour le décodeur de modem spécifique, échafaudage d'objets de tas RTOS pour l'émulation complète de la Phase 1, configuration radio over-the-air — sont délibérément absentes.

### 11.2 Pourquoi la boucle locale ZMQ et l'émulation constituent l'approche éthique

La boucle locale ZMQ signifie qu'aucun signal n'a jamais été transmis par les ondes. Aucun appareil réel n'a été ciblé. Aucun réseau d'opérateur n'a été impliqué. La preuve s'exécute entièrement dans un environnement logiciel contenu sur du matériel appartenant à l'analyste. C'est l'approche correcte pour valider une vulnérabilité radio de pré-association — transmettre une diffusion malformée affecterait tout appareil à portée.

L'émulation Unicorn démontre que le comportement vulnérable se trouve dans le binaire du firmware lui-même, de manière reproductible, indépendamment de tout état d'appareil ou environnement radio spécifique. C'est une affirmation techniquement plus solide qu'un simple plantage matériel, et cela évite de déployer quoi que ce soit par les ondes.

### 11.3 Propriété intellectuelle MediaTek

Toute l'analyse a été effectuée sur un firmware obtenu légitimement à partir d'un appareil grand public et des packages de firmware publiés publiquement par Samsung. Aucune documentation propriétaire n'a été utilisée. Les définitions de structures internes MediaTek et les formats de messages IPC sont décrits uniquement dans la mesure nécessaire pour expliquer la défaillance de sûreté mémoire. Ils ne sont pas publiés en tant que spécifications.

---
Télécharger l’outil
Itérationsh écrit dansEffet
0–33si_sched_arr[0..33]Dans les limites
34–35new_sp+0xDC — s0 sauvegardés0 corrompu
36–37new_sp+0xE0 — s1 sauvegardés1 corrompu
38new_sp+0xE4 — ra sauvegardé [15:0]Demi-mot faible du RA
39new_sp+0xE6 — ra sauvegardé [31:16]Demi-mot fort du RA
ConditionÉtatOù vérifié
Chemin actif NB-IoTcfg_type == 1el1_ch_nbcch_cphy_cfg_req_process
Canal non completdone_flag == 0ch_ctx[0x438]
Machine à états 0x0BNBCCH en état de repriseRépartition de el1_ch_nbcch_main
si_count non nulch_ctx[0x40A] > 0Condition de boucle
Classe de bande ≤ 2Mode NB-IoT valideEntrée de el1_ch_nbcch_resume_req
el1_chmgm_cell_info_get non nulCellule dans la table de serviceAppelé dans el1_ch_nbcch_start
FonctionAdresseRôleBornage ?
errc_chm_l1_set_bcch_si_receptionPlage ERRCÉcrit CPHY_CFG_REQ[+0x99]Aucun
el1_ch_nbcch_cphy_cfg_req_process0x90213F80Achemine la configuration CPHY vers L1N/A — ne lit pas si_count
el1_chmgm_cell_info_get0x9020E0D0Valide EARFCN/PCIN/A
el1_ch_nbcch_start0x90213444Copie le compteur vers BSSAucun
el1_ch_nbcch_resume_req0x90213940Utilise le compteur comme borne de boucleAucun
2025-04-23