この大会は2021/2/20 19:30(JST)~2021/2/21 19:30(JST)に開催されました。
今回もチームで参戦。結果は1467点で663チーム中134位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity Check (Misc)
問題にフラグが書いてあった。
darkCON{free_Fl4g_4_every0ne_G00d_Luck}
Take It Easy (Crypto)
添付のzipファイルにはgetkey.txtとパスワード付きzipが入っている。getkey.txtにはこう書いてある。
p = 147310848610710067833452759772211595299756697892124273309283511558003008852730467644332450478086759935097628336530735607168904129699752266056721879451840506481443745340509935333411835837548485362030793140972434873394072578851922470507387225635362369992377666988296887264210876834248525673247346510754984183551 ct = 43472086389850415096247084780348896011812363316852707174406536413629129 e = 3
RSA暗号として、復号してみる。
from Crypto.Util.number import * p = 147310848610710067833452759772211595299756697892124273309283511558003008852730467644332450478086759935097628336530735607168904129699752266056721879451840506481443745340509935333411835837548485362030793140972434873394072578851922470507387225635362369992377666988296887264210876834248525673247346510754984183551 ct = 43472086389850415096247084780348896011812363316852707174406536413629129 e = 3 phi = p - 1 d = inverse(e, phi) m = pow(ct, d, p) pw = long_to_bytes(m) print pw
RSA暗号を復号した結果は以下の通り。
Ju5t_@_K3Y
これでパスワード付きzipを解凍すると、chall.pyとcipher.txtが展開された。この暗号処理の概要は以下の通り。
・chunks: フラグを4バイトブロックに分割 ・2ブロック先とのXORを出している。
"darkCON{"から始まることを前提に復号する。
#!/usr/bin/env python3 from struct import pack, unpack def Tup_Int(chunk): return unpack('I', chunk)[0] ct = [b'\nQ&4', b"\x17'\x0e\x0f", b'1X5\r', b'072E', b'\x18\x00\x15/'] flag = b'darkCON{' for i in range(5): block = pack("I", Tup_Int(flag[i*4:i*4+4]) ^ Tup_Int(ct[i])) flag += block print(flag)
darkCON{n0T_Th@t_haRd_r1Ght}
Tony And James (Crypto)
暗号化処理は以下の通り。
・l: フラグの長さ ・raw, seed = get_seed(l) ・rand: lビットランダム整数 ・以下、randが0より大きい場合に繰り返し実行 ・rand: 1ビット右にシフト ・seed: randをプラス ・rawのリストにrandを追加 ・rawとseedを返却 ・random.seed(seed) ・以下フラグの各文字に対して実行 ・r: 1~2**512のランダム整数 ・i=0の場合のみ、rを表示 ・encoded = hex(r ^ m[i] ^ raw[i])[2:] ⇒表示
r0はわかている。フラグが"darkCON{"で始まることからm[0]はわかる。r0、m[0]とF0からraw[0]を算出でき、rand(末尾1ビットは動作に関係ない)はraw[0]から左シフトすればよい。そこまで絞れば、seedを算出でき、各フラグに対するrを計算でき、フラグを求めることができる。
#!/usr/bin/env python3 import random def get_seed(r): seed = 0 rand = r raw = list() while rand > 0: rand = rand >> 1 seed += rand raw.append(rand) return raw, seed r0 = 1251602129774106047963344349716052246200810608622833524786816688818258541877890956410282953590226589114551287285264273581561051261152783001366229253687592 pre_flag = b'darkCON{' with open('encrypted.txt', 'r') as f: encs = [line.rstrip().split(' ')[-1] for line in f.readlines()] raw0 = r0 ^ pre_flag[0] ^ int(encs[0], 16) rand = raw0 << 1 raw, seed = get_seed(rand) random.seed(seed) flag = '' for i in range(len(encs)): r = random.randint(1, 2**512) m = r ^ raw[i] ^ int(encs[i], 16) flag += chr(m) print(flag)
darkCON{user_W4rm4ch1ne68_pass_W4RM4CH1N3R0X_t0ny_h4cked_4g41n!}
Rookie's_Choice_4_you (Crypto)
RC4で同じKEYでの平文、暗号文のペアが複数あり、フラグより長い暗号文があるので、XORで復号できる。
from Crypto.Util.strxor import strxor pt = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' ct = '3d5d841c4df203758189060d7ba5ef0460c90faeae890dc621dfb563a03cc5f728d42794ae8a08102f2766acece427f3c6514fc7'.decode('hex') enc_flag = '385e95136bdb2a66baa0593e27b8df03228f1785ea9925c768d08b74b06bffe27bd17da1aed51c21342026bdacb173f8'.decode('hex') key = strxor(pt, ct) flag = strxor(enc_flag, key[:len(enc_flag)]) print flag
darkCON{RC4_1s_w34k_1f_y0u_us3_s4m3_k3y_tw1c3!!}