greeting
Host : pwn2.chal.ctf.westerns.tokyo Port : 16317 greeting Note: DoS攻撃に対する対策の為,出力が131072文字に制限されています.
main関数のみのシンプルなバイナリ.FSBがあるが,その後すぐにreturnするため1度しか実行できないように見える.FSBによる攻擊の流れは以下の通り.
- stack上のreturn addressの位置をリーク
- 必要であればlibcのアドレスリーク(今回はsystemがpltに存在するので不要)
- stackを書き換えて
system("/bin/sh")を実行
今回の場合は,.fini_arrayをmain関数のアドレスに書き換えることで再度mainを呼ぶことができるようになり,上記の攻擊が可能となる.
入力文字列をsprintfに投げてからFSBが発生するため,最初に20文字文字が書き込まれている.libformatstrを使う場合はstart_lenを指定する必要があることに注意.
最後にsystem("/bin/sh")を実行するにあたって,"/bin/sh"をアドレス上に配置,または取得するのが面倒なときがある.このようなときには"sh\0"や"ed\0"を探すと良い.
今回の問題バイナリでは.dyn_str上に"_IO_stdin_used\0"が存在したので,それを利用した.シェルを起動するときには,ed上で!shを入力するとshが起動できる.
exploit: greeting - Tokyo Westerns / MMA CTF 2nd 2016
Interpreter
$ nc pwn1.chal.ctf.westerns.tokyo 62839 befunge.7z
befungeというプログラミング言語のインタプリタ.befungeでは,g, p命令を使うことで,プログラム上のメモリの読み書きができる.
ただし,Full RELROなので,GOTを書き換えて任意アドレスに飛ぶということができない.
GOTに書き込みはできないがリークはできるので,libcのベースアドレスをリークする.libc内に存在する__libc_argvからスタック上にあるargvのアドレスを取得し,mainのリターンアドレスを書き換えることにより,shellを起動した.
&はscanf("%d", number)より数値を入力してその値をスタックpushする.スタックのpush時には,movsxdにより64bit長のレジスタに符号拡張されるため,signed intの範囲よりも大きい数値を入力したい場合は2つの値の掛け算により表現する必要があった.

exploit: Interpreter - Tokyo Westerns / MMA CTF 2nd 2016
diary
Host : pwn1.chal.ctf.westerns.tokyo Port : 13856 もし必要であるなら,./bash が使えます. diary
独自mallocにより管理される.確保される領域はrwxであるため,おそらくheap上に飛んでshellcode実行させる問題だろうと思われる.
getnlineにはoff by oneの脆弱性がある.これにより,独自mallocで管理されるchunkのサイズを書き換えることができる.これを利用することでchunkがfree済みかどうかの状態を自分で指定でき,free済みchunkのlinked listの状態を書き換えることができるようになる.
あとは,unlink attackによりGOTを書き換えheap上のshellcodeに飛ばす.
この問題ではseccomp mode 2により実行できるsyscallが制限されている.
bpf filterのdisassembleにはlibseccompに付属しているscmp_bpf_disamを使う.ただしsyscall番号をそのまま表示してしまうので読みにくい.拙作のdisas-seccomp-filter akitools/disas-seccomp-filter at master · akiym/akitools · GitHub を使うと読みやすいようにしてくれる.
line OP JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000000 ld seccomp_data.nr 0001: 0x15 0x00 0x01 0x00000002 jeq SYS_open true:0002 false:0003 0002: 0x06 0x00 0x00 0x00000000 ret KILL 0003: 0x15 0x00 0x01 0x00000101 jeq SYS_openat true:0004 false:0005 0004: 0x06 0x00 0x00 0x00000000 ret KILL 0005: 0x15 0x00 0x01 0x0000003b jeq SYS_execve true:0006 false:0007 0006: 0x06 0x00 0x00 0x00000000 ret KILL 0007: 0x15 0x00 0x01 0x00000038 jeq SYS_clone true:0008 false:0009 0008: 0x06 0x00 0x00 0x00000000 ret KILL 0009: 0x15 0x00 0x01 0x00000039 jeq SYS_fork true:0010 false:0011 0010: 0x06 0x00 0x00 0x00000000 ret KILL 0011: 0x15 0x00 0x01 0x0000003a jeq SYS_vfork true:0012 false:0013 0012: 0x06 0x00 0x00 0x00000000 ret KILL 0013: 0x15 0x00 0x01 0x00000055 jeq SYS_creat true:0014 false:0015 0014: 0x06 0x00 0x00 0x00000000 ret KILL 0015: 0x15 0x00 0x01 0x00000142 jeq 0x142 true:0016 false:0017 0016: 0x06 0x00 0x00 0x00000000 ret KILL 0017: 0x06 0x00 0x00 0x7fff0000 ret ALLOW
特定のsyscallのみを拒否するブラックリスト方式による制限を行っている.アーキテクチャチェックとsyscall番号の上限チェックが行われていない.今回はsyscall番号の上限チェック不備によるx32 syscallを呼ぶようにした.
exploit: diary - Tokyo Westerns / MMA CTF 2nd 2016
Candy Store
Host : candystore1.chal.ctf.westerns.tokyo Port : 11111 Do you want something sweet...? candystore -- 更新1: flagは「/home/candystore/flag」にあります. また, このバイナリは最新のRaspbian上で動作しています.
この問題はコンテスト終了後に解いた.ARMのバイナリ.動作やデバッグはQEMUのarmhf環境上で行った.
adminモードにてストア名の書き換え,アイテムの追加や削除ができる.ただし,admin(パスワードはランダム)でなければいけない.
profileの入力時にadmin flagの書き換えが発生するため,パスワードを知らなくてもadminモードに移行できる.
adminモードではmax item amountを変更することができるが,現在の値よりも大きい数を指定すると拒否される.

bhiによる比較ではあるが,そもそもread_int32関数内で呼ばれるatoiはsigned intの正の範囲のみを返すため,任意の値に書き換えることができない.
ストア名に限界の128文字まで指定して,末尾に\0を含めないようにすることで,strcpy時にmax item amountの書き換えができるようになる.

ストアのアイテムは16個以下であることが決めうちされているため,それ以上追加するとストア名が入っているバッファにはみ出る.これを使うことで,アイテムのポインタを任意アドレスに書き換えることができ,リークができる.
orderコマンドにはスタックバッファオーバーフローの脆弱性が存在するが,stack canaryにより防がれている.canaryのリークをする必要がある.なんと,ARM環境ではcanaryの値が.bssセクション上に存在する.すでに任意アドレスリークはできているので,canaryとlibcのアドレスをリークし,system("/bin/sh")を実行すれば終わり.
exploit: Candy Store - Tokyo Westerns / MMA CTF 2nd 2016
作問者によると,これは想定していない解法とのこと.作問者自らwriteupを書くとのことなので期待.
https://twitter.com/hhc0null/status/773309856417652736
shadow
Host : pwn2.chal.ctf.westerns.tokyo Port : 18294 shadow
バッファオーバフローと任意アドレスの読み書きができる,明らかな脆弱性があるバイナリ.ただし,独自のmitigationにより関数のcall, retのチェックがされているため,任意のコードに飛ぶことすら難しい.
.bssセクション上にはmitigationで使われているsp, stack_bufのアドレスが存在しているが以下のようなチェックが存在する.

spを書き換えたとしても,gs:0x20に保存された値に上書きされてしまう.stack_bufは正しい範囲に入ってなければいけない.
gs:0x20はTLS上に配置されているため,TLSのアドレスを求めてgs:0x20を丸ごと書き換えてしまえばmitigation自体のstackを置き換えて任意の関数を呼ぶことができるようになる.
TLSのアドレスはstack上に存在するため,リークするだけで求めることができる.