Ethernaut: 16. 보존

Play the level

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

contract Preservation {
  // public library contracts 
  address public timeZone1Library;
  address public timeZone2Library;
  address public owner; 
  uint storedTime;
  // Sets the function signature for delegatecall
  bytes4 constant setTimeSignature = bytes4(keccak256("setTime(uint256)"));

  constructor(address _timeZone1LibraryAddress, address _timeZone2LibraryAddress) public {
    timeZone1Library = _timeZone1LibraryAddress; 
    timeZone2Library = _timeZone2LibraryAddress; 
    owner = msg.sender;
  }

  // set the time for timezone 1
  function setFirstTime(uint _timeStamp) public {
    timeZone1Library.delegatecall(abi.encodePacked(setTimeSignature, _timeStamp));
  }

  // set the time for timezone 2
  function setSecondTime(uint _timeStamp) public {
    timeZone2Library.delegatecall(abi.encodePacked(setTimeSignature, _timeStamp));
  }
}

// Simple library contract to set the time
contract LibraryContract {
  // stores a timestamp 
  uint storedTime;  

  function setTime(uint _time) public {
    storedTime = _time;
  }
}


여기서 우리는 전능자의 손 안에 있습니다delegatecall . 주어진 계약은 실제로 6단계(위임)에서 익스플로잇으로 사용한 버그로 인해 어려움을 겪고 있습니다. setFirstTime를 호출하면 실제로 timeZone1Library 저장 변수의 값을 덮어씁니다! 우리가 하는 일은 다음과 같습니다.
  • 서명이 setTime(uint256)인 기능이 있는 계약을 만듭니다. 이 계약에는 호출자의 컨텍스트에서 변수를 덮어쓸 수 있도록owner 충분한 스토리지 변수가 있어야 합니다.
  • timeZone1Library 주소를 setFirstTime(<your contract address>)를 통해 이 계약의 주소로 설정합니다.
  • setFirstTime(<whatever>)를 다시 호출하여 사용자 정의 함수를 실행하십시오.
  • 짜잔! 당신은 소유자입니다.

  • 저자의 메시지를 인용하여 이 수준에서 좋은 시사점을 얻습니다.

    좋은 웹페이지 즐겨찾기