DEV Community

bin2chen
bin2chen

Posted on

Ethernaut系列-Level 14(GatekeeperTwo)

LEVEL 14 (GatekeeperTwo):

// 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;
  }
}
Enter fullscreen mode Exit fullscreen mode

通关要求

entrant=player

要点

1.tx.origin和msg.sender的区别,这个前面有讲
2.EOA和合约区别,以及extcodesize
3.位计算
^ 异或 两个位相同为0,相异为1

解题思路

gateOne:在自己的合约调用其他合约,则tx.origin和msg.sender就会不一样
gateTwo:正常EOA账号的codesize=0,合约不等于0,但有个例外就是在合约的构造器constructor里代用外部合约,这时是codesize为0的,因为还没初始化完合约。
gateThree:位计算,见下面的代码提示

        //gateThree:require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == uint64(0) - 1);
        //结果再异或下
        uint64 gateKey;
        unchecked {
            gateKey = (uint64(0) - 1) ^
                uint64(bytes8(keccak256(abi.encodePacked(address(this))))); 
        }
        ILevel(_runAddress).enter(bytes8(gateKey));
    }
Enter fullscreen mode Exit fullscreen mode

Top comments (0)