MNCTF 2021 Writeup
毎年開催され参加していたマクニカCTFですが、去年は開催されず、今年は2年ぶりに開催されました。 2017年から毎年参加していたので、今年も半分骨髄反射的に申し込み参加しました。
今年はCTFシステムが前回から大きく変更され、ちょっと新鮮な気持ち(?)で参加させていただきました。
★これからやる人はネタバレ注意
CTFゲームシステムについて
Writeupに入る前にCTFのゲームシステムが前回から変わっていたのでご紹介です。 今回はいわゆるダンジョンシステム(名前があっているのか??)が導入されました。プレイヤーはいろいろとマップ内を動き回ることができ、情報を得たりしてストーリーを進めていく形式です。
CTFシステムがこのゲーム内で完結しており、ストーリーに沿って問題が出題され1つずつ回答していくことになります。そのため途中で躓いたりすると次に進めず非常に焦りました。。
なお以下の画像はゲームに入る前のヘルプ画面ですが、ここにもヒントが隠されているとのことでした。(「チート行為は禁止ではない」=??)
またステージ(ストーリー)は大きく2つに分かれており、上の画像の「てしがわら君 空港編」と、「株式会社マクニキ編」というものがありました。解説の時間に説明がありましたが、各ステージはそれぞれ、攻撃に関するカテゴリの問題、インシデントレスポンスに関するカテゴリの問題というかたちで分かれていました。
てしがわら君 空港編
※問題一覧は上の画像のように見ることができますが、問題の中身はこのページの中には記載がなく、ゲームを通して問題を入手し解いていくスタイルでした(ゲーム内でフラグゲットすると、自動的にこちらの画面にも反映される)。
序盤のストーリーは以下のような流れでした。
- 搭乗手続きしたいがチケット番号がわからない。
- チケットの画像をSNSにアップロードしたが、今度は通信手段がない。
- 空港のサービスでWifiを利用できるが、1時間100ドルと高額。
- 人のアカウントでタダで利用し、SNSにアップロードしたチケット画像を入手。
- チケット画像に記載されているチケット番号を使い搭乗手続き。
Wifiユーザ情報
PCAPからWifi用認証Webサイトのユーザ名、パスワードを見つけ、パスワードを入力してください。
Wifiの通信(を記録したPCAP)を解析し、Wifiを利用するシステムのユーザ名、パスワードを調査する問題です。 ざっと流してみたところWEB通信がいくつかあったので、「http」で絞りました。
認証っぽいリクエストをしている通信が2つありましたのでそれぞれ「追跡」→「HTTPストリーム」で確認しました。 その結果、2つ目の通信のほうにユーザ名・パスワードの通信記録がありました。(1つ目のほうにも通信記録がありますが、サーバからfaildの文字が返ってきており、間違った認証情報だと判断しました。)
FLAG:c5GZDHbQ
チケット番号
この写真から12桁のチケット番号を調べて、入力してください。
Wifiを利用できる情報を入手したので、SNSにアップロードした画像を取得し、チケット番号を確認します。
ただ肝心のチケット番号の部分はぼかしが入っており、簡単には読むことができない状態でした。 そこで下部にあるバーコードに情報が含まれているのでは?と考えWEB検索してみました。 「搭乗チケット バーコード 読み取り」などで検索したところ、以下のサイトに記載がありました。 www.bousaid.com
このサイトによると、画像のバーコードの種類はPDF417というもののようです。 スマホアプリでPDF417を読み取れるアプリがないかなぁと探したところ、結構あるようで、以下のアプリを使ってみました。 play.google.com
さっそくアプリ内のカメラで画像のバーコードを読み込んでみたところ、すぐにデコードできました。
問題文に「12桁のチケット番号を答える」という記載(ヒント)があったので、デコードした画像の中の数字列を入力したところパスしました。
FLAG:809213423472
解説では、人が読み取れる部分だけを隠しても思わぬところから情報流出したり、ぼかしについても、今回のように隠されているのが数字だとわかっていると比較的容易に解析されてしまうようで、SNSにアップする際などは気を付けましょう、ということでした。
ラウンジクーポン
このAndroidアプリに入力すべきクーポンの文字列を入力してください。
搭乗手続きを終えると、ゲート前の部屋に入れますが、さらにその先のラウンジに行く必要があるようです。 ラウンジに入るためにはラウンジ券が必要なようです。ラウンジ入口手前の人に話しかけるとアンドロイドアプリを渡され、クーポンを入力することでラウンジ券を入手できるとのこと。
APK形式のファイルなので、中身をデコードし見ていきます。
user1@trg:~/work$ ls loungeapp.apk user1@trg:~/work$ mv loungeapp.apk loungeapp.zip user1@trg:~/work$ unzip loungeapp.zip Archive: loungeapp.zip inflating: res/animator/linear_indeterminate_line1_head_interpolator.xml inflating: res/color/material_on_surface_disabled.xml inflating: res/layout/test_toolbar.xml (snip) inflating: classes.dex inflating: res/drawable/abc_ic_menu_cut_mtrl_alpha.xml extracting: res/drawable-hdpi-v4/notification_bg_normal.9.png user1@trg:~/work$
dexファイルの変換はこちらを使いました。 sourceforge.net
user1@trg:~/work$ ../dex2jar-2.0/d2j-dex2jar.sh classes.dex dex2jar classes.dex -> ./classes-dex2jar.jar Detail Error Information in File ./classes-error.zip Please report this file to http://code.google.com/p/dex2jar/issues/entry if possible. user1@trg:~/work$ user1@trg:~/work$ ls AndroidManifest.xml META-INF classes-dex2jar.jar classes-error.zip classes.dex loungeapp.zip res resources.arsc user1@trg:~/work$ user1@trg:~/work$ mv classes-dex2jar.jar classes-dex2jar.zip user1@trg:~/work$ unzip classes-dex2jar.zip Archive: classes-dex2jar.zip creating: android/ creating: android/support/ creating: android/support/v4/ creating: android/support/v4/app/ (snip) inflating: androidx/core/view/WindowInsetsCompat$Impl30.class inflating: androidx/transition/ViewUtilsApi29.class inflating: com/google/android/material/bottomsheet/BottomSheetDialogFragment.class inflating: com/shinosec/loungecheckin/MainActivity.class user1@trg:~/work$
classファイルが大量にあり、どう調査しようか迷いましたが、とりあえずgrepをかけてみました。(クーポン文字列を探しているため、安直に「coupon」などで検索しました。)
user1@trg:~/work$ grep -ri coupon Binary file res/layout/fragment_second.xml matches Binary file loungeapp.zip matches Binary file resources.arsc matches Binary file androidx/core/util/PatternsCompat.class matches Binary file classes.dex matches Binary file com/shinosec/loungecheckin/R$id.class matches Binary file com/shinosec/loungecheckin/SecondFragment$2.class matches user1@trg:~/work$
するといくつかヒットがあり、特に下のほうのファイルのパスが特徴的(「shinosec」に「loungecheckin」)だったので、「com/shinosec/loungecheckin/」配下のclassファイルに絞って解析を進めます。
classファイルのデコンパイルには、FLARE VMに搭載されているjd-guiというツールを利用しました。ツールを起動後、ファイルを1つD&Dすると同じフォルダにあるclassファイルを自動でデコンパイルしてくれて便利でした。 上のgrapコマンドの結果でヒットしたものの中で1番最後に出たものを確認してみました。
するとif文の中で何やら長い文字列を比較対象として使っており、これがクーポンの文字列でした。
FLAG:ILOVENAFIRSTCLASS9432
解説ではdexファイルを解析するツールということで以下の2つのツールが紹介されていました。 mobsf.github.io www.javadecompilers.com
謎のおとこ
ラウンジに入ると、奥に男性がおり、話をすると隠しの個室があり行くと良いということを教えてくれます。
右下にあからさまに怪しい部分がありますが、最初どうやって行けばいいかわからずこのフロアを歩き回っては調査をしていました・・
結局何も見つからなかったので、何となしに開発者ツールを開き、コンソールに何か出ていないか見てみました。 すると、何か調査した場所で座標らしきものが出ているのがわかります。
ここで「座標の管理はcookieを使っている・・?」と思い、cookieを見てみます。 思った通りでいくつか項目があり、特に数字が格納されている「MNCTF2021_airportx」と「MNCTF2021_airporty」が怪しそうです。 移動→ページリロードしcookie画面更新、を繰り返した結果、やはり上記の2つがマップ上の座標を示していました。 この部分を直接変更しリロードすれば右下の空いている1マスに飛べそうです。
以下のように変更し、ページをリロードしてみます。
思った通り中に入ることができ、フラグをゲットできました。
FLAG:MNCTF{GAME_CHEATER}
上のほうで掲載した操作手順の画像のヒントとはこの部分に対するもの(cookieを利用している、ということと、チート行為を許容している(=使わないといけない)というヒント)でした。冷静にこのヒントを思い出し考えていれば、フロア中を歩き回ることもなくすんなりとけていたかもしれませんね・・
株式会社マクニキ編
2つ目のステージです。このステージではストーリーに沿って様々なログが提供され、インシデントレスポンスしていく流れになっていました。
IPアドレス特定
サーバルームからFWログを入手し、ブラックリストのIPアドレス「87.113.49[.]99」と通信をしている端末のIPアドレスを調べてください。
C2サーバと通信している端末があり、FWログを調査し通信元の端末のIPアドレスを特定する問題です。
エディタで開き突き止めました。
FLAG:192.168.108.21
MACアドレス
最初の問題で端末のIPアドレスがわかりましたが、DHCPだったので、端末を特定するためMACアドレスを特定する問題です。 最初の問題と同様にエディタで開き検索したところ、2件ヒットしました。
最初の問題で特定したログの日時は「2021-07-01 08:15:17」ですので、この日時よりも過去でかつ一番最近のログが対象のログになります。
FLAG:54:0b:20:1b:ce:a2
不正なプロセス
いくつかのコマンド結果を採取しました。不正なプロセスを特定してください。
端末を特定できたので、端末の調査に入ります。調査対象のログとして、netstatコマンドの結果と、tasklistコマンドの結果が提供されるので、このログから不正なプロセスを見つけます。
最初の問題で不正な通信先の情報は得ている(87.113.49[.]99)ので、netstaatコマンドの結果の中からこの通信先へ通信している項目を探します。
ログからプロセスID11444のプロセスだと判明しました。次にtasklistのログの中からこのプロセスの情報を検索します。
検索したところ2件出てきましたが、Chromeのほうは間違いとのことです😅
FLAG:DriverUploader.exe
マルウェア発動条件
このマルウェアは発動条件があるようですが、どの社員を狙ったものでしょうか?なお、ローマ字はユーザアカウントとして利用されています。
※解けなかった問題です。
マルウェアを解析し、マルウェアが動作する条件を探りどの社員をターゲットにしているか特定する問題です。調査に際し、マルウェア本体と社員リストが提供されます。
解説では、マルウェアは.Net Frameworkで生成されており、対応するデコンパイラ(dnSpyなど)でソースコードを取り出し、中身を解析する、という問題でしたが、正常にデコンパイルできず時間切れとなりました。(アプリケーションの生成方法が間違っていた??みたいで、想定したものではなかったようです。故に正答者は0でした。)
最後に
今回は新たにゲーム要素が加わり、またストーリーに沿って問題を進めていくということで、半分くらいは楽しめましたが半分はかなり焦ってしまっていました(途中で躓くと次の問題に進めない、マップ内を歩き回っていろいろ探らないといけない、など)。
※ちなみに以下のマップは、ステージ2の「不正なプロセス」問題で対象の人を探す場面です。人が多く探すのに少し手こずりました😓
毎年様々な面白い問題や仕組みを取り入れており、今回もとても楽しめました。また来年の開催もあればぜひ参加し、今度こそ全問正答を果たしたいと思います。(毎年言っている気がする。)