Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
工具/GitHubGitHub/ethicbrudhack/cve-2008-0166-btc-satoshi-mining-wallets
漏洞分析漏洞利用哈希分析逆向工程密码学论文与研究学习与教育
GitHubethicbrudhack/cve-2008-0166-btc-satoshi-mining-wallets

CVE-2008-0166-BTC-satoshi-mining-wallets

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →

对2009-2012年比特币中CVE-2008-0166的技术分析,考察OpenSSL 0.9.8c PRNG弱点、Windows熵故障以及密钥空间重建。

查看仓库
114小时49分前尚未审核
分享

GhostRNG — 漏洞分析:Bitcoin 2009-2012 中的 OpenSSL 0.9.8c (CVE-2008-0166)

作者: 基于 bitcoin-code-r252 (0.1.5 / 0.2.0 / 0.3.24) 以及 原始 make-OpenSSL-0-9-8c-vulnerable-again.diff (THC) 的分析 日期: 2026-09-10


1. 引言

Bitcoin 0.1.5(2009 年 1 月)仅在 Windows 上运行,使用 OpenSSL 0.9.8c 进行 EC 密钥生成(EC_KEY_generate_key)。2008 年, CVE-2008-0166 在 Debian 的 OpenSSL 软件包中被发现,但在 Windows 上该问题有着不同的根本原因——并非缺少 /dev/urandom,而是 Bitcoin 源代码中 RandAddSeed() 的实现本身。


2. 密钥生成前的 PRNG 状态(0.1.5)

在 bitcoin-code-r252(tags-0.1.5)中,RNG 初始化序列 (util.cpp):

root@kitploit:~
CInit::CInit() {
    RAND_screen();                    // (a) 屏幕位图抓取
    RandAddSeed(true);                // (b) QPC + PerfMon
}

RandAddSeed():

util.cpp:57-92
  • QueryPerformanceCounter -> RAND_add(&PerformanceCount, 8, 1.5)
  • RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", ..., buf=250000) -> 如果 ERROR_SUCCESS:SHA256(pdata) -> RAND_add(&hash, 32, entropy)

密钥生成(key.h:75-78):

root@kitploit:~
CKey::MakeNewKey() {
    EC_KEY_generate_key(pkey);  // 内部:RAND_bytes(32)
}

重要提示:0.1.5 至 0.3.24 版本没有 keypool。GetRand() 将 RAND_bytes(8) 用于其他目的(网络 nonce、IRC 昵称),从而 在连续的 GenerateNewKey() 调用之间扰乱 PRNG 状态。

0.4.0 版本(2011 年 9 月)引入了 TopUpKeyPool(),默认 池大小为 100 个密钥(GetArg("-keypool", 100))。


3. 补丁:make-OpenSSL-0-9-8c-vulnerable-again.diff

THC 组织(The Hackers Choice)开发了 thc-btc-rng-bruteforce, 使用修改过的 OpenSSL 0.9.8c。三处关键改动:

A. 引入 THC_hitme()(md_rand.c:133-180)

  • THC_hitme(0):将 state_num、state_index、entropy、 initialized、stirred_pool、md_count[0..1]、md[]、state[] 清零——完全重置 PRNG。
  • THC_hitme(pid):将 pid 存入静态变量 thc_pid。

B. ssleay_rand_add() — 缓冲区内容被忽略(第 344 行)

root@kitploit:~
- MD_Update(&m, buf, j);
+ //MD_Update(&m, buf, j);   // 已注释掉!

RAND_add 仍会将 state_index 推进 num 并递增 md_count[1],但缓冲区内容对 PRNG 状态没有影响。

C. ssleay_rand_bytes() — PID 替换(第 550-561 行)

  • 原始的 getpid() 调用被移除。
  • curr_pid = thc_pid——来自 THC_hitme 的常量值。
  • 额外的 MD_Update(&m, &curr_pid, sizeof(curr_pid)) 将 PID 作为唯一的外部变量输入注入。

结论

在打过补丁的 OpenSSL 中,PRNG 状态仅取决于:

  1. PID 值(通过 THC_hitme)
  2. RAND_add 调用的顺序和大小(num 参数,而非缓冲区内容)
  3. 密钥生成前 RAND_bytes 的调用次数

4. 架构差异:le32 与 le64

在 OpenSSL 0.9.8c 中,BN_ULONG 由 opensslconf.h 定义:

root@kitploit:~
#ifdef SIXTY_FOUR_BIT_LONG   -> BN_ULONG = unsigned long (64 位)
#ifdef THIRTY_TWO_BIT        -> BN_ULONG = unsigned long (32 位)

在 64 位 Linux 上,OpenSSL 默认使用 SIXTY_FOUR_BIT_LONG,将 sizeof(BN_ULONG) 从 4 字节变为 8 字节。这会影响:

  • static long md_count[2] 的大小(8 字节 vs 16 字节)
  • SHA 内部的 bignum 表示
  • 整个 PRNG 输出流

THC SelfCheck 测试向量(profile 0.3.24,PID 31337):

  • le32: 1FkLYqPpfKPAR6EZh2RC6sDwTUA6Axb1XQ
  • le64: 1JbxBrkBiSwpJUJN2bXrYJc51pH5rjrzTD

Bitcoin 2009 运行在 Windows XP 32 位上,因此正确的密钥重建 需要强制使用 THIRTY_TWO_BIT 进行编译(在构建前编辑 include/openssl/opensslconf.h)。


5. Sergio Lerner 的 Bug(Bitcointalk 2012)

在 2012 年 9 月 27 日的一篇帖子中(topic=113496),Sergio Lerner 描述:

(a) RandAddSeed() 调用 QueryPerformanceCounter()——要求 其参数按 QWORD 对齐。Windows 上的 gcc 编译器可能无法 将栈变量按 8 字节对齐,导致静默失败。

(b) RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", ...) 使用 固定大小的 250,000 字节缓冲区。在 Windows XP 上,性能数据约为 280 KB——该函数返回 ERROR_MORE_DATA,并且再也不会用 更大的缓冲区调用。debug.log 中没有任何警告。

如果这两个机制都失败了,唯一的熵源就是 RAND_screen() (屏幕位图)。在打过补丁的 OpenSSL 中,即使 RAND_screen 也无关紧要, 因为缓冲区内容被忽略。

Lerner 建议将这些失败记录到 debug.log——该修复被 纳入后来的 Bitcoin Core 版本中。


6. Bitcoin Core 中 RNG 初始化的演变(2009-2012)

已在 bitcoin-code-r252(tags:0.1.5、0.2.0、0.3.0)和 bitcoin/bitcoin 仓库(tags:0.3.24、0.4.0、0.5.0、0.6.0)中验证:

版本日期初始化 RNG(Windows)Keypool
0.1.52009-01RAND_screen + RandAddSeed(true)无
QPC->RAND_add(8) + perfmon->SHA256->RAND_add(32)
0.2.02009-12RAND_screen(仅 __WXMSW__)无
QPC->RAND_add(8),perfmon 每 10 分钟单独执行
0.3.02010相同无
0.3.242011-07perfmon 每 10 分钟,RegQueryValueExA无
0.4.02011-09相同TopUpKeyPool 100
0.5.02011-12相同100
0.6.02012-03相同100

关键发现

  • RAND_screen() 在截至 2012 年的所有 Windows 版本上都被使用。
  • keypool(预生成 100 个密钥且不重置 PRNG)仅在 0.4.0 中 出现——更早的版本每次请求生成一个密钥。
  • Perfmon:0.1.5 使用 SHA256(pdata) -> RAND_add(32),后续版本 将原始 pdata 传给 RAND_add(在打过补丁的 OpenSSL 中, 不同的 num 大小很重要,因为只有大小而非内容会影响状态)。

7. 结论

攻击的密钥空间(在打过补丁的 OpenSSL 中):

root@kitploit:~
  PID (1..32767)
  x poll(init 中 RAND_add 调用次数,模拟 WinXP 上的 Toolhelp32)
  x keypool 位置(0.4.0 之前为 1,0.4.0+ 为 100)
  x profile(每个 Bitcoin 版本的 RAND 调用序列)
  x 架构(le32 / le64)

在此模型中,tick、screen、cursor、hwnd、queue 参数 无关紧要,因为 RAND_add 缓冲区内容被忽略。

THC 原作者写道:“我们没有找到任何。”——他们 没有在区块链上找到任何密钥。分析证实了他们的发现: 链上存在易受攻击密钥的概率完全取决于 是否真的有任何 Bitcoin 钱包是在 Windows XP 系统上使用 有缺陷的 OpenSSL 以及静默失败的 perfmon/QPC 生成的。


参考文献

[1] Sergio Lerner,“可能的新漏洞:Windows 生成的密钥对中 熵不足”,Bitcointalk 2012-09-27: 链接

[2] Bitcoin StackExchange — “中本聪使用的是 Windows 还是 Linux?”: 链接

[3] THC,thc-btc-rng-bruteforce: 链接

[4] Bitcoin Core tags(0.1.5、0.2.0、0.3.0、0.3.24、0.4.0、0.5.0、0.6.0): 链接

[5] OpenSSL 0.9.8c + 补丁 make-OpenSSL-0-9-8c-vulnerable-again.diff

[6] Analiza_entropy_win.txt — 技术报告,2026-09-10

下载工具