この大会は2024/2/24 21:00(JST)~2024/2/26 9:00(JST)に開催されました。
今回もチームで参戦。結果は201点で294チーム中113位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome (Misc)
Discordに入り、各チャネルを見るが、フラグは見当たらない。
#announcementsチャネルのCTF開始のメッセージあたりがあやしい。以下のように書いてあるが、文字が隠されているのかもしれない。
"Welcome" to the game https://ctf.bi0s.in/
Sakuraエディタにコピーする。
"Welcome" to the game https://bi0sctf%7Bh1dd3n_1n_pl41n_s1ght%7D:hehe@ctf.bi0s.in/
フラグが含まれていた。
bi0sctf{h1dd3n_1n_pl41n_s1ght}
lalala (Cryptography)
unknowsまで割り出すことができれば、下3桁がフラグの{}の中の各文字のASCIIコードになるので、フラグを割り出せる。
unknowsを割り出す方法を考える必要がある。
100種類の以下の値がわかっている。
aa(0~2**1024のリスト), bb(0~9のリスト), cc(0~9のリスト), sum([a + unknowns[b]^2 * unknowns[c]^3 for a, b, c in zip(aa, bb, cc)]) % p
aaの合計値は分かっているので、以下のような値の合計値がわかっていることになる。
x00 * unknowns[0]^2 * unknowns[0]^3 + x01 * unknowns[0]^2 * unknowns[1]^3 + ... + x99 * unknowns[9]^2 * unknowns[9]^3
x00~x99の値がわかるので、100元方程式として各(unknowns[b]^2 * unknowns[c]^3) % pの値を算出できる。各iについて、以下の式が導ける
pow(unknowns[i], 5, p) = Ci
unknowns[i]の5乗がpに届かないと推測し、5乗根を求めることによってunknowns[i]を算出する。
#!/usr/bin/env sage with open('out.py', 'r') as f: params = f.read().splitlines() p = int(params[0].split(' = ')[1]) output = eval(params[1].split(' = ')[1]) rows = [] C = [] for i in range(0, len(output), 4): aa = output[i] bb = output[i + 1] cc = output[i + 2] S = output[i + 3] C.append([(S - sum(aa)) % p]) row = [0] * 100 for j in range(1000): index = bb[j] * 10 + cc[j] row[index] += 1 rows.append(row) M = matrix(Zmod(p), rows) C = matrix(Zmod(p), C) X = M.inverse() * C e = 5 flag = '' for i in range(10): c = int(X[i * 11][0]) m = c ^ (1 / e) assert m ^ e == c flag += chr(m % 1000) flag = 'bi0sctf{%s}' % flag print(flag)
bi0sctf{8d522ae1a7}
Feedback (Misc)
アンケートに答えたら、フラグが表示された。
bi0sctf{th4nk5_f0r_pl4y1ng_bi0sctf2024}