blockchain靶场练习记录

题目地址 https://blockchain-ctf.securityinnovation.com

玩玩区块链练练手

前期准备:

关于remix ide的搭建方式,我只能说docker yyds

图片[1]-blockchain靶场练习记录-魔法少女雪殇


docker pull remixproject/remix-ide

docker run -p 80:80 remixproject/remix-ide

润起来就行了

0x1.Donation

签到题了算是,给的代码仍在ide里面,不过他的代码中import了一个safemath.sol,百度下载就行

safemath.sol

pragma solidity >=0.4.22 <0.6.0;
 
/**
 * @title SafeMath
 * @dev Unsigned math operations with safety checks that revert on error
 */
 
library SafeMath {
    /**
     * @dev Multiplies two unsigned integers, reverts on overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }
 
        uint256 c = a * b;
        require(c / a == b);
 
        return c;
    }
 
    /**
     * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
 
        return c;
    }
 
    /**
     * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;
 
        return c;
    }
 
    /**
     * @dev Adds two unsigned integers, reverts on overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);
 
        return c;
    }
 
    /**
     * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
     * reverts when dividing by zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}

题目代码

pragma solidity 0.4.24;

import "../CtfFramework.sol";
import "../../node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol";

contract Donation is CtfFramework{

    using SafeMath for uint256;

    uint256 public funds;

    constructor(address _ctfLauncher, address _player) public payable
        CtfFramework(_ctfLauncher, _player)
    {
        funds = funds.add(msg.value);
    }

    function() external payable ctf{
        funds = funds.add(msg.value);
    }

    function withdrawDonationsFromTheSuckersWhoFellForIt() external ctf{
        msg.sender.transfer(funds);
        funds = 0;
    }

}

直接跑起来调用withdrawDonationsFromTheSuckersWhoFellForIt,填入自己的合约地址就可以了。

0x2.Lock Box

pragma solidity 0.4.24;

import "../CtfFramework.sol";

contract Lockbox1 is CtfFramework{

    uint256 private pin;

    constructor(address _ctfLauncher, address _player) public payable
        CtfFramework(_ctfLauncher, _player)
    {
        pin = now%10000;
    }
    
    function unlock(uint256 _pin) external ctf{
        require(pin == _pin, "Incorrect PIN");
        msg.sender.transfer(address(this).balance);
    }

}

now的意思是获取当前时间戳,然后unlock这里还需要获取pin值,pin作为private的变量,无法被外部call,所以可以使用getStorageAt来获取值,这里pin的话是因为framework它有个mapping占了一位,所以是1

代码:web3.eth.getStorageAt(‘题目地址’, 1, console.log);

图片[2]-blockchain靶场练习记录-魔法少女雪殇
获得pin的地址,ide处直接编译输入自己的合约和这个pin值就成功了
图片[3]-blockchain靶场练习记录-魔法少女雪殇
图片[4]-blockchain靶场练习记录-魔法少女雪殇

0x3 Piggy bank

代码:

pragma solidity 0.4.24;

import "../CtfFramework.sol";
import "..//SafeMath.sol";

contract PiggyBank is CtfFramework{

    using SafeMath for uint256;

    uint256 public piggyBalance;
    string public name;
    address public owner;
    
    constructor(address _ctfLauncher, address _player, string _name) public payable
        CtfFramework(_ctfLauncher, _player)
    {
        name=_name;
        owner=msg.sender;
        piggyBalance=piggyBalance.add(msg.value);
    }
    
    function() external payable ctf{
        piggyBalance=piggyBalance.add(msg.value);
    }

    
    modifier onlyOwner(){
        require(msg.sender == owner, "Unauthorized: Not Owner");
        _;
    }

    function withdraw(uint256 amount) internal{
        piggyBalance = piggyBalance.sub(amount);
        msg.sender.transfer(amount);
    }

    function collectFunds(uint256 amount) public onlyOwner ctf{
        require(amount<=piggyBalance, "Insufficient Funds in Contract");
        withdraw(amount);
    }
    
}


contract CharliesPiggyBank is PiggyBank{
    
    uint256 public withdrawlCount;
    
    constructor(address _ctfLauncher, address _player) public payable
        PiggyBank(_ctfLauncher, _player, "Charlie") 
    {
        withdrawlCount = 0;
    }
    
    function collectFunds(uint256 amount) public ctf{
        require(amount<=piggyBalance, "Insufficient Funds in Contract");
        withdrawlCount = withdrawlCount.add(1);
        withdraw(amount);
    }
    
}

参考文章:https://www.anquanke.com/post/id/168037

漏洞点是spolidity的继承,进行分析,在charliesPiggybank与piggybank中都有collectfunds函数,但是

图片[5]-blockchain靶场练习记录-魔法少女雪殇

piggybank中只有owner能调用,而前者是继承自piggy板块,那么就把自己的collectfunds的函数覆盖了piggybank中的函数,所以只需要调用合约中的collectfund函数即可解决

图片[6]-blockchain靶场练习记录-魔法少女雪殇
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情