Skip to content

The Ethernaut writeups: 17 - Recovery

Posted on:July 23, 2018

Update 2022 Feb: Do level 17 Locked trước đây đã bị bỏ đi, giờ đây Recovery trở thành level 17 chứ không phải 18 như trước.

17 Recovery

Nhiệm vụ: tác giả đã tạo ra contract Recovery đóng vai trò như một token factory để có thể dễ dàng tạo ra những đồng tiền ảo mới. Thật không may khi tạo ra đồng tiền ảo đầu tiên và gửi vào đó 0.5 ether để mua token, ông đã quên mất địa chỉ của token contract này. Nhiệm vụ của chúng ta là phải tìm ra địa chỉ của token contract đó và lấy lại 0.5 ether.

// 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);
  }
}

Phân tích & Solution

Để tìm xem tác giả đã gửi tiền vào địa chỉ nào, rất đơn giản, ta paste địa chỉ contract lên trên https://rinkeby.etherscan.io, trong trường hợp của mình là https://rinkeby.etherscan.io/address/0x9998be07d49f52d93d98ebf78c7526d712246bf3#internaltx.

Sau đó tìm tới phần internal Txns, ta thấy ngay transaction tạo ra token contract.

png

Nhấn vào Contract Creation, ta thấy ngay được địa chỉ của token contract với 0.5 ether trong đó, trong trường hợp của mình là 0x417e544648E583Dc15004e86Ef94E1D79a068BFc.

png

Tiếp theo, tiến hành load SimpleToken với địa chỉ 0x417e544648E583Dc15004e86Ef94E1D79a068BFc trên Remix IDE.

png

Trong contract Simple Token có hàm destroy:

function destroy(address _to) public {
  selfdestruct(_to);
}

Trong solidity, khi ta gọi selfdestruct(_to) trong một contract, thì contract đó sẽ bị huỷ và chuyển toàn bộ tiền về cho địa chỉ _to.

Do đó ta sẽ tiến hành destroy contract 0x417e544648E583Dc15004e86Ef94E1D79a068BFc, địa chỉ nhận là địa account của mình, để lấy lại 0.5 ether.

png

Quay trở lại địa chỉ của token contract trên etherscan.io, ta thấy balance của contract đã trở về 0, nghĩa là ta đã thành công.

png

Submit && all done!

completed

Bình luận

Enjoy coding!