Tokyo Westerns / MMA CTF 2nd 2016: greeting, Interpreter, diary, Candy Store, shadow

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つの値の掛け算により表現する必要があった.

f:id:akiym:20160910003648p:plain

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を変更することができるが,現在の値よりも大きい数を指定すると拒否される.

f:id:akiym:20160910003508p:plain

bhiによる比較ではあるが,そもそもread_int32関数内で呼ばれるatoiはsigned intの正の範囲のみを返すため,任意の値に書き換えることができない.

ストア名に限界の128文字まで指定して,末尾に\0を含めないようにすることで,strcpy時にmax item amountの書き換えができるようになる.

f:id:akiym:20160910003512p:plain

ストアのアイテムは16個以下であることが決めうちされているため,それ以上追加するとストア名が入っているバッファにはみ出る.これを使うことで,アイテムのポインタを任意アドレスに書き換えることができ,リークができる.

orderコマンドにはスタックバッファオーバーフロー脆弱性が存在するが,stack canaryにより防がれている.canaryのリークをする必要がある.なんと,ARM環境ではcanaryの値が.bssセクション上に存在する.すでに任意アドレスリークはできているので,canaryとlibcのアドレスをリークし,system("/bin/sh")を実行すれば終わり.

exploit: Candy Store - Tokyo Westerns / MMA CTF 2nd 2016

作問者によると,これは想定していない解法とのこと.作問者自らwriteupを書くとのことなので期待.

shadow

Host : pwn2.chal.ctf.westerns.tokyo
Port : 18294

shadow

バッファオーバフローと任意アドレスの読み書きができる,明らかな脆弱性があるバイナリ.ただし,独自のmitigationにより関数のcall, retのチェックがされているため,任意のコードに飛ぶことすら難しい.

.bssセクション上にはmitigationで使われているsp, stack_bufのアドレスが存在しているが以下のようなチェックが存在する.

f:id:akiym:20160910012429p:plain

spを書き換えたとしても,gs:0x20に保存された値に上書きされてしまう.stack_bufは正しい範囲に入ってなければいけない.

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

exploit: shadow - Tokyo Westerns / MMA CTF 2nd 2016