// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import 'openzeppelin-contracts-06/math/SafeMath.sol';
contract Fallout {
using SafeMath for uint256;
mapping (address => uint) allocations;
address payable public owner;
/* constructor */
function Fal1out() public payable {
owner = msg.sender;
allocations[owner] = msg.value;
}
modifier onlyOwner {
require(
msg.sender == owner,
"caller is not the owner"
);
_;
}
function allocate() public payable {
allocations[msg.sender] = allocations[msg.sender].add(msg.value);
}
function sendAllocation(address payable allocator) public {
require(allocations[allocator] > 0);
allocator.transfer(allocations[allocator]);
}
function collectAllocations() public onlyOwner {
msg.sender.transfer(address(this).balance);
}
function allocatorBalance(address allocator) public view returns (uint) {
return allocations[allocator];
}
}
소스 코드가 주어지고 해당 contract의 owner를 탈취하라는 mission이 있다.
/* constructor */
function Fal1out() public payable {
owner = msg.sender;
allocations[owner] = msg.value;
}
코드를 한번 살펴보면 Fal1out() 함수를 호출하면 owner는 해당 contract를 호출한 사람의 것으로 바뀌고 allocations[owner]는 입력한 값으로 바뀐다....?? Fal1out() ?? 조금 이상하다 constructor이면 Fallout()인데?? 암튼 넘어 가자
function allocate() public payable {
allocations[msg.sender] = allocations[msg.sender].add(msg.value);
}
function sendAllocation(address payable allocator) public {
require(allocations[allocator] > 0);
allocator.transfer(allocations[allocator]);
}
function collectAllocations() public onlyOwner {
msg.sender.transfer(address(this).balance);
}
function allocatorBalance(address allocator) public view returns (uint) {
return allocations[allocator];
}
}
allocate() 함수를 이용하여 allocations[msg.sender]에 ETH를 전송할 수 있다.
sendAllocation() 함수는 allocations[allocator] > 0 이면 allocator에게 해당 금액 만큼 송금한다.
collectAllocations() 함수는 owner만 호출할 수 있는데 msg.sender에게 해당 balance만큼 송금한다.
그리고 allocatorBalance() 함수는 allocations[allocator]의 금액을 return해준다.
이렇게 전체적인 흐름을 보고나니까 contract의 owner를 얻을 수 있는 함수는 Fal1out() 함수밖에 없다.
함수를 호출한 결과 owner를 얻을 것을 확인할 수 있다.
그러자 바로 level을 completed 했다는 msg가 나왔다.
무슨 일이지....??
Ethernaut의 해석을 보니까 실제 Rubixi의 해킹 사례를 가지고 문제를 만들었다.