ナゾトキ x CTF🔰 -虹色の研究- WriteUp

## はじめに

本記事は、技術書典14やBOOTHで のみぞうさん ([@nomizooone](https://twitter.com/nomizooone)) が制作されている「ナゾトキCTF-虹色の研究-」に関するWriteupです。

クリアしていない方は**ネタバレにご注意**ください。

## ナゾトキCTF-虹色の研究- とは

ナゾトキとCTFを組み合わせた初心者向けCTFイベントです。購入すると手に入るクリアファイルとペーパーがものすごく巧妙に作りこまれていて感動します。これらを物理的に使うナゾトキもあり、物をいじりながら閃いたときの爽快感も味わえる、とても楽しめるコンテンツです。

Jeopardy（ジョパディ）形式でおこなれます。

ナゾトキCTFのTwitterハッシュタグ: [#nazotokiCTF](https://twitter.com/hashtag/nazotokiCTF)

(2023/05/31時点)
CTFイベント開催期間は 2024年1月3日13:30 までなのでご注意ください。
クリアファイルとレジストレーションコードが書かれたペーパーは、下記サイトで購入できます。

https://booth.pm/ja/items/4797758

## 1st Challenge

### 1st Challenge 赤:Reversing

#### 問題

- マインナンバー777の方を探してるニャ
- 1_Reversingという実行ファイルがダウンロードできる

    ![1st_red_top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/61948a81-3dc8-5073-748a-2d6d0a8ed0d1.png)

#### 情報収集

- 問題にある`nc`コマンドで問題サーバに接続すると"Enter your name:"と名前を求められる。"DonGury"と入力するとMineNumberは712だと返ってきた。これが777になる文字列を探せばよい。

  ``` bash
  ┌──(kali㉿kali)-[~]
  └─$ nc xxx.xxx.xxx.xxx 12345
  ************************
  MineNumber Search Engine
  ************************
  Enter your name:
  DonGury
  Your MineNumber is : 712
  Don’t mind. I'm looking for the 777.
  ```

- ダウンロードした "1_Reversing" に対して、`strings`コマンドで怪しげな平文が無いか検索すると、flag.txtという文字が見つかった。おそらく`nc`コマンドで接続した先にflag.txtがあってその中にフラグがあると思われる。

  ``` bash
  ┌──(kali㉿kali)-[~/work/nazotoki_7color/1st_red]
  └─$ strings 1_Reversing | grep -E "((nazo)|(777)|(flag))"
  flag.txt
  t mind. I'm looking for the 777.
  flag
  ```

#### 逆アセンブル

- Ghidra 10.2.2をインストールする (名前だけは聞いたことあったけど初めて使います！)
- 1_Reversingを読み込む
- "Symbol Tree"から`main`関数を選択しデコンパイルコードを確認する。

    ![decompile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/07190f6e-3ddc-fcf4-c61f-06f706e13b7b.png)


- デコンパイルしたコードを見ると、`local_64` が `777` (`0x309`) になる入力文字を探せばflagを出力してくれそう。

  ``` c++
  // デコンパイルしたコード
  while ((local_60 < 0x40 && (local_58[(int)local_60] != 10))) {
    local_64 = local_64 + (int)local_58[(int)local_60];
    local_60 = local_60 + 1;
  }
  printf("Your MineNumber is : %d\n",(ulong)local_64);
  if (local_64 == 0x309) {
    puts(flag);
    puts("You are the luckiest!");
  }
  ```

- なおデコンパイルしたコードには "You are Mr. Polmes. Your crypto key is \'**VIGENERE**\'. but, This is not Flag!" という怪しげな記述があった。後で使えるかもしれないので覚えとく。

#### デコンパイルコードから結果が777になる文字列を考える

- デコンパイルしたコードから、入力文字を1文字ずつ`int`にキャストして加算しその合計が`777`になればよいということがわかる。
- ASCIIコードでは "d" が "100", "M" が "77" なので, "dddddddM" を入力すればよさそう。
- `nc`コマンドで問題サーバに接続し"dddddddM"と入力すると無事にフラグが取れた！

---

### 1st Challenge 橙:Crypto

#### 問題

- 暗号を解くにはポームズの番号を調べるといいニャ

  "FWTS ZSEHVQ TS XSKEZ PG WHMU HZAA.WHMU XJPG WRX LWZZ OH AS ICVSA HRWL."

    ![1st_orange_top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/3a7ac498-08a4-7ed1-d7c8-86660ba17c36.png)

#### ポームズの番号を調べる

- 「1st Challenge 赤:Reversing」のコード内に、"You are Mr. Polmes. Your crypto key is \'**VIGENERE**\'. but, This is not Flag!" という記述があったのでこれが使えそう。

- 問題文の"FWTS ZSEHVQ TS XSKEZ PG WHMU HZAA.WHMU XJPG WRX LWZZ OH AS ICVSA HRWL."が暗号化された文字列で、"VIGENERE"が暗号キーとして復号してみる。

#### 復号

- スペース や "." が入っていたので、アルファベットを何かしら変換して読むんじゃないかなぁとあたりをつけてみたがわからない…

- "VIGENERE"がヒントなのかな？なぞなぞ？

- …全くわからん。保留。

- (数時間後) Google先生なら "VIGENERE" をご存じか？と思ってググるとヴィジュネル暗号というものがあることを知った。知らなかった…

- ヴィジュネル暗号を解くとフラグが判明！！ (自分でコードを書かなくてもサッと変換できるサイトはありそうですねｗ)

  ``` python
  # ヴェジェネル暗号で暗号化された文字列を復号するサンプルコード
  enc_code = "FWTS ZSEHVQ TS XSKEZ PG WHMU HZAA.WHMU XJPG WRX LWZZ OH AS ICVSA HRWL."
  key = "VIGENERE"

  A_ASCII = ord('A')
  ALFABET_NUM = ord('Z') - (A_ASCII - 1)

  dec_code = ""
  i_key = 0

  for i in range(0,len(enc_code)):
      if enc_code[i] == " " or enc_code[i] == ".":
          dec_code = dec_code + enc_code[i]
          next
      else:
          tmp_num = ord(enc_code[i]) - (ord(key[i_key]) - A_ASCII) 
          if tmp_num < A_ASCII:
              tmp_num = tmp_num + ALFABET_NUM 

          dec_code = dec_code + chr(tmp_num)

          i_key = i_key + 1
          if i_key >= len(key):
              i_key = 0

  print(dec_code)
  ```

---

### 1st Challenge 黄:Forensics

#### 問題

- 世界一かわいい犬が虹色の布に巻かれて宇宙位置かわいくなった瞬間ニャ。
- ここでデイジーちゃん登場！かわいい！！！
- 3_Forensics.pngというデイジーちゃん画像をダウンロードできる。これは良いサービス。

    ![1st_yellow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/f84ce3d2-8aa9-a62c-3112-026d25015741.png)

#### デイジーちゃん画像を解析してみる

- 拡大してくりくりお目目などを見てみたが ただただ可愛かった。

- exiftoolをインストールして情報を見るも怪しい情報はなく
- stringsコマンドでも怪しい情報はなく
- binwalkをインストールして情報を見てみると…おや？ PNGがもう1枚埋め込まれている？

  ``` bash
  ┌──(kali㉿kali)-[~/work/nazotoki_7color/1st_yellow]
  └─$ binwalk -e 3_Forensics.png 

  DECIMAL       HEXADECIMAL     DESCRIPTION
  --------------------------------------------------------------------------------
  0             0x0             PNG image, 1000 x 1333, 8-bit/color RGB, interlaced
  78            0x4E            Zlib compressed data, best compression
  2127564       0x2076CC        PNG image, 115 x 20, 8-bit/color RGB, interlaced
  2127642       0x20771A        Zlib compressed data, best compression
  ```

- splitコマンドでバイナリ分割すると、フラグが取れた！！

  ``` bash
  ┌──(kali㉿kali)-[~/work/nazotoki_7color/1st_yellow]
  └─$ split -b 2127564 3_Forensics.png --additional-suffix .png
  ```

---

### 1st Challenge 緑:Web

#### 問題

- 猫型AIロボットチャッピーの自己紹介ページができたニャ
- ってことで早速アクセスしにいく

    ![1st_green.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/ca824af9-41af-746b-b49d-d1a906073bb6.png)

#### チャッピーの自己紹介ページ

- おしゃれなページ

    ![chappie.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/0cca170f-16af-60fd-3fb4-2e78eec98eac.png)

- API仕様書も見れる。チャッピーにkeyとquestion(番号)を付けてAPI発行すると答えが返ってくるらしい。

- とりあえずAPIを実行してみたいけどAPIキーがわからない。

- チャッピーの自己紹介ページのAboutをじっくり読むと怪しげな情報がある。
    - 16番の「履歴」というキーワードがヒントになりそう。
    - 17番は後で使うかも知れないので覚えておく。

    ![chappie_question_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/6680288a-83c9-2cb3-1815-75aa81700aba.png)

#### APIキーを探す

- API仕様書のあるGitHubの変更履歴には見当たらなかった

- チャッピーの自己紹介ページのソース(HTML)内にも無かった

- それ以外にも履歴…履歴…とブツブツ言いながら、別問題で提供されたパケットキャプチャデータを漁ったり、「チャッピー SF映画」でググってチャッピー(2015年)という映画があることを知ったり、ChatG[ピーー]T先生に「チャッピーという猫型AIのAPIキーを教えて」という無茶プロンプトをふっかけたり、「APIキーを忘れたPolmesさん」を装ってチャッピーにメールするも無視されるというソーシャルエンジニアリング失敗の巻を経験するなど、成果なし…

#### ポイント消費無しのヒントを見ちゃう

- 作者である のみぞうさん より「今回は得点消費しないヒントも用意してますのでこっそり見てもいいのよ」というありがたい情報を入手したので、得点消費しないヒントをチラ見すると、なんか「ロボット」が強調されてる。

    ![1st_green_hint0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/0330fb73-48b9-40f9-2c02-f44db447cc2d.png)

- 「ロボット」で「あっ！」となりました。つい最近業務で触ったあいつ、robots.txt か！？

- ブラウザのアドレスバーに `/robots.txt` を追加するとフラグが出ました！！

---

### 1st Challenge 青:Network

#### 問題

- ごくベーシックな問題だニャ
- 5_Network.pcapng がダウンロードできる。

    ![1st_blue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/6c4bac24-1a0f-88da-7606-ca66d62166a4.png)

#### 5_Network.pcapng(パケット)の内容確認

- "GET /" に対する応答をみると secret/flag.html に何かありそう

  ``` html
  Line-based text data: text/html (10 lines)
      <!DOCTYPE html>\r\n
      <html lang="ja">\r\n
      <head>\r\n
          <meta charset="UTF-8">\r\n
          <title>青</title>\r\n
      </head>\r\n
      <body>\r\n
          <a href="secret/flag.html">secret</a>\r\n
      </body>\r\n
      </html>\r\n
  ```

- "GET /secret/flag.html" に対する応答パケットを見る。初回アクセスの応答は 401 Unauthorized が返っている。"WWW-Authenticate"ヘッダ情報より Basic認証でrealmは"Restricted Content"であることがわかる。

  ``` html
  Hypertext Transfer Protocol
      HTTP/1.1 401 Unauthorized\r\n
      :
      WWW-Authenticate: Basic realm="Restricted Content"\r\n
      :
  ```

- パケットを読み進めていくと、その後何度か認証を試行し最終的に "Authorization" ヘッダの"Credentials"に正しい認証情報を与えて200OKが返っている。bodyに書かれた情報より、"Credentials"に書かれた情報がフラグであることわかる。

  ``` html
  (リクエスト)
  Hypertext Transfer Protocol
      GET /secret/flag.html HTTP/1.1\r\n
      :
      Authorization: Basic bmF6b3Rva2lDVEY6T0FVVEg=\r\n
          Credentials: ※ここの文字をフラグ形式にするとよい※
      :
  ```

  ``` html
  (レスポンス)
  <!DOCTYPE html>\r\n
  <html lang="ja">\r\n
  <head>\r\n
      <meta charset="UTF-8">\r\n
      <meta name="viewport" content="width=device-width, initial-scale=1.0">\r\n
      <title>blue</title>\r\n
  </head>\r\n
  <body>\r\n
      The basic flag is in the password on this page.\r\n
  </body>\r\n
  </html>\r\n
  ```

---

### 1st Challenge 藍:OSINT

#### 問題

- 画像のTシャツはあるバンドのオフィシャルグッズ。バンド名を調べてほしいニャ

    ![1st_indigo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/75bc032f-5829-06d4-18ee-ce43b634925f.png)

#### 画像検索する

- Googleレンズで検索すると見つかる。バンド名を全部大文字にすればフラグ完成！！

---

### 1st Challenge 紫:Misc

#### 問題

- いや待ってどういうことｗｗｗ 謎の暗号文が書かれている。

    ![1st_purple.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/d34672ee-764e-95ed-bc1d-d43947026051.png)

#### この暗号文は何？

- 文字はどうやら1行で構成されているもよう。211文字…わからん…

- ブラウザの横幅を変えたり目を細めたりしたが、おぼろげながらも何も浮かんでこない。

- ぜんっっっぜんわからないのでダメ元でこのまんまググってみる。するとブレインファック(Brainf**k)という8命令チューリング完全プログラミング言語らしいことが判明。知らなかった…

https://atmarkit.itmedia.co.jp/ait/articles/1707/25/news026.html

- 解析してくれるサイトがあったのでそこに放り込んでみるとフラグ判明！！

https://kachikachi.net/brainfuck/

## 2nd Challenge

### 2nd Challenge クロスワード

#### 問題

- 1st Challengeで獲得したフラグを全て使って手元のクロスワードパズルを完成させるニャ

    ![2nd_crossword.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/57fd24ae-6073-bb50-487e-8b2596c485ee.png)

##### クロスワードパズルを埋めて番号順にならべる

- 1st Challengeが全て解けていればフラグがわかる問題

---

### 2nd Challenge フリーな暗号

#### 問題

- 暗号を解くだけじゃ終わらないかもニャ

    ![2nd_free_encryption.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/ebe17c42-1ac0-3672-5053-9f4235f84c70.png)

#### 情報収集

- 提示されたURLへアクセスすると、謎の暗号文とPassword入力フォームがある。

    ![encrypted_word.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/82167e34-2cf7-59e3-07a1-59786ece8767.png)

- 謎の暗号文を解く必要がありそうだけど、何も思いつかない。ナメック語かな。

- いくら考えてもわからないのでGoogleレンズで画像＆追加キーワードに「暗号」を入れて検索すると、フリーメイソンの「ビッグベン暗号」であることがわかった。知らなかった…
- ビッグベン暗号はとても上手に表現された暗号であることが理解でき、すぐ覚えれました。

#### 暗号文の解読とナゾトキ

- ビッグベン暗号を解読すると「ANGOU NO ITO TANI ORI SEYO」

- ペーパーを開いて糸の直線を谷折りすると、割り印みたいに隠されていた文字がでてくる。「🐱(ねこマーク)アワセ△(三角マーク)ニジイロジュンニヨメ」

- ペーパーとクリアファイルにはそれぞれ同じ絵柄のチャッピー(自称超高性能ネコ型AIロボット)が描かれている。それがぴったり合わさるようにペーパーをクリアファイルに入れると、クリアファイル裏面に印刷された〇や△のマークがクロスワードパズル上にぴったり合う！

- △部分の文字を虹色の順に繋げるとPasswordが完成する。

- 完成したPasswordで認証するとフラグ入手！！

- さらに最後のフラグにつながるナゾ「final.zip」がDOWNLOADできた。

## Final Challenge

### Final Challenge 虹の研究

#### 問題

- 最後の問題

    ![final_research_rainbow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/a4eac674-b573-7a56-e355-f0d55c36666b.png)

#### 「2nd Challenge フリーな暗号」で入手した final.zip を確認

- 解凍時にパスワードを求められる…。そういえば「2nd Challenge フリーな暗号」の認証後ページにはこんなことが書いてあった。「問い合わせ先」で思いつくのは、チャッピーのプロフィールページに書かれていたメールアドレスかAPIの2つ。にゃ～ん？

    ![2nd_nyaaaan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/d0c6390b-ba5e-31e3-ef57-9089dc1faad2.png)

- チャッピーにメールで問い合わせるも「でもごめんニャ。チャッピーへのお問い合わせはAPI経由でお願いしているのニャ。」と丁重にお断りされる。やはりAPIキーを探さないとダメなのかなぁ。

- チャッピーは1日1回しかメール返信してくれないのか（？）塩対応だし、APIキーを入手するしかないもよう。改めてチャッピーのプロフィールページを訪れる。まってろチャッピー。

#### APIキー探索

- 「1st Challenge 緑:Web」のときにAPIキーを探して見つからなかったが、見落としが無いかもう一度確かめる。

- まずAPI仕様書があるGitHub上で見落とし無いか確認する。
  - GitHubのInsightsでCommitの動向を確認すると 5月に12件のCommitがある。
  - CodeのHistoryを見るも、やはりそれらしき変更がないなぁ…と思ってたらcommitが10件しかない！なんで？
  - …どうやらREADME.mdのHistoryだけを見ていたことに気づく…GitHub弱者(´;ω;｀)
  - Historyの対象をプロジェクト全体にして変更履歴を確認すると…あったーーー！！！

    ![github_history_of_apikey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/2a88443b-71ce-eb2f-ef88-c9399e18878d.png)

- "Create api.key"の内容から無事APIキーを入手

#### APIを使ってチャッピーにリクエストを投げる

- 「1st Challenge 緑:Web」からチャッピーのプロフィールページに移動し、入手したAPIキーを含むURIでチャッピーにリクエストをぶん投げると以下のような回答が返ってきた。

  ``` json
  {
      "answer": "Number not found"
  }
  ```

- 質問番号が合っていない模様。ここで「1st Challenge 緑:Web」で気になっていた 17番の情報が 使える。質問番号は虹の色の数、つまり 7 を指定すればよい。

    ![question_no.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/a522c2f7-05db-2238-c4e9-61aa00dd9d3a.png)


- 正しい質問番号でAPIを発行するとパスワード情報が手に入った。

#### 入手したパスワードを使って final.zip を解凍

- 入手したパスワードでfinal.zipを解凍すると最後のフラグにつながる問題が書かれたPDFが手に入る。 (冒頭だけ載せます。この下に問題文があります。)

    ![final_challenge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/5977478f-9f46-b1c2-cb52-0684e4a83dd1.png)

#### 問題文から最後のフラグをあぶりだす

- 問題文に書かれたCTFのジャンル名を虹色で読みかえる。
- その虹色と横に書かれた数字に従って、ペーパーとクリアファイルを動かす。
  - クリアファイル表紙のポームズくんの虫眼鏡(透明)に、ペーパー裏表紙の英語の文字が写るようにクリアファイルとペーパーを配置する。
  - 問題文の虹色と数字に従って、クリアファイル表面右端中央あたりの指マークをペーパー裏表紙の虹色線のメモリ位置に合わせる。
  - ポームズくんの虫眼鏡に出てくる文字を順番に繋げていくと文字列が完成する。
- 問題文に書かれている謎のアイコンの意味は「1st Challenge 藍:OSINT」の問題文の中に答えがある。それは「鏡」。アイコンがついている箇所の文字を鏡で映した文字で置き換えると**最後のフラグが完成**！！

#### Final Challenge Congratulations

- Final Challenge 虹の研究のフラグをSubmitすると、Congratulationsステージが出現

    ![Congratulations.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514738/3debb3f4-4c70-8a0d-ccbc-171b82661d3c.png)

- Congratulations内のエピローグにはボーナスフラグが書かれています。200ポイントもらえるので忘れずにSubmitしましょう！！