Falha em Coldcard expõe carteiras: ataque em 2026 drena 1.719 BTC
Resumo de mercado por IA
Uma falha de entropia no firmware da Coldcard, conforme reportado, permitiu a recuperação offline por força bruta de seeds em dispositivos com configuração padrão, resultando em roubo confirmado de pelo menos 1.719 BTC em milhares de endereços. O incidente é significativo porque reenquadra o risco de "armazenamento a frio" em torno da qualidade da geração de chaves, em vez de comprometimento de rede, potencialmente pressionando a confiança em carteiras de hardware, levando a atualizações urgentes de firmware e aumentando, no curto prazo, movimentações de fundos motivadas por segurança e o escrutínio sobre práticas de custódia de BTC.
Nível de impacto
● Alto
Ativos afetados
BTC/USDT-1.03%
Insight de IA · BTC/USDTInsight de IA
▼ Baixista
Negociar agora
⚠️ Os insights gerados por IA são baseados em conteúdo de notícias e fornecidos apenas para fins informativos. Eles não constituem aconselhamento de investimento nem representam as opiniões da BingX. Investir envolve riscos. Negocie com responsabilidade.
Em 30 de julho de 2026, uma movimentação incomum chamou atenção na blockchain: uma sequência de endereços passou a transferir fundos em série. Em 41 minutos, 1.196 endereços de assinatura única foram esvaziados, com o sumiço de cerca de 1.082 bitcoins. A ofensiva não parou ali. Até o início de agosto, as perdas confirmadas chegaram a pelo menos 1.719 BTC (cerca de US$ 111 milhões), envolvendo mais de 5.200 endereços, em três a quatro ondas.
O ponto mais intrigante foi o perfil das carteiras atingidas: em grande parte, tratava-se de fundos guardados em cold wallets, parados por meses ou anos. O problema não foi acesso ao dispositivo, mas sim às chaves privadas. Segundo a apuração, todas as chaves comprometidas foram geradas por carteiras físicas Coldcard, em configuração padrão — sem uso de entropia adicional com dados (dice entropy) e sem ativar passphrase BIP39.
O alcance varia por linha de firmware. Nos modelos Mk2 e Mk3 com firmware 4.0.1 a 4.1.9, a entropia efetiva cai para cerca de 40 bits, o cenário mais grave. Já em Mk4, Mk5 e Q, em versões específicas, a entropia fica em torno de 72 bits, ainda considerada atacável via força bruta offline.
A Coinkite reagiu rapidamente. Em 30 de julho, publicou um alerta. No dia seguinte, liberou firmware corrigido: Mk2 e Mk3 para versão 4.2.0 ou superior; Mk4 e Mk5 para 5.6.0 ou superior; Q para 1.5.0Q ou superior. A empresa também informou a destruição do estoque com versões vulneráveis e a suspensão de embarques.
De acordo com a análise, o episódio não envolve invasão remota nem comprometimento de cadeia de suprimentos. O atacante não precisou tocar em nenhum aparelho: obteve as chaves por bruteforce offline, testando sistematicamente sementes possíveis dentro de um espaço de busca limitado. A falha teria permanecido latente por anos, até que pesquisadores externos desenvolveram uma ferramenta de força bruta e tornaram o problema evidente. Posteriormente, Muan reproduziu toda a cadeia do ataque.
A investigação parte do código do firmware (com Mk3 v4.1.9 como referência) para identificar a linha que abriu caminho ao esvaziamento em massa. O Coldcard foi projetado para gerar seeds usando o TRNG (true random number generator) do chip STM32L475. Dois erros, combinados, transformaram esse processo em um PRNG por software com estado quase idêntico entre dispositivos. O PRNG em questão é o Yasmarang, reduzindo a entropia efetiva do Mk3 para algo próximo de 40 bits.
Erro 1: o RNG de hardware foi desativado. Na configuração de build, o Coldcard desliga explicitamente o suporte ao RNG de hardware do MicroPython em mpconfigboard.h por meio de `#define MICROPY_HW_ENABLE_RNG (0)`. À primeira vista, isso parece justificável, já que a Coinkite mantém o próprio `ckcc.rng_bytes` para chamar diretamente o TRNG do STM32. O problema aparece em outra camada: a função `my_random_bytes()` do libngu lê aleatoriedade via o macro `CHIP_TRNG_32()`, que, após expansão, chama `rng_get()` do port STM32 do MicroPython, assumindo que isso seja TRNG. Com `MICROPY_HW_ENABLE_RNG` em 0, `rng_get()` degrada silenciosamente para um PRNG por software.
Erro 2: o fallback de `rng_get()` foi tratado como se fosse TRNG. Ao seguir as expansões até `ports/stm32/rng.c`, vê-se que, quando o macro está em 0, o código compila o ramo alternativo e retorna a saída do `pyb_rng_yasmarang()`. Nesse caminho, a semente do Yasmarang é inicializada com combinações de `MP_HAL_UNIQUE_ID_ADDRESS` e `SysTick->VAL`, além de registros do RTC (`RTC->TR` e `RTC->SSR`) lidos logo após o power-on, antes de inicialização pela aplicação.
A estimativa de entropia fica limitada: `SysTick->VAL` varia entre 0 e 79.999 (chip a 80 MHz com reload 80.000), cerca de 17 bits. O UID contribui algo em torno de 14 bits na prática do espaço observado. Os campos `RTC_TR` e `RTC_SSR` têm espaço pequeno e, nos vetores on-chain verificados, aparecem como 0 (0 bits efetivos). Pressionamentos de botões adicionariam cerca de 5 bits. No agregado, isso produz algo como 36 a 37 bits de entropia real para a geração da seed — em linha com a afirmação da Coinkite de “cerca de 40 bits” e, sobretudo, dentro do alcance de força bruta com cluster de GPUs em poucos dias.
Como a chave foi reconstruída (visão de alto nível)
No primeiro boot do Mk3, o consumo de números “aleatórios” segue perfis relativamente previsíveis. A missão do atacante é modelar esses perfis e reproduzir, passo a passo, a evolução do PRNG.
Fase 1 — Estado inicial: ao energizar o dispositivo, o libngu mantém um Yasmarang com constantes globais (`pad=0x0a8ce26f`, `n=69`, `d=233`, `dat=0`). Em paralelo, a primeira chamada a `rng_get()` faz o seeding do Yasmarang do MicroPython com `pad=UID^SysTick`, `n=RTC_TR=0`, `d=RTC_SSR=0`, `dat=0`. A “aleatoriedade” fica comprimida em um `pad` de 32 bits e algumas dimensões pequenas enumeráveis.
Fase 2 — Botões e menus: na configuração inicial, o usuário define PIN, aceita termos, navega menus. Cada tecla aciona rotinas que embaralham ordens (Fisher-Yates), consumindo chamadas a `_rand_below()` (ligado a `ngu.random.uniform` no C). A análise do v4.1.9 aponta três perfis de consumo.
• Perfil A (primeiro uso típico): duas teclas antes de aceitar termos; o `settings.save()` procura slot vazio entre 32 (excluindo o atual), gerando 30 chamadas a `_rand_below()`; depois a digitação do PIN e navegação (com número de pressionamentos `kpad_b` enumerável entre 4 e 34); por fim, `random_bytes(32)`.
• Perfil B (primeiro boot após flash/wipe com NVRAM vazia): o nvstore executa `shuffle(32)` (31 chamadas), depois consome 3.072 passos em sincronia (3 slots × 16 blocos × 256 bytes) sem realimentar saída, apenas avançando estado; em onboarding com NVRAM vazia ocorre mais um `shuffle(32)`, depois consumo por teclas (`kpad_b` entre 4 e 34), e então `my_random_bytes(32)`.
• Perfil C (paper wallet): após uma carteira já existir, ao entrar no menu Paper Wallets o usuário pressiona de 8 a 25 vezes; em seguida, `my_random_bytes(32)` vira diretamente a chave privada, sem passar pela lista de palavras BIP39.
Fase 3 — Construção da seed e derivação de endereço: a partir de `random_bytes(32)`, o Mk3 segue um pipeline determinístico: `entropy = SHA256(raw_bytes)` (SHA-256 simples, não sha256d), `mnemonic = BIP39` (24 palavras em inglês), `seed = PBKDF2-HMAC-SHA512` com 2048 rounds e salt “mnemonic”, depois `master = HMAC-SHA512("Bitcoin seed", seed)`. A derivação padrão usada é `m/{44,49,84}'/0'/0'/0/0`, e o endereço final é Bech32 (P2WPKH/BIP84) via `hash160` da chave pública comprimida. Como todas as etapas são reproduzíveis, acertar o estado do PRNG permite recalcular toda a cadeia offline.
Fase 4 — Força bruta em GPU: o método descrito divide-se em quatro passos. (1) Montar o conjunto de `pad` candidato combinando coordenadas de wafer X e Y (0 a 72), espaço de UID de cerca de 5.300 valores e `SysTick` de 0 a 79.999, chegando a 424 milhões de candidatos. (2) Enumerar `kpad_b` de 4 a 34; como `rtc_tr` e `rtc_ssr` têm hits em 0, ficam no laço externo como dimensões simples. (3) Rodar no kernel de GPU o pipeline completo (SHA256, BIP39, PBKDF2 2048, BIP32, Hash160, Bech32). O fluxo constante do libngu pode ser pré-computado e acessado por índice. (4) Fazer o match contra um conjunto de `hash160` de endereços P2WPKH de assinatura única, usando Bloom filter ou array ordenado (O(log n)).
O custo estimado mostra por que o ataque foi viável. Rodar o espaço do Perfil A em uma GPU Apple M1, com UID 72×72, 80.000 variações de SysTick e 31 contagens de teclas, gerou cerca de 14,8 bilhões de candidatos e levou aproximadamente 8,6 dias. Um cluster com GPUs A100 reduziria isso para poucas horas.
Nos modelos Mk4, Mk5 e Q, o espaço em ~72 bits é 2^32 vezes maior que o do Mk3, mas a origem da falha e o método de modelagem permanecem os mesmos. Na prática, a ferramenta sai de uma máquina única para um cluster e o tempo sobe de dias para semanas — custo que atacantes ainda aceitam pagar, o que ajuda a explicar por que esses modelos também aparecem nas listas de vítimas.