Ferramenta de aquisição bare-metal que extrai e valida o conteúdo da memória Flash de um RP2040 alvo via protocolo SWD, usando outro RP2040 como sonda.
O Dolos transforma um Raspberry Pi Pico (Sonda) em um extrator forense capaz de adquirir 2 MB de firmware em menos de 60 segundos, com validação criptográfica SHA-256 e registro estruturado da sessão, sem depender de nenhuma ferramenta de debug convencional (CMSIS-DAP, OpenOCD, picotool).
O diferencial não está apenas em implementar SWD sem biblioteca pronta. Está em tratar a extração como uma "operação forense": integridade verificável, política explícita de não-modificação do alvo e evidência auditável do processo.
Este projeto é continuação direta de uma fase de pesquisa onde o RP2040 foi controlado sem nenhuma abstração de SDK, boot manual, clock tree manual, GPIO e UART via MMIO direto. Essa fase estabeleceu a base técnica para as decisões de arquitetura aqui tomadas.
→ Ver Fase 0: uart-baremetal-rp2040
Fundação da sonda validada: ambiente de build, firmware modular, USB CDC funcional e controle do alvo.
- Ambiente CMake + TinyUSB configurado
- Firmware inicial modular com FSM mínima (ST_BOOT → ST_IDLE)
- Controle do pino RUN do alvo via GPIO
- USB CDC enumerado e validado com echo PC ↔ Sonda
- Comandos básicos de controle recebidos e respondidos via USB
Implementação da camada física SWD em assembly ARM via SIO e início da camada de protocolo.
-
swd_phy_init: inicialização de GPIO_OE e estado inicial dos pinos -
writebit: transmissão determinística de 1 bit via SIO, timing calibrado por NOPs -
readbit: leitura de 1 bit com chaveamento de direção via GPIO_OE -
turnaround_host_to_targeteturnaround_target_to_host -
line_reset: 50 ciclos HIGH via loop assembly -
swd_enter_swd_mode: sequência completa: line_reset → 0xE79E → line_reset → idle cycles - Validação no analisador lógico
- Leitura do IDCODE
- Navegação DAP
O projeto adota uma arquitetura híbrida onde cada camada tem uma justificativa técnica explícita.
flowchart TD
%% Estilização e formas semânticas para arquitetura multicore
subgraph SONDA["Sonda RP2040 (Projeto Dolos)"]
direction LR
subgraph CORE1["⚡ CORE 1 (Domínio Crítico / Tempo Real)"]
direction TB
PHY{{"SWD PHY<br>(Assembly ARM)"}}
PROT["Protocolo SWD / DAP<br>(C Bare-metal)"]
PHY ==>|Timing determinístico| PROT
end
subgraph CORE0["CORE 0 (Domínio de I/O e Logs)"]
direction TB
BUF[/"Buffer Circular<br>de Logs em RAM"\]
USB{{"TinyUSB CDC<br>(Pico SDK)"}}
BUF -.->|Consumo Assíncrono| USB
end
SRAM[("SRAM Compartilhada<br>(FIFO HW)")]
%% Conexões internas de sincronização
PROT ===|Push de Ponteiros| SRAM
SRAM ===|Pull de Ponteiros| BUF
end
ALVO["Alvo (RP2040)<br>Flash ROM / QSPI"]
HOST["Host (PC - Python)<br>FSM Espelhada / PDF"]
%% Conexões externas
PROT ===|Barramento SWD| ALVO
USB <==>|Transporte USB CDC| HOST
%% Definição de Classes (Paleta Tech/Hardware)
classDef sonda fill:#1E293B,stroke:#475569,stroke-width:2px,color:#F8FAFC,rx:10,ry:10
classDef core1 fill:#450A0A,stroke:#EF4444,stroke-width:2px,color:#FECACA,stroke-dasharray: 5 5
classDef core0 fill:#082F49,stroke:#0EA5E9,stroke-width:2px,color:#BAE6FD,stroke-dasharray: 5 5
classDef nodeCrit fill:#7F1D1D,stroke:#FCA5A5,stroke-width:1px,color:#FFF
classDef nodeIO fill:#0284C7,stroke:#7DD3FC,stroke-width:1px,color:#FFF
classDef mem fill:#4B5563,stroke:#D1D5DB,stroke-width:2px,color:#FFF
classDef ext fill:#111827,stroke:#10B981,stroke-width:2px,color:#FFF
class SONDA sonda
class CORE1 core1
class CORE0 core0
class PHY,PROT nodeCrit
class BUF,USB nodeIO
class SRAM mem
class ALVO,HOST ext
Por que bit-banging em Assembly e não PIO ou C?
O pino SWDCLK opera de forma simétrica com atrasos calculados ciclo a ciclo via NOPs. Implementar em C delegaria o timing ao compilador, gerando instabilidade. O PIO automatizaria o processo, mas a implementação em Assembly ARM puro garante o controle cirúrgico e o determinismo necessários para auditoria forense.
Por que isolamento multicore (Core 1 vs Core 0)?
Rotinas de exibição ou stacks de comunicação (como TinyUSB) possuem latências imprevisíveis de milissegundos. No Core 1, o barramento roda com zero interrupções e acesso exclusivo aos pinos via bloco SIO (Single-cycle IO) conectado ao barramento IOPORT do Cortex-M0+, garantindo escritas atômicas e livres de jitter de crossbar.
Por que o pino RUN é controlado sob Reset?
Ao segurar a linha RUN do alvo em LOW antes da inicialização, a sonda impede o processador alvo de executar código local malicioso ou de reconfigurar os registradores do subsistema QSPI, assumindo o controle do silício a partir de um estado virgem e previsível.
O gerenciamento de falhas do sistema é centralizado em uma Look-Up Table (LUT) estática armazenada em Flash. Toda transição de erro na FSM passa obrigatoriamente pela função unificada error_policy(code).
As falhas são categorizadas por severidade, disparando reações determinísticas imediatas:
-ACTION_RETRY: Reexecução de operações (ex: colisões de ACK_WAIT).
-ACTION_ABORT: Encerramento seguro da sessão preservando os dados coletados até o momento.
-ACTION_FATAL_HALT: Paralisação imediata da sonda com liberação do pino RUN do alvo em HIGH (mecanismo de Safety Net contra travamentos).
A sonda opera sob um modelo de Safe-Read forçado por software. Após o handshake inicial e a configuração estrita do subsistema QSPI/XIP do alvo, o firmware bloqueia qualquer envio de payloads de escrita. Qualquer tentativa de desvio ou comando não autorizado aborta a sessão imediatamente (ST_ABORT), invalidando o token de sessão criptográfico gerado no boot.
- 2× Raspberry Pi Pico
- 1× Resistor 330 Ω
- 1× Resistor 1 kΩ
- Analisador lógico (ex: Hantek 6022BL com DSView)
- Protoboard e jumpers
| Sinal | GPIO Sonda | Componente | Pino Alvo | Função |
|---|---|---|---|---|
| SWCLK | GP2 |
Fio direto | SWCLK |
Clock SWD —> sempre saída |
| SWDIO | GP3 |
Resistor 330 Ω série | SWDIO |
Dados bidirecionais |
| RESET | GP22 |
Resistor 1 kΩ série | RUN (pino 30) |
Kill switch |
| GND | GND |
Fio direto | GND |
Referência comum —> obrigatório |
| Ferramenta | Versão |
|---|---|
arm-none-eabi-gcc |
13.2 |
| CMake | ≥ 3.13 |
| Pico SDK | em PICO_SDK_PATH |
git clone https://github.com/StheffannyNAlves/swd-forensic-extractor.git
cd swd-forensic-extractor/firmware
mkdir build && cd build
cmake ..
make -j$(nproc)Para flashar: segure BOOTSEL no Pico sonda, conecte o USB e copie dolos.uf2 para o drive que aparecer.
- RP2040 Datasheet — §2.3.1 (SIO), §4.7 (Watchdog)
- ARM ADIv5 Architecture Specification — protocolo SWD
- ARMv6-M Architecture Reference Manual — DHCSR, Cortex-M0+
- TinyUSB — stack USB CDC
Desenvolvido por Stheffanny N. Alves