はじめに
超初心者向けの CTF(セキュリティ謎解き)CpawCTFの全問題を解いたので、その解答をまとめました。各問題にはヒントと解答があります。解答は一例であり、他にも解き方はあるかもしれません。
必要事項
- Python の基本知識
- Linux 環境(Windows であれば、WSL を使うと簡単。こちらの記事が参考になる)
用語説明
- CTF: Capture The Flag の略。隠されたフラグを見つけるコンピュータセキュリティの競技
-
フラグ: 問題の答え。今回は
cpaw{}
で囲まれた文字列 - フラグには LEET 表記 と呼ばれるアルファベットを数字や記号に置き換える表記法が使われることがある。例えば、
leet
は1337
などと表記される。1
問題一覧
Q1.[Misc] Test Problem
まずは CTF の趣旨説明の問題です。問題文を読んでみましょう。
[Misc]とは Miscellaneous(その他)の略。
解答
問題文中のcpaw{this_is_Cpaw_CTF}
を入力するとクリアです。
Q6.[Crypto] Classical Cipher
暗号の問題です。非常に古典的なシーザー暗号を解いてみましょう。
[Crypto]とは Cryptography(暗号)の略。
ヒント
解くための Python のコードを用意しました。
入力として、
暗号文
シフトさせる数
を入力します。実行環境がない方は、Wandboxで実行できます。
C = input()
shift = int(input())
M = ""
for c in C:
code = ord(c)
if c.islower():
code = (code - ord('a') - shift) % 26 + ord('a')
elif c.isupper():
code = (code - ord('A') - shift) % 26 + ord('A')
M += chr(code)
print(M)
解答
このコードを実行すると、cpaw{Caesar_cipher_is_classical_cipher}
というフラグが得られます。
Q7: [Reversing] Can you execute ?
与えられたファイルを実行する問題です。
[Reversing]とは Reverse Engineering(逆アセンブル)の略。
ヒント
ファイルの種類を調べるために、file
コマンドを使いましょう。ここを参考にしてください。
解答
file コマンドを実行すると、linux で実行可能なファイルであることがわかります。実行すると、cpaw{Do_you_know_ELF_file?}
というフラグが得られます。
Q8: [Misc] Can you open this file ?
ファイルを開いてフラグを探す問題です。
Q7 を先に解いたほうが良いでしょう。
ヒント1
ファイルの種類を調べるために、file
コマンドを使いましょう。
ヒント2
file コマンドでファイルの種類を調べると、Name of Creating Application: Microsoft Office Word
と表示されます。拡張子をdoc
に変更して、word や libreoffice で開いてみましょう。
解答
拡張子を doc にして、word ファイルを開くと、次のような画像が表示されます。
テキストエクストラクトするか、目で見て文字を入力すると、cpaw{Th1s_f1le_c0uld_be_0p3n3d}
というフラグが得られます。
Q9: [Web] HTML Page
HTML のソースコードを見てフラグを探す問題です。
[Web]とは Web サイトの脆弱性を見つける問題。
ヒント
ページのソースコードを見て、フラグを探しましょう。
フラグはcpaw
で始まります。
解答
ctrl + u
または、右クリック -> ページのソースを表示
でソースコードを見ることができます。
ソースコードをで、cpaw
を検索すると、cpaw{9216ddf84851f15a46662eb04759d2bebacac666}
というフラグが得られます。
何らかのSHA-1
ハッシュ値のようですが、復号化できませんでした。
Q10: [Forensics] River
EXIF 情報を見てフラグを探す問題です。2
[Forensics]とはコンピュータのファイルなどの中に隠された情報を見つける問題。
ヒント
EXIF 情報を見るために、exiftool
コマンドを使うか、オンラインツールを使いましょう。Google 画像検索でも可能です。
解答
EXIF 確認くんを使って、画像の撮影位置を見ると、甲突川とわかります。
よって、フラグはcpaw{koutsukigawa}
です。
Q11: [Network]pcap
pcap ファイルを解析してフラグを探す問題です。
wiresharkを使えば開けるのですが、コマンドラインで解析する方法もあります。
[Network]とはネットワークの通信を解析する問題。
ヒント
バイナリ内の文字列を見るために、strings
コマンドを使いましょう。
解答
strings
コマンドで pcap ファイルを解析すると、Qcpaw{gochi_usa_kami}
というフラグが得られます。
Q12: [Crypto]HashHashHash!
ハッシュの問題です。ハッシュ値を解析してフラグを探しましょう。ハッシュとは、どんな長さのデータでも固定長のデータに変換する関数です。3
ヒント
ハッシュは復元が困難です。有名な単語であれば、SHA-1 Centerで検索すると見つかるかもしれません。
解答
SHA-1
ハッシュ値を複合すると、cpaw{Shal}
というフラグが得られます。
Q13: [Stego]隠されたフラグ
画像の中にフラグが隠されています。画像を解析してフラグを探しましょう。
[Stego]とは Steganography の略。画像や音声などのデータに隠された情報を見つける問題。
ヒント1
画像の左上、右下を見てみましょう。
ヒント2
文字列は、-.-. .--. .- .-- .... .. -.. -.. . -. ..--.- -- . ... ... .- --. . ---... -.--.-
です。 -、.と空白のみが使われているところから、モールス信号であることがわかります。ここでデコードしてみましょう。
解答
写真のかどに書かれたモールス信号を解釈すると、cpaw{HIDDEN_MESSAGE:)}
というフラグが得られます。
Q14: [PPC]並べ替えろ!
指示されて通りに数字を並べ替える問題です。
[PPC]とは Professional Programming and Coding の略。プログラミングやコーディングの問題。
ヒント
python コードを用意しました。リストを降順にソートして、文字列として結合します。
A = [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]
A.sort(reverse=True)
print("".join([str(x) for x in A]))
解答
このコードを実行すると、cpaw{2112102072011931901881711671601591511501461441431361301211191111101091081051031021009994938785828180777672666360585755545250494642413634333127252420191815141210743210}
というフラグが得られます。
Q15: [Web] Redirect
リダイレクト中を見てフラグを探す問題です。
ヒント
curl
コマンドを使って、リダイレクト先を見てみましょう。
解答
curl
コマンドでリダイレクト先を見ると、cpaw{4re_y0u_1ook1ng_http_h3ader?}
というフラグが得られます。
Q16: [Network+Forensic]HTTP Traffic
パケットキャプチャファイルから Web ページを復元する問題です。
ヒント1
wiresharkを使って、pcap ファイルを開いてみましょう。
ヒント2
ファイル > オブジェクトをエクスポート > HTTP を選択して、アクセスしたファイルを保存します。
解答
wireshark
で HTTP パケットをエクスポートすると、接続時に読み込まれたファイルが復元されます。button2.js を js フォルダに、.css ファイルを css フォルダに保存します。正しいディレクトリにファイルを保存すると、cpaw{Y0u_r3st0r3d_7his_p4ge}
というフラグが得られます。
Q17: [Recon]Who am I ?
Google 検索をうまく使ってフラグを探す問題です。
[Recon]とは Reconnaissance(偵察)の略。情報収集をする問題。
解答
@porisuteru、スペシャルフォース2
で検索すると、ゲームのアカウント名がparock
であることがわかります。よって、フラグはcpaw{parock}
です。
Q18: [Forensic]leaf in forest
バイナリファイル?を解析してフラグを探す問題です。
ヒント1
バイナリファイルを解析するために、strings
コマンドを使いましょう。strings $filename > log.txt
で、バイナリファイルの文字列をテキストファイルに保存できます。
ヒント2
ファイルの中はlovelive!
と繰り返し書かれています。まずは、lovelive!
を削除してみましょう。
解答
strings
コマンドでバイナリファイルを解析し、sed
コマンドでlovelive!
を削除します。
strings misk100 | sed 's/lovelive\!//g'
# e!CCCelive!lovelivPPPovelive!loveAAAe!lovWWWve!{{{elive!loveliMMMelive!lovelGGG!lovelivRRRovelive!lEEElive!PPPelive!}}}
さらに、sed
コマンドで英小文字を削除します。
strings misk100 | sed 's/lovelive\!//g' | sed 's/[a-z]//g'
# !CCC!PPP!AAA!WWW!{{{!MMM!GGG!RRR!EEE!PPP!}}}
よって、フラグはcpaw{mgrep}
です。
ちなみに、python で三文字連続しているものを抽出すれば直接得られます。
with open("misc100") as f:
data = f.read()
ans = ""
for i in range(len(data)-2):
if data[i] == data[i+1] == data[i+2]:
ans += data[i]
print(ans)
Q19: [Misc]Image!
zip ファイルを解凍してフラグを探す問題です。
ヒント
例えば word ファイルの実態が zip ファイルであることを知っていると得するでしょう。
このファイルはなんのファイルか調べてみましょう。
解答
file
コマンドでファイルの種類を調べると、OpenDocument Drawing
と表示されます。拡張子をodg
に変更して、libreoffice や word で開けます。開くと、cpaw{It_is_fun__isn't_it?}
というフラグが得られます。
Q20: [Crypto]Block Cipher
C 言語を解読する問題です。
ヒント
実際に解読しても良いし、適当にいくつかの文字列を入れてみて、どのように暗号化されているかを推測しても良いでしょう。
また、AI に聞けば仕組みを答えてくれるはずです。
解説
単に文字列を一定毎に反転しているだけです。
暗号文を見ると、Your という言葉が見えるので 4 文字毎に反転していることがわかります。
二回反転すると元に戻るので、このプログラムに暗号文と 4 を入力すれば、元の文字列が得られます。
フラグはcpaw{Your_deciphering_skill_is_great}
です。
Python で実装すると次のようになります。
S = "cpaw{ruoYced_ehpigniriks_i_llrg_stae}"
inner = S[5:-1]
block = 4
ans = ""
for i in range(0, len(inner), block):
ans += inner[i:i+block][::-1]
print(ans)
Q21: [Reversing]reversing easy!
逆アセンブル問題です。アセンブル言語を読んでフラグを探しましょう。
32bit のバイナリなので、実行にはsudo apt install lib32z1
が必要です。
ヒント
実行すると、cpaw{}
と表示されます。問題文通りなら出力のみを忘れたはずなので、objdump
コマンドで逆アセンブルしてみましょう。
解答
objdump -d -M intel --no-show-raw-insn --endian=little rev100 > rev100.log
などとして、逆アセンブル結果を保存します。
rev100.log
を見ると、0804849d <main>:
の途中に
01: mov DWORD PTR [esp+0x46],0x77617063
02: mov WORD PTR [esp+0x4a],0x7b
03: mov DWORD PTR [esp+0x20],0x79
04: mov DWORD PTR [esp+0x24],0x61
05: mov DWORD PTR [esp+0x28],0x6b
06: mov DWORD PTR [esp+0x2c],0x69
07: mov DWORD PTR [esp+0x30],0x6e
08: mov DWORD PTR [esp+0x34],0x69
09: mov DWORD PTR [esp+0x38],0x6b
10: mov DWORD PTR [esp+0x3c],0x75
11: mov DWORD PTR [esp+0x40],0x21
12: mov WORD PTR [esp+0x15],0xa7d
と書かれており、それぞれを ASCII コードとして変換すると0x77617063
はcpaw
(リトルエンディアン)、その後に一文字ずつ{yakiniku!§
と書かれています。
よって、フラグはcpaw{yakiniku!}
と推測されます。
ちなみに、strings
コマンドでバイナリファイルを解析しても、わかってしまいます。
スマートな方法
gdb を用いてデバッグし、出力できていない原因を探り、プリントする処理を正しく実行する方法もあるようです。5
(cmpl
が比較命令、je
がジャンプ命令を意味します。また、0x1c(%esp)
は$esp+0x1c
を意味することを知っておくとわかりやすいはずです。)
Q22: [Web]Baby's SQLi - Stage 1-
SQL の確認問題です。SQL をしっかり学びたい方は、こちら。SQL のコマンドをまとめた記事はこちらです。
解答
SELECT * FROM palloc_home
を入力すると、cpaw{palloc_escape_from_stage1;(}
というフラグが得られます。
Q23: [Reversing]またやらかした!
逆アセンブル問題です。アセンブル言語を読んでフラグを探しましょう。
ヒント
Q21 と同様に、objdump
コマンドで逆アセンブルしてみましょう。
解答
objdump -d -M intel --no-show-raw-insn --endian=little rev200 > rev200.log
などとして、逆アセンブル結果を保存します。フラグが見つからないので諦めてコードを読み取ります。(真剣にやってもいいですが、Gemini にやってもらったほうが楽です。)
S = ["0x7a", "0x69", "0x78", "0x6e", "0x62", "0x6f", "0x7c", "0x6b", "0x77", "0x78", "0x74", "0x38", "0x38", "0x64"]
S = [int(x, 16) for x in S]
k = int("0x19",16)
for i in range(14):
S[i] ^= k
print("".join([chr(x) for x in S]))
実行すると、cpaw{vernam!!}
というフラグが得られます。
Q24: [Web]Baby's SQLi - Stage 2-
SQL インジェクションの問題です。
まずは、Q22 を解いてここにアクセスします。
解答
基本通り、パスワードに' OR 1=1 --
を入力すると、cpaw{p@ll0c_1n_j@1l3:)}'
というフラグが得られます。7
Q26: [PPC]Remainder theorem
あまりについての問題です。
問題名の Remainder theorem は中国剰余定理のことです。中国剰余定理とは、2 つの整数$m1,m2$が互いに素であるとき、$x \equiv a_1 \pmod{m1}$かつ$x \equiv a_2 \pmod{m2}$を満たす整数$x$が一意に存在するという定理です。
ヒント
全探索するしかありません。
解答
$1584891$で割った余りが$32134$であるような数は、$32134$から$1584891$ずつ増やしていくと見つかります。中国剰余定理より、高々$3438478$回の探索で答えが見つかります。
a = 32134; b = 1584891; c = 193127; d = 3438478
x = a
while x % d != c:
x += b
print(x)
実行すると、cpaw{35430270439}
がフラグとわかります。
Q28: [Network] Can you login?
パケットキャプチャファイルを見て、暗号化されていない情報からフラグを探す問題です。
ヒント
wireshark
でパケットキャプチャファイルを開いて、なにをしているかを確認しましょう。
解答
wireshark
でパケットキャプチャファイルを開くと、ftp://118.27.110.77
にcpaw_user,5f4dcc3b5aa765d61d8327deb882cf99
でログインしていることがわかります。ftp
コマンドで接続、ログインして、ls -a
でファイルを確認すると、.hidden_flag_file
が見つかります。get .hidden_flag_file
でファイルをダウンロードし、中身を見ると、cpaw{f4p_sh0u1d_b3_us3d_in_3ncryp4i0n}
というフラグが得られます。
Q29: [Crypto] Common World
RSA 暗号の問題です。暗号文を解読してフラグを探しましょう。
ヒント1
ページ内の[これは…?]からヒントを得ることができます。
ヒントファイルには同一の平文が暗号化されています。
ヒント2
これには、有名な攻撃が関わっています。
解答
Common Modulus Attack
によって解くことができます。
いま、平文を$m$、暗号文を$c_1, c_2$、公開鍵を$(N, e_1), (N, e_2)$とします。$c_1 = m^{e_1} \mod N, c_2 = m^{e_2} \mod N$です。今回は、$e_1, e_2$が互いに素であるため、$e_1s + e_2t = 1$を満たす$s, t$が存在します。このとき、$m^{e_1s}m^{e_2t} = m^{e_1s + e_2t} = m \mod N$です。よって、$c_1^s c_2^t = m \mod N$です。
def extgcd(a, b): # 拡張ユークリッドの互除法
if b == 0:
return a, 1, 0
d, x, y = extgcd(b, a % b)
return d, y, x - a // b * y
gcd, s, t = extgcd(e1, e2)
assert gcd == 1 # e1, e2 は互いに素
m = pow(c1, s, N) * pow(c2, t, N) % N
print(m)
実行すると、424311244315114354
が得られます。よって、フラグはcpaw{424311244315114354}
です。
別解
$e_1$と$e_2$の差が 2 であることから、$c_1m^2 = c_2 \mod N$となります。今回$c_2$が$c_1$の倍数であり、$c_2/c_1$が平方数であることから、$c_2/c_1$を平方根にすることで平文が得られます。
k = c2//c1
print(k)
ng = 0; ok = k
while ok - ng > 1:
mid = (ok + ng)//2
if mid**2 < k:
ng = mid
else:
ok = mid
print(ok)
今回は使用できないが、一般的な解法
$N$が有名な素数であることを期待して、ここで素因数分解してみます。
$N$を素因数分解して、$N=pq(p<q)$とします。
以降は RSA を復号化します。
phi = (p-1)*(q-1)
d = pow(e,-1,phi)
m = pow(c,d,N)
print(m)
しかし、今回は逆元が存在しません。(phiとeが互いに素でないため)
そのため今回は使えません。