この大会は2026/2/6 22:00(JST)~2026/2/8 22:00(JST)に開催されました。
今回もチームで参戦。結果は1250点で893チーム中125位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity Check (SanityCheck)
Discordに入り、#rulesチャネルでリアクションすると、たくさんのチャネルが現れた。
#primary-announcementsチャネルのメッセージにフラグが書いてあった。
p_ctf{WELCOMe7Opr@GY4N}
Lost in the Haze (misc)
OSINT問題で、問題文はこうなっている。
I remember stepping outside for a moment. The air felt heavy, the lights too bright, the streets unfamiliar.
All I know is that this location has a name.
Flag Format p_ctf{ward_name}添付の画像は次の通り。

画像検索すると、以下のページに近い画像が見つかる。
https://kiji.life/vending-machine-in-japan/

この写真より前の文章を翻訳すると、どうやら場所は秋葉原らしいので、千代田区であることがわかる。
p_ctf{chiyoda}
R0tnoT13 (crypto)
問題文はこうなっている。
During a security audit of a custom cryptographic module, you obtain partial diagnostic logs from a faulty randomness subsystem. The subsystem maintains an internal 128-bit state derived from AES, which is periodically inspected for integrity using bit-rotation consistency checks. For specific, preconfigured rotation offsets k, the firmware records the value: S ⊕ ROTR(S, k) where S is the internal state at that time. These checks are intended only to verify hardware wiring correctness and were never meant to be exposed. Due to a logging misconfiguration, only a small subset of these diagnostic frames was captured before the system crashed. Given: -Several leaked diagnostic frames of the form S ⊕ ROTR(S, k) -The corresponding rotation offsets k -Two anchor bits of the internal state -A ciphertext encrypted using the internal state Reconstruct the state and recover the flag.
challege.txtを見ると、ログはこうなっている。
== States == 8 183552667878302390742187834892988820241 4 303499033263465715696839767032360064630 16 206844958160238142919064580247611979450 2 163378902990129536295589118329764595602 64 105702179473185502572235663113526159091 32 230156190944614555973250270591375837085
kのべき乗回転がすべてそろっている。アンカービットは不明だが、可能性があるビットは4パターンのみなので、ブルートフォースで復号する。
#!/usr/bin/env python3 from itertools import product T = { 2: 163378902990129536295589118329764595602, 4: 303499033263465715696839767032360064630, 8: 183552667878302390742187834892988820241, 16: 206844958160238142919064580247611979450, 32: 230156190944614555973250270591375837085, 64: 105702179473185502572235663113526159091 } def bits(x): return [(x >> i) & 1 for i in range(128)] Tbits = {k: bits(v) for k, v in T.items()} S = [None] * 128 S[0] = 0 for i in range(0,128,2): for k in Tbits: j = (i + k) % 128 if j % 2 == 0: S[j] = S[i] ^ Tbits[k][i] S[1] = 0 for i in range(1,128,2): for k in Tbits: j = (i + k) % 128 if j % 2 == 1: S[j] = S[i] ^ Tbits[k][i] cipher = bytes.fromhex("477eb79b46ef667f16ddd94ca933c7c0") for even_base, odd_base in product([0, 1], [0, 1]): Sb = S[:] for i in range(128): if i % 2 == 0: Sb[i] ^= even_base else: Sb[i] ^= odd_base key = int("".join(map(str, Sb[::-1])), 2).to_bytes(16, "big") flag = bytes(a ^ b for a, b in zip(cipher, key)) if b"{" in flag and all(32 <= c < 127 for c in flag): flag = flag.decode() print(flag) break
p_ctf{l1nyrl34k}