目录
-
- [1. 什么是地址投毒](#1. 什么是地址投毒)
- [2. 核心前提:靓号地址 (Vanity Address) 是可以"算"出来的](#2. 核心前提:靓号地址 (Vanity Address) 是可以"算"出来的)
- [3. 受害者视角:一次典型的"上当流程"](#3. 受害者视角:一次典型的"上当流程")
- [4. 主要变体](#4. 主要变体)
-
- [4.1 零额转账投毒 (Zero-Value Transfer)](#4.1 零额转账投毒 (Zero-Value Transfer))
- [4.2 假代币 / 伪造 Transfer 事件投毒 (Fake Token)](#4.2 假代币 / 伪造 Transfer 事件投毒 (Fake Token))
- [4.3 假充值 / 钓鱼空投投毒](#4.3 假充值 / 钓鱼空投投毒)
- [4.4 合约地址投毒 (针对 DApp / 多签)](#4.4 合约地址投毒 (针对 DApp / 多签))
- [5. 为什么这种攻击如此泛滥](#5. 为什么这种攻击如此泛滥)
- [6. 用户视角:怎么避坑](#6. 用户视角:怎么避坑)
- [7. 安全平台视角:怎么自动检测](#7. 安全平台视角:怎么自动检测)
-
- [7.1 零额转账检测](#7.1 零额转账检测)
- [7.2 靓号相似度检测(核心)](#7.2 靓号相似度检测(核心))
- [7.3 假代币合约识别](#7.3 假代币合约识别)
- [7.4 行为聚类 / 攻击者画像](#7.4 行为聚类 / 攻击者画像)
- [7.5 用户告警产品化](#7.5 用户告警产品化)
- [8. 与其他骗局的区别](#8. 与其他骗局的区别)
- [9. 一句话总结](#9. 一句话总结)
面向新人和安全研究者。读完应该能回答:什么是地址投毒?攻击者怎么骗人转错账?有哪几种变体?我作为用户怎么避坑?我作为安全平台怎么自动检测它?
1. 什么是地址投毒
以太坊地址是一串 42 个字符的十六进制(如 0x7a3b...F9c2)。人脑记不住中间那 38 个字符,所以几乎所有钱包 UI 都只显示首尾几位 (0x7a3b...F9c2),而用户转账时最常见的操作是------从历史记录里复制上次的收款地址。
地址投毒(Address Poisoning,也叫 Address Spoofing)正是利用这两个习惯:
攻击者制造一个首尾几位和你常用地址几乎一样的"李鬼"地址,想方设法把它塞进你的交易历史里。等你下次转账时,从历史里挑了那个看起来眼熟的地址,钱就直接打给攻击者了。
它不攻击合约漏洞,也不需要你签任何恶意授权------它攻击的是人的视觉惯性和复制粘贴习惯。这是一种典型的社会工程学攻击(Social Engineering),但实施完全在链上。
2. 核心前提:靓号地址 (Vanity Address) 是可以"算"出来的
要伪造一个首尾相同的地址,攻击者需要一个私钥,其对应地址恰好满足"前 4 位 + 后 4 位 = 目标地址首尾"。
- 地址是私钥经过 keccak256 哈希后取末 20 字节得到的,无法反推,只能暴力枚举(生成大量私钥,逐个比对地址首尾)。
- 匹配 前后各 4 个字符 (约 16^8 ≈ 43 亿分之一)用普通 GPU 几分钟到几小时就能跑出来,工具如
profanity、vanity-eth、create2crunch都能做。 - 匹配位数越多越慢,但攻击者通常只需骗过"首尾各 4~6 位"的视觉检查即可,成本很低。
关键认知:首尾相同不代表是同一个地址。中间 30 多位完全不同,钱进的是攻击者的钱包。
3. 受害者视角:一次典型的"上当流程"
1. 你经常给交易所充值地址 0x7a3bFa...9c2F 转 USDT
2. 攻击者监控到这笔转账,立刻用靓号地址 0x7a3bAb...9c2F(首尾相同)
向【你的地址】发起一笔操作,让这个李鬼地址出现在你的交易历史里
3. 几天后你又要充值,打开钱包历史 / 区块浏览器,"复制上次地址"
4. 你只瞄了一眼首尾 0x7a3b...9c2F → 看起来对!→ 粘贴 → 转 50000 USDT
5. 钱进了攻击者钱包,链上不可逆,无法找回
整个过程你没有被钓鱼网站骗、没签恶意授权、私钥也没泄露------你只是复制错了一行历史记录。
4. 主要变体
地址投毒的"塞历史记录"这一步有好几种技术实现,危害和隐蔽性各不相同。
4.1 零额转账投毒 (Zero-Value Transfer)
最经典的一种。利用 ERC-20 transferFrom 的一个特性:转账金额为 0 时,不需要授权 (allowance) 也能成功执行 ,并且会正常触发 Transfer 事件。
solidity
// 标准 ERC20,转 0 不检查 allowance,任何人都能代发
token.transferFrom(victim, attackerVanityAddr, 0);
- 攻击者用合约批量调用
transferFrom(你的地址, 李鬼地址, 0)。 - 链上就出现一条"从你的地址转出 0 个 USDT 到 0x7a3bAb...9c2F"的记录。
- 你的钱包/浏览器把这条 Transfer 显示在历史里,李鬼地址就"眼熟"了。
- 不花你一分钱,也不需要你授权,所以极难防。
4.2 假代币 / 伪造 Transfer 事件投毒 (Fake Token)
攻击者部署一个自己控制的山寨合约 ,名字也叫 "USDT"、"USD Coin",然后随意 emit Transfer 事件:
solidity
// 攻击者自己的合约,emit 是免费的,可以伪造任何 from/to/amount
emit Transfer(victim, attackerVanityAddr, 1000e6); // 看起来你转出了 1000 USDT
- 这条记录里的金额可以是任意大数字(比零额更显眼,更像"真实交易")。
- 但它来自假合约地址,不是真 USDT 合约。
- 很多浏览器/钱包早期不校验合约真伪,照单全收显示。
4.3 假充值 / 钓鱼空投投毒
攻击者主动给你转一笔小额真币(比如 0.01 USDT),转出方用靓号地址伪装成你认识的某个地址(交易所、朋友、合约)。你看到"某某给我转过钱",下次回转时就可能用错地址。
4.4 合约地址投毒 (针对 DApp / 多签)
针对开发者和机构:伪造一个和真实合约首尾相同的地址,诱导运维在配置文件、多签白名单、前端常量里填错,导致资金或权限打给攻击者合约。危害比个人转账大得多。
5. 为什么这种攻击如此泛滥
| 原因 | 说明 |
|---|---|
| 成本极低 | 靓号地址几分钟跑出来;零额转账一次 gas 几美分,可批量喷射成千上万个目标 |
| 无需授权 | 零额 transferFrom 和伪造 emit 都不需要受害者签名或授权 |
| 利用 UI 惯例 | 钱包只显示首尾、用户依赖"复制历史地址",是被动触发 |
| 不可逆 | 一旦转错,链上无法回滚,无客服可申诉 |
| 高回报 | 喷一万个目标只要有一个大额转错,就血赚 |
2023~2024 年,仅以太坊和 Tron 上的地址投毒造成的单笔损失就有多起超过百万美元的案例(如 2023 年 5 月某用户误转 2000 万 USDT 给投毒地址,后部分追回属极个别幸运情况)。
6. 用户视角:怎么避坑
- 永远不要从交易历史里复制收款地址。历史记录是攻击者唯一能"投毒"的入口。
- 校验完整地址,而不是只看首尾。至少核对中间若干位,最好逐字符比对或用 ENS 域名。
- 使用地址簿 / 白名单:钱包里手动保存常用地址并打标签,转账时从地址簿选,不从历史选。
- 首次大额转账前先转一笔小额测试,确认到账方正确再转大额。
- 用 ENS / 域名(
alice.eth)代替裸地址,人类可读、不易伪造。 - 对"我没操作过却出现的转账记录"保持警惕------尤其是 0 金额或来路不明的小额转入,很可能就是投毒诱饵。
- 硬件钱包/多签在签名时核对设备屏幕上的完整目标地址,不要只信电脑前端显示。
7. 安全平台视角:怎么自动检测
地址投毒在链上有很强的可识别特征,适合做自动化检测和告警。
7.1 零额转账检测
对每一笔 Transfer 事件:
IF value == 0:
标记为可疑(正常用户极少发起 0 额转账)
统计同一发起者在短时间内的 0 额转账数量 → 批量喷射特征
零额转账几乎没有正常业务场景,是最强的单一信号。
7.2 靓号相似度检测(核心)
对一个用户新出现的交互对手地址 ,与其历史高频/大额交互地址做"首尾相似度"比对:
python
def is_poisoning_candidate(new_addr, known_addr, prefix=4, suffix=4):
a, b = new_addr.lower(), known_addr.lower()
if a == b:
return False # 完全相同,是本人
# 去掉 0x 前缀
a, b = a[2:], b[2:]
head_match = a[:prefix] == b[:prefix]
tail_match = a[-suffix:] == b[-suffix:]
middle_diff = a[prefix:-suffix] != b[prefix:-suffix]
return head_match and tail_match and middle_diff
- 首尾相同 + 中间不同 = 高度疑似投毒地址。
- 可对
prefix/suffix取不同阈值分级告警(4 位低危、6 位高危)。
7.3 假代币合约识别
对 Transfer 事件里的 token 合约地址:
- 是否在官方稳定币/主流代币白名单内?(真 USDT/USDC 合约地址是固定已知的)
- 合约名字/符号是 "USDT" 等知名符号,但合约地址不在白名单 → 假币告警
- 合约是否在攻击者地址簇内、是否近期部署且只 emit 不实际转账
7.4 行为聚类 / 攻击者画像
- 同一地址在短时间内向大量不同受害者发起零额转账或假 Transfer → 投毒喷射机。
- 投毒地址通常只收款、不主动正常交易,余额异常集中。
- 把"靓号生成器产出地址"与已知投毒簇做关联,建立黑名单库。
7.5 用户告警产品化
钱包/浏览器/安全插件可以在用户发起转账时实时拦截:
用户输入/粘贴目标地址 →
与该用户历史交互地址做相似度比对 →
IF 命中靓号相似(首尾同、中间异):
弹强提醒 "⚠️ 该地址与你常用地址 0x7a3bFa...9c2F 仅首尾相同,中间不一致,可能是投毒地址!"
要求用户二次确认完整地址
这是目前最有效的防御点------在转账发生前的最后一刻把人拦下来。
8. 与其他骗局的区别
| 骗局 | 攻击对象 | 核心手法 | 是否需要受害者签名/授权 |
|---|---|---|---|
| 地址投毒 | 用户的复制粘贴习惯 | 伪造首尾相同地址混入历史 | 否 |
| 貔貅币 (Honeypot) | 买入用户 | 合约里禁止/惩罚卖出 | 是(买入交易) |
| Rugpull | 流动性提供者 | 项目方撤池跑路 | 否(被动受损) |
| 授权钓鱼 (Approval Phishing) | 用户的 approve | 诱导签署无限授权后盗刷 | 是(恶意授权签名) |
地址投毒的独特之处在于:它不碰你的合约交互,只污染你的"参考数据",让你自己亲手把钱转给攻击者。
9. 一句话总结
地址投毒 = 攻击者算一个和你常用地址首尾相同 的靓号,再用零额转账或假 Transfer 事件把它塞进你的交易历史,赌你下次"复制历史地址"时看走眼。
防御核心:用户端永不从历史复制地址、用地址簿/ENS、小额先试 ;平台端做零额转账检测 + 靓号首尾相似度比对 + 转账前实时拦截告警。