CTF-OwnerBuy

题目源码有很多文件。就看一个最关键的

// 0.5.1-c8a2
// Enable optimization
pragma solidity ^0.5.0;
import "./contracts/ERC20.sol";
import "./contracts/IERC20.sol";
import "./contracts/ERC20Detailed.sol";

interface Changing {
function isOwner(address) external returns (bool);
}

contract Ownable {
address public _owner;
address public _previousOwner;

event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);

/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() internal {
address msgSender = msg.sender;
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}

/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}

/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == msg.sender, "Ownable: caller is not the owner");
_;
}

/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}

/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(
newOwner != address(0),
"Ownable: new owner is the zero address"
);

emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}

//Locks the contract for owner for the amount of time provided
function lock() public onlyOwner {
_previousOwner = _owner;
_owner = address(0);
emit OwnershipTransferred(_owner, address(0));
}

//Unlocks the contract for owner when _lockTime is exceeds
function unlock() external payable {
require(msg.value >= 1 ether);
emit OwnershipTransferred(_owner, _previousOwner);
_owner = _previousOwner;
}
}

contract OwnerBuy is Ownable, ERC20, ERC20Detailed {
mapping(address => bool) public status;
mapping(address => uint256) public Times;
mapping(address => bool) internal whiteList;
uint256 MAXHOLD = 100;

event finished(bool);

constructor() public ERC20Detailed("DEMO", "DEMO", 18) {}

// 查看是否位于白名单中
function isWhite(address addr) public view returns (bool) {
return whiteList[addr];
}

// 只有owner才能设置白名单
function setWhite(address addr) external onlyOwner returns (bool) {
whiteList[addr] = true;
return true;
}

// 只有owner才能设置白名单
function unsetWhite(address addr) external onlyOwner returns (bool) {
whiteList[addr] = false;
return true;
}

// 转账
function _transfer(address sender, address recipient, uint256 amount) internal {
_balances[sender] = _balances[sender].sub(amount);
_balances[recipient] = _balances[recipient].add(amount);
// 如果接收者不是白名单的用户,那么该用户最多拥有金额MAXHOLD
if (!isWhite(recipient)) {
require(_balances[recipient] <= MAXHOLD, "hold overflow");
}
emit Transfer(sender, recipient, amount);
}

// 如果调用者是合约,则它可以设置自己的状态
function changestatus(address _owner) public {
Changing tmp = Changing(msg.sender);
if (!tmp.isOwner(_owner)) {
status[msg.sender] = tmp.isOwner(_owner);
}
}

// 更改owner
function changeOwner() public {
// 需要用合约
require(tx.origin != msg.sender);
// 调用者地址的低2字节为ffff
require(uint(msg.sender) & 0xffff == 0xffff);
// 需要合约已经设置状态为true
if (status[msg.sender] == true) {
status[msg.sender] = false;
_owner = msg.sender;
}
}

// 购买
function buy() public payable returns (bool success) {
//只有_owner为 0x220866B1A2219f40e72f5c628B65D54268cA3A9D 才能调用
require(_owner == 0x220866B1A2219f40e72f5c628B65D54268cA3A9D);
// 要用合约买
require(tx.origin != msg.sender);
require(Times[msg.sender] == 0);
// msg.sender没钱
require(_balances[msg.sender] == 0);
// 要发1 wei
require(msg.value == 1 wei);
// 得到100
_balances[msg.sender] = 100;
// 记录
Times[msg.sender] = 1;
return true;
}

// 很明显的重入
function sell(uint256 _amount) public returns (bool success) {
// 至少卖200
require(_amount >= 200);
// 调用者地址的低2字节为ffff
require(uint(msg.sender) & 0xffff == 0xffff);
// 必须调用buy之后
require(Times[msg.sender] > 0);
// 足够的余额
require(_balances[msg.sender] >= _amount);
// 足够的余额
require(address(this).balance >= _amount);
msg.sender.call.gas(1000000)("");
_transfer(msg.sender, address(this), _amount); // 这个有安全库保护,因此余额无法下溢
Times[msg.sender] -= 1; // 这个可以下溢
return true;
}

// 任务是Times至少100
function finish() public onlyOwner returns (bool) {
require(Times[msg.sender] >= 100);
Times[msg.sender] = 0;
msg.sender.transfer(address(this).balance);
emit finished(true);
return true;
}
}

从finish() 函数可以看见要求,