2015年3月18日水曜日

B-Sides Vancouver 2015

最近はbinja|EDでCTFやってたんですが、初心者and学生対象とのことで久しぶりにぼっち参戦しました。

初心者向けあってp(o)wnそこそこ解けました☆(ゝω・)v 以下writeup~

sushi(Ownable100)

教本通りのスタックオーバーフロー。offset計算すら必要無いレベル。やるだけです。
https://gist.github.com/m---/3c12a5c0872043edcc8d

Delphi(Ownable200)

Go言語製のバイナリでした(半ギレ)。
初心者なりにがんばって読んだ限り、標準入力で
> go 引数1 引数2
とか渡すと最終的にlibtwenty.soのcheck_answer関数に渡るみたいです。
で、 引数2 + 0x2a < 4 が真だとsystem("echo 引数1")が実行されるっぽいです。
整数オーバーフロー自明だったので
> go ;cat<flag.txt 9223372036854775770
とかやったらflag出ました。

www(Ownable200)

"www"とかいうタイトルですがweb要素ありませんでした。
ASLR有りですが、sushi同様、No RELRO、No canary、NX disabledで、
ご丁寧にスタックのアドレスまで教えてくれます。

独自のcanaryもどきが実装されていましたが、
自明なスタックオーバーフロー&strcpyが連続して
呼び出されているので、GOT書き換えて終了。
https://gist.github.com/m---/029c8827c12a24506270

Glorious Modern(Ownable350)

初っ端から"Welcome to Glorious Modern C++ 15"と歓迎してくれますが、
結局C++要素が解りませんでした。C++のプロ、教えてください。

CTFにありがちな謎サービスで、とりあえずデータの追加参照機能が備わってます。

pwn初心者なのでeipとれそうな脆弱性は見つけられませんでしたが、
main関数っぽいところで、flag.txtを読んでスタックに配置していました。
がんばってリークすればいいみたいです。方針が自明で"優しさ"を感じますね。

debugを有効にすると各機能で呼び出されている(s)printfの指定子の
数値部分(%こ↑こ↓s)を00~99の範囲で自由に変更できます。

とりあえず、add時のsprintf指定子を99にして適当なデータを追加し、
printを実行するとSEGVが発生しました。

SEGVまでの軌跡を辿ってみると、"Optional note for the new element"で
入力した値の一部がRAXに代入されていることが解りました。


SEGVしないギリギリのところで指定子&入力値を調整したら本来printfで
出力されるはずのアドレスに、入力値の一部が加算されていました。

そのアドレスのすぐ後ろくらいにflagが配置されていたので、
例によって整数オーバーフローで負数が加算されるようにして終了。
https://gist.github.com/m---/149fafa610cce43f90e9

Wild Blue Yonder(Ownable400)

自分でダンジョン?を生成して冒険出来るサービス。

今回はNX Enabledの上にflag.txtを事前に読んでくれる
親切設計ではありませんでした。悲しい。

初回の"By what name shall we know thee? "と
再設定のところで入力サイズが異なっていたので、
スタックオーバーフロー余裕でした。

とりあえず、適当にROPがんばるかーという感じで
めぼしいgadgetを探していたらmmapを発見し、
一応、呼び出し元を確認したらPROT_EXECで
確保してくれていました。"優しさ"を感じますね。

あとは適当にシェルコード配置してそこに飛ばして終了…
と思ったのですが、どうやらnameは0x1f以下の文字は
受け付けてくれないようでした。。。
 80490be: 01 d0                 add    %edx,%eax
 80490c0: 0f b6 00              movzbl (%eax),%eax
 80490c3: 3c 1f                 cmp    $0x1f,%al
 80490c5: 7e 0f                 jle    80490d6 
 80490c7: 8b 55 08              mov    0x8(%ebp),%edx
 80490ca: 8b 45 f4              mov    -0xc(%ebp),%eax

上記mmapの開始アドレスは0x20150000でしたので、
最短でも+0x52020のところにシェルコードを配置する
必要があります。。。が、配置できる範囲は
"How many levels should your dungeon have [1-3]:"
で数値入力し、その値 * 0x1000までという感じでした。
入力数値は0x0もしくは0x3より大きいとダメっぽいです。
 8048bff: 88 45 f3              mov    %al,-0xd(%ebp)
 8048c02: 80 7d f3 00           cmpb   $0x0,-0xd(%ebp)
 8048c06: 74 06                 je     8048c0e 
 8048c08: 80 7d f3 03           cmpb   $0x3,-0xd(%ebp)
 8048c0c: 7e 25                 jle    8048c33 
 8048c0e: 83 ec 0c              sub    $0xc,%esp

はい。そうですね、負数は通りますね。
例によって整数オーバーフローで0xff * 0x1000まで配置出来るようにし、
+0x52020の位置にシェルコード置いて飛ばして無事終了。
https://gist.github.com/m---/dc0b0092f57e8813fb36

Kicker of Elves(Forensics200)

なんかobjdumpすらできない意味不明なelf 32bitを渡されました。
適当にIDAで開いて、適当にコピペして、適当にxorしたらflagになりました。

https://gist.github.com/m---/bed395db35a397664cfc