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上に存在するため,リークするだけで求めることができる.