CpawCTFからやさしい問題を抜き出して解いてみる回
この記事はmyjlabアドベントカレンダーの10日目です。
今回は以前より書こうと思っていた初心者向けCTF入門記事です。
以前弊研究室の院生である@marutaku0131氏とおはなししていたときに「CTF、一度チャレンジしてみたことがあるが、問題を見たときに何をしたらいいのかさっぱりわからなくて敷居が高いように感じた」と聞きました。
確かに解く上での取っ掛かりの探し方、考え方が醸成されるまでの厳しさはあるなと感じていたので、初心者の感覚を忘れないうちに備忘録的に記しておこうと思います。
いやまずCTFについて教えてくれ
CTF:Capture The Flag
コンピュータ関連の技術を用いて、隠された旗(FLAG)を探し出すというゲームのこと。ここでは特にJeopardyと呼ばれる、様々なジャンルから問題が出題される形式のものを指す。
今回は特に常設コンと呼ばれる、インターネット上で常に公開されており、制限時間のないCTFについて解いていきましょう。
ジャンルとして今回ピックアップした問題はそれぞれ
- Misc:miscellaneous 他のジャンルに入らない問題
- Crypto:Cryptography 暗号解読
- Web:Webサイトなど
- Forensics:ファイルのフォーマット調べたり壊れたもの復元したりするやつ
- PPC:ぷろぐらみんぐ
といったジャンルのものですね。
CTF中はわからないことについてインターネットで調べることができます。考えてもわからないものはわからないので、とにかくいっぱいググるのがよいですね。
ただし「Write Up」とタイトルについているものは、他のプレイヤーが自分の解答をまとめたもの なので、問題と格闘したいときには見ない方がよいかもしれません。
実戦(ヒント)
今回はCpawCTFの問題のうち、特に環境を用意することなく、特に初心者が取り掛かりやすい問題を取り上げ、ヒントを示しながら一緒に5問くらい解いてみます。
Q1.[Misc] Test Problem
ウォーミングアップとしてこのCTFにおけるFLAGの形式や提出について確認しましょう。
cpaw{xxx}
ということで以降はこの形のFLAGを探します。
Q6.[Crypto] Classical Cipher
Q1の次ですがQ6ですね。
問題文にある通り、シーザー暗号を解読してあげればよさそうです。
今回のように「シーザー暗号だよ!」と明記されていなかったとしても、タイトル「Classical Cipher」より、「古典的暗号」などと調べることで辿り着けるかと思います。
「n文字ずらすよ!」といったヒントがない場合についても、文章そのものが暗号化されているならば、「この文字列がよく出てくるな?」といった視点で一部の文字対応が推測できることがありますね。
また、アルファベットがそれぞれ一対一で対応するシーザー暗号においては総当たり攻撃が有効ですね。(1文字ずらしで復号、2文字ずらしで復号、3文字ずらしで復号、……といった感じでずらして意味が通る文章が出てくるまで続ける)
Q9.[Web] HTML Page
CTFにおいてはタイトルが大きなヒントになります。今回はタイトルでも、問題文においてもHTMLがやたらと強調されているのでとりあえず指定されたページのソースコードを見てみましょう。
Webの問題はなにはともあれとりあえずソースを見てから考えるのがよいですね。
Q10.[Forensics] River
川の名前を探せばよいようです。
問題文にもある通り、なんとかして 「Exif情報」 を見ることができればよさそうです。
これについてはもう考えても仕方なさそうなので、Exif情報を見る方法をGoogleで調べてしまいます。
Q14.[PPC]並べ替えろ!
競技プログラミングのような問題(それにしてはちょっと簡単ですが)です。
CTF中に小さなプログラムを書くことは多々あるので、これなら書ける! という言語がひとつあると取っ掛かりやすいです。
実戦(解答)
Q1.[Misc] Test Problem
問題文よりそのままコピペします。
Q6.[Crypto] Classical Cipher
fsdz{Fdhvdu_flskhu_lv_fodvvlfdo_flskhu}
を3文字ずつ前に戻すコードを書く(コード書きたくない人はGoogleでシーザー暗号を復号してくれるページを見つけるのもよい)
Pythonで適当に書くと
cry = "fsdz{Fdhvdu_flskhu_lv_fodvvlfdo_flskhu}"
for code in list(cry):
ASC = ord(code)
#大文字の処理
if ASC > 64 and ASC < 91:
ASC -= 3
if ASC < 64:
ASC += 26
#小文字の処理
if ASC < 123 and ASC > 97:
ASC -= 3
if ASC < 97:
ASC += 26
print(chr(ASC), end="")
文字列を一旦ASCIIコードに変換、小文字と大文字だけ抽出して、それぞれ3つずつ前の文字コードに処理、文字列に戻して出力するコードです。暗号文中に出てくる大文字、_
や{
、}
について考えず、まとめて文字コードで3つ戻したあと変わってしまった部分を手作業で戻すというのもひとつの手ですね。
解ければいいという気持ちに満ち溢れたコードですが、出力をそのままFLAGの形式に合わせておしまい。
Q9.[Web] HTML Page
指定されたページのソースを見ると
<meta name="keyword" content="ctf,flag">
<meta name="description" content="flag is cpaw{9216ddf84851f15a46662eb04759d2bebacac666}">
<meta name="author" content="takahoyo">
との記述があるのでこのままFLAG部分をコピーして解答。
Q10.[Forensics] River
Macであれば画像をFinderで表示したあとツール>インスペクタを表示>GPSより鹿児島県の川が出てくるのでおしまい。
Q14.[PPC]並べ替えろ!
Cpaw14 = [15,1,93,52,66,31,87,0,42,77,46,24,99,10,19,36,27,4,58,76,2,81,50,102,33,94,20,14,80,82,49,41,12,143,121,7,111,100,60,55,108,34,150,103,109,130,25,54,57,159,136,110,3,167,119,72,18,151,105,171,160,144,85,201,193,188,190,146,210,211,63,207]
Cpaw14.sort()
Cpaw14.reverse()
print(Cpaw14)
print(*Cpaw14, sep='')
Pythonであれば、このような感じで書くと
[211, 210, 207, 201, 193, 190, 188, 171, 167, 160, 159, 151, 150, 146, 144, 143, 136, 130, 121, 119, 111, 110, 109, 108, 105, 103, 102, 100, 99, 94, 93, 87, 85, 82, 81, 80, 77, 76, 72, 66, 63, 60, 58, 57, 55, 54, 52, 50, 49, 46, 42, 41, 36, 34, 33, 31, 27, 25, 24, 20, 19, 18, 15, 14, 12, 10, 7, 4, 3, 2, 1, 0]
2112102072011931901881711671601591511501461441431361301211191111101091081051031021009994938785828180777672666360585755545250494642413634333127252420191815141210743210
といった風に出力されるので、下部分を入力します。
後記
CpawCTFは今まで触れてこなかったのですが、少し簡単すぎたというか、問題文がある上にかなり丁寧な誘導があるので解説とは、という気持ちになってしまいました。
今回はWireSharkやLinux環境といった多少の事前準備が必要な問題を飛ばしていますが、これらの問題に関してもツールの導入として最適だなと思えるものばかりだったのでおすすめです。
あと書いてるうちにLevel2が開放され……とかやってたら一生終わらないですね。