【2022Paradigm.ctf】random writeup

介绍

区块链智能合约相关题目,挺有意思,简单分享。

题目在这里插入图片描述

题目内包含两个链接:
https://github.com/paradigmxyz/paradigm-ctf-infrastructure
对应后端服务搭建相关,只看eth-challenge-base目录即可。
random.zip,合约代码内容,也是题目关键,合约代码贴在后面。

实现&分析

nc连接返回三个选项

1 - launch new instance
2 - kill instance
3 - get flag

1:表示启动一个实例,就是具体实现见后端代码,我理解就是部署了智能合约,会返回以下几个参数:
uuid:唯一标示,实例校验使用。
rpc endpoint: 理解为智能合约节点地址,通过该地址可以访问智能合约。
private key: 钱包地址私钥
setup contract: 智能合约的地址。
2:删掉当前实例。
3:返回flag。

返回flag的前提

在这里插入图片描述
前面校验不细讲,关键是这里。
查看具体代码是:

def is_solved_checker(web3: Web3, addr: str) -> bool:
    result = web3.eth.call(
        {
            "to": addr,
            "data": web3.sha3(text="isSolved()")[:4],
        }
    )
    return int(result.hex(), 16) == 1

调用合约Setup.isSolved返回true。

思路

两个合约代码如下:

contract Setup {

    Random public random;

    constructor() {
        random = new Random();
    }

    function isSolved() public view returns (bool) {
        return random.solved();
    }
}
contract Random {

    bool public solved = false;

    function _getRandomNumber() internal pure returns (uint256) {   // chosen by fair dice roll.
        return 4;                                                   // guaranteed to be random.
    }
    
    function solve(uint256 guess) public {
        require(guess == _getRandomNumber());
        solved = true;
    }
}

从代码看,基本就是调用Random.solve(4),即解决问题。

因此实现先获取返回的合约地址拿到当前的Setup实例(个人理解,不一定对)

contract2 = web3.eth.contract(address=contract, abi=config["abi"])

接着获取其中的random对象,也就是Random实例的合约地址,

randomAddress = contract2.functions.random().call()

然后调用random.solve(4)。

contract1 = web3.eth.contract(address=randomAddress, abi=config1["abi"])
result = contract1.functions.solve(4).transact()

这里调用不能像上面一样调用call,是因为带有参数需要调用transact,正常交易还需要往里面填入gas才能发起(个人理解)。

writeup


from socket import *
from web3 import Web3
from eth_utils import *
from eth_typing import *

uuid = "XXXX"
url = "http://34.66.135.107:8545/" + uuid
pkey = "xxxx"
contract = "xxxx"
ticket = "xxxx"
header = {'Content-type':'application/json'}

config = {
    "abi":
[
	{
		"inputs": [],
		"stateMutability": "nonpayable",
		"type": "constructor"
	},
	{
		"inputs": [],
		"name": "isSolved",
		"outputs": [
			{
				"internalType": "bool",
				"name": "",
				"type": "bool"
			}
		],
		"stateMutability": "view",
		"type": "function"
	},
	{
		"inputs": [],
		"name": "random",
		"outputs": [
			{
				"internalType": "contract Random",
				"name": "",
				"type": "address"
			}
		],
		"stateMutability": "view",
		"type": "function"
	}
]
}
config1 = {"abi":[
	{
		"inputs": [
			{
				"internalType": "uint256",
				"name": "guess",
				"type": "uint256"
			}
		],
		"name": "solve",
		"outputs": [],
		"stateMutability": "nonpayable",
		"type": "function"
	},
	{
		"inputs": [],
		"name": "solved",
		"outputs": [
			{
				"internalType": "bool",
				"name": "",
				"type": "bool"
			}
		],
		"stateMutability": "view",
		"type": "function"
	}]
}

web3 = Web3(Web3.HTTPProvider(url))
contract2 = web3.eth.contract(address=contract, abi=config["abi"])
result = contract2.functions.isSolved().call()
print(result)
randomAddress = contract2.functions.random().call()
print(randomAddress)

contract1 = web3.eth.contract(address=randomAddress, abi=config1["abi"])
# result = contract1.functions.solve(4).call()
result = contract1.functions.solve(4).transact()
print(result)
result = contract1.functions.solved().call()
print(result)

总结

一直没有时间学习智能合约这块,通过比赛反而带动学习兴趣,也找到一些学习的方向。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
  

)">
< <上一篇
下一篇>>