Caloogy 文章
English

地址投毒:首尾相同的假地址

日期
2025 年 9 月 4 日
系列
链上
阅读
3 分钟
主题
Address poisoningEthereumEip 55Checksum

一句话版本

以太坊地址是 40 个十六进制字符,人眼通常只看开头几位和结尾几位。攻击者批量生成首尾和你常用地址一样的假地址,再给你转一笔 0 金额或极小金额的"交易",让它出现在你的转账历史里。下次你从历史记录里复制地址时,复制到的就是攻击者的地址。 这种攻击不需要偷任何东西,只利用人的习惯。防御靠的是:不从历史里复制地址、用地址簿、比对更多字符、钱包主动标记相似地址。

全文分三层:

  1. 通俗理解:攻击是怎么做的
  2. 实际用处:真实损失案例,钱包和交易所的应对
  3. 原理与工程要点:生成相似地址的成本、EIP-55 校验和能做什么不能做什么、检测规则

第一层:通俗理解

1.1 攻击步骤

攻击者 0x7a3f...91c2(假)你的朋友 0x7a3f...91c2你攻击者 0x7a3f...91c2(假)你的朋友 0x7a3f...91c2你监控到这笔转账,生成一个首尾相同的地址历史记录里多了一条,对方显示为 0x7a3f...91c2正常转账 1000 USDC0 金额转账 / 假币转账下次从历史里复制"朋友的地址",转出 5000 USDC

钱包界面为了好看,地址常常被缩写成 0x7a3f...91c2。真地址和假地址在缩写后一模一样。

1.2 为什么有效


第二层:实际用处

Caloogy Wallet 也采用了地址投毒检测。


第三层:原理与工程要点

3.1 生成相似地址有多难

以太坊地址由公钥的哈希截取而来,可以看作 40 个随机的十六进制字符。要让假地址和真地址前 aa 位、后 bb 位都相同,平均要试

16a+b=24(a+b)16^{a + b} = 2^{4(a+b)}

个私钥。

匹配位数(首 + 尾) 平均尝试次数 难度
4 + 4 168≈4.3×10916^8 \approx 4.3 \times 10^9 一块显卡几秒到几分钟
6 + 6 1612≈2.8×101416^{12} \approx 2.8 \times 10^{14} 显卡集群,可行
10 + 10 1620≈1.2×102416^{20} \approx 1.2 \times 10^{24} 实际不可行

注意这是第二原像式的搜索(给定一个地址找相似的),不是生日攻击,所以不能开平方(见《生日悖论与哈希碰撞》)。结论是:只核对首尾 4 位远远不够,核对得越多越安全。

3.2 EIP-55 校验和:能防手误,防不了投毒

以太坊地址的大小写不是随便的。EIP-55 规定:对小写地址取 Keccak-256 哈希,哈希的第 ii 个十六进制位 ≥8\ge 8 时,地址第 ii 位的字母就写成大写。

EIP-55 标准里的测试地址

正确写法:0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed

如果最后一位抄错,...BeAed 变成 ...beaee,那么对应地址的正确大小写变为 0x5Aaeb6053f3e94c9B9a09F33669435e7EF1BeAee,几乎每个字母的大小写都变了。

钱包发现你输入的大小写模式和正确的不一致,就会报错。(已用 Python 验算。)

和弃九法与校验位里的身份证、银行卡校验位一样,EIP-55 能抓住随机的抄写错误。但投毒地址本身就是一个合法的地址,有它自己正确的校验和,所以 EIP-55 完全挡不住投毒。

3.3 检测规则

规则 说明
和历史交易对象的首尾相似度比较 前后若干位相同,但整体不同,就标记为可疑
对方是否给你发过 0 金额或假币转账 投毒的典型前奏
这是不是第一次转给这个地址 首次转账本身就应该加一道确认
代币是否在白名单里 投毒常伴随假代币(名字也叫 USDT,但合约地址不同)

3.4 界面设计


总结

层次 要点
攻击 生成首尾相同的地址,用 0 金额转账混进你的历史
成本 首尾 8 位匹配只要几十亿次尝试,很便宜
校验和 EIP-55 防手误,不防投毒(投毒地址本身合法)
防御 不从历史复制;地址簿;完整显示;相似度检测;带外核对