SECCON Beginners CTF 2020 - writeup
50000年ぶりの記事です。
SECCON Beginners CTF 2020に参加しました。
結果は4問解いて469点、201位でした。
解いた問題
[Pwn]Beginner's Heap
参考
解法
アクセスすると
- ヒープオーバーフローの脆弱性を持つチャンクAがある
- オーバーフローしないチャンクBもallocateしたりfreeしたりできる
__free_hook
のアドレス、win
のアドレスwin
を呼び出すとFLAG出る
の旨が伝えられます。
できることは
- チャンクAへの書き込み
- チャンクBのallocate及び書き込み
- チャンクBをfree
- ヒープを確認する
- tcacheを確認する
- ヒントを確認する
の6つです。2と3は、それが既に行われている場合繰り返し実行することができません。ヒントは進行状況に応じてメッセージが変わり、これを確認しながら進めます。
chunk
: mallocがメモリを管理するときの単位。8ビット境界。
Tcache
: ヒープを管理する技術。fastbinsのような感じらしいが、mallocのときにchunk sizeをチェックしないらしい。
方針
どうにかして
__free_hook
のアドレスにアクセスできるようにする__free_hook
にwin
のアドレスを入れる(__free_hook
は関数ポインタ)free()
を呼び出す (=win
が呼び出される)
といった感じです。
解く
以下不正確な記述である恐れがあります。
チャンクBをallocateののちにfree
これをすると、チャンクBが割り当てられたアドレスがtcacheのリンクリストにつながれます。
チャンクAでヒープオーバーフロー
チャンクAでは、確保されている領域を超えて書き込むことが出来ます。
そこで、チャンクBが割り当てられていたアドレスに__free_hook
のアドレスを書き込むことで、__free_hook
をtcacheのリンクリストに加えます。
このとき、チャンクBのチャンクサイズを、0x21
から0x30
等に変えておきます。チャンクサイズの下位3bitは特殊な使われ方をしている(各種フラグ)ので、全部下げておきます。
チャンクBが割り当てられていたアドレスをリンクリストから外す
チャンクBのallocateは2回繰り返して行うことが出来ないので、一度allocateしてfreeします。
すると、先程チャンクBのチャンクサイズを変えたことでこのアドレスは0x30
のリンクリストに加えられ、晴れて__free_hook
のアドレスがtcacheの先頭に位置します。
winを呼ぶ
いま、チャンクBは__free_hook
のアドレスで確保されるようになったため、__free_hook
にwin
のアドレスを書き込むことが出来ます。
そののちfreeすることでwin
が呼び出され、flagを手に入れることが出来ました。
[Crypto] R&B
処理の際、頭に「R」(rot13でエンコードされた)や「B」(Base64でエンコードされた)が付くのでそれを目安にデコードします。 冒頭の「R」や「B」ごとデコードするとおかしくなるので気を付けましょう。(1敗)
[Reversing] mask
逆アセンブルされたコードを読むと、
0x75
でANDを取ってatd4`qdedtUpetepqeUdaaeUeaqau
と一致する0xeb
でANDを取って`c`bbk`kj`KbababcaKbacaKiack
と一致する
それぞれを満たすような文字列を要求されていることが分かります。総当たりで探すと、flagを手に入れることが出来ました。
解けなかった問題
[Pwn]Beginner's Stack
リターンアドレスを書き換えRSPをそろえ「Conglaturations!」を出し、そしてシェルを制御できませんでした。 大会後Discordで行われた情報交換を見るに、どうやら標準入力も一緒にパイプしてあげるとよかったっぽい。
$ cat ./input - | nc (server_address)
感想
運営並びに作問者の皆様、ありがとうございました。これ解けたら最高に気持ちいいんだろうな~~~~と思う問題が多かったです。 私はBeginner's Heapで気持ち良くなっちゃいました。ヒントにおんぶにだっこ。このままだと一生Beginnersらしいなという危機感が生えた大会でもありました。
楽観的怠惰に起因する破滅をそろそろやめないといけませんね。