随便溯来玩玩的,不保证100%正确
上一篇创建的博客就是ETHPanda的残酷共学的每日签到日志,也勉强算是跟下来了,结果共学刚结束没几天群里就传出来有人参加那个新手Hackathon拿的奖金被偷了:关于收获休闲黑客松奖金后钱包被盗分析(EIP-7702) - General - LXDAO
当时刚好也是在给新生赛出题,本来就打算用7702模拟一次恶意攻击拿来出题,这下Buy One Get One Free了,于是简单溯源了一下
别问我为什么这么晚才解禁,问就是还在给新生赛出题
0. 引子——EIP-7702简述
我觉得完全轮不到我来解释7702到底是个啥东西,毕竟这EIP有点臭名昭著了,总之就是以太坊在实现账户抽象进行的一次重大尝试,但是这次尝试很明显…炸了喵
简单来说就是规定了一种新的交易类型,该交易类型会将某一个/某一些EOA地址升级为智能钱包,并且该改变是永久的,即如果不进行重置则该EOA将永久为智能钱包,直到出现一次新的交易改变其指向的地址
整个交易只多了一个Authorization List,里面包含的是chainId
,address
和nonce
以及签名数据,其中address
则是EOA指向的合约地址,nonce
为EOA地址当前的nonce值,除此之外就没有东西了
由此我们可以看出来被升级的EOA地址是通过ecrecover()
计算得到的,也就是说我们只需要一个简单的签名就能进行EIP-7702的升级,这可太TM利好钓鱼攻击了,太TM方便了,稍微引诱一下受害者签个名就能偷走所有的资金,那可太TM爽了😅
升级后的EOA可以视为一个简单代理合约,向其发送的所有交易都会通过delegatecall调用其指向的合约的代码,而这很明显就会出现非常大的问题,比如如下的合约:
1 | // SPDX-License-Identifier: MIT |
将receiver
修改为攻击者的地址,token
为某ERC20的地址,这样攻击者通过钓鱼让受害者指向该合约,然后攻击者向受害者调用attack()
就能偷走其所有的ERC20资产
还有一点:《EOA升级为智能钱包》和《包含calldata的交易》两者完全不冲突,可能我没表述清楚,简单来说就是我们可以在同一个交易里面对地址A使用EIP-7702升级,同时正常调用合约B的函数,这会在我们之后的溯源中看到
好的,接下来进入正题…
1. 正文——公链溯源
根据受害者的自述,他们将私钥放在.env
文件里面,还一个不小心传到repo上了…我记得Patrick Collins当时教怎么用web3py进行合约开发的时候不就特别强调别把env传上去吗,都提及了gitignore🤔,总之木已成舟,那很明显就是私钥泄露了
接下来说是被偷走了200个USDT,那直接看ERC20交易详情就能找到攻击交易:Ethereum Transaction Hash: 0xe247b175ca… | Etherscan
开头就是一个巨大的EIP-7702 Action,自此我们已经可以找到攻击者和恶意合约了:
- 攻击者:0x3847f3F8F74A202b357406D86CFbbB03BE4432CC
- 恶意合约:0xB2BeFaDFeB2407995D7d27c64D0De9D492b682D3
简单反编译一下恶意合约:EVM Bytecode Decompiler | Dedaub Security Suite
这里的0x0a7c8ed6
是一个类似Multicall3合约里面的Aggregate
函数,其内容实现大致来说是这样的:
1 | address constant OWNER = 0x3847f3F8F74A202b357406D86CFbbB03BE4432CC; |
这里的require
块是防止其它攻击者调用(不然到嘴的USDT飞了),除此之外就是一个纯粹的Multicall3 Aggregate函数,内容上就是进行一个Multicall操作
接下来我们看交易本身,该交易的To
字段是地址0xcA11bde05977b3631167028862bE2a173976CA11
,是一个实打实的公开的Multicall3合约,然后看交易的Internal Txns
,我们发现这次交易中衍生的内部交易有两个,一是Multicall3向受害者发送了交易,然后就是受害者执行了USDT的Transfer
函数,那么自此我们已经可以得到完整的攻击链路了:
攻击者使用受害者泄露的私钥进行签名,从而使得受害者通过EIP-7702升级为智能钱包,指向的合约地址为恶意合约地址
攻击者在同一交易内调用Multicall3的
Aggregate
函数进行Multicall操作Multicall3调用受害者的
Aggregate
函数进行Multicall操作受害者接收到的calldata内容是“调用USDT合约的
Transfer
函数”,即让受害者将自己的USDT转给攻击者攻击完成
一个简陋的攻击流程图长这样:

由于智能钱包运行代码时是在自己的上下文中,因此完全不需要复杂的Approve操作,直接Transfer就行了
自此,整个攻击的流程就已经基本摸清楚了,使用一个Multicall合约当恶意合约也是为了窃取存在多种资产的合约
2. 后记——一些废话
其实查看受害者地址的交易详情,我们发现还有另一个攻击者(0x221225800dd383E59b89F7B6F3fE9DF8dc310334
和0xd66C1Bb58858dC92378AD1135443Db979dA52D16
)在7天前也进行了攻击,稍微瞄了一眼也没有找到这个攻击者的后续执行地址
借此顺带看了看一些可疑地址的EIP-7702交易,全都是一套公式,闹麻了,只能说开头提到的7702全都是用于钓鱼这一点还真没说错
还看到了有两个交易在同一个块内同时对一个地址进行7702升级,笑死了,Alea jacta est!这块
- 本文作者: 9C±Void
- 本文链接: https://cauliweak9.github.io/2025/09/03/web3-trace/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!