Ethernaut: 14. 게이트키퍼 2

Play the level

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract GatekeeperTwo {
  address public entrant;

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

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

  modifier gateThree(bytes8 _gateKey) {
    require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == uint64(0) - 1);
    _;
  }

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


통과해야 할 또 다른 게이트 퍼즐이 있습니다! 다시 세 개의 게이트가 있습니다.
  • 심플 msg.sender != tx.origin .
  • 인라인 어셈블리를 통한 귀여운 extcodesize 호출.
  • 일련의 require는 게이트 키가 어떤 것인지 알려줍니다.

  • 게이트 1



    이전 퍼즐과 마찬가지로 계약을 중개인으로 사용하십시오.

    게이트 2



    다음은 실제 게이트입니다.

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

    extcodesize는 기본적으로 주어진 주소의 코드 크기를 반환하며 이 경우 호출자입니다. 계약에는 코드가 있고 사용자 계정에는 코드가 없습니다. 코드 크기가 0이 되려면 계정이어야 합니다. 하지만 잠깐만, 그렇다면 첫 번째 게이트를 어떻게 통과할까요? 이 게이트의 트릭은 다음과 같습니다. extcodesizeconstructor에서 호출되는 경우 0을 반환합니다. 여기 내가 이 정보를 우연히 발견한 link이 있습니다.

    요컨대, 생성자 내에서 공격을 실행해야 합니다.

    게이트 3



    이 게이트의 형식은 다음과 같습니다.

    modifier gateThree(bytes8 _gateKey) {
      require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == uint64(0) - 1);
      _;
    }
    


    이것은 단지 XOR 연산(종종 ⊕로 표시됨)이며 여기서 제어할 수 있는 매개변수는 게이트 키 하나뿐입니다. 글쎄, 우리는 그것을 어떻게 찾을 수 있습니까? XOR은 동일한 값이 자체적으로 XOR되면 취소되는 속성을 가지고 있습니다. 또한 XOR은 가환적이므로 a ⊕ b = b ⊕ a . a ⊕ b = c 로 시작하여 양쪽을 a 로 XOR하면 a ⊕ a ⊕ b = c ⊕ a 가 되고 왼쪽은 취소되어 b = c ⊕ a 가 됩니다.

    한 가지 더: (uint64(0) - 1) 원인은 Solidity에 실제로 좋지 않으며 심지어 가스 추정 오류를 유발했습니다! 결과는 기본적으로 uint64 의 가능한 최대 값이며 type(uint64).max 를 통해 찾을 수 있는 멋진 방법이 있습니다.

    다음과 같이 게이트 키를 안전하게 찾을 수 있습니다.

    bytes8 key = bytes8(type(uint64).max ^ uint64(bytes8(keccak256(abi.encodePacked(address(this))))));
    


    이것이 전부입니다!

    좋은 웹페이지 즐겨찾기