はじめての CTF! CpawCTF 全問題ヒント+解答集

# はじめに

超初心者向けの CTF(セキュリティ謎解き)[CpawCTF](https://ctf.cpaw.site/index.php)の全問題を解いたので、その解答をまとめました。各問題にはヒントと解答があります。解答は一例であり、他にも解き方はあるかもしれません。

#### 必要事項

- Python の基本知識
- Linux 環境(Windows であれば、WSL を使うと簡単。[こちら](https://zenn.dev/atsushifx/articles/wsl2-windowswsl-setup)の記事が参考になる)

#### 用語説明

- **CTF**: Capture The Flag の略。隠されたフラグを見つけるコンピュータセキュリティの競技
- **フラグ**: 問題の答え。今回は`cpaw{}`で囲まれた文字列
- フラグには **LEET 表記** と呼ばれるアルファベットを数字や記号に置き換える表記法が使われることがある。例えば、`leet`は`1337`などと表記される。[^LEET]

[^LEET]: [Wikipedia](https://ja.wikipedia.org/wiki/Leet)、[書き換え方](https://esports-doga.com/whats-leet/)

# 問題一覧

## Q1.[[Misc] Test Problem](https://ctf.cpaw.site/questions.php?qnum=1)

まずは CTF の趣旨説明の問題です。問題文を読んでみましょう。

:::note info
[Misc]とは Miscellaneous(その他)の略。
:::

<details><summary>解答</summary>

問題文中の`cpaw{this_is_Cpaw_CTF}`を入力するとクリアです。

</details>

## Q6.[[Crypto] Classical Cipher](https://ctf.cpaw.site/questions.php?qnum=6)

暗号の問題です。非常に古典的なシーザー暗号を解いてみましょう。

:::note info
[Crypto]とは Cryptography(暗号)の略。
:::

<details><summary>ヒント</summary>

解くための Python のコードを用意しました。
入力として、

```md
暗号文
シフトさせる数
```

を入力します。実行環境がない方は、[Wandbox](https://wandbox.org/permlink/Q2P56uwLzYGM6s3O)で実行できます。

```python
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)
```

</details>

<details><summary>解答</summary>

このコードを実行すると、`cpaw{Caesar_cipher_is_classical_cipher}`というフラグが得られます。

</details>

## Q7: [[Reversing] Can you execute ?](https://ctf.cpaw.site/questions.php?qnum=7)

与えられたファイルを実行する問題です。

:::note info
[Reversing]とは Reverse Engineering(逆アセンブル)の略。
:::

<details><summary>ヒント</summary>

ファイルの種類を調べるために、`file`コマンドを使いましょう。[ここ](https://qiita.com/shinnshinn/items/e11dc2bf0c2368fdc38e)を参考にしてください。

</details>

<details><summary>解答</summary>

file コマンドを実行すると、linux で実行可能なファイルであることがわかります。実行すると、`cpaw{Do_you_know_ELF_file?}`というフラグが得られます。

</details>

## Q8: [[Misc] Can you open this file ?](https://ctf.cpaw.site/questions.php?qnum=8)

ファイルを開いてフラグを探す問題です。
Q7 を先に解いたほうが良いでしょう。

<details><summary>ヒント1</summary>

ファイルの種類を調べるために、`file`コマンドを使いましょう。

</details>

<details><summary>ヒント2</summary>

file コマンドでファイルの種類を調べると、`Name of Creating Application: Microsoft Office Word`と表示されます。拡張子を`doc`に変更して、word や libreoffice で開いてみましょう。

</details>

<details><summary>解答</summary>

拡張子を doc にして、word ファイルを開くと、次のような画像が表示されます。

![q8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840768/07dce0d3-7609-b51f-0000-524a8ae84609.png)

テキストエクストラクトするか、目で見て文字を入力すると、`cpaw{Th1s_f1le_c0uld_be_0p3n3d}`というフラグが得られます。

</details>

## Q9: [[Web] HTML Page](https://ctf.cpaw.site/questions.php?qnum=9)

HTML のソースコードを見てフラグを探す問題です。

:::note info
[Web]とは Web サイトの脆弱性を見つける問題。
:::

<details><summary>ヒント</summary>

ページのソースコードを見て、フラグを探しましょう。
フラグは`cpaw`で始まります。

</details>

<details><summary>解答</summary>

`ctrl + u`または、`右クリック -> ページのソースを表示`でソースコードを見ることができます。

![q9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840768/8d54555b-e051-54e7-ce1b-f2b5115c87b9.png)

ソースコードをで、`cpaw`を検索すると、`cpaw{9216ddf84851f15a46662eb04759d2bebacac666}`というフラグが得られます。
何らかの`SHA-1`ハッシュ値のようですが、復号化できませんでした。

</details>

## Q10: [[Forensics] River](https://ctf.cpaw.site/questions.php?qnum=10)

EXIF 情報を見てフラグを探す問題です。[^forensics]

[^forensics]: [forensics 入門](https://qiita.com/knqyf263/items/6ebf06e27be7c48aab2e)

:::note info
[Forensics]とはコンピュータのファイルなどの中に隠された情報を見つける問題。
:::

<details><summary>ヒント</summary>

EXIF 情報を見るために、`exiftool`コマンドを使うか、オンラインツールを使いましょう。Google 画像検索でも可能です。

</details>

<details><summary>解答</summary>

[EXIF 確認くん](http://exif-check.org/)を使って、画像の撮影位置を見ると、甲突川とわかります。
![q10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840768/ee2199c5-c625-13cd-6d96-1bc3ba46b5a7.png)
よって、フラグは`cpaw{koutsukigawa}`です。

</details>

## Q11: [[Network]pcap](https://ctf.cpaw.site/questions.php?qnum=11)

pcap ファイルを解析してフラグを探す問題です。
[wireshark](https://www.wireshark.org/)を使えば開けるのですが、コマンドラインで解析する方法もあります。

:::note info
[Network]とはネットワークの通信を解析する問題。
:::

<details><summary>ヒント</summary>

バイナリ内の文字列を見るために、`strings`コマンドを使いましょう。

</details>

<details><summary>解答</summary>

`strings`コマンドで pcap ファイルを解析すると、`Qcpaw{gochi_usa_kami}`というフラグが得られます。

</details>

## Q12: [[Crypto]HashHashHash!](https://ctf.cpaw.site/questions.php?qnum=12)

ハッシュの問題です。ハッシュ値を解析してフラグを探しましょう。ハッシュとは、どんな長さのデータでも固定長のデータに変換する関数です。[^hash]

[^hash]: [ハッシュ関数](https://qiita.com/KEINOS/items/c92268386d265042ea16)

<details><summary>ヒント</summary>

ハッシュは復元が困難です。有名な単語であれば、[SHA-1 Center](https://sha1.gromweb.com/)で検索すると見つかるかもしれません。

</details>

<details><summary>解答</summary>

`SHA-1`ハッシュ値を複合すると、`cpaw{Shal}`というフラグが得られます。

</details>

## Q13: [[Stego]隠されたフラグ](https://ctf.cpaw.site/questions.php?qnum=13)

画像の中にフラグが隠されています。画像を解析してフラグを探しましょう。

:::note info
[Stego]とは Steganography の略。画像や音声などのデータに隠された情報を見つける問題。
:::

<details><summary>ヒント1</summary>

画像の左上、右下を見てみましょう。

</details>

<details><summary>ヒント2</summary>

文字列は、`-.-. .--. .- .-- .... .. -.. -.. . -. ..--.- -- . ... ... .- --. . ---... -.--.-`です。 -、.と空白のみが使われているところから、モールス信号であることがわかります。[ここ](https://morsedecoder.com/)でデコードしてみましょう。

</details>

<details><summary>解答</summary>

写真のかどに書かれたモールス信号を解釈すると、`cpaw{HIDDEN_MESSAGE:)}`というフラグが得られます。

</details>

## Q14: [[PPC]並べ替えろ!](https://ctf.cpaw.site/questions.php?qnum=14)

指示されて通りに数字を並べ替える問題です。

:::note info
[PPC]とは Professional Programming and Coding の略。プログラミングやコーディングの問題。
:::

<details><summary>ヒント</summary>

python コードを用意しました。リストを降順にソートして、文字列として結合します。

```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]))
```

</details>

<details><summary>解答</summary>

このコードを実行すると、`cpaw{2112102072011931901881711671601591511501461441431361301211191111101091081051031021009994938785828180777672666360585755545250494642413634333127252420191815141210743210}`というフラグが得られます。

</details>

## Q15: [[Web] Redirect](https://ctf.cpaw.site/questions.php?qnum=15)

リダイレクト中を見てフラグを探す問題です。

<details><summary>ヒント</summary>

`curl`コマンドを使って、リダイレクト先を見てみましょう。

</details>

<details><summary>解答</summary>

`curl`コマンドでリダイレクト先を見ると、`cpaw{4re_y0u_1ook1ng_http_h3ader?}`というフラグが得られます。

</details>

## Q16: [[Network+Forensic]HTTP Traffic](https://ctf.cpaw.site/questions.php?qnum=16)

パケットキャプチャファイルから Web ページを復元する問題です。

<details><summary>ヒント1</summary>

[wireshark](https://www.wireshark.org/)を使って、pcap ファイルを開いてみましょう。

</details>

<details><summary>ヒント2</summary>

ファイル > オブジェクトをエクスポート > HTTP を選択して、アクセスしたファイルを保存します。

</details>

<details><summary>解答</summary>

`wireshark`で HTTP パケットをエクスポートすると、接続時に読み込まれたファイルが復元されます。button2.js を js フォルダに、.css ファイルを css フォルダに保存します。正しいディレクトリにファイルを保存すると、`cpaw{Y0u_r3st0r3d_7his_p4ge}`というフラグが得られます。

![q16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840768/ffc17463-dfaa-0db6-ea95-8a37a386d976.png)

</details>

## Q17: [[Recon]Who am I ?](https://ctf.cpaw.site/questions.php?qnum=17)

Google 検索をうまく使ってフラグを探す問題です。

:::note info
[Recon]とは Reconnaissance(偵察)の略。情報収集をする問題。
:::

<details><summary>解答</summary>

`@porisuteru、スペシャルフォース2`で検索すると、ゲームのアカウント名が`parock`であることがわかります。よって、フラグは`cpaw{parock}`です。

</details>

## Q18: [[Forensic]leaf in forest](https://ctf.cpaw.site/questions.php?qnum=18)

バイナリファイル?を解析してフラグを探す問題です。

<details><summary>ヒント1</summary>

バイナリファイルを解析するために、`strings`コマンドを使いましょう。`strings $filename > log.txt`で、バイナリファイルの文字列をテキストファイルに保存できます。

</details>

<details><summary>ヒント2</summary>

ファイルの中は`lovelive!`と繰り返し書かれています。まずは、`lovelive!`を削除してみましょう。

</details>

<details><summary>解答</summary>

`strings`コマンドでバイナリファイルを解析し、`sed`コマンドで`lovelive!`を削除します。

```bash
strings misk100 | sed 's/lovelive\!//g'
# e!CCCelive!lovelivPPPovelive!loveAAAe!lovWWWve!{{{elive!loveliMMMelive!lovelGGG!lovelivRRRovelive!lEEElive!PPPelive!}}}
```

さらに、`sed`コマンドで英小文字を削除します。

```bash
strings misk100 | sed 's/lovelive\!//g' | sed 's/[a-z]//g'
# !CCC!PPP!AAA!WWW!{{{!MMM!GGG!RRR!EEE!PPP!}}}
```

よって、フラグは`cpaw{mgrep}`です。

ちなみに、python で三文字連続しているものを抽出すれば直接得られます。

```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)
```

</details>

## Q19: [[Misc]Image!](https://ctf.cpaw.site/questions.php?qnum=19)

zip ファイルを解凍してフラグを探す問題です。

<details><summary>ヒント</summary>

例えば word ファイルの実態が zip ファイルであることを知っていると得するでしょう。
このファイルはなんのファイルか調べてみましょう。

</details>

<details><summary>解答</summary>

`file`コマンドでファイルの種類を調べると、`OpenDocument Drawing`と表示されます。拡張子を`odg`に変更して、libreoffice や word で開けます。開くと、`cpaw{It_is_fun__isn't_it?}`というフラグが得られます。

![q19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840768/f97261ae-5b25-cf41-015c-f98a5a8c420e.png)

</details>

## Q20: [[Crypto]Block Cipher](https://ctf.cpaw.site/questions.php?qnum=20)

C 言語を解読する問題です。

<details><summary>ヒント</summary>

実際に解読しても良いし、適当にいくつかの文字列を入れてみて、どのように暗号化されているかを推測しても良いでしょう。
また、AI に聞けば仕組みを答えてくれるはずです。

</details>

<details><summary>解説</summary>

単に文字列を一定毎に反転しているだけです。
暗号文を見ると、Your という言葉が見えるので 4 文字毎に反転していることがわかります。
二回反転すると元に戻るので、このプログラムに暗号文と 4 を入力すれば、元の文字列が得られます。
フラグは`cpaw{Your_deciphering_skill_is_great}`です。

Python で実装すると次のようになります。

```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)
```

</details>

## Q21: [[Reversing]reversing easy!](https://ctf.cpaw.site/questions.php?qnum=21)

逆アセンブル問題です。アセンブル言語を読んでフラグを探しましょう。
32bit のバイナリなので、実行には`sudo apt install lib32z1`が必要です。

<details><summary>ヒント</summary>

実行すると、`cpaw{}`と表示されます。問題文通りなら出力のみを忘れたはずなので、`objdump`コマンドで逆アセンブルしてみましょう。

</details>

<details><summary>解答</summary>

`objdump -d -M intel --no-show-raw-insn --endian=little rev100 > rev100.log`などとして、逆アセンブル結果を保存します。
`rev100.log`を見ると、`0804849d <main>:`の途中に

```asm
 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`コマンドでバイナリファイルを解析しても、わかってしまいます。

また、[radare2](https://github.com/radare/radare2#install)を使うとわかりやすく逆アセンブルできるようです。[^radare2]

[^radare2]: [radare2 を用いて Q21 を解いている writeup](https://www.serotoninpower.club/archives/894/#q21-reversing-reversing-easy)

</details>

<details><summary>スマートな方法</summary>

gdb を用いてデバッグし、出力できていない原因を探り、プリントする処理を正しく実行する方法もあるようです。[^gdb]
(`cmpl`が比較命令、`je`がジャンプ命令を意味します。また、`0x1c(%esp)`は`$esp+0x1c`を意味することを知っておくとわかりやすいはずです。)

[^gdb]: [gdb を用いて Q21 を解いている writeup](https://www.tuatmcc.com/blog/2024-04-24-cpawctf/#q21reversingreversing-easy)

</details>

## Q22: [[Web]Baby's SQLi - Stage 1-](https://ctf.cpaw.site/questions.php?qnum=22)

SQL の確認問題です。SQL をしっかり学びたい方は、[こちら](https://sql.main.jp/)。SQL のコマンドをまとめた[記事](https://qiita.com/tatsuya4150/items/69c2c9d318e5b93e6ccd)はこちらです。

<details><summary>解答</summary>

`SELECT * FROM palloc_home`を入力すると、`cpaw{palloc_escape_from_stage1;(}`というフラグが得られます。

</details>

## Q23: [[Reversing]またやらかした！](https://ctf.cpaw.site/questions.php?qnum=23)

逆アセンブル問題です。アセンブル言語を読んでフラグを探しましょう。

<details><summary>ヒント</summary>

Q21 と同様に、`objdump`コマンドで逆アセンブルしてみましょう。

</details>

<details><summary>解答</summary>

`objdump -d -M intel --no-show-raw-insn --endian=little rev200 > rev200.log`などとして、逆アセンブル結果を保存します。フラグが見つからないので諦めてコードを読み取ります。(真剣にやってもいいですが、Gemini にやってもらったほうが楽です。)

```python
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!!}`というフラグが得られます。

</details>

<details><summary>スマートな方法</summary>

出力を忘れているので、スタック内に積まれた文字を確認する[こちら](https://www.tuatmcc.com/blog/2024-04-24-cpawctf/#q23reversing%E3%81%BE%E3%81%9F%E3%82%84%E3%82%89%E3%81%8B%E3%81%97%E3%81%9F)のほうがスマートです。
ちなみに、Ghidra というツールを使うと、簡単なようです。[^ghidra]

[^ghidra]: [Ghidra を用いて Q23 を解いている writeup](https://note.com/misoterasu/n/nab67d55d0689)

</details>

## Q24: [[Web]Baby's SQLi - Stage 2-](https://ctf.cpaw.site/questions.php?qnum=24)

SQL インジェクションの問題です。

まずは、Q22 を解いて[ここ](https://ctf.spica.bz/baby_sql/stage2_7b20a808e61c8573461cf92b1fe63b3f/index.php)にアクセスします。

<details><summary>解答</summary>

基本通り、パスワードに`' OR 1=1 --`を入力すると、`cpaw{p@ll0c_1n_j@1l3:)}'`というフラグが得られます。[^SQL]

[^SQL]: [SQL インジェクションの解説](https://qiita.com/ryota_seto/items/4ad1a9c2ef6c5f763d05)

</details>

## Q26: [[PPC]Remainder theorem](https://ctf.cpaw.site/questions.php?qnum=26)

あまりについての問題です。

:::note info

問題名の Remainder theorem は中国剰余定理のことです。中国剰余定理とは、2 つの整数$m1,m2$が互いに素であるとき、$x \equiv a_1 \pmod{m1}$かつ$x \equiv a_2 \pmod{m2}$を満たす整数$x$が一意に存在するという定理です。

:::

<details><summary>ヒント</summary>

全探索するしかありません。

</details>

<details><summary>解答</summary>

$1584891$で割った余りが$32134$であるような数は、$32134$から$1584891$ずつ増やしていくと見つかります。中国剰余定理より、高々$3438478$回の探索で答えが見つかります。

```python
a = 32134; b = 1584891; c = 193127; d = 3438478
x = a
while x % d != c:
    x += b
print(x)
```

実行すると、`cpaw{35430270439}`がフラグとわかります。

</details>

## Q28: [[Network] Can you login？](https://ctf.cpaw.site/questions.php?qnum=28)

パケットキャプチャファイルを見て、暗号化されていない情報からフラグを探す問題です。

<details><summary>ヒント</summary>

`wireshark`でパケットキャプチャファイルを開いて、なにをしているかを確認しましょう。

</details>

<details><summary>解答</summary>

`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}`というフラグが得られます。

</details>

## Q29: [[Crypto] Common World](https://ctf.cpaw.site/questions.php?qnum=29)

RSA 暗号の問題です。暗号文を解読してフラグを探しましょう。


<details><summary>ヒント1</summary>

ページ内の[これは…？]からヒントを得ることができます。
ヒントファイルには同一の平文が暗号化されています。

</details>

<details><summary>ヒント2</summary>

これには、[有名な攻撃](https://zenn.dev/anko/articles/ctf-crypto-rsa#%E6%94%BB%E6%92%83)が関わっています。

</details>

<details><summary>解答</summary>

`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$です。

```python
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}`です。

</details>

<details><summary>別解</summary>

$e_1$と$e_2$の差が 2 であることから、$c_1m^2 = c_2 \mod N$となります。今回$c_2$が$c_1$の倍数であり、$c_2/c_1$が平方数であることから、$c_2/c_1$を平方根にすることで平文が得られます。

```python
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)
```

</details>

<details><summary>今回は使用できないが、一般的な解法</summary>

$N$が有名な素数であることを期待して、[ここ](http://www.factordb.com/)で素因数分解してみます。

$N$を素因数分解して、$N=pq(p<q)$とします。
以降は RSA を復号化します。

```python
phi = (p-1)*(q-1)
d = pow(e,-1,phi)
m = pow(c,d,N)
print(m)
```

しかし、今回は逆元が存在しません。(phiとeが互いに素でないため）
そのため今回は使えません。

</details>