チャレンジ一覧
プログラミング - IoTファームウェアの解析
起動のたびに乱数で作られたネットワークカメラのファームウェアイメージ firmware.bin を解析します(実行コードは含まれません)。形式は、先頭に `KFW2`(4バイト)、パーティション数(uint16)、パーティション表(name: 16バイト(NUL 埋め)、offset・size・crc32: 各 uint32。数値はすべてビッグエンディアン)、本体の順です。CRC32 が一致しないパーティションは壊れているか古いものです。`bootinfo` にはシリアル番号(`serial=...`)が平文で入っており、`config` は設定テキストを zlib で圧縮し、SHA-256(シリアル番号の文字列 + b"config") のダイジェストを繰り返し XOR したものです。名前がちょうど `config` で CRC32 が一致するパーティションに書かれた `admin_token` の値(16進32桁)が答えです。工場出荷時の既定値やバックアップの古い値は、いま有効な値ではありません。答えを `python3 challenge.py '<答え>'` に渡すと、正解のときだけフラグが表示されます。
プログラミング - カバレッジ誘導ファジング
起動のたびに乱数で作られたカバレッジ誘導ファザーの実行記録 coverage-queue.jsonl を解析します(対象プログラムは実行しません)。各行は `{"id": ..., "t": ..., "edges": [{"edge": ..., "hits": ...}, ...]}` の形で、行の順番は処理した順ではありません。エントリを t の昇順に1件ずつ処理し、各 edge のヒット数をバケット(1 / 2 / 3 / 4–7 / 8–15 / 16–31 / 32–127 / 128以上)に分けます。そのエントリの (edge, バケット) の組のうち、それまでに見たことのない組が1つでもあれば、そのエントリをコーパスに保存します(保存したかどうかにかかわらず、組はすべて「見た」ことにして次へ進みます)。保存されたエントリの id を処理した順に `-` でつないだもの(例: `1a2b3c-4d5e6f-...`)が答えです。答えを `python3 challenge.py '<答え>'` に渡すと、正解のときだけフラグが表示されます。
プログラミング - ゼロクリック通信の解析
messages.ndjson は起動のたびに乱数で作られる、メッセージアプリの通信記録です(/challenge にあります)。1行が1つの断片(message_id、frag_index、frag_count、payload_hex)で、断片は複数のメッセージが混ざっています。同じ message_id の断片を frag_index の順につなぎ、SHA256(message_id) の先頭4バイトを鍵に繰り返し XOR で復号すると、TLV(type 1バイト、長さ 2バイト big-endian、値)の並びになります。宣言された長さが残りのバイト数を超える TLV を含むメッセージが、パーサーを狙った攻撃です。攻撃メッセージのその TLV の中にある stage2=<16桁の16進> の値を、message_id の昇順に - でつないだ文字列を python3 challenge.py '<答え>' に渡すとフラグが表示されます(正しい長さの TLV にある stage2= は攻撃ではありません)。
プログラミング - タイミング攻撃データの解析
timings.csv は起動のたびに乱数で作られる、タイミング攻撃の生の測定値です(/challenge にあります)。秘密の16進文字列を1文字ずつ比較するサーバーに対して、各位置(position)で候補の文字(candidate、0〜f)を送ったときの応答時間(sample_us、マイクロ秒)が、各位置・各候補に複数回ずつ記録されています。正しい文字のときだけ応答がわずかに遅くなりますが、測定には雑音があり、ときどき大きな外れ値も混ざります。各位置で本当に遅い候補を選び、position 0 から順につないだ秘密の16進文字列を python3 challenge.py '<答え>' に渡すとフラグが表示されます。
暗号解析 - RSA e=3ブロードキャスト攻撃
broadcast.jsonには同じ平文をパディングなしRSA・e=3で3つの互いに素なmodulusへ暗号化した結果があります。中国剰余定理と整数立方根で平文を復元してください。