この大会は2023/5/14 0:00(JST)~2023/5/15 0:00(JST)に開催されました。
今回もチームで参戦。結果は223点で140チーム中83位でした。
自分で解けた問題をWriteupとして書いておきます。
Recurrent (crypto)
暗号の処理概要は以下の通り。
・p: 2**511以上2**512-1未満のランダム素数 ・F = GF(p) ・a, b, s0, n_a, n_b: 1以上p未満のランダム整数 ・p, a, b, s0を出力 ・A = recurrent(s0, a, b, n_a) ・s = s0 ・以下iが1からn_aまでについて繰り返し実行 ・s = s + a * i + b ・sを返却 ・B = recurrent(s0, a, b, n_b) ・A, Bを出力 ・master_secret = int(recurrent(A, a, b, n_b)) ・key = sha256(master_secret.to_bytes(64, 'big')).digest()[:16] ・iv = sha256(key).digest()[:16] ・flagをパディングして、key, ivを使ってAES-CBC暗号化し、ivの後ろに結合して出力
Aの値はどのように計算されるかを見てみる。
s1 = s0 + a * 1 + b s2 = s1 + a * 2 + b = s0 + a * 1 + b + a * 2 + b = s0 + a * (1 + 2) + b * 2 s3 = s2 + a * 3 + b = s0 + a * (1 + 2 + 3) + b * 3 : sn_a = s0 + a * (1 + 2 + ... + n_a) + b * n_a = A
同様に以下の式になる。
sn_b = s0 + a * (1 + 2 + ... + n_b) + b * n_b = B
以上から以下の式が成り立つ。
master_secret = A + a * (1 + 2 + ... + n_b) + b * n_b = A + B - s0
これでAES暗号(CBCモード)のkey, ivがわかるので、暗号文を復号し、フラグを得る。
#!/usr/bin/env python3 from hashlib import sha256 from Crypto.Cipher import AES from Crypto.Util.Padding import unpad with open('params', 'r') as f: params = f.read().splitlines() p = int(params[0].split(' ')[-1]) s0 = int(params[3].split(' ')[-1]) A = int(params[4].split(' ')[-1]) B = int(params[5].split(' ')[-1]) enc = eval(params[6].split(' ')[-1]) master_secret = (A + B - s0) % p key = sha256(master_secret.to_bytes(64, 'big')).digest()[:16] iv = sha256(key).digest()[:16] ct = enc[16:] assert iv == enc[:16] cipher = AES.new(key, AES.MODE_CBC, iv=iv) flag = unpad(cipher.decrypt(ct), 16).decode() print(flag)
VolgaCTF{y0u_r3_s0_g00d_1_s33_n0w}
Feedback (misc)
アンケートに答えたら、フラグが表示された。
VolgaCTF{c3aa7ef4a5ff6cd9cf0b94e0}