Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
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
profanity-verifier — Verificação comprovável para CVE-2022-40769: a chave privada de uma EOA está no espaço de chaves alcançável pelo Profanity? | Kitploit
Ferramentas/GitHubGitHub/artsbykriss/profanity-verifier
Quebra de SenhasScanners de VulnerabilidadesAnálise de VulnerabilidadesExploraçãoCriptografiaPapers e Pesquisa
GitHubartsbykriss/profanity-verifier

profanity-verifier

Verificação comprovável para CVE-2022-40769: a chave privada de uma EOA está no espaço de chaves alcançável pelo Profanity?

Ver Repositório
1há 17h 14mAinda 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

profanity-verifier

Verificação comprovável para CVE-2022-40769: a chave privada de uma EOA está no espaço de chaves alcançável pelo gerador de endereços vanity Profanity? Se sim, a chave é recuperável e a conta (e tudo o que ela controla) pode ser drenada por qualquer pessoa.

Sem heurísticas. O resultado é um booleano respaldado por uma busca completa do espaço de chaves exato, reproduzível ao reexecutar o mesmo shard.

O bug, a partir do código-fonte original

Dispatcher.cpp, createSeed():

root@kitploit:~
std::random_device rd;
std::mt19937_64 eng(rd());                 // seeded with only 32 bits  <- CVE-2022-40769
std::uniform_int_distribution<cl_ulong> distr;
cl_ulong4 r;
r.s[0] = distr(eng); r.s[1] = distr(eng);  // 256-bit seed, used directly
r.s[2] = distr(eng); r.s[3] = distr(eng);  // as the private key

O kernel OpenCL então toma G^k para essa chave e avança, incrementando a chave em um por rodada até que o endereço corresponda ao padrão solicitado. Portanto, todo o espaço de chaves alcançável é:

root@kitploit:~
key(x, i) = mt19937_64(x) as a 256-bit scalar + i
x ∈ [0, 2^32)    the 32-bit seed (four billion possibilities)
i ∈ [0, depth]   rounds the generator ran

O que este programa faz

  1. Percorre para baixo a partir da chave pública do candidato: P_j = P − j·G para j ≤ depth. Se o Profanity gerou a chave, um desses pontos é uma chave pública semente.
  2. Varre as sementes em seu shard; para cada x, deriva mt19937_64(x) e seu endereço.
  3. Uma correspondência significa que P_j é a chave pública semente, então a chave privada do candidato é seed(x) + j — recuperável, portanto drenável.

Uma correspondência é prova. A ausência de correspondência em toda a faixa de sementes é prova do oposto, até a profundidade escolhida.

Verificado

  • MT19937-64 corresponde exatamente ao libstdc++. Amostras brutas de std::mt19937_64 para as sementes 0, 1, 12345 e 4294967295 foram comparadas limb a limb contra um programa g++ usando std::mt19937_64 + std::uniform_int_distribution<unsigned long long>; idênticas.
  • Duas bibliotecas de curva independentes concordam. Os mesmos vetores de teste foram produzidos com k256 (Rust puro) e secp256k1 (bindings libsecp256k1): semente 0 → 0xfef2583edde5637dad990bc5d05d52c8247019cf, semente 12345 → 0x7712c45360f5dfa3a622a815b6073f0351050f13.
  • --selftest verifica a derivação, o endereço, a caminhada na cadeia, a recuperação por caminhada descendente e uma varredura de sementes de ponta a ponta que encontra uma semente conhecida.

Execute você mesmo:

root@kitploit:~
cargo run --release -- --selftest

Uso

root@kitploit:~
profanity-verifier --address 0x... [--pubkey 0x...] --shard i/n [--depth 16777216]
  • --pubkey — a chave pública não comprimida do candidato (64 bytes de x||y, com ou sem o prefixo 0x04). Recupere-a de qualquer transação que o endereço tenha assinado. Sem ela, apenas a posição 0 da cadeia pode ser testada.
  • --shard i/n — a fatia do espaço de sementes de 32 bits a ser pesquisada, para que o trabalho seja paralelizado entre máquinas.
  • --depth — até onde ao longo da cadeia do gerador procurar. 2^24 cobre um vanity de seis caracteres com folga; mais profundo custa memória e tempo.

A saída é uma única linha JSON, por exemplo:

root@kitploit:~
{"address":"0x...","shard":"0/64","depth":16777216,"seeds_checked":67108864,"seconds":833.4,"match":true}

A semente e a chave privada nunca são impressas ou armazenadas. Apenas o booleano, o endereço e o shard são emitidos, para que um resultado possa ser publicado sem entregar a chave a ninguém.

Executando em escala

.github/workflows/verify.yml distribui a busca em uma matriz de jobs (candidate, shard) em runners públicos.

Taxa de transferência medida: ~20.000 sementes/s em 2 núcleos (libsecp256k1). O espaço completo de 2^32 sementes é ~59 horas-núcleo, então 64 shards × 4 núcleos ≈ 14 minutos de tempo real por candidato — gratuito em um repositório público.

Dispare com a lista de candidatos:

root@kitploit:~
gh workflow run profanity-verify -f candidates='[{"address":"0x...","pubkey":"0x..."}]' -f shards=64

Limitações

  • Assume que o gerador usou std::mt19937_64 do libstdc++, o que a comparação limb a limb cobre. Builds contra uma biblioteca padrão diferente teriam um mapeamento diferente.
  • depth limita a busca. Um candidato gerado após uma busca excepcionalmente longa (padrões vanity muito longos) pode estar além dela.
  • A cobertura completa requer uma chave pública. Sem uma assinatura do endereço, apenas a posição 0 da cadeia é testável.
  • Um resultado negativo diz "não está no espaço do Profanity" — não diz nada sobre qualquer outra fraqueza.
Baixar ferramenta