Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
profanity-verifier — CVE-2022-40769에 대한 검증 가능한 확인: EOA의 개인 키가 Profanity로 도달 가능한 키 공간에 있는가? | Kitploit
도구/GitHubGitHub/artsbykriss/profanity-verifier
Password CrackingVulnerability ScannersVulnerability AnalysisExploitationCryptographyPapers & Research
GitHubartsbykriss/profanity-verifier

profanity-verifier

CVE-2022-40769에 대한 검증 가능한 확인: EOA의 개인 키가 Profanity로 도달 가능한 키 공간에 있는가?

저장소 보기
117시간 14분 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

profanity-verifier

CVE-2022-40769에 대한 증명 가능한 검사: EOA의 개인 키가 Profanity vanity-address 생성기로 도달 가능한 키 공간에 존재하는가? 만약 그렇다면, 그 키는 복구 가능하며 해당 계정(그리고 그것이 제어하는 모든 것)은 누구나 탈취할 수 있다.

휴리스틱은 없다. 결과는 정확한 키 공간에 대한 전체 검색으로 뒷받침되는 불리언 값이며, 동일한 샤드를 다시 실행하여 재현할 수 있다.

원본 소스에서의 버그

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

그런 다음 OpenCL 커널은 해당 키에 대해 G^k를 취하고 앞으로 이동하며, 주소가 요청된 패턴과 일치할 때까지 라운드마다 키를 1씩 증가시킨다. 따라서 도달 가능한 전체 키 공간은 다음과 같다:

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

이 프로그램이 하는 일

  1. 후보의 공개 키로부터 아래로 이동한다: P_j = P − j·G (단, j ≤ depth). 만약 Profanity가 키를 생성했다면, 이 점들 중 하나가 시드 공개 키이다.
  2. 해당 샤드의 시드들을 스캔한다; 각 x에 대해 mt19937_64(x)와 그 주소를 도출한다.
  3. 일치하면 P_j가 시드 공개 키이며, 따라서 후보의 개인 키는 seed(x) + j이다 — 복구 가능하므로 탈취 가능하다.

일치는 증명이다. 전체 시드 범위에 걸친 불일치는 선택된 깊이까지 반대의 증명이다.

검증됨

  • MT19937-64는 libstdc++와 정확히 일치한다. 시드 0, 1, 12345, 4294967295에 대한 원시 std::mt19937_64 추출값을 std::mt19937_64 + std::uniform_int_distribution<unsigned long long>을 사용하는 g++ 프로그램과 림(limb) 단위로 비교했다; 동일하다.
  • 두 개의 독립적인 곡선 라이브러리가 일치한다. 동일한 테스트 벡터를 k256(순수 Rust)과 secp256k1(libsecp256k1 바인딩)으로 생성했다: 시드 0 → 0xfef2583edde5637dad990bc5d05d52c8247019cf, 시드 12345 → 0x7712c45360f5dfa3a622a815b6073f0351050f13.
  • **--selftest**는 도출, 주소, 체인 이동, 아래로 이동 복구, 그리고 알려진 시드를 찾는 종단 간 시드 스캔을 검증한다.

직접 실행해 보라:

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

사용법

root@kitploit:~
profanity-verifier --address 0x... [--pubkey 0x...] --shard i/n [--depth 16777216]
  • --pubkey — 후보의 비압축 공개 키 (x||y의 64바이트, 0x04 접두사가 있든 없든). 주소가 서명한 임의의 트랜잭션에서 복구할 수 있다. 이것이 없으면 체인 위치 0만 테스트할 수 있다.
  • --shard i/n — 검색할 32비트 시드 공간의 조각으로, 여러 머신에 작업을 병렬화할 수 있다.
  • --depth — 생성기의 체인을 얼마나 멀리까지 살펴볼지. 2^24는 6자리 vanity를 여유 있게 커버하며, 더 깊게 하면 메모리와 시간이 더 든다.

출력은 단일 JSON 라인이다, 예:

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

시드와 개인 키는 절대 출력되거나 저장되지 않는다. 불리언, 주소, 샤드만 출력되므로, 누구에게도 키를 넘기지 않고 결과를 공개할 수 있다.

대규모 실행

.github/workflows/verify.yml은 공개 러너에서 (candidate, shard) 작업 매트릭스에 걸쳐 검색을 분산한다.

측정된 처리량: 2코어에서 ~20,000 시드/초 (libsecp256k1). 전체 2^32 시드 공간은 약 59 코어-시간이므로, 64 샤드 × 4 코어 ≈ 후보당 14분 실시간 — 공개 저장소에서는 무료이다.

후보 목록으로 디스패치:

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

한계

  • 생성기가 **libstdc++의 std::mt19937_64**를 사용했다고 가정하며, 이는 림 단위 비교가 커버한다. 다른 표준 라이브러리로 빌드하면 매핑이 달라진다.
  • depth는 검색 범위를 제한한다. 비정상적으로 긴 검색(매우 긴 vanity 패턴) 후에 생성된 후보는 그 범위를 벗어날 수 있다.
  • 전체 커버리지를 위해서는 공개 키가 필요하다. 주소로부터의 서명이 없으면 체인 위치 0만 테스트할 수 있다.
  • 부정적인 결과는 "Profanity 공간에 없음"을 의미한다 — 다른 어떤 취약점에 대해서도 말해주지 않는다.
도구 다운로드