この大会は2022/8/5 22:00(JST)~2022/8/6 22:00(JST)に開催されました。
今回もチームで参戦。結果は700点で733チーム中125位でした。
自分で解けた問題をWriteupとして書いておきます。
Weird Fs (forensics 300)
Autospyで開くと、Flag.zipがあることがわかる。エクスポートして確認すると、パスワードがかかっているので、クラックして展開する。
$ fcrackzip -u -D -p dict/rockyou.txt Flag.zip PASSWORD FOUND!!!!: pw == juelma $ unzip -P juelma Flag.zip Archive: Flag.zip extracting: Flag.txt $ cat Flag.txt ASCWG{M4C_4N6_1$_Co0l}
ASCWG{M4C_4N6_1$_Co0l}
Rsa In The Wild (crypto 100)
RSA暗号。確認してみたところ、JohnとY4mm1のnの公約数、SaraとGaryのnの公約数は1でないため、素因数分解できる。あとは通常通り復号する。
#!/usr/bin/env python3 import json from Crypto.Util.number import * with open('output.json', 'r') as f: json_data = json.load(f) users =['John', 'Sara', 'Y4mm1', 'Gary'] ns = [] cs = [] for i in range(4): ns.append(json_data[i][users[i]]['key']) cs.append(json_data[i][users[i]]['msg']) assert GCD(ns[0], ns[2]) > 1 assert GCD(ns[1], ns[3]) > 1 e = 0x10001 p0 = GCD(ns[0], ns[2]) p1 = GCD(ns[1], ns[3]) ps = [p0, p1, p0, p1] for i in range(4): q = ns[i] // ps[i] assert ps[i] * q == ns[i] assert isPrime(ps[i]) assert isPrime(q) phi = (ps[i] - 1) * (q - 1) d = inverse(e, phi) m = pow(cs[i], d, ns[i]) assert pow(m, e, ns[i]) == cs[i] msg = long_to_bytes(m) print(msg)
実行結果は以下の通り。
b'\x0cX\x08\x0b\xc4)\xcd\xcd\x8f<\xb0]\x87\x03\xcd\xf0\x0e\xac\xbd9\x079\x86$\'ej\xdfl\xa2\xf7\xa8)\x15\xe3\xef3\x9e\xd9\x89\xd9&\x99"\x03[\x83\x12\xb8\x0b\xa9WEm\x9a\x80\'\x9bHB\x03\x12\xb6?\xf5$\xec\x10\xdc\xa8P\x8f\x88\x06\xad"\xe6\xe1\xa5\xb0*\xac\xd3\xf4\x9c\x03\xf9\xd1\xc3\xd6[X\xc2\xb4T\xe0<\xbc\x8cF.5?\x11\x14<\xe8\x9dN\xbd9\xc9\xe0\xf9b\xbd\xbc\x05\x0e\xa1\x9b\xc7~\x94\xcb\xd7\xa2\x04' b"Hello, friend! It's me again. I can cipher things with my mind! ASCWG{7h3_c0mM0n_9re4t_P0W3r_0f_6r0k3N_R$A}" b'a{\x8c\xcb=\xe8\xe5$z\xb2\x08\xa50fz\xc6\x96\x9e\xc8@RP\x18\x01V\x85N\x80\xa7A\x03\xfa\xbbhxw\xa3\xbc\x9d\x85\xcb\x85{"\xa5\xf8-\xf7\xb8\x96\xbc\xcc\x04\xb0\xfa{u:\xa5h\xc2j\xba\x96\x02\x81\xa4\x10\x0c7p\\\xf2\xbc\xa5u\xc5\xf9r\xac/\xe4U\xe3\xcc\xcb\xb7\xe8\xa3\xedO\x91\x89\x15\x9e\x11G9\xff\xea>\xb3\x94\x11\xc4\x9b\xa4eC\x93\x12\xe5[\x15u\xae5\xbb\xe2&\xca!\xf5\xf2\xa3KM' b"\x17\xfe&\x9c.\\e\xb6\x91\xdc7\xcf\xf0UA\x10(\x915}4\x05\x1d\xf23\x17\x0co\x1d\xa5\xccO\t\x89\x98\x12\xe4\x06\xaa\xc2B\xbe#v9\xa5[m\x96\x91\xfe\xef\x1f{\xf3\xd8\x06\x9c\x05\x18zW\x01\xda(\xac3\x8f\xa1\x02\x92F\x96\xe0\xf9\x8c+\xb0\xb2\x9be\x0e1\x97\xd6\xec%\xf8\x16\xf6\xf0\xb3Y\xcb\xeb\xc4\xc8\xa4Y\x0bWy\xff\xc4IDw\\\xa7\x9b\xf5P\xb4\xd9\xdaM\xca\xb4\x9b\x8a\x95'\r\x08\xa9\xe1n%"
ASCWG{7h3_c0mM0n_9re4t_P0W3r_0f_6r0k3N_R$A}
Osp (crypto 300)
kをブルートフォースで暗号化数値から引き算し、32~126でブルートフォースで割り切れ、割った数が素数のものを探す。
#!/usr/bin/env python3 from Crypto.Util.number import * with open('output.txt', 'r') as f: cs = f.read().splitlines() for c in cs: for k in range(256): v = int(c) - k for code in range(32, 127): if v % code == 0: p = v // code if isPrime(p) and p.bit_length() == 256: print(cs.index(c), chr(code))
実行結果は以下の通り。
0 N 0 A★ 1 S★ 1 t 2 A 2 C★ 3 W★ 3 D 4 G★ 4 ? 5 {★ 6 W★ 6 D 6 c 7 h★ 8 4★ 8 / 9 + 9 5 9 B 9 7★ 10 _★ 10 F 10 N 11 1★ 11 @ 11 = 12 f★ 13 _★ 13 F 13 N 14 1★ 14 @ 14 = 15 + 15 5 15 B 15 7★ 15 H 16 '★ 17 s★ 17 a 18 _★ 18 F 18 N 19 N★ 20 0★ 20 E 21 + 21 5 21 B 21 7★ 22 r 22 _★ 23 @★ 23 \ 24 r 24 _★ 25 ` 25 P★ 25 h 26 r★ 26 T 26 ^ 27 1★ 27 @ 27 = 28 K 28 M★ 28 Y 28 m 29 3★ 29 2 30 !★ 31 6 31 -★ 32 f★ 33 0★ 33 E 34 f★ 35 f★ 36 M 36 a★ 37 3★ 38 6★ 38 A 39 D 39 5★ 40 7★ 40 H 40 * 41 e★ 42 }★
候補は複数出るので、フラグとして正しそうな文字を組み合わせる。
ASCWG{Wh47_1f_17's_N07_@_Pr1M3!-f0ffa3657e}