こんにちは!!!24B の「りすりす/TwoSquirrels」ですよ!!!はい!その通り!僕は新入生です!!!(うるさいですか、ごめんなさい。今やめますね)
競プロと CTF を組み合わせた traP 主催のコンテスト「CPCTF 2024」に参加したのでその記録を残そうと思います。
CPCTF の詳細はここに乗ってます。
https://trap.jp/post/2204/
おはようございます。一日目が始まります
僕は競プロは普段からやっていますが CTF は初めてなのでとてもわくわくしていました。
CPCTF 2024 は土日に開催されました。コンテスト開始は 2024/04/20 10:00 で、それより前に起きて準備は万全かと思っていました。
はい、鋭い皆さんなら分かると思いますがこの書き方をするということは何かがありますね……
10:00 になりコンテストが始まったので、まずは競プロの簡単な問題を解こうとしました。
[PPC/NEWBIE] About half
正答者数: 92, 得点: 10/10, 提出時間: 2024/4/20 11:35:22
2 変数を受け取り場合分けをするだけなはずでした……
やるだけ~と思って書いてローカルのサンプルのテストを通して提出したら CE (Compile Error)。
CPCTF 2024 の競プロ問題のジャッジは YukiCoder が使われていたのですが、なぜかローカルでは動くのにジャッジ環境だけ CE になる現象が発生して、コンパイルエラーも C++ 特有の原因が分からないエラーで困っていました……
色々原因を調べると YukiCoder の GCC (C++ のコンパイラの一つ) のバージョンが低くバグが存在したのが原因だったらしいです。#pragma GCC
の行をコメントアウトすると無事正解できました。この原因究明に一時間以上を費やしてしまいました……
[PPC/NEWBIE] Compound Word
正答者数: 72, 得点: 10/10, 提出時間: 2024/4/20 12:00:03
制約が小さいので、普通に全部試せばよさそうです。C++ で std::set<std::string>
を使うことで楽に全通りを重複なく記憶することができるので、これを使います。
(実は問題の誤読をして一回ミスりました)
[Web/NEWBIE] Typing game
正答者数: 124, 得点: 10/10, 提出時間: 2024/4/20 12:11:54
とりあえず開発者ツールを開きソースを見てみると、フラグが書いてありました。/main.js
を見ても同じフラグがソースコードに直に書かれています。
他にも、コンソールから clearTimeout(timeout);
を叩いてゆっくりタイピングしてみたり、changeScene("game-clear");
を叩いてみたりするとクリアでき、フラグが見れます。
[Crypto/NEWBIE] Substitution
正答者数: 90, 得点: 10/10, 提出時間: 2024/4/20 12:45:16
問題文そのものが暗号になっていますが、おそらくこれは単一換字式暗号と呼ばれるアルファベットを置き換えただけの暗号なので、頻度分析などをすることで解けそうです。
まず最後の ETEIB
は CPCTF
なので、IJP
は T
から始まることになり、THE
だろうと推測できます。すると EKRTIU
は CRYPTO
っぽい……のように探っていくと、問題文が復号できます。
Well done! Solving this cryptogram requires both skill and patience. You've demonstrated exceptional acumen and perseverance. Bravo for cracking the code and unlocking its secrets! CPCTF{hello_crypto_world}
[OSINT/NEWBIE] mokomoko
正答者数: 97, 得点: 10/10, 提出時間: 2024/4/20 13:04:00
写真を見ると花畑のようですが、奥にゴルフ場が見えます。これだけだとよくわからないので特徴的な花を Google 画像検索にかけてみると……ありました。ひたち海浜公園という所らしいです。
[Reversing/NEWBIE] peeping
正答者数: 79, 得点: 10/10, 提出時間: 2024/4/20 13:07:30
実行ファイルを実行してみると、フラグを当てろと言われるだけで何もわかりません。strings
コマンドでバイナリのテキストを全列挙してみるとフラグが出てきました。
[Shell/NEWBIE] netcat
正答者数: 101, 得点: 10/10, 提出時間: 2024/4/20 13:10:22
nc
コマンドを叩いてもいいですが、http://shell-netcat.web.cpctf.space:30010/
にブラウザでアクセスしてもフラグが手に入りました。
[OSINT/NEWBIE] omu-napo
正答者数: 36, 得点: 10/10, 提出時間: 2024/4/20 13:21:10
EXIF 情報を確認してみると、GPS のデータが残っているので Google マップで店舗名を調べればフラグが手に入ります。
[OSINT/EASY] Doctor yellow
正答者数: 69, 得点: 76.77/76.77, 提出時間: 2024/4/20 14:13:16
ドクターイエローが走る線路を調べて、Google マップでその線路を辿りながら川を調べると、多摩川が写真と一致していました。座標からフラグが得られます。
[Reversing/EASY] Just reversing?
正答者数: 60, 得点: 106/106, 提出時間: 2024/4/20 14:26:21
暗号化のプログラムとそのプログラムで暗号化されたフラグが渡されます。ソースコードを読んでみると文字列を 4 bit 毎に区切ってひっくり返しているので、同じことをもう一度すれば復元できそうです。
与えられた C 言語のプログラムをそのまま使ってもなぜか上手く復元できなかったので、自分で JS でプログラムを書いて復元しました。
const fs = require("fs");
const flagEnc = fs.readFileSync("./flag_enc.txt", "hex");
const flag = flagEnc.split("").reverse().join("");
console.log(Buffer.from(flag, "hex").toString());
[Web/EASY] Let's buy some array
正答者数: 67, 得点: 99.02/99.02, 提出時間: 2024/4/20 14:35:08
バックエンドのソースコードが与えられるので見てみると PHP で書かれていて、/src/purchase.php
を見てみると eval
とありやばいです。Web のフォームから任意コードが実行できそうですが、そのままだと文字列が数字しか書けないので開発者ツールからフォームの type="number"
を type="text"
とでも書き換えてやってから getenv("FLAG");//
を送ると、フラグが見れました。
[Reversing/EASY] Number Guesser
正答者数: 52, 得点: 133.09/133.09, 提出時間: 2024/4/20 15:48:43
実行ファイルしか渡されませんが、strings
コマンドを使ってもフラグは見つかりません。おそらくプログラムでフラグを動的に構築しているので、その関数をどうにかして直接呼び出すか、数字を当てるかしかなさそうです。僕は objdump
コマンドや adb
コマンドに慣れていない上アセンブリも読めないので IDA という逆アセンブルソフトをインストールして確認すると、以下のような判定ロジックが見つかるので
数字は 17704
と分かります。実行してこれを入力するとフラグが得られます。
この程度の整数ならローカルで 0
から順に全探索して調べても見つかりそうです。
[Pwn/NEWBIE] Attack! Attack! Win!
正答者数: 80, 得点: 10/10, 提出時間: 2024/4/20 15:53:13
ソースコードが渡されるので読んでみると、どうやら負の数の入力の対策ができていない上 3 で関数のアドレスまで分かるので、差のバイト数を計算して -2
を送ると、フラグがでてきました。
[Forensics/EASY] Register
正答者数: 19, 得点: 289.68/289.68, 提出時間: 2024/4/20 17:21:38
問題文で「packetをcapture」と言ってるので Wireshark をダウンロードして見てみますが、どうやらこれば USB 入力のキャプチャーのようです。Wireshark ってネット通信以外のキャプチャーも取れるんだと驚きながら色々ググってみるとキーボード入力とコードの対応表が見つかりました。この表をもとに JS で変換プログラムを書いてあげて
const keyboard = [
[],
[],
[],
[],
["a", "A"],
["b", "B"],
["c", "C"],
["d", "D"],
["e", "E"],
["f", "F"],
["g", "G"],
["h", "H"],
["i", "I"],
["j", "J"],
["k", "K"],
["l", "L"],
["m", "M"],
["n", "N"],
["o", "O"],
["p", "P"],
["q", "Q"],
["r", "R"],
["s", "S"],
["t", "T"],
["u", "U"],
["v", "V"],
["w", "W"],
["x", "X"],
["y", "Y"],
["z", "Z"],
["1", "!"],
["2", "@"],
["3", "#"],
["4", "$"],
["5", "%"],
["6", "^"],
["7", "&"],
["8", "*"],
["9", "("],
["0", ")"],
["[Enter]", "[Shift+Enter]"],
["[Escape]", "[Shift+Escape]"],
["[Backspace]", "[Shift+Backspace]"],
["[Tab]", "[Shift+Tab]"],
["[Space]", "[Shift+Space]"],
["-", "="],
["^", "~"],
["@", "`"],
["[", "{"],
[],
["]", "}"],
[";", "+"],
[":", "*"],
["[半角/全角]", "[Shift+半角/全角]"],
[", ","<"],
[".", ">"],
["/", "?"],
["[CapsLock]", "[Shift+CapsLock]"],
["[F1]", "[Shift+F1]"],
["[F2]", "[Shift+F2]"],
["[F3]", "[Shift+F3]"],
["[F4]", "[Shift+F4]"],
["[F5]", "[Shift+F5]"],
["[F6]", "[Shift+F6]"],
["[F7]", "[Shift+F7]"],
["[F8]", "[Shift+F8]"],
["[F9]", "[Shift+F9]"],
["[F10]", "[Shift+F10]"],
["[F11]", "[Shift+F11]"],
["[F12]", "[Shift+F12]"],
["[PrintScreen]", "[Shift+PrintScreen]"],
["[ScrollLock]", "[Shift+ScrollLock]"],
["[Pause]", "[Shift+Pause]"],
["[Insert]", "[Shift+Insert]"],
["[Home]", "[Shift+Home]"],
["[PageUp]", "[Shift+PageUp]"],
["[Delete]", "[Shift+Delete]"],
["[End]", "[Shift+End]"],
["[PageDown]", "[Shift+PageDown]"],
["[→]", "[Shift+→]"],
["[←]", "[Shift+←]"],
["[↓]", "[Shift+↓]"],
["[↑]", "[Shift+↑]"],
["[NumLock]", "[Shift+NumLock]"],
["/"],
["*"],
["-"],
["+"],
["[Enter]"],
["1", "[End]"],
["2", "[↓]"],
["3", "[PageDown]"],
["4", "[←]"],
["5"],
["6", "[→]"],
["7", "[Home]"],
["8", "[↑]"],
["9", "[PageUp]"],
["0", "[Insert]"],
[".", "[Delete]"],
];
const input = "0206021302060217020902300232005000090059005c005e2087001a005c005d20870006005c0061005f0018001500200007";
console.log(
input.match(/..../g)
.map((hex) => parseInt(hex, 16))
.map((id) => keyboard[id % 256]?.[id >> 9] ?? `[${id.toString(16)}]`)
.join("")
);
実行してみると CPCTF{}[←]f146[2087]w45[2087]c497ur3d
が得られるので、これを元にフラグを復元できました。
[Web/EASY] Read Novels
正答者数: 87, 得点: 50/50, 提出時間: 2024/4/20 17:24:56
バックエンドのソースコードが与えられるので見てみると、パスを構築している所に好きな文字列を入れられるのが怪しいです。試しにディレクトリを ../
で遡ってみるとすべてのファイルの中身が見れてしまうので、フラグも見れました。
[Forensics/EASY] white has much information
正答者数: 60, 得点: 125.13/125.13, 提出時間: 2024/4/20 17:39:26
空白文字のみの文字列には見覚えがあって、すぐに Whitespace 言語だと分かったので、オンラインのインタプリタで実行するとフラグが得られました。
[Shell/EASY] veeeeeeery long text
正答者数: 66, 得点: 83.92/83.92, 提出時間: 2024/4/20 17:41:51
ssh 接続をすると、64 文字ごとに改行で区切られたとても長いテキストファイルが置いてあるので、とりあえず grep CPCTF flag.txt
とかをするとフラグが見つかりました。
[OSINT/EASY] leaving
正答者数: 44, 得点: 174.09/174.09, 提出時間: 2024/4/20 19:51:44
電光掲示板や新幹線乗換の存在などから浜松駅と分かるので、そこから Yahoo! 乗換案内アプリで調べると現在時刻より前に終点駅の熱海についてしまうので、折り返し時間を適当に見積もって逆方向に調べるのを何度か繰り返すと目的の駅が分かりフラグが作れました。
[OSINT/MEDIUM] Great view
正答者数: 50, 得点: 146.27/146.27, 提出時間: 2024/4/20 20:45:43
とりあえず Google 画像検索に投げてみると卯辰山公園見晴らし台だとわかり、聖地巡礼のブログからゲームは「Link!Like!ラブライブ!」だと分かります。これをググるとピクシブ百科事典が出てきてリリース時間が書いてあるので、フラグが分かりました。
[PPC/EASY] Time is money
正答者数: 25, 得点: 244.76/244.76, 提出時間: 2024/4/21 0:59:52
競プロがしたくなったのでやります。
時間と金の二要素がありますがよく考えると時間の価値を金に変換して考えれば金だけになりダイクストラ法が使えます。最後に時間を切り上げ除算をします。
[PPC/EASY] Old Maid
正答者数: 35, 得点: 191.89/191.89, 提出時間: 2024/4/21 1:14:29
うまくシミュレーションをします。
途中の要素をすぐに消せるように連結リストを使い、数とそのイテレータの連想配列を持てばできました。
[PPC/EASY] CPC To F
正答者数: 40, 得点: 174.09/174.09, 提出時間: 2024/4/21 1:43:41
後ろから見て貪欲法をしましたが、実は前から見ても解けるらしいです。
[PPC/EASY] Balanced Choice
正答者数: 32, 得点: 211.42/211.42, 提出時間: 2024/4/21 2:09:40
どう見てもナップザック DP です。石が二種類あるので DP を二本持って最後に答えを探せばよさそうです。
[Pwn/EASY] CPCT......
正答者数: 61, 得点: 114.68/120.72, 提出時間: 2024/4/21 2:31:04
さらっと printf
と書いてあるのに気付かずヒントを一つ開けてしまいました……%99d
とか入れれば 99 文字になってくれます。
[OSINT/MEDIUM] Patlite
正答者数: 38, 得点: 186.77/196.6, 提出時間: 2024/4/21 3:06:38
ヒントを一つ開けてしまいました。ゆりかもめに注目するらしいので、その条件で大きな駅を探すと新橋駅が見つかり、そのあたりの座標を色々試すと正解できました。
[OSINT/EASY] Dokoda?
正答者数: 40, 得点: 255.09/255.09, 提出時間: 2024/4/21 3:11:59
fukushin
が怪しいです。ググると福しんというチェーン店が出てくるので、店舗情報 から最寄り駅を全探索すると正解できました。
疲れたので寝ます。
ふつかめです
解けそうな競プロ問があと 1 問あったのでそれから解きます。
[PPC/MEDIUM] Car Flow
正答者数: 21, 得点: 270.5/270.5, 提出時間: 2024/4/21 10:27:11
実験すると 0
と 1
の数は常に変わらなそうと予想でき、じっくり考えてみると渋滞を表していることが分かります。(これがタイトルの伏線回収になっていることは後で気がつきました)
さらに実験をすると周期は n
でそのうちシグマの中が 1 になるのは 1
の数と 0
の数の少ないほうになることが予想できるので、その確率を求めたら正解できました。
[Forensics/MEDIUM] which is true flag
正答者数: 30, 得点: 25.51/255.09, 提出時間: 2024/4/21 11:33:28
ほとんど同じファイルばかりで色々調べてもよくわからず、ヒントを開けると正しいアドレスを調べる必要があることが分かりました。dig
コマンドを知らなかったので全てのヒントを開けてしまいました……
[OSINT/HARD] Electric Town
正答者数: 15, 得点: 50/500, 提出時間: 2024/4/21 11:44:48
この問題は一日目から考えていました。
ぱっと見で秋葉原のラジオ会館前ということは分かりますが、時間はどこにも書いてありません。
NieR:Automata の旗から大体 2023 年の 08 月中旬以降ということが分かり、ソフマップのシャッターが閉まっていることから朝から 11:00 までということは分かります。
天気予報が書いてあるのでその時期の天気予報の履歴を見ながら日にちを絞り、細かな時間までは分からないので頑張って全探索をしますが正解が見つかりません……
他の怪しい日も全探索したいですが流石に手がつかれました。ルールを見てみると鯖に負荷をかけてはいけないというのはありますが自動化は禁止されていなかったので、手で全探索するのと同じくらいの速度で自動化します。
これで怪しい日を色々調べましたが見つからず、自動化禁止のルールが加えられました。
あきらめて二日目にヒントを全て開けると、雲とライブカメラを使うとあり、流石に無理~~~となりました。
[Misc/EASY] turning over
正答者数: 26, 得点: 25.94/259.38, 提出時間: 2024/4/21 14:34:18
Blender の使い方を知らなかったのでヒントを全て開けてしまいました……
[Pwn/EASY] The sky's the limit
正答者数: 35, 得点: 26.82/268.23, 提出時間: 2024/4/21 14:44:34
gets
関数が怪しいということしか分からなくてヒントを全て開けました。
[OSINT/MEDIUM] Forbidden Code 1
正答者数: 28, 得点: 32.84/328.36, 提出時間: 2024/4/21 14:55:44
面白そうでしたがとても難しいのでヒントを全て開けました。
[Misc/NEWBIE] 参加者アンケート
正答者数: 31, 得点: 10/10, 提出時間: 2024/4/21 15:26:31
アンケートを開くとフラグが貰えました。
終了!!!お疲れ様でした!!!
新入生 3 位になれました!!!わーい
CTF は初めてでしたが面白かったです。
全探索に関しては、ごめんなさい!!!
運営の方々ありがとうございました!