自称セキュリティエンジニアがCTFでまったく歯が立たなかったお話

自称セキュリティエンジニアがCTFでまったく歯が立たなかったお話

皆さまは「CTF」というものをご存じでしょうか。旗取りゲームのことで、SECCON主催のセキュリティ技術を使って問題に挑む大会があります。普段はセキュリティエンジニアとして働いていますが、CTFの経験や参加はなく、自身の現時点でのスキルの確認と向上の為、チャレンジしてみました。今回はReversingとMiscを解いてみたお話です。

CTFとは?

CTFとは、「Capture The Flag」の略で、PCで技術を駆使した旗取りゲームを意味します。攻撃(Red Team)と防御(Blue Team)に分かれ、それぞれのFlagを奪い合うAttack & Defense形式と呼ばれるものや、クイズ形式でポイントを重ねるJeopardy形式があります。

今回出場した大会は、2020年5月23日~24日にかけて開催された、日本では知名度の高い「SECCON」が行っている初心者向け大会、「第3回 SECCON Beginners CTF」に出場しました。
https://www.seccon.jp/2020/beginners/about-seccon-beginners.html

大会といってもオンライン大会で気軽に出場でき、パソコンとインターネット環境さえあれば参加可能です。また、一人でも参加可能ですが、CTFはチーム戦であることが多く、今回もチーム戦形式だった為、社内でメンバーを募り興味をもってくれたメンバーで参加しました。

どのような問題が出るのか?

CTFはいくつかカテゴリがあり、大会によって微妙に違いがある場合もありますが、今回は以下のようなカテゴリでした。

  • Pwn:脆弱性を見つけて、その脆弱性を攻撃してFlagを取得する
  • Crypto:暗号化されたファイル等を復号化し、Flagを取得する
  • Web:Webページに隠されたFlagを取得する
  • Reversing:アプリやプログラムを解析し、Flagを取得する
  • Misc:上記のカテゴリ以外の問題

他、ファイル解析を行う「Forensics」や、パケットキャプチャファイルを解析する「Network」といったカテゴリがある場合があります。

具体的に、何を用意するか?

最低限必要なものは、前述の通り、パソコンとインターネット環境があれば十分ですが、解析で使用するツールや、検証で使用する検証機等があると便利だと思います。特に、Linux環境はなにかと使用するので用意してあると良いと思います。仮想環境などで用意するのが大変な場合は、最近はWSL(Windows Subsystem for Linux)という、簡易Linux環境がWindowsでも手軽に用意できますので、まずはそちらでもよいと思います。

今回私は、ペネトレーションテストなどで良く使用される、「KALI Linux」というものを用意しましたが、私にはそれらの機能を使いこなすことはほとんどなく、使用したのはLinuxの基本コマンドくらいでした。

他、今回の大会は連絡事項等のアナウンスがDiscordを使用していたので、Discordのアカウント等が用意しておく必要がありました。

大会の申し込み

今回は、大会数日前にスコアサーバーが起動し、そこへアクセスしてユーザー登録、チーム登録をするだけで、特に費用も掛かりませんでした。

もちろんエントリー方法や費用については大会によって異なるので、事前の確認が必要となります。

大会開始!

さて、有志を集めてエントリーしたら、あとは大会に臨むだけです。今回は土曜日の14時から翌日の14時までの長丁場。時間はたっぷりあります。

開始時間になると、スコアサーバーの「Challenge」ページが有効になり、そのページに掲載されている問題を解いていきます。

まず初めにWelcome問題のようなものがあります。これは大会のアナウンスで使用されているDiscord上のアナウンスにFlagが投稿されるので、それを入力するだけ。

これは、参加していれば誰でもポイントが取れるものですので、サクッと取って本題の問題に移ります。

問題がさっぱりわからない、、、

まず、問題ごとに「Beginner」「Easy」「Medium」「Hard」と難易度がランク付けされているので、各ジャンルの問題の難易度の低いものを見てみます。

うーん、わからない、、、。

右往左往していると、正解者の多い問題はどんどん得点が下がっていきます。

今回のルールでは、正解者の多い問題は得点が低くなり、正解者の少ない問題は得点が高くなるようなルールとなっているため、正解者が出るたびにその問題の点数が下がっていきます(正解した後も、正解者が増える度に自分の獲得ポイントも下がります)。同じ「Beginner」問題の中でも、点数が低いものは解きやすいもの、と信じて、しばらくにらめっこします。

まずは1問目、「Reversing」

はじめに解いたのは、Reversing の問題でした。「mask」というファイルが提供されます。

ファイル名に拡張子もなく、どのようなファイルかもわかりませんので、まずはLinuxを用いてfileコマンドを実行してみると、以下のように「ELF 64-bit LSB shared object…」という表示がされ、バイナリファイルであることがわかります。

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

バイナリファイルということなので、まずは実行してみると、以下のようなメッセージが返ってきます。おそらく、maskの後ろにフラグを入力する必要があるのでしょう。

$ ./mask
Usage: ./mask [FLAG]

今度は、今回のCTFのフラグのフォーマットに合わせて、ctf4b{thisistest}と入力してみます。(thisistestは適当に入力してみました)

$ ./mask ctf4b{thisistest}
Putting on masks...
atd4`qt`aqaqteqtu
c`b bk`hicic`ac`i
Wrong FLAG. Try again.

masks に置き換えられたと思われる文字の羅列と、フラグが間違っているメッセージが返ってきます。うーん、どうもこの返ってくる文字列をヒントに解く必要がありそうです。

IDAで中身を見てみた

この後も色々やってみますがよくわからず。今度は、IDAというフリーのディスアセンブラツールで中身を見てみます。

使い方が良く分かってないのですが、色々探していると、先ほど置き換えられた文字列と似たような文字列がコード内に書かれていることに気が付きました。

見つけた文字列は以下の通りです。

"atd4`qdedtUpetepqeUdaaeUeaqau"
"c`b bk`kj`KbababcaKbacaKiacki"

適当に入力した文字列の、最初の「ctf4b{」に合致すると思われる個所が全く同じです。おそらく、入力した後に出てきた二つの文字列が、このコード内の文字列と合致すればよいのでは!?と判断し、以下のように色々な文字列を入力し、文字の組み合わせを探っていきます。

$ ./mask abcdefghijklmnopqrstuvwxyz_
Putting on masks...
a`adede`a`adedepqpqtutupqpU
abc`abchijkhijk`abc`abchijK
Wrong FLAG. Try again.

上記で得た文字から、それぞれIDA上の文字列の組み合わせと同じになるようにアルファベットを探し、組み合わせていきます。

すると、、、

$ ./mask ctf4b{dont_reverse_face_mask}
Putting on masks...
atd4`qdedtUpetepqeUdaaeUeaqau
c`b bk`kj`KbababcaKbacaKiacki
Correct! Submit your FLAG.

ということで、正解を導き出すことができました!このフラグをスコアサーバーに入力すると、見事ポイントをもらうことができました。

2問目は「Misc」に挑戦

次に取り掛かったのは、これも多くの人が解いている問題で、「emoemoencode」というものです。

エモエモ?なんだろう?と思いながら、問題から「emoemoencode.txt」をダウンロードし、素直にメモ帳で開いてみると、以下のような絵文字が表示されました。

🍣🍴🍦🌴🍢🍻🍳🍴🍥🍧🍡🍮🌰🍧🍲🍡🍰🍨🍹🍟🍢🍹🍟🍥🍭🌰🌰🌰🌰🌰🌰🍪🍩🍽

ここからどうやって解くのか、皆目見当もつかないですが、他のテキストエディタで開いてみると、今度は漢字の羅列で表示されます。

坤唆恨原困砂叉唆婚懇今紺顕懇佐今魂昏沙此困沙此婚痕顕顕顕顕顕顕根昆鎖

おそらく、フラグを何らかのかたちで変換(エンコード)するとこれらの漢字になるのでしょうが、どのように変換されているのかが全くわかりません。漢字の画数から変換するなども疑ってみましたが、ちょっと難しそうです。ここから数時間、色々悩んだ挙句、それぞれの漢字のJISコードに行き当たりました。

カギはJISコードとASCIIコード

といっても、それぞれのJISコードの値からフラグはさっぱり導き出せません。そこで、漢字の前回同様に、ctf4b{~~~~}の形式に当てはめてみることにしました。

コードにもいろいろありますが、ASCIIコードと照らし合わせると、以下のようになります。(カッコ内は漢字がJISコード、英数字はASCIIコード)

坤(2605) = c(99)
唆(2622) = t(116)
恨(2608) = f(102)
原(2422) = 4(52)
困(2604) = b(98)
砂(2629) = {(123)
鎖(2631) = }(125)

すると、「原」以外の漢字はJISコードとASCIIコードの差分が「2506」になりました。「原」だけいびつになってしまいましたが、JISコードが2506より小さい数字だと、少し違うのかもしれません。

とりあえずこれでなにかわかりそうなので、このルール、「漢字のJISコードから2506引いた値がASCIIコード」に当てはめてみます。

すると、、、、

ctf4b{steganXgraphy_by_emXXXXXXji}

ああ、惜しいです。もう少しです。「X」だけ不自然ですが、おそらく言葉の並びから推測すると、「steganography(ステガノグラフィー)by emooooooji(絵文ーーーーー字)」で、oになると思うのですが、これは先ほどの「4」と同じように、「顕」のJISコードが「2418」となり、2506よりも小さい値の為に、なぜかずれてしまっていると思われます。

そこで、「4」に当てはまる「原」と比較してみると、JISコードの値が「原」よりも4小さいことがわかります。そこで、今度は「顕」の文字を、「4」よりもASCIIコードの値が4つ小さい文字を当てはめてみました。

ctf4b{stegan0graphy_by_em000000ji}

しっくりきました。パスワードなどでよくある、o(オー)をゼロに置き換えた文字列になりました。これを入力すると、これも見事に正解。ポイントゲットとなりました。

大会終了

結局、Welcomeを除くとこの2問のみを正解することができましたが、他は歯が立たず、終了となりました。結果を見ると、1009チーム中429位でした。ビギナー向け大会という割には、Welcome問題以外解けていないチームも多く、CTFの難しさが身に沁みました。

Write Up

さあ、答え合わせです。答え合わせといっても特に決まった解き方はないのですが、参加者たちがブログなどで解き方を解説してくれているページが多数あり、その方がどのように解いたのかを確認することができます。「ctf4b writeup」等で検索すれば色々出てくると思います。

解き方を見ると、面倒な処理はpythonにやらせたり、IDA等で解析後、バイナリエディタで書き換えて処理をスキップさせたり、様々な方法があることがわかります。

解けなかった問題も解けた問題も参考になりましたが、今後、参加してみたいな、と思っている方も是非一度参照されることをお勧めします。今回、私の解いた手順を解説していますが、他の方の解き方を見ると、あまりにも原始的でとても恥ずかしくなりました、、、。

最後に

今回、CTF4bに参加することで、新しい世界を知ることができました。自分の知識がどれほど足りていないかを実感することになりましたが、同時にまだまだ自分が知らないことがたくさんあることを知り、とてもワクワクできました。

今後も少しずつ勉強していきながら、こちらのコラムでも紹介できたらと思います。

記事は、予告なく変更または削除される場合があります。
記載された情報は、執筆・公開された時点のものであり、予告なく変更されている場合があります。
また、社名、製品名、サービス名などは、各社の商標または登録商標の場合があります。