快捷搜索: 王者荣耀 脱发

以太Ethernaut靶场打靶—5 Token

概括

本题主要利用智能合约里的整型溢出漏洞来实现攻击; 整型溢出:在 solidity 中,当一个整型变量高于或者低于他所能承受的范围时,就会发生溢出,导致一些不可预期的情况出现。例如,当用户转账金额超过系统预设的最大值时,只要用户金额大于零,用户就可以直接将巨额的代币转走。

要求

获取代币越多越好。

源码审计

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

contract Token {
          
   

  mapping(address => uint) balances;
  uint public totalSupply;

  constructor(uint _initialSupply) public {
          
   
    balances[msg.sender] = totalSupply = _initialSupply;
  }

  function transfer(address _to, uint _value) public returns (bool) {
          
   
    require(balances[msg.sender] - _value >= 0);
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    return true;
  }

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

由于balances[msg.sender]与_value都是uint型所以结果也是uint则balances[msg.sender] - _value >= 0一定是满足>=0的因为可能出现下溢。 这里通过源码可以看到在转载函数transfer里直接用的运算符导致没有对溢出作检测

balances[msg.sender] -= _value;

同时我们的账户里只有20个代币 那就可以通过利用减法溢出转走合约里的代币

function transfer(address _to, uint _value) public returns (bool) {
          
   
    require(balances[msg.sender] - _value >= 0);
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    return true;
  }

攻击流程

首先调用balanceOf可以看到当前账户只有20个代币 然后直接调用transfer函数向合约地址转21个导致溢出看会发生什么情况 此时再查看我的账户里有多少代币 成功,提交实例

经验分享 程序员 微信小程序 职场和发展