Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2024-20154 — Technical writeup for CVE-2024-20154 | Kitploit
Ferramentas/GitHubGitHub/sneakid/cve-2024-20154
Embedded Systems SecurityIoT SecurityVulnerability AnalysisExploitationReverse EngineeringMobile SecurityPapers & ResearchLearning & EducationFirmware AnalysisBinary Exploitation
GitHubsneakid/cve-2024-20154
21há 2 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2024-20154

Technical writeup for CVE-2024-20154

Ver Repositório

CVE-2024-20154: Estouro de Pilha SIB1-NB NB-IoT no Baseband MediaTek MT6769

Classificação: CWE-121 — Estouro de Buffer Baseado em Pilha
Gravidade: Crítica (boletim MediaTek) · 8.8 Alta, Vetor de Ataque: Adjacente (CISA-ADP)
Tipo: Execução Remota de Código — sem interação do usuário, sem associação prévia
Divulgação: Boletim de Segurança MediaTek, 6 de janeiro de 2025 https://corp.mediatek.com/product-security-bulletin/January-2025 Alvo analisado: Samsung Galaxy A14 SM-A145R — família MT6769 (Helio G80), dentro da lista de chipsets afetados da MediaTek - Firmware foi emulado em condições seguras. Status: Corrigido.


Contexto e motivação

Esta foi minha primeira pesquisa publicada sobre baseband. Venho de uma área distante da infraestrutura de telecomunicações, camadas de intermediação de interceptação legal, análise de stingray e IMSI-catcher, e segurança de dispositivos embarcados — eu nunca havia feito engenharia reversa profunda de firmware em um modem celular. Queria provar para mim mesmo que uma metodologia analítica estruturada se adapta entre alvos, e que a familiaridade com uma plataforma específica pode ser substituída por um rastreamento rigoroso de cadeia. O NB-IoT se destacou por estar em uma interseção genuinamente perigosa: o protocolo é projetado para dispositivos IoT restritos, a superfície de ataque é pré-associação, e a pilha do modem processa independentemente do que o usuário do aparelho está fazendo.

Quando o firmware corrigido foi analisado e o padrão vulnerável confirmado ausente, o sistema de IA usado para análise em massa do firmware antes de segmentar funções específicas

correspondeu de forma independente a classe de bug reconstruída, condições e família de firmware afetada à descrição do CVE-2024-20154.

As conclusões técnicas são do analista.


1. Introdução

O telefone no seu bolso contém pelo menos dois computadores separados. Aquele com o qual você interage roda Android. O outro — o baseband — roda de forma completamente independente, lida com toda a comunicação de rádio, e é quase totalmente invisível para o sistema operacional acima dele. O Android pode estar totalmente corrigido. O navegador pode estar em sandbox. O usuário pode nunca tocar em um link malicioso. Nada disso importa se o código vulnerável está no firmware do modem que processa sinais de rádio antes que o processador de aplicação seja envolvido.

O CVE-2024-20154 é exatamente esse tipo de vulnerabilidade.

Uma transmissão NB-IoT de informações de sistema malformada faz com que o firmware do modem MediaTek aceite uma contagem de agendamento controlada pelo atacante, transporte essa contagem pelo caminho de configuração RRC-para-L1 sem nunca limitá-la, e eventualmente a use como o limite de um loop de escrita na pilha dentro do manipulador do canal de broadcast NB-IoT. Quando a contagem excede a capacidade dos arrays de destino, o loop escreve além deles, atinge registradores salvos na pilha e sobrescreve o endereço de retorno salvo. A função então restaura o valor corrompido para o registrador de endereço de retorno e salta para ele.

O que torna a gravidade o que é:

  • O caminho de código vulnerável é exercitado durante o camping de célula — após sincronizar com uma célula mas antes de qualquer conexão RRC, qualquer autenticação, qualquer interação do usuário.
  • A entrada é uma transmissão over-the-air. O telefone não pode autenticar a fonte.
  • O firmware baseband na build analisada roda sem ASLR, sem stack canaries, sem pilha não executável e sem integridade de fluxo de controle. Uma sobrescrita do endereço de retorno salvo traduz-se diretamente em controle do contador de programa.

A vulnerabilidade foi publicada no Boletim de Segurança da MediaTek de 6 de janeiro de 2025 com uma classificação de gravidade Crítica, afetando a família de modems LR12A entre outras. A Samsung incorporou a correção em sua Liberação de Manutenção de Segurança de fevereiro de 2025.

Este post não publica um exploit armado e não é reproduzível a partir do que está publicado aqui. O objetivo é mostrar onde a cadeia quebra, por que cada camada falhou em impedir isso, e o que é necessário para validar um bug de baseband de forma responsável quando você não pode anexar um depurador ao modem em funcionamento.


2. Alvo e Ambiente

2.1 Dispositivo e firmware

Alvo principal: Samsung Galaxy A14 (SM-A145R). O subsistema de rádio é conduzido por um processador baseband MediaTek na família de chipsets MT6769 (Helio G80). A família MT6769 está explicitamente listada na lista de chipsets afetados da MediaTek para o 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:~
O firmware de banda base não é código Android. É um sistema embarcado separado no subsistema
de rádio do SoC com sua própria CPU, seu próprio RTOS e seu próprio espaço de memória, fora da
sandbox de processos do Android.

### 2.2 Arquitetura do modem

A análise do binário extraído mostra que o processador do modem executa MIPS32 com instruções
comprimidas MIPS16e2 em modo little-endian. MIPS16e2 é uma extensão de codificação de 16 bits para
redução de tamanho de código embarcado — consistente com a abordagem da MediaTek para bandas base
da geração Helio, confirmada por pesquisas independentes publicadas sobre banda base nesta família de SoCs.

O sistema operacional é o Nucleus RTOS, fornecendo escalonamento de tarefas, filas de mensagens IPC e um
alocador de memória baseado em pool. Não há separação de privilégios kernel/usuário, nenhuma aplicação
de unidade de proteção de memória entre tarefas e nenhum mecanismo de guarda de pilha por hardware.

Todos os endereços neste post são endereços virtuais, conforme carregados no Ghidra na base `0x90000000`.

### 2.3 Mitigações (observadas na compilação analisada)

| Mitigação | Status | Efeito |
|---|---|---|
| ASLR | Ausente | Endereços do firmware são estáticos e previsíveis a partir da imagem |
| Canário de pilha | Ausente | `SAVE`/`RESTORE` armazena registradores salvos pelo callee sem valor de guarda |
| NX / W^X | Ausente | A memória da pilha é executável |
| CFI | Ausente | Endereços de retorno não são validados contra nenhuma política |

### 2.4 Abordagem de análise

Três frentes paralelas:

**Análise estática.** Pacote de firmware Samsung → extração da partição CP → `md1img.img` →
Ghidra (MIPS LE 32-bit, base `0x90000000`) com símbolos de engenharia da MediaTek recuperados da
seção de debug do firmware usando o conjunto de ferramentas `mtk_bp` da NCC Group.

**Validação dinâmica.** O Unicorn Engine (emulação MIPS32) foi usado para executar rotinas
específicas do firmware de forma isolada em duas fases. A Fase 1 tentou provar a cópia sem
verificação de limites de `si_count` para o contexto do canal através do par de instruções nativo. A Fase 2
executou o loop vulnerável em bytes reais do firmware e confirmou que as próprias instruções do firmware
corrompem o endereço de retorno salvo. Onde a Fase 1 não pôde ser executada totalmente de forma nativa —
porque o ambiente de objeto de serviço do RTOS exigido pelo caminho de despacho CPHY não foi reconstruído —
o efeito colateral foi modelado diretamente e rotulado como tal em toda a saída.

**Validação no lado do rádio.** srsRAN 4G com um loopback ZMQ — apenas software, sem emissão de RF —
confirmou que o payload de teste sobrevive à codificação PHY NB-IoT e à entrega de bloco de transporte.

---

## 3. Superfície de Ataque: NB-IoT e SIB1-NB

### 3.1 Superfície de ataque pré-associação

NB-IoT (Internet das Coisas de Banda Estreita) é o 3GPP Release 13, projetado para conectar
dispositivos IoT com recursos limitados usando o espectro LTE licenciado existente. É implementado em uma
ampla gama de SoCs celulares modernos, incluindo aqueles em smartphones de consumo.

Enquanto no estado RRC_IDLE, antes que qualquer conexão RRC seja estabelecida, um dispositivo
procurando serviço irá:

1. Sincronizar com os sinais de temporização da célula (NPSS/NSSS)
2. Decodificar o Master Information Block via NPBCH (janela de transmissão de 640 ms)
3. Decodificar SIB1-NB via NPDSCH (agendamento de 2560 ms)
4. Usar as informações de agendamento em SIB1-NB para localizar blocos de informações de sistema adicionais

No passo 3, o modem processa uma mensagem de uma entidade que não autenticou, antes de qualquer
conexão ou interação do usuário. Um transmissor fraudulento que satisfaça as condições normais de
seleção de célula será processado.```
+------------------+                   +---------------------+
|  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 O campo de contagem de agendamento

SIB1-NB é definido em 3GPP TS 36.331. Seu campo schedulingInfoList carrega quantas mensagens de Informação de Sistema a célula transmite, limitado pela especificação a um máximo de 8 entradas (1..maxSI-Message-NB-r13 = 8). Esta é uma restrição da camada de protocolo. A restrição de segurança de memória — que o comprimento da lista não deve exceder a capacidade dos arrays de destino — deve ser aplicada separadamente pelo firmware.

Não foi.


4. Extração de Firmware e Recuperação de Símbolos

O firmware foi obtido de um pacote CP da Samsung e extraído usando o conjunto de ferramentas mtk_bp do NCC Group:``` md1img.img → md1_extract.py → 000_md1rom (17.8 MB code image) → 017_md1_dbginfo (XZ-compressed CATI debug symbols)

root@kitploit:~
A seção de debug do CATI foi descomprimida e analisada com `mtk_dbg_extract.py symbols` e, em seguida, importada no Ghidra via `ImportSymbolsScript.py`. O resultado foram nomes completos de funções internas em toda a pilha do modem — camada ERRC, gerenciamento de canal L1, subsistema IPC e a cadeia de manipuladores NB-IoT BCCH — permitindo a reconstrução da cadeia guiada por semântica.

Todos os nomes de funções neste post vêm dos símbolos de debug incorporados da MediaTek extraídos da imagem do firmware.

---

## 5. Vulnerabilidade

### 5.1 O loop vulnerável

`el1_ch_nbcch_resume_req` (`0x90213940`) lida com o evento de retomada do canal de broadcast NB-IoT. Seu prólogo de função MIPS16e2:```asm
90213940:  save  0xE8, ra, s0-s1

A instrução SAVE decrementa sp em 0xE8 e armazena os registros preservados pela função chamada (callee-saved) para baixo:``` 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:~
A partir da descompilação do Ghidra do binário 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] é ch_ctx[+0x40A] — um byte persistente na estrutura BSS do contexto do canal. O limite do loop é usado diretamente, sem comparação prévia com as capacidades do array.

5.2 A aritmética de transbordamento

O fluxo A (escritas de meia palavra sh) começa em new_sp+0x98 e avança 2 bytes por iteração. Ele atinge o RA salvo em new_sp+0xE4 na iteração 38:``` new_sp + 0x98 + i×2 = new_sp + 0xE4 i = (0xE4 - 0x98) / 2 = 0x4C / 2 = 38

root@kitploit:~
Stream B (byte `sb` writes) começa em `new_sp+0x78` e precisaria da iteração 108 para alcançar o slot RA:```
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108

Com si_count = 40 (o valor demonstrativo, escolhido para exceder o limite de overflow de 38) o loop executa 40 iterações. O Stream B nunca atinge o slot RA. A corrupção do RA vem inteiramente do Stream A.

Após 40 iterações, a instrução MIPS16e2 RESTORE recarrega o valor corrompido da pilha para $ra, e jrc ra transfere o controle.

5.3 A cópia sem fixação — Camada B

ch_ctx[+0x40A] é escrito por el1_ch_nbcch_start em 0x90213444. Duas instruções MIPS consecutivas sem nada entre elas:```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 O construtor ERRC — Camada A

O buffer CPHY_CFG_REQ é construído na camada ERRC a partir do SIB1-NB decodificado. A função `errc_chm_l1_set_bcch_si_reception` escreve `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
    }
}

5.5 O caminho IPC

O limite do laço é a contagem de entradas decodificadas do SIB1-NB. O contador é incrementado uma vez por entrada decodificada, para tantas entradas quantas forem decodificadas, sem guarda máxima.

Uma vez que o buffer CPHY_CFG_REQ é populado, o ERRC o despacha para o L1 com sap_id = 0x501F como chave de roteamento:``` 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 Ausência de restrição em três camadas

| Camada | Função | Endereço | Restrição presente? |
|---|---|---|---|
| A — construtor ERRC | `errc_chm_l1_set_bcch_si_reception` | Intervalo ERRC | **Nenhuma** |
| B — cópia L1 | `el1_ch_nbcch_start` | `0x90213444` | **Nenhuma** |
| C — loop L1 | `el1_ch_nbcch_resume_req` | `0x90213940` | **Nenhuma** |

Qualquer verificação única em qualquer uma das camadas teria quebrado a cadeia.

### 5.7 Causa raiz

Um invariante violado:

> O número de entradas de agendamento SI nunca deve exceder a capacidade do array de destino.

O 3GPP fornece o limite de protocolo pretendido (8 entradas). O firmware precisava impor o limite de segurança de memória em cada camada onde a contagem se torna um índice ou limite de loop. Na compilação vulnerável, a contagem viajou do campo de broadcast SIB1-NB através do decodificador ERRC, para a mensagem CPHY_CFG_REQ, através de um limite IPC para a tarefa L1, para o contexto do canal BSS, e para um loop de escrita na pilha — sem qualquer camada a restringir.

---

## 6. A Cadeia de Chamadas — Como Foi Encontrada

### 6.1 A confusão de dois caminhos

Dois caminhos estruturalmente semelhantes, mas distintos, podem entregar um buffer de configuração de 0x760 bytes para `el1_ch_nbcch_main`:

| Caminho | Fonte | Valor `[+0x99]` | Relevância |
|---|---|---|---|
| Caminho A (ERRC → L1 IPC) | ERRC constrói CPHY_CFG_REQ a partir do SIB1-NB decodificado | `schedulingInfoList.count` da OTA | **O caminho vulnerável** |
| Caminho B (L1 interno) | `el1_ch_scs_ind_send` constrói corpo IPC interno | Codificado como `1` | Não vulnerável |

O Caminho B confirmou o formato da mensagem — o byte `+0x99` é a contagem SI consumida por `el1_ch_nbcch_start`. Como sua contagem está sempre codificada como 1, não pode transbordar. O caminho influenciado externamente é o Caminho A.

### 6.2 A busca pelo escritor

A busca por padrões no firmware por qualquer instrução que escreva no offset `+0x99` produziu ruído: T1 (`sb` direto, ~100 ocorrências), T2 (base dividida, 5 ocorrências), T3 (offset computado, 0), T4 (sobreposição `sh`/`sw`, ~465). As funções de gerenciamento de canal ERRC estavam ausentes da lista de referências cruzadas `msg_send6` porque ERRC usa `errc_com_send_msg`. Uma sonda de emulação confirmou que a escrita era do lado ERRC: executar o harness Unicorn a partir do dispatcher L1 e observar escritas no offset `+0x99` do buffer não capturou nada do 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 Resolução via chave de roteamento IPC

Seguindo sap_id = 0x501F em errc_com_send_msg identificou o roteamento para el1_chmgm_errc_cfg_req_in_idle, que armazena o ponteiro CPHY_CFG_REQ em L1_ctx[+0x323C] e inicia o despacho downstream.

6.4 Cadeia de chamadas 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. Validação

Este modelo específico SM-A145R não parece exercitar o caminho de código NB-IoT vulnerável na operação normal de fábrica, razão pela qual foram utilizadas emulação híbrida e análise estática em vez de reprodução direta em hardware.

**Comprovado estaticamente.** O binário do firmware contém o par de instruções vulnerável. A cadeia de chamadas é reconstruída a partir de símbolos, referências cruzadas e corpos de funções descompilados.

**Executado nativamente em emulação.** O loop dentro de `el1_ch_nbcch_resume_req` foi executado em bytes reais de firmware MediaTek no Unicorn Engine (MIPS32). A própria instrução `sh` do firmware em `0x90213B02` escreveu no slot do endereço de retorno salvo. A instrução `RESTORE` carregou o valor corrompido em `$ra`, e `jrc ra` transferiu o controle.

**Modelado explicitamente.** A cópia `lbu`/`sb` em `el1_ch_nbcch_start` não pôde ser executada totalmente nativamente porque o caminho de despacho da tabela de callbacks do RTOS dentro de `el1_ch_nbcch_cphy_cfg_req_process` esperava objetos de heap Nucleus ativos que o emulador plano não fornecia. O manipulador de retomada (`el1_ch_nbcch_resume_req`) na Fase 2 lê apenas do contexto de canal residente em BSS e não atinge o mesmo caminho de despacho, razão pela qual a Fase 2 foi executada nativamente sem exigir a mesma estrutura. O efeito colateral da Fase 1 — um byte de `IPC_msg[+0x99]` escrito em `ch_ctx[+0x40A]` — foi modelado diretamente e rotulado como `[PHASE1-MODEL]`.

**Não reivindicado.** Uma reprodução completa de hardware ponta a ponta over-the-air.

### 7.1 Anti-adulteração

O harness impôs uma regra: nenhum hook podia escrever o marcador de prova no slot do endereço de retorno salvo. Cada escrita de memória não pertencente ao firmware foi rastreada.```
[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 é a instrução sh dentro do corpo do loop. O firmware colocou esses bytes no deslocamento de pilha previsto. No armazenamento little-endian, as meias-palavras 0xBEEF e 0xDEAD em new_sp+0xE4 e new_sp+0xE6 combinam para [ef be ad de] = 0xDEADBEEF.

7.2 Resultado da emulação```

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

Para confirmar que a carga de teste sobrevive à codificação PHY NB-IoT e à entrega de blocos de transporte, foi utilizado o srsRAN 4G com um loopback ZMQ (sem emissão RF). A carga era um vetor deliberadamente não conforme — a restrição ASN.1 SIZE em `schedulingInfoList` foi relaxada para permitir 40 entradas, com a decodificação de ida e volta do pycrate confirmando o campo de contagem no byte 14.```
SIB1 received
SIB2 activated
exit 0

Isso confirma a entrega em nível de transporte. O comportamento ASN.1 do lado do firmware é estabelecido pela análise estática da Camada A.


8. Mecânica de Fluxo de Controle

8.1 Duas fases, uma tarefa, estado persistente

A tarefa el1_ch tem uma pilha. A Fase 1 e a Fase 2 são dois eventos IPC separados processados sequencialmente pela mesma tarefa, com a pilha completamente desenrolada entre eles. A contagem persiste no BSS do contexto do canal, não na pilha:``` 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]` vive na BSS e retém o valor do atacante até que o modem reinicie ou uma configuração de canal subsequente o substitua.

### 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]

Tamanho do quadro confirmado por medição de emulação. Posições do array confirmadas pelo resultado da emulação — RA escrito na iteração 38, consistente com si_sched_arr começando em new_sp+0x98.


9. Evidências

9.1 Gates antes do loop vulnerável

9.2 Funções confirmadas por não realizar clamp no si_count


10. Análise do Patch

10.1 Versões

BuildFirmware do modemData de compilação
VulnerávelA145RXXU1AWD1, MOLY LR12A...V1.P52023-04-18
CorrigidoA145RXXUDDZC2, MOLY

Datas de compilação confirmadas extraindo metadados md1_dbginfo de ambas as imagens. ID do patch: MOLY00720348 · ID do problema: MSV-2392.

10.2 O que mudou

el1_ch_nbcch_start (0x90213444 no binário vulnerável): O par de instruções lbu/sb está ausente. A cópia direta de IPC_msg[+0x99] para ch_ctx[+0x40A] foi removida.

el1_ch_nbcch_resume_req (0x90213940 no binário vulnerável): O loop de escrita na pilha sobre ch_ctx[0x40A] está ausente. A arquitetura onde um byte não confiável se torna um limite de loop sobre arrays de pilha de tamanho fixo não existe mais. O corpo da função é substituído por uma estrutura de despacho diferente.

errc_chm_l1_set_bcch_si_reception: O loop de contador ilimitado é substituído por chamadas auxiliares orientadas a validação.

10.3 Novas funções de validação

Duas funções presentes no binário corrigido estão ausentes no binário vulnerável:``` el1_ch_nbcch_param_check el1_ch_scell_param_check

root@kitploit:~
Uma verificação de limites de uma única linha apareceria como algumas instruções adicionadas dentro de uma função existente no mesmo endereço. O que o binário corrigido mostra é uma revisão arquitetural: o caminho de agendamento NBCCH foi redesenhado para que o padrão `si_count`-como-limite-de-loop não exista mais em nenhum lugar do caminho.

### 10.4 Atribuição de CVE

A vulnerabilidade descrita aqui corresponde à CVE-2024-20154 conforme publicada pela MediaTek em 6 de janeiro de 2025. Base de confirmação:

- Família de firmware afetada (LR12A) corresponde ao boletim da MediaTek.
- Classe de vulnerabilidade — estouro de pilha, falta de verificação de limites, RCE a partir de estação base falsa, sem interação do usuário — corresponde à descrição da CVE e ao registro NVD.
- O firmware corrigido remove exatamente as estruturas de código identificadas como vulneráveis.
- ID do patch MOLY00720348 confirmado pelo boletim da MediaTek e pelo Android Security Bulletin (A-376809176).
- Análise assistida por IA combinou independentemente o padrão reconstruído com a CVE-2024-20154 antes da confirmação manual.

---

## 11. Ética e Divulgação Responsável

### 11.1 O que este post não contém

Nenhum exploit armado. Nenhum conteúdo binário de firmware. Nenhum byte de payload malformado. Nenhum procedimento passo a passo para desencadear a vulnerabilidade contra um dispositivo real. As informações necessárias para reproduzir um ataque funcional — construção completa de payload para o decodificador de modem específico, scaffolding de objeto heap RTOS para emulação completa da Fase 1, configuração de rádio over-the-air — estão deliberadamente ausentes.

### 11.2 Por que loopback ZMQ e emulação são a abordagem ética

Loopback ZMQ significa que nenhum sinal foi transmitido pelo ar. Nenhum dispositivo real foi alvo. Nenhuma rede de operadora foi envolvida. A prova é executada inteiramente em um ambiente de software contido em hardware de propriedade do analista. Esta é a abordagem correta para validar uma vulnerabilidade de rádio pré-associação — transmitir uma transmissão malformada afetaria qualquer dispositivo dentro do alcance.

A emulação Unicorn demonstra que o comportamento vulnerável está no próprio binário do firmware, de forma reproduzível, independentemente de qualquer estado específico do dispositivo ou ambiente de rádio. Esta é uma afirmação tecnicamente mais forte do que uma única falha de hardware, e evita implantar qualquer coisa pelo ar.

### 11.3 Propriedade intelectual da MediaTek

Toda a análise foi realizada em firmware obtido legitimamente de um dispositivo de consumo e dos pacotes de firmware publicamente disponíveis da Samsung. Nenhuma documentação proprietária foi utilizada. Definições internas de estruturas da MediaTek e formatos de mensagens IPC são descritas apenas na medida necessária para explicar a falha de segurança de memória. Elas não são publicadas como especificações.

---
Baixar ferramenta
Iteraçãosh escreve emEfeito
0–33si_sched_arr[0..33]Dentro dos limites
34–35new_sp+0xDC — s0 salvos0 corrompido
36–37new_sp+0xE0 — s1 salvos1 corrompido
38new_sp+0xE4 — ra salvo [15:0]Meia palavra baixa do RA
39new_sp+0xE6 — ra salvo [31:16]Meia palavra alta do RA
GateCondiçãoOnde verificado
Caminho ativo NB-IoTcfg_type == 1el1_ch_nbcch_cphy_cfg_req_process
Canal não completodone_flag == 0ch_ctx[0x438]
Máquina de estado 0x0BNBCCH no estado de retomadael1_ch_nbcch_main despacho
si_count diferente de zeroch_ctx[0x40A] > 0Condição do loop
Classe de banda ≤ 2Modo NB-IoT válidoEntrada de el1_ch_nbcch_resume_req
el1_chmgm_cell_info_get diferente de zeroCélula na tabela de serviçoChamado em el1_ch_nbcch_start
FunçãoEndereçoPapelClamp?
errc_chm_l1_set_bcch_si_receptionIntervalo ERRCEscreve CPHY_CFG_REQ[+0x99]None
el1_ch_nbcch_cphy_cfg_req_process0x90213F80Roteia configuração CPHY para L1N/A — não lê si_count
el1_chmgm_cell_info_get0x9020E0D0Valida EARFCN/PCIN/A
el1_ch_nbcch_start0x90213444Copia contador para BSSNone
el1_ch_nbcch_resume_req0x90213940Usa contador como limite do loopNone
LR12A...V3.P8
2025-04-23