1. What?
在区块链中删除代码的唯一方法是该地址的合约执行自毁操作,即 selfdestruct()。
存储在该地址的剩余以太被发送到指定目标,然后从该状态中删除存储和代码。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Example{
constructor(address payable to) payable {
// redirect all the `msg.value` to `to` when selfdestructing
selfdestruct(to);
}
}
如上例所示,这是一个包含着selfdestruct()
函数的简单合约。
constructor
构造器,payable
关键词使得该合约在被创建时就能够接收以太
selfdestruct()
自毁函数,合约在创建之时,就直接自毁,删除代码,并且将合约本身的余额强制发送到to
这个地址上;
说的简单点,自毁函数只有两个核心作用
- 它使合约变为无效,有效地删除该地址的字节码。
- 它把合约的所有资金强制发送到目标地址。
2. Why?
或许你对我上一部分举出的合约例子可能会感到疑惑,为什么不说得简洁一些呢?
那到底为什么要禁用自毁函数呢?
答案就在这个例子中!
这是一个具有攻击性的自毁合约;
刚刚说到,当调用自毁函数之时,合约余额将会被强制发送指定的地址上。
注意强制这一个词,这意味着接收地址合约无论是否拥有接收以太的函数,它都无法拒绝这笔余额打进来。
而这正是自毁函数被禁用的原因:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
//被攻击合约
contract Attacked {
//部署时传入0.08 ether
constructor() payable {}
//获取合约余额
function getBalance() public view returns (uint256 balance) {
balance = address(this).balance;
return balance;
}
//提款函数
function withdraw(uint256 amount) external {
require(address(this).balance > 0.1 ether);
require(amount <= address(this).balance);
payable(msg.sender).transfer(address(this).balance);
}
}
如上例所示:这是一个被攻击的合约
那么问题来了,如何使用上面所学知识,将合约中的0.08 ether
装进自己的钱包?
3. Try !
让我们研究一下此合约
- 无
receive()
、以及任何实现payable
的function,说明合约无法正常接收以太交易; -
withdraw()
是外部函数,并且最关键的限制条件是使合约余额大于0.1 ether;
结论
只要我们能够有办法将0.021个甚至更少的ether打进该合约,让调用withdraw()
函数满足条件,就可以成功赚到0.08个ether。
讲到这里,相信大家已经悟了,摩拳擦掌准备大展身手了!
实战 !
- 被攻击合约本身就有0.08 ether
- 部署攻击合约,传入大于0.02个ether
- 查看合约余额是否大于0.1 ether
- 调用
withdraw()
函数提取合约所有余额,大功告成!
更多区块链技术干货请关注
岚链技术论坛文章来源:https://www.toymoban.com/news/detail-791456.html
77Brother的技术小栈(个人博客)文章来源地址https://www.toymoban.com/news/detail-791456.html
到了这里,关于区块链骇客第二讲: 自毁攻击的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!