如何利用这个简单的智能合约?

问题描述

我一直在尝试很多方法来利用这个用 solidity 为以太坊区块链编写的简单代币合约;但是,我无法成功做到这一点。

pragma solidity ^0.8.2;

contract Simpletoken{

mapping(address => uint) public balances;

function buyToken() payable public {
    balances[msg.sender]+=msg.value / 1 ether;
}

function sendToken(address _recipient,uint _amount) public {
    require(balances[msg.sender]!=0); // You must have some tokens.
    balances[msg.sender]-=_amount;
    balances[_recipient]+=_amount;
    }
}

我已经能够通过将交易发送到 sendToken() 函数来实现这种利用,但我正在尝试编写一个合约作为它的利用代码

这是我尝试过的:

pragma solidity ^0.8.2;

import "./vuln.sol";

contract Exploit {
    
    function buyPoisoned() payable public {
        Simpletoken t = new Simpletoken();
        t.buyToken{gas: 50000,value: 10}();
    }

    function exploit(address recpt,uint amount) public {
        Simpletoken t = new Simpletoken();
        t.sendToken{gas: 50000}(recpt,amount);
    }
}

我也尝试过以前版本的 solidity 编译器(更准确地说是 0.4.2),但我无法成功。

我不知道我缺少什么才能让它发挥作用。

预先感谢您的帮助!

解决方法

由于合约是用 Solidity 0.8 编译的,目前似乎无法利用。

Solidity 0.8 引入了整数下溢/溢出的自动异常,请参阅 docs

我通过 mythril 运行源代码,它也没有发现任何漏洞。


如果它是用 v0.7.6 或更早的版本编译的,它很容易受到 balances[msg.sender]-=_amount; 行上的 integer underflow 的攻击。

例如你有 100 个代币,你想发送 200 个:

它将通过 require() 检查,并从 100(实际余额)中减去 200(发送金额),这将导致整数下溢:

  • msg.sender 将有 2^256 - 101 个标记(因为在整数下溢的情况下,0-1 会导致 2^256-1)
  • _recipient 将有 200 个代币(发送的数量)