bi0sCTF 2024 Writeup

この大会は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}