Beginners CTF 2019 - writeup
この記事は投稿から 3 年以上経過しています。
最新の情報は各種公式ドキュメント等をご覧下さい。
SECCON 主催の Beginners CTF 2019 に参加して、2問ほど解けたのでその解法を残しておこうと思います。二問とも Misc です。
containers
1つのバイナリファイルから Flag を抜き出す問題。
運営から tar.gz
のファイルをいただけたのでとりあえずそれを解凍して cat
で中身を見る。と、なんか色々化けた文字が大量に出てきて最後に Python のコードが確認。file
で確認すると application/octet-stream; charset=binary
。cat
の結果を眺めていたら .PNG
という文字が何回か目に入ったので複数の PNG ファイルがあることを察知。でも正直ここからどうすればいいかわからなかった。
調べてみると、バイナリファイルを調査して埋め込まれているファイルを調査してくれるコマンドがあるらしいのでそれを実行。binwalk
と foremost
を触ってみた。最初 binwalk
の結果を見て39個もの PNG があることを確認。この時点で Zlib で圧縮されたものだとわかったんで、そのまま解凍すればよかったんだけどその時の僕は foremost
を実行。foremost
はどうやら中に入ってるファイルを吐き出してくれるらしく、それを把握していなかった僕は ls
を打って output
ディレクトリを見つけたときにびっくりした。その中にはご丁寧に 1文字/ファイル で Flag があった。
後記: 前から CTF 自体は興味があって、1つのバイナリファイルに複数のファイルが埋め込まれている問題がよくあるということ自体は把握していたのでわりとすんなりいけた。xxd
、binwalk
、foremost
をはじめて触った。
Dump
こちらは運営から渡される TCP Dump を解析して Flag を見つける問題。
TCP Dump 自体はじめて触るので、わりとチャレンジングな選択をしたと思ってる。とりあえず TCP Dump の中身を見たいので WireShark をインストール。開いてみると4つほど HTTP 通信のログがあったので中を見てみる。
どうやら PHP 製の WebShell とやらを叩いているところらしい。最初のリクエストで Flag がディレクトリ下にあることを確認し、2つ目のリクエストでそのダンプを取得しているっぽい。レスポンスを見てみると hexdump
で吐き出された結果が表示されていた。最初はこれを xxd
で読み込ませてさっきと一緒のように解析すればいっかと思ってたがどうもそんなに単純ではない模様。いくら xxd
でレスポンスの内容を読み込んでも次へのステップに行く内容が一切見つからない。これは知見不足かと半ば諦めながら見直してみるとレスポンスが 8進数ダンプ ということがわかった。 xxd -r
で読み込むときは 16進数ダンプ じゃないといけない。8進数ダンプを16進数ダンプに変換できないかと調べてみたが見つからない。仕方がないので慣れない Python で 8進数 -> 16進数 にするコードを書いた。それが以下。
line = ''
read_line = ''
print('Start convert')
print('----------------------')
with open('flag_dump', 'r') as f:
read_line = f.readline()
while read_line:
print(read_line.split())
print('Length:', len(read_line.split()))
for value in read_line.split():
print('Converted one value')
line = line + hex(int(f'0o{value}', 0))[2:].zfill(2) + ' '
line += '\n'
read_line = f.readline()
print('Converted one line')
f.close()
print(line)
with open('flag_dump_hex', 'w') as f2:
f2.write(line)
f2.close()
print('Finish!')
競技中に書いたコードを無修正で載せている。ひどすぎる…。もともと Python は食わず嫌いだったのだが、彼女の得意言語ということでここ1か月ほど勉強していた。まさかここで役に立つとは思わなかった。
これを実行して xxd -r
で読み込んでみるとちゃんといい感じの結果を得られた。調べてみると gzip なファイルだったので解答すると jpeg が1枚。そこに Flag が書いてあった。画像で Flag を保存するのはいいのですがせめて画質ももう少し下げておいてほしかった、可読性を考慮してのことなんかな?(3MB ほどあった。)
Flag に「hexdump はめっちゃ便利や!」みたいなことが書いてあって、確かにとなった。どうやらこうやってバイナリファイルを調査することを (Computer)Forensics と呼ぶらしい。結構やってて楽しかった。
後記: Python のコードがひどすぎる。いくら即席とはいえもっとマシなコードを組めるようになりたい。あとダンプが大きいので WireShark で開こうと試みたらすぐ固まった。 CLI でやるともっと手軽にできたのか?
チャレンジしたけど無理だった問題
ほかにも Flag 取得には至らなかったけどチャレンジして色々学んだという問題をいくつか挙げておきます。
[warmup]Seccompare
運営から配られたバイナリファイルを確認してみると ELF 実行ファイルでした。それを objdump
で逆アセンブルして Flag を見つけようって感じです。そもそも C や アセンブラ に関してほとんど知見がなかったので、20分ほどチャレンジしてほかのチームメイトに託しました。とりあえずやってみて素人ながらもチームメモにわかったことを書いていくのは大事かなと思いました。
Go RSA
RSA で暗号化された Flag を渡されるので解読しようというもの。特徴としては生成毎に N が変わることと、暗号文と共に D(N とともに秘密鍵とされるやつ)が送られることです。Wikipedia を見てみると 「同一平文」という項目 があったのでこれかと思って色々試したのですがなかなかうまくいきませんでした。N が素数であることと中国の余剰定理を利用してなんとかしてみたんですが、いい感じの値が出ない。当然 E は決まってないので、3
、17
、65537
あたりを使ってみたのですが Flag は出ず…。誰かが writeup を出してくださるのを待ちます。
初 CTF を終えて
めちゃくちゃ楽しかったです。今回たまたま直前に @stmkza が 学生 LT の Discord 鯖で声掛けしてたので軽い気持ちで参加してみました。CTF といえばガチプロな方が超スーパースキルを駆使して死闘を繰り広げるみたいなイメージがありましたが、今回はチームメイトとお互い励まし合いながらマイペースに和気あいあいと解くことができました。成績的にも2問も解けましたし、stmkza 氏やチームメンバーののおかげでチーム順位40位と非常に良い CTF デビュー戦だったと思います。まったくの初心者でもググりながらやるとなんとか解けるのだなとわかったので、これからも積極的に参加していこうと思います。もし CTF に興味あるけど全然始められないって方いらっしゃったらぜひ僕(@OJI_1941)を誘ってください。一緒にがんばりましょう!