Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/harbingerse7en/cve-2024-20154
Seguridad de Sistemas EmbebidosSeguridad IoTForensia de MemoriaAnálisis de VulnerabilidadesIngeniería InversaSeguridad MóvilSeguridad de Hardware e IoTAnálisis de BinariosPapers e Investigación

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Aprendizaje y Educación
Análisis de Firmware
GitHubharbingerse7en/cve-2024-20154

CVE-2024-20154

Análisis técnico de CVE-2024-20154, un desbordamiento de búfer basado en pila en el firmware del módem baseband MediaTek MT6769 NB-IoT, que abarca ingeniería inversa y cadena de explotación.

Ver Repositorio
hace 3 mesesAún no revisado

CVE-2024-20154: Desbordamiento de pila en SIB1-NB de NB-IoT en la banda base MediaTek MT6769

Clasificación: CWE-121 — Desbordamiento de búfer basado en pila
Gravedad: Crítica (boletín de MediaTek) · 8.8 Alta, Vector de ataque: Adyacente (CISA-ADP)
Tipo: Ejecución remota de código — sin interacción del usuario, sin asociación previa
Divulgación: Boletín de seguridad de MediaTek, 6 de enero de 2025 https://corp.mediatek.com/product-security-bulletin/January-2025 Objetivo analizado: Samsung Galaxy A14 SM-A145R — familia MT6769 (Helio G80), dentro de la lista de chipsets afectados de MediaTek - El firmware fue emulado en condiciones seguras. Estado: Parcheado.


Antecedentes y motivación

Esta fue mi primera investigación publicada sobre banda base. Vengo de un entorno muy alejado de la infraestructura de telecomunicaciones, las capas de mediación de interceptación legal, el análisis de stingray y capturadores de IMSI, y la seguridad de dispositivos embebidos — no había realizado previamente ingeniería inversa profunda de firmware en un módem celular. Quería demostrarme a mí mismo que una metodología analítica estructurada se adapta a distintos objetivos, y que la familiaridad con una plataforma específica puede reemplazarse por un rastreo riguroso de la cadena. NB-IoT destacaba porque se sitúa en una intersección genuinamente peligrosa: el protocolo está diseñado para dispositivos IoT con recursos limitados, la superficie de ataque es previa a la asociación, y la pila del módem lo procesa independientemente de lo que esté haciendo el usuario del teléfono.

Cuando se analizó el firmware parcheado y se confirmó la ausencia del patrón vulnerable, el sistema de IA utilizado para el análisis masivo del firmware antes de apuntar a funciones específicas

coincidió de forma independiente con la clase de bug reconstruida, las condiciones y la familia de firmware afectada con la descripción de CVE-2024-20154.

Las conclusiones técnicas son del propio analista.


1. Introducción

El teléfono que llevas en el bolsillo contiene al menos dos computadoras separadas. Con la que interactúas ejecuta Android. La otra — la banda base — se ejecuta de forma completamente independiente, gestiona toda la comunicación por radio, y es casi totalmente invisible para el sistema operativo que está por encima. Android puede estar completamente parcheado. El navegador puede estar en sandbox. El usuario puede no tocar nunca un enlace malicioso. Nada de eso importa si el código vulnerable está en el firmware del módem que procesa las señales de radio antes de que el procesador de aplicaciones intervenga.

CVE-2024-20154 es exactamente ese tipo de vulnerabilidad.

Una difusión de información de sistema NB-IoT malformada hace que el firmware del módem MediaTek acepte un conteo de planificación controlado por el atacante, arrastre ese conteo a través de la ruta de configuración RRC-a-L1 sin acotarlo nunca, y finalmente lo use como límite de bucle para un bucle de escritura en pila dentro del manejador del canal de difusión NB-IoT. Cuando el conteo excede la capacidad de los arrays de destino, el bucle escribe más allá de ellos, alcanza los registros guardados en la pila y sobrescribe la dirección de retorno guardada. La función entonces restaura el valor corrupto en el registro de dirección de retorno y salta a él.

Lo que hace que la gravedad sea la que es:

  • La ruta de código vulnerable se ejecuta durante el campamento en celda — después de sincronizarse con una celda pero antes de cualquier conexión RRC, cualquier autenticación, cualquier interacción del usuario.
  • La entrada es una difusión por el aire. El teléfono no puede autenticar la fuente.
  • El firmware de la banda base en la compilación analizada se ejecuta sin ASLR, sin canarios de pila, sin pila no ejecutable y sin integridad de flujo de control. Una sobrescritura de la dirección de retorno guardada se traduce directamente en control del contador de programa.

La vulnerabilidad se publicó en el Boletín de Seguridad de MediaTek del 6 de enero de 2025 con una calificación de gravedad Crítica, afectando a la familia de módems LR12A entre otras. Samsung incorporó la corrección en su Versión de Mantenimiento de Seguridad de febrero de 2025.

Esta publicación no publica un exploit weaponizado y no es reproducible a partir de lo que se publica aquí. El objetivo es mostrar dónde se rompe la cadena, por qué cada capa falló en detenerlo, y qué se necesita para validar un bug de banda base de forma responsable cuando no puedes conectar un depurador al módem en vivo.


2. Objetivo y entorno

2.1 Dispositivo y firmware

Objetivo principal: Samsung Galaxy A14 (SM-A145R). El subsistema de radio está controlado por un procesador de banda base MediaTek de la familia de chipsets MT6769 (Helio G80). La familia MT6769 está explícitamente incluida en la lista de chipsets afectados de MediaTek para 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:~
El firmware de banda base no es código Android. Es un sistema embebido separado en el
subsistema de radio del SoC con su propia CPU, su propio RTOS y su propio espacio de memoria,
fuera del sandbox de procesos de Android.

### 2.2 Arquitectura del módem

El análisis del binario extraído muestra que el procesador del módem ejecuta MIPS32 con
instrucciones comprimidas MIPS16e2 en modo little-endian. MIPS16e2 es una extensión de
codificación de 16 bits para la reducción del tamaño de código embebido — consistente con el
enfoque de MediaTek para las bandas base de la generación Helio, confirmado por investigación
independiente publicada sobre bandas base de esta familia de SoC.

El sistema operativo es Nucleus RTOS, que proporciona planificación de tareas, colas de
mensajes IPC y un asignador de memoria basado en pools. No hay separación de privilegios
kernel/usuario, no hay aplicación de unidad de protección de memoria entre tareas y no hay
mecanismo de protección de pila por hardware.

Todas las direcciones en este post son direcciones virtuales, tal como se cargan en Ghidra con
base `0x90000000`.

### 2.3 Mitigaciones (observadas en la compilación analizada)

| Mitigación | Estado | Efecto |
|---|---|---|
| ASLR | Ausente | Las direcciones del firmware son estáticas y predecibles a partir de la imagen |
| Stack canary | Ausente | `SAVE`/`RESTORE` almacena registros callee-saved sin valor de guarda |
| NX / W^X | Ausente | La memoria de pila es ejecutable |
| CFI | Ausente | Las direcciones de retorno no se validan contra ninguna política |

### 2.4 Enfoque de análisis

Tres vías paralelas:

**Análisis estático.** Paquete de firmware de Samsung → extracción de la partición CP → `md1img.img` →
Ghidra (MIPS LE 32-bit, base `0x90000000`) con símbolos de ingeniería de MediaTek recuperados de
la sección de depuración del firmware usando el conjunto de herramientas `mtk_bp` de NCC Group.

**Validación dinámica.** Se utilizó Unicorn Engine (emulación MIPS32) para ejecutar rutinas
específicas del firmware de forma aislada en dos fases. La Fase 1 intentó demostrar la copia sin
restricciones de `si_count` en el contexto del canal a través del par de instrucciones nativo. La
Fase 2 ejecutó el bucle vulnerable sobre bytes reales del firmware y confirmó que las propias
instrucciones del firmware corrompen la dirección de retorno guardada. Donde la Fase 1 no pudo
ejecutarse completamente de forma nativa — porque el entorno de objetos de servicio del RTOS
requerido por la ruta de despacho CPHY no fue reconstruido — el efecto secundario se modeló
directamente y se etiquetó como tal en toda la salida.

**Validación del lado de radio.** srsRAN 4G con un loopback ZMQ — solo software, sin emisión de RF —
confirmó que el payload de prueba sobrevive a la codificación PHY de NB-IoT y a la entrega del
bloque de transporte.

---

## 3. Superficie de ataque: NB-IoT y SIB1-NB

### 3.1 Superficie de ataque previa a la asociación

NB-IoT (Narrowband Internet of Things) es 3GPP Release 13, diseñado para conectar dispositivos
IoT de recursos limitados usando espectro LTE licenciado existente. Está implementado en una
amplia gama de SoCs celulares modernos, incluidos los de smartphones de consumo.

Mientras está en RRC_IDLE, antes de que se establezca cualquier conexión RRC, un dispositivo que
busca servicio:

1. Se sincroniza con las señales de temporización de la celda (NPSS/NSSS)
2. Decodifica el Master Information Block sobre NPBCH (ventana de transmisión de 640 ms)
3. Decodifica SIB1-NB desde NPDSCH (programación de 2560 ms)
4. Usa la información de programación en SIB1-NB para localizar bloques de información de sistema adicionales

En el paso 3, el módem procesa un mensaje de una entidad que no ha autenticado, antes de
cualquier conexión o interacción del usuario. Un transmisor malicioso que cumpla las condiciones
normales de selección de celda será procesado.```
+------------------+                   +---------------------+
|  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 El campo de recuento de planificación

SIB1-NB se define en 3GPP TS 36.331. Su campo schedulingInfoList indica cuántos mensajes de Información de Sistema difunde la celda, restringido por la especificación a un máximo de 8 entradas (1..maxSI-Message-NB-r13 = 8). Esta es una restricción de la capa de protocolo. La restricción de seguridad de memoria —que la longitud de la lista no debe exceder la capacidad de los arrays de destino— debe ser aplicada por separado por el firmware.

No lo fue.


4. Extracción de firmware y recuperación de símbolos

El firmware se obtuvo de un paquete CP de Samsung y se extrajo utilizando el conjunto de herramientas 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 sección de depuración CATI se descomprimió y se analizó con `mtk_dbg_extract.py symbols`, y luego
se importó en Ghidra mediante `ImportSymbolsScript.py`. El resultado fueron nombres de funciones
internas completos en toda la pila del módem — la capa ERRC, la gestión de canales L1, el subsistema IPC y la
cadena de gestores BCCH de NB-IoT — lo que permitió la reconstrucción de la cadena guiada por semántica.

Todos los nombres de funciones en esta publicación provienen de los propios símbolos de depuración
integrados de MediaTek extraídos de la imagen del firmware.

---

## 5. Vulnerabilidad

### 5.1 El bucle vulnerable

`el1_ch_nbcch_resume_req` (`0x90213940`) gestiona el evento de reanudación del canal de difusión NB-IoT.
Su prólogo de función MIPS16e2:```asm
90213940:  save  0xE8, ra, s0-s1

La instrucción SAVE decrementa sp en 0xE8 y almacena los registros guardados por el destinatario hacia abajo:``` 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:~
Desde la descompilación de Ghidra del binario de firmware real:```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] es ch_ctx[+0x40A] — un byte persistente en la estructura BSS del contexto del canal. El límite del bucle se utiliza directamente, sin comparación previa con las capacidades del array.

5.2 La aritmética del desbordamiento

El flujo A (escrituras de media palabra sh) comienza en new_sp+0x98 y avanza 2 bytes por iteración. Alcanza la RA guardada en new_sp+0xE4 en la iteración 38:``` new_sp + 0x98 + i×2 = new_sp + 0xE4 i = (0xE4 - 0x98) / 2 = 0x4C / 2 = 38

root@kitploit:~
Stream B (escrituras de byte `sb`) comienza en `new_sp+0x78` y requeriría la iteración 108 para alcanzar
la ranura RA:```
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108

Con si_count = 40 (el valor del demostrador, elegido para superar el umbral de desbordamiento de 38) el bucle se ejecuta 40 iteraciones. El Stream B nunca alcanza el slot de RA. La corrupción de RA proviene enteramente del Stream A.

Tras 40 iteraciones, la instrucción RESTORE de MIPS16e2 recarga el valor corrompido desde la pila en $ra, y jrc ra transfiere el control.

5.3 La copia sin restricción — Capa B

ch_ctx[+0x40A] es escrito por el1_ch_nbcch_start en 0x90213444. Dos instrucciones MIPS consecutivas sin nada entre ellas:```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 El constructor de ERRC — Capa A

El búfer CPHY_CFG_REQ se construye en la capa ERRC a partir del SIB1-NB decodificado. La función
`errc_chm_l1_set_bcch_si_reception` escribe `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
    }
}

El límite del bucle es el recuento de entradas decodificadas de SIB1-NB. El contador se incrementa una vez por entrada decodificada, para tantas entradas como se hayan decodificado, sin ninguna protección de máximo.

5.5 La ruta IPC

Una vez que el búfer CPHY_CFG_REQ está poblado, ERRC lo despacha a L1 con sap_id = 0x501F como clave de enrutamiento:``` 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 Ausencia de limitación en tres capas

| Capa | Función | Dirección | ¿Limitación presente? |
|---|---|---|---|
| A — constructor ERRC | `errc_chm_l1_set_bcch_si_reception` | Rango ERRC | **Ninguna** |
| B — copia L1 | `el1_ch_nbcch_start` | `0x90213444` | **Ninguna** |
| C — bucle L1 | `el1_ch_nbcch_resume_req` | `0x90213940` | **Ninguna** |

Cualquier verificación única en cualquiera de las capas habría roto la cadena.

### 5.7 Causa raíz

Un invariante violado:

> El número de entradas de planificación de SI nunca debe exceder la capacidad del array de destino.

3GPP proporciona el límite de protocolo previsto (8 entradas). El firmware necesitaba aplicar el
límite de seguridad de memoria en cada capa donde el conteo se convierte en un índice o límite de bucle. En la
compilación vulnerable, el conteo viajó desde el campo de difusión SIB1-NB a través del decodificador
ERRC, hacia el mensaje CPHY_CFG_REQ, cruzando una frontera IPC hacia la tarea L1, hacia
el contexto de canal BSS, y hacia un bucle de escritura en pila — sin que ninguna capa lo limitara.

---

## 6. La cadena de llamadas — Cómo se encontró

### 6.1 La confusión de dos rutas

Dos rutas estructuralmente similares pero distintas pueden entregar un búfer de configuración de 0x760 bytes a
`el1_ch_nbcch_main`:

| Ruta | Origen | Valor de `[+0x99]` | Relevancia |
|---|---|---|---|
| Ruta A (ERRC → L1 IPC) | ERRC construye CPHY_CFG_REQ a partir de SIB1-NB decodificado | `schedulingInfoList.count` desde OTA | **La ruta vulnerable** |
| Ruta B (L1 interna) | `el1_ch_scs_ind_send` construye el cuerpo IPC interno | `1` codificado | No vulnerable |

La Ruta B confirmó el formato del mensaje — el byte `+0x99` es el conteo de SI consumido por
`el1_ch_nbcch_start`. Debido a que su conteo siempre está codificado a 1, no puede desbordarse. La
ruta influenciada externamente es la Ruta A.

### 6.2 La búsqueda del escritor

La búsqueda por patrones en el firmware de cualquier instrucción que escriba en el desplazamiento `+0x99` produjo ruido:
T1 (`sb` directo, ~100 coincidencias), T2 (base dividida, 5 coincidencias), T3 (desplazamiento calculado, 0), T4
(`sh`/`sw` superpuestos, ~465). Las funciones de gestión de canales ERRC estaban ausentes de la
lista de referencias cruzadas de `msg_send6` porque ERRC utiliza `errc_com_send_msg`. Una sonda de emulación
confirmó que la escritura era del lado ERRC: ejecutar el arnés Unicorn desde el despachador L1 y
observar escrituras en el desplazamiento `+0x99` del búfer no capturó nada desde el lado 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 Resolución mediante clave de enrutamiento IPC

El seguimiento de sap_id = 0x501F en errc_com_send_msg identificó el enrutamiento hacia el1_chmgm_errc_cfg_req_in_idle, que almacena el puntero CPHY_CFG_REQ en L1_ctx[+0x323C] y comienza el despacho descendente.

6.4 Cadena de llamadas confirmada```

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. Validación

Este modelo específico SM-A145R no parece ejecutar
la ruta de código NB-IoT vulnerable en la operación normal de compilación de envío, por lo que se utilizaron
emulación híbrida y análisis estático en lugar de reproducción directa en hardware.

**Probado estáticamente.** El binario del firmware contiene el par de instrucciones vulnerable. La cadena
de llamadas se reconstruye a partir de símbolos, referencias cruzadas y cuerpos de funciones descompilados.

**Ejecutado de forma nativa en emulación.** El bucle dentro de `el1_ch_nbcch_resume_req` se ejecutó sobre bytes
reales del firmware MediaTek en Unicorn Engine (MIPS32). La instrucción `sh` del propio firmware en
`0x90213B02` escribió en la ranura de dirección de retorno guardada. La instrucción `RESTORE` cargó el
valor corrupto en `$ra`, y `jrc ra` transfirió el control.

**Modelado explícitamente.** La copia `lbu`/`sb` en `el1_ch_nbcch_start` no pudo ejecutarse completamente
de forma nativa porque la ruta de despacho de la tabla de callbacks del RTOS dentro de `el1_ch_nbcch_cphy_cfg_req_
process` esperaba objetos de heap de Nucleus activos que el emulador plano no proporcionaba. El manejador
de reanudación (`el1_ch_nbcch_resume_req`) en la Fase 2 lee únicamente del contexto de canal residente en BSS
y no alcanza esa misma ruta de despacho, por lo que la Fase 2 se ejecutó de forma nativa sin
requerir el mismo andamiaje. El efecto secundario de la Fase 1 — un byte de `IPC_msg[+0x99]`
escrito en `ch_ctx[+0x40A]` — se modeló directamente y se etiquetó como `[PHASE1-MODEL]`.

**No afirmado.** Una reproducción completa de extremo a extremo por aire en hardware.

### 7.1 Anti-manipulación

El arnés impuso una regla: no se permitió que ningún hook escribiera el marcador de prueba en la ranura
de dirección de retorno guardada. Se rastreó cada escritura en memoria que no fuera del firmware.```
[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 es la instrucción sh dentro del cuerpo del bucle. El firmware colocó estos bytes en el desplazamiento de pila previsto. En almacenamiento little-endian, las medias palabras 0xBEEF y 0xDEAD en new_sp+0xE4 y new_sp+0xE6 se combinan para formar [ef be ad de] = 0xDEADBEEF.

7.2 Resultado de la emulación```

[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 Entrega ZMQ

Para confirmar que el payload de prueba sobrevive a la codificación PHY de NB-IoT y a la entrega del bloque de transporte, se utilizó srsRAN 4G con un loopback ZMQ (sin emisión de RF). El payload era un vector deliberadamente no conforme — la restricción de SIZE de ASN.1 sobre `schedulingInfoList` se relajó para permitir 40 entradas, con una decodificación round-trip de pycrate que confirma el campo de conteo en el byte 14.```
SIB1 received
SIB2 activated
exit 0

Esto confirma la entrega en la capa de transporte. El comportamiento ASN.1 del lado del firmware queda establecido por el análisis estático de la Capa A.


8. Mecánica del flujo de control

8.1 Dos fases, una tarea, estado persistente

La tarea el1_ch tiene una sola pila. La Fase 1 y la Fase 2 son dos eventos IPC separados procesados secuencialmente por la misma tarea, con la pila desenrollándose por completo entre ellos. El contador persiste en el BSS del contexto del canal, no en la pila:``` 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]` reside en BSS y conserva el valor del atacante hasta que el módem se reinicie o una configuración de canal posterior lo sobrescriba.

### 8.2 Marco de pila```
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]

El tamaño del frame confirmado por medición de emulación. Las posiciones del array confirmadas por el resultado de la emulación — RA escrito en la iteración 38, consistente con si_sched_arr comenzando en new_sp+0x98.


9. Evidencia

9.1 Puertas antes del bucle vulnerable

9.2 Funciones confirmadas como no limitadoras de si_count


10. Análisis del parche

10.1 Versiones

CompilaciónFirmware del módemFecha de compilación
VulnerableA145RXXU1AWD1, MOLY LR12A...V1.P52023-04-18
ParcheadaA145RXXUDDZC2, MOLY

Fechas de compilación confirmadas extrayendo los metadatos md1_dbginfo de ambas imágenes. ID del parche: MOLY00720348 · ID del problema: MSV-2392.

10.2 Qué cambió

el1_ch_nbcch_start (0x90213444 en el binario vulnerable): El par de instrucciones lbu/sb está ausente. La copia directa de IPC_msg[+0x99] en ch_ctx[+0x40A] ha desaparecido.

el1_ch_nbcch_resume_req (0x90213940 en el binario vulnerable): El bucle de escritura en pila sobre ch_ctx[0x40A] está ausente. La arquitectura donde un byte no confiable se convierte en un límite de bucle sobre arrays de pila de tamaño fijo ya no existe. El cuerpo de la función se reemplaza con una estructura de despacho diferente.

errc_chm_l1_set_bcch_si_reception: El bucle de contador sin límites se reemplaza con llamadas a funciones auxiliares orientadas a la validación.

10.3 Nuevas funciones de validación

Dos funciones presentes en el binario parcheado están ausentes del binario vulnerable:``` el1_ch_nbcch_param_check el1_ch_scell_param_check

root@kitploit:~
Una comprobación de límites de una sola línea aparecería como unas pocas instrucciones añadidas dentro de una función existente en la misma dirección. Lo que muestra el binario parcheado es una revisión arquitectónica: la ruta de planificación de NBCCH fue rediseñada para que el patrón de `si_count`-como-límite-de-bucle ya no exista en ningún punto de la ruta.

### 10.4 Atribución de CVE

La vulnerabilidad descrita aquí coincide con CVE-2024-20154 tal como fue publicada por MediaTek el 6 de enero de 2025. Base de la confirmación:

- La familia de firmware afectada (LR12A) coincide con el boletín de MediaTek.
- La clase de vulnerabilidad — desbordamiento de pila, comprobación de límites ausente, RCE desde una estación base maliciosa, sin interacción del usuario — coincide con la descripción del CVE y el registro de NVD.
- El firmware parcheado elimina exactamente las estructuras de código identificadas como vulnerables.
- ID de parche MOLY00720348 confirmado a partir del boletín de MediaTek y el Boletín de Seguridad de Android (A-376809176).
- El análisis asistido por IA coincidió de forma independiente con el patrón reconstruido con CVE-2024-20154 antes de la confirmación manual.

---

## 11. Ética y divulgación responsable

### 11.1 Lo que esta publicación no contiene

Ningún exploit weaponizado. Ningún contenido de binario de firmware. Ningún byte de payload malformado. Ningún procedimiento paso a paso para desencadenar la vulnerabilidad contra un dispositivo en vivo. La información necesaria para reproducir un ataque funcional — la construcción completa del payload para el decodificador de módem específico, el andamiaje de objetos del heap del RTOS para la emulación completa de la Fase 1, la configuración de radio por aire — está deliberadamente ausente.

### 11.2 Por qué el loopback ZMQ y la emulación son el enfoque ético

El loopback ZMQ significa que nunca se transmitió ninguna señal por el aire. No se atacó ningún dispositivo real. No se involucró ninguna red de operador. La prueba se ejecuta enteramente en un entorno de software contenido sobre hardware propiedad del analista. Este es el enfoque correcto para validar una vulnerabilidad de radio previa a la asociación — transmitir un broadcast malformado afectaría a cualquier dispositivo dentro del alcance.

La emulación con Unicorn demuestra que el comportamiento vulnerable está en el propio binario del firmware, de forma reproducible, independientemente de cualquier estado específico del dispositivo o entorno de radio. Esta es una afirmación técnicamente más sólida que un único fallo de hardware, y evita desplegar cualquier cosa por el aire.

### 11.3 Propiedad intelectual de MediaTek

Todo el análisis se realizó sobre firmware obtenido legítimamente de un dispositivo de consumo y de los paquetes de firmware publicados públicamente por Samsung. No se utilizó documentación propietaria. Las definiciones internas de estructuras de MediaTek y los formatos de mensajes IPC se describen solo en la medida necesaria para explicar el fallo de seguridad de memoria. No se publican como especificaciones.

---
Descargar herramienta
Iteraciónsh escribe enEfecto
0–33si_sched_arr[0..33]Dentro de los límites
34–35new_sp+0xDC — s0 guardados0 corrompido
36–37new_sp+0xE0 — s1 guardados1 corrompido
38new_sp+0xE4 — ra guardado [15:0]Mitad baja de RA
39new_sp+0xE6 — ra guardado [31:16]Mitad alta de RA
PuertaCondiciónDónde se verifica
Ruta activa NB-IoTcfg_type == 1el1_ch_nbcch_cphy_cfg_req_process
Canal no completodone_flag == 0ch_ctx[0x438]
Máquina de estados 0x0BNBCCH en estado de reanudacióndespacho de el1_ch_nbcch_main
si_count distinto de ceroch_ctx[0x40A] > 0Condición del bucle
Clase de banda ≤ 2Modo NB-IoT válidoEntrada de el1_ch_nbcch_resume_req
el1_chmgm_cell_info_get distinto de ceroCelda en tabla de servicioInvocado en el1_ch_nbcch_start
FunciónDirecciónRol¿Limita?
errc_chm_l1_set_bcch_si_receptionRango ERRCEscribe CPHY_CFG_REQ[+0x99]Ninguno
el1_ch_nbcch_cphy_cfg_req_process0x90213F80Enruta la configuración CPHY hacia L1N/A — no lee si_count
el1_chmgm_cell_info_get0x9020E0D0Valida EARFCN/PCIN/A
el1_ch_nbcch_start0x90213444Copia el conteo a BSSNinguno
el1_ch_nbcch_resume_req0x90213940Usa el conteo como límite del bucleNinguno
LR12A...V3.P8
2025-04-23