CakeCTF 2021 WriteUp
[TOC]
![Scoreboard](https://i.imgur.com/DpGexEM.png)
# 比賽資訊
- 時間: 8/28 ~ 8/29
- 官網: https://2021.cakectf.com/
- 題目: https://github.com/theoremoon/cakectf-2021-public/
# 前言
跟 NCftU 一起參加ㄉ CTF 得到了第五名
maple 大神 carry 了所有的 crypto 跟 web 膜拜 m(_ _)m
來記錄一下我解的幾題題目 主要是 Misc 類的
# WriteUp
## Reverse
### rflag
這題是用 Rust 寫的 會產生一個 32 位的 16 進位數字
可以輸入 4 次 regex 他會回傳符合條件的起始 index 給你
把 0 ~ 15 轉成二進位 然後看每一位的 bit 決定要在哪個 query 送
以下是送的 query 後面是二進位形式
```
[13579bdf] # xxx1
[2367abef] # xx1x
[4567cdef] # x1xx
[89abcdef] # 1xxx
```
這樣只要收集 index 會在哪幾個 query 出現 就能回推原來的數字
script:
```python
from pwn import *
host, port = "misc.cakectf.com", 10023
nc = remote(host, port)
query = [[] for _ in range(4)]
for n in range(16):
for i in range(4):
if (n >> i) & 1 == 1:
query[i].append(f"{n:x}")
result = []
for q in query:
nc.sendlineafter(b": ", f"[{''.join(q)}]".encode())
res = nc.recvline().decode()
result.append(safeeval.expr(res.split(": ")[1]))
ans = [""] * 32
# start from msb
for r in result[::-1]:
for i in range(32):
ans[i] += "1" if i in r else "0"
nc.recvline()
nc.sendline("".join([f"{int(b, 2):x}" for b in ans]).encode())
# "Correct!"
nc.recvline()
print(nc.recvline().decode().split(": ")[1])
```
## Misc
### Telepathy
題目中有個簡單的 go web server 前面有個 nginx 反代
而 nginx.conf 中有個 regex 會驗大括號 符合的話就會被 replace 掉
```
location / {
# I'm getting the flag with telepathy...
proxy_pass http://app:8000/;
# I will send the flag to you by HyperTextTelePathy, instead of HTTP
header_filter_by_lua_block { ngx.header.content_length = nil; }
body_filter_by_lua_block { ngx.arg[1] = ngx.re.gsub(ngx.arg[1], "\\w*\\{.*\\}", "I'm sending the flag to you by telepathy... Got it?\n"); }
}
```
透過 `Range` header 避免掉 `}` 或是去除前面的 `CakeCTF{` 都可以
可以用 `curl -r` 來指定範圍
*p.s. 一看到就覺得似曾相識 ~~被偷[梗][1]啦~~*
## Cheating
### Kingtaker
一個 web 的推箱子遊戲 有數關 通關後會顯示 SUCCESS
所以打開他的 js 跟一下這個字串會在哪裡被用到
之後發現 global 變數有個地方用來儲存此關卡通過沒
手動改就可以通關了
*p.s. 一開始 flag 好像放錯 submit 沒過就沒管他 ~~首殺不見了QQ~~*
### Yoshi-Shogi
**首殺**
又是歡樂 Rust 是個 GUI 將棋遊戲
strings 抓起來看 有個 `http://yoshi-shogi.cakectf.com:15061/ponder` 的 API 位置跟 JSON 的字樣
所以拿 Wireshark 起來抓封包
發現會回傳一個 `{"bestmove": "8a8b"}` 之類的 json 回來 裡面回傳的是起始與終點位置
接著就是試電腦如果輸了會回傳什麼資料
...
我就拿出 iPad 然後找了個夠強的[將棋 APP][2] 跟他打
![ipad shogi](https://i.imgur.com/b4JwQhB.jpg)
![winning shogi](https://imgur.com/CdMHgNK.png)
大概花了 15 分鐘左右
...
發現他輸了之後 會回傳 `{"bestmove": "resign"}`
可以寫個簡單的 server hijack API 傳 resign 給他 就能拿到 flag 了
```javascript
const express = require('express');
const fetch = require('node-fetch');
const app = express();
app.get('*', async (req, res) => {
console.log(req.url)
// let r = await fetch(`http://yoshi-shogi.cakectf.com:15061${req.url}`);
// let d = await r.json();
// console.log(JSON.stringify(d, null, 2));
// res.json(d);
res.json({"bestmove": "resign"});
});
app.listen(15061, () => {
console.log("web server started.");
});
```
![shogi flag](https://imgur.com/uLRRtYi.png)
#### 事後補充
比賽結束後發現 拿 `shogi bestmove ponder` 之類的關鍵字就能查到一個叫[USI](http://hgm.nubati.net/usi.html)的 protocol
裡面就有寫到 resign 這個值了
[1]: https://stackoverflow.com/questions/64916189/after-using-http-substitutions-filter-module-nginx-ignores-range-http-header
[2]: https://apps.apple.com/jp/app/%E3%81%B4%E3%82%88%E5%B0%86%E6%A3%8B/id1104881942
2021-08-31 00:34:49
留言
Last fetch: --:--
現在還沒有留言!