简介
做完前面几个 CTF 想查查是否有未发现的解法,结果查到了 Paradigm CTF 2021
它是今年二月份举办的一场夺旗比赛,共 17 题,为时两天。这里 是大佬们各显神通的最终排名
此次比赛群英荟萃:主要出题人为 samczsun,作为知名白帽于去年加入 Paradigm 任职研究合伙人,暂列 以太坊赏金榜 第二名;另外,排行榜中也有几个熟悉的 ID,比如解出 15 题的冠军队伍 dilicious,其成员 smarx 是 Capture the Ether 的出题人;而在 Capture the Ether 中并列第一的队伍 WHOAMI,此次比赛名列第四,解出 11 题
环境
声明
实际上可以手工部署合约,所以本地环境不是必须,只是无法体验参赛的感觉,少了部分压力
我在网上搜了一圈,没找到比赛环境相关的信息..
因此只能参考赛后放出的环境代码,以下都是推测,且有多处存疑..
欢迎大佬告知,提前谢过了~
环境推测
eth_challenge_base/eth_sandbox/server.py
eth_challenge_base/eth_sandbox/launcher.py
Paradigm CTF 2021 使用 Docker
创建隔离的容器,作为各个队伍的的比赛环境,不至互相影响
为了公平,容器内使用 ganache-cli
克隆主链得到私链,比赛在私链上进行,因此队伍间无法看到他人的解题过程
所有题目都是对应智能合约 Setup.sol
的实例,其构造函数执行出题逻辑,公有函数 function solve() public;
测试题目是否成功解答
一道题目可以有多个 setup contract
实例,每次请求出题都会得到重新克隆的私链,多条私链将会共存,因此队伍内成员间可以同时解题,不会影响
每次请求出题,除了返回 setup contract
之外,还会返回 uuid
,请求通关时需要输入,表示通关哪个实例
ganache-cli
监听在随机端口上,不与外界互通,因此无法将其作为 Web3 Provider
节点提交解题交易
容器启动时会创建代理服务,默认监听在 8545 端口上,与外界互通,参赛者必须将解题交易提交至代理服务,由其转发给私链
代理服务遵循 Ethereum JSON-RPC Specification,只是请求时 header
中必须包括 X-Auth-Key
字段,作为鉴权;它是个随机数,每个容器唯一,其他队伍无法猜出
X-Auth-Key
我来回看了环境代码,还是没确定参赛队伍怎样得到自己的 X-Auth-Key
一种很显然的推论是登陆自己容器查询 /tmp/auth
,但结合后面请求出题时,要求输入的 工作量证明来看,感觉容器无法登陆,否则工作量证明失去意义..
另一种方式,可能是组织者私下分发
赛制推测
是否实时排名
比赛在私链进行,所以比赛过程中,应该没有实时排名,也就无法根据题目通关人数判断难易程度,权衡解题策略
退一步说,即使组织者安排了实时排名,参与者也可以在解答后,暂时不提交通关交易,隐藏自己的解题分布
除非比赛积分计算时,包括消耗时间
积分
每道题有不同的积分,首位通关者应该有额外积分
除了首位通关者,后续答出此题的参赛者,计算积分时是否根据解题次序变化,个人存疑
搭建
了解环境原理后,搭建其实挺简单的,基本参考 官方文档 即可
准备
$ pip3 install solc-select
$ solc-select install 0.4.16 0.4.24 0.5.12 0.6.12 0.7.0 0.7.6 0.8.0
$ pip3 install ecdsa sha3
构建
$ ./build
参与
这里以送分题 HELLO
为例
启动
$ export RPC_URL="https://mainnet.infura.io/v3/7044f2db16e84c559b57b67b565be7ae"
$ ./run hello 31337 31338
[+] running eth challenge
[+] running /startup/00-create-xinetd-service
[+] running /startup/98-start-gunicorn
[+] running /startup/99-start-xinetd
==> /var/log/ctf/gunicorn.access.log <==
==> /var/log/ctf/gunicorn.error.log <==
[2021-08-29 15:14:24 +0000] [14] [INFO] Starting gunicorn 20.0.4
[2021-08-29 15:14:24 +0000] [14] [INFO] Listening at: http://0.0.0.0:31338 (14)
[2021-08-29 15:14:24 +0000] [14] [INFO] Using worker: sync
[2021-08-29 15:14:24 +0000] [17] [INFO] Booting worker with pid: 17
启动前需要配置环境变量 RPC_URL
,作为私链的克隆来源
注意这里必须是主链的 endpoint
,因为题目用到不少主链上的合约地址,如 WETH9
,UniswapV2Pair
等
请求出题
$ nc localhost 31337
1 - launch new instance
2 - get flag
action? 1
hashcash -mb24 bwrsartb = ? 1:24:210830:bwrsartb::lPMmFUGK:66b1dc
your private blockchain has been deployed
it will automatically terminate in 30 minutes
here's some useful information
uuid: 8dc44d42-1b55-49b2-aef9-163a8c5d57cb
rpc endpoint: http://127.0.0.1:31338/8dc44d42-1b55-49b2-aef9-163a8c5d57cb
private key: 0xee958753a7e115323be41435c0fafac5f5f83024107cb06c4f76f40d318776f0
setup contract: 0xD535677b44ffe3e32C64F26bcB191186c182A33f
这里需要输入 bwrsartb
的计算结果作为工作量证明,容器以之提高请求出题的成本,避免泛滥的出题
Hashcash
计算如下
$ python3 eth_challenge_base/eth_sandbox/hashcash.py -mb24 bwrsartb
1:24:210830:bwrsartb::lPMmFUGK:66b1dc
服务器验证通过后,返回如下信息
uuid
: 实例标识,请求通关时要求输入
rpc endpoint
: 代理服务
private key
: 解题账户,balance 为 5000 ETH
setup contract
: 题目实例
一个小坑
返回信息中还包括一个提示 it will automatically terminate in 30 minutes
这是个容易漏过的小坑,后文描述
题外
关于 Hashcash
,可以参考 比特币与密码朋克的延续
请求通关
$ nc localhost 31337
1 - launch new instance
2 - get flag
action? 2
uuid? 8dc44d42-1b55-49b2-aef9-163a8c5d57cb
PCTF{placeholder}
完成题目后,就可以请求通关了,这里需要输入前面的 uuid
验证通关会返回 PCTF{placeholder}
,其中 placeholder
就是一面旗子
网友评论已有0条评论, 我也要评论