# CpawCTF by asn407
## はじめに
### CpawCTF
https://ctf.cpaw.site/
### 筆者の環境
- Windows10
- WSL2
### 諸注意
CpawCTFは有名なCTF練習サイトであるため、問題文そのものを検索すれば答えにたどり着きます(多くの方が解説を行っているため)。
本ページでは、そのようなサイトを用いることなく、作問者が想定する手順で答えにたどり着くような解答作成に取り組みましたが、もしかすると一部の解答ではあまり賢くない、もしくは正規ルートでない解き方をしているかもしれません。
その場合、お手数ですがコメント等の指摘をしてくだされば幸いです。
## Level 1
### Q1
#### 問題文
この問題の答え(FLAG)は、cpaw{this_is_Cpaw_CTF} です。
下の入力欄にFLAGを入力してSubmitボタンを押して、答えを送信しましょう!
Enjoy CpawCTF!!!!
#### 答え
```
cpaw{this_is_Cpaw_CTF}
```
#### 解説
問題文を読み、素直に従えばフラグ獲得。
(cpaw{\~}全体が答え。\~のみが答えでないことに注意)
### Q2
#### 問題文
暗号には大きく分けて、古典暗号と現代暗号の2種類があります。特に古典暗号では、古代ローマの軍事的指導者ガイウス・ユリウス・カエサル(英語読みでシーザー)が初めて使ったことから、名称がついたシーザー暗号が有名です。これは3文字分アルファベットをずらすという単一換字式暗号の一つです。次の暗号文は、このシーザー暗号を用いて暗号化しました。暗号文を解読してフラグを手にいれましょう。
暗号文: fsdz{Fdhvdu_flskhu_lv_fodvvlfdo_flskhu}
#### 答え
```
cpaw{Caesar_cipher_is_classical_cipher}
```
#### 解説
1. 問題文の`fsdz`から始まる暗号文をコピー。
2. Googleで「シーザー暗号 変換 サイト」と検索。
3. 「DenCode」という名前のサイトにアクセス:https://dencode.com/ja/cipher/caesar
4. コピーした暗号文をペーストし、エンコードされたものがフラグとなる。
### Q3
#### 問題文
拡張子がないファイルを貰ってこのファイルを実行しろと言われたが、どうしたら実行出来るのだろうか。
この場合、UnixやLinuxのとあるコマンドを使ってファイルの種類を調べて、適切なOSで実行するのが一般的らしいが…
問題ファイル: exec_me
#### 答え
```
cpaw{Do_you_know_ELF_file?}
```
#### 解説
Linux環境にて以下のコマンドを実行する。
```
$ file exec_me
```
実行結果
```
exec_me: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=663a3e0e5a079fddd0de92474688cd6812d3b550, not stripped
```
ELFとは「Executable and Linking Format」の略であり,Red Hatを始めとするLinuxディストリビューションの多くでは標準バイナリ形式として採用されている(Google先生より)。
参考:https://www.itmedia.co.jp/help/tips/linux/l0448.html
という訳なので、以下のコマンドを実行すると、フラグを得る。
```
$ ./exec_me
```
### Q4
#### 問題文
このファイルを開きたいが拡張子がないので、どのような種類のファイルで、どのアプリケーションで開けば良いかわからない。
どうにかして、この拡張子がないこのファイルの種類を特定し、どのアプリケーションで開くか調べてくれ。
問題ファイル: open_me
#### 答え
```
cpaw{Th1s_f1le_c0uld_be_0p3n3d}
```
#### 解説
Q3同様にファイル形式を調べる。
```
$ file open_me
```
実行結果
```
open_me: Composite Document File V2 Document, Little Endian, Os: Windows, Version 10.0, Code page: 932, Author: v, Template: Normal.dotm, Last Saved By: v, Revision Number: 1, Name of Creating Application: Microsoft Office Word, Total Editing Time: 28:00, Create Time/Date: Mon Oct 12 04:27:00 2015, Last Saved Time/Date: Mon Oct 12 04:55:00 2015, Number of Pages: 1, Number of Words: 3, Number of Characters: 23, Security: 0
```
「Composite Document File V2 Document」がこのファイルの形式になるため、Google検索。
色々調べると「.doc」っぽいことが分かるので、「open_me.doc」としてファイルを開き、フラグを得る。
### Q5
#### 問題文
HTML(Hyper Text Markup Language)は、Webサイトを記述するための言語です。
ページに表示されている部分以外にも、ページをより良くみせるためのデータが含まれています。
次のWebサイトからフラグを探して下さい。
http://q9.ctf.cpaw.site
※この問題のサーバへの攻撃はお止めください。
#### 答え
```
cpaw{9216ddf84851f15a46662eb04759d2bebacac666}
```
#### 解説
サイトにアクセスする。
「ページに表示されている部分以外」を見るために、F12キーを押しページの情報を表示する(定石)。
そんなに大きくないページなので、ソースコードを上から読む。
(コメントアウトだろうなと予想がついていたので)
headタブ中の以下の一文よりフラグを得る。
```
<meta name="description" content="flag is cpaw{9216ddf84851f15a46662eb04759d2bebacac666}">
```
### Q6
#### 問題文
JPEGという画像ファイルのフォーマットでは、撮影時の日時、使われたカメラ、位置情報など様々な情報(Exif情報)が付加されることがあるらしい。
この情報から、写真に写っている川の名前を特定して欲しい。
問題ファイル: river.jpg
FLAGの形式は、"cpaw{river_name}"
例:隅田川 → cpaw{sumidagawa}
#### 答え
```
cpaw{koutsukigawa}
```
#### 解説
river.jpgのプロパティを開き、詳細タブから以下の情報を見つける。
```
GPS----
緯度 31; 35; 2.759999...
経度 130; 32; 51.72720000...
```
緯度と経度の座標を入手したので、Googleにて以下のキーワードで検索する。
```
31°35'2.76"N130°32'51.7272"E
```
表示された川の名前からフラグを得る。
### Q7
#### 問題文
ネットワークを流れているデータはパケットというデータの塊です。
それを保存したのがpcapファイルです。
pcapファイルを開いて、ネットワークにふれてみましょう!
pcapファイル
#### 答え
```
cpaw{gochi_usa_kami}
```
#### 解説(邪道)
以下のコマンドを実行すると一瞬だった。
```
$ cat network10.pcap
```
実行結果
```
EDs@DQPE(@7PQcpaw{gochi_usa_kami}
```
#### 解説(王道)
味気ないので真面目に取り組む。
pcapファイルが分からなかったので、Google検索。
参考:https://e-words.jp/w/pcap.html
WSLにWiresharkがインストールされていなかったのでインストール。
```
$ sudo apt update && sudo apt upgrade -y && sudo apt install wireshark-qt -y
```
以下のコマンドを実行すると、フラグを得る。
```
$ wireshark network10.pcap
```
### Q8
#### 問題文
ハッシュ関数とは、値を入れたら絶対にもとに戻せないハッシュ値と呼ばれる値が返ってくる関数です。
ですが、レインボーテーブルなどでいくつかのハッシュ関数は元に戻せてしまう時代になってしまいました。
以下のSHA1というハッシュ関数で作られたハッシュ値を元に戻してみてください!(ヒント:googleで検索)
e4c6bced9edff99746401bd077afa92860f83de3
フラグは
cpaw{ハッシュを戻した値}
です。
#### 答え
```
cpaw{Shal}
```
#### 解説
1. 「e4c6bced9edff99746401bd077afa92860f83de3」をGoogle検索。
2. 一番上に表示されたサイトにアクセス:https://sha1.gromweb.com/?hash=e4c6bced9edff99746401bd077afa92860f83de3
3. サイトにアクセスすると、「The SHA-1 hash e4c6bced9edff99746401bd077afa92860f83de3 was successfully reversed into the string Shal」という表示が確認できる。
4. 上記の表示より、問題文のハッシュ値の元が「Shal」であることが分かる。
### Q9
#### 問題文
下にある配列の中身を大きい順に並べ替えて、くっつけてcpaw{並べ替えた後の値}をフラグとして提出してください。
例:もし配列{1,5,3,2}っていう配列があったら、大きい順に並べ替えると{5,3,2,1}となります。
そして、フラグはcpaw{5321}となります。
同じようにやってみましょう(ただし量が多いので、ソートするプログラムを書いたほうがいいですよ!)
[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]
#### 答え
```
cpaw{2112102072011931901881711671601591511501461441431361301211191111101091081051031021009994938785828180777672666360585755545250494642413634333127252420191815141210743210}
```
#### 解説
`1q9.py`
```python=
list=[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]
flag_list=sorted(list,reverse=True)
for i in range(len(list)):
print(flag_list[i], end='')
```
#### 余談
ChatGPTを使ってみた。
====================
**You**
次のリストを降順に並べ替えて、全ての数字を繋ぎ合わせたものを表示してください。
[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]
**ChatGPT**
与えられたリストを降順に並び替え、数字を繋ぎ合わせたものは以下の通りです。
[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, 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, 15, 14, 12, 10, 7, 4, 3, 2, 1, 0]
これを繋ぎ合わせると:
2112102072011931901881711671601591511501461441431361301211191111101091081051031021009493878582818077767266636058575554525049464241363433312725242019151412107432101110976543210
====================
分かりづらいけど、微妙に文字列が違う(間違っている)。
こんな簡単なタスクですら間違えちゃうんだから、やっぱChatGPTはあまり信用できないね。
## Level 2
### Q1
#### 問題文
以下の画像には、実はフラグが隠されています。
目を凝らして画像を見てみると、すみっこに何かが…!!!!
フラグの形式はcpaw{***}です。フラグは小文字にしてください。
stego100.jpg
#### 答え
```
cpaw{hidden_message:)}
```
#### 解説
画像の左上と右下にモールス信号が書かれている。
これを解読すると、それぞれ以下の原文を得る。
```
CPAWHIDDEN_
```
```
MESSAGE:)
```
### Q2
#### 問題文
このURLにアクセスすると、他のページにリダイレクトされてしまうらしい。
果たしてリダイレクトはどのようにされているのだろうか…
http://q15.ctf.cpaw.site
※この問題のサーバへの攻撃はお止め下さい
#### 答え
```
cpaw{4re_y0u_1ook1ng_http_h3ader?}
```
#### 解説
とりあえずリンクを踏む。
リダイレクトされたことが確認できる。
そもそも「リダイレクト」とは何か、気になったので「リダイレクトとは」でGoogle検索。
どうやらリダイレクトにも種類があるらしく、主に「301リダイレクト」と「302リダイレクト」というのが存在する。
参考:https://www.webdeki.com/column/1697/
おそらく今回は302リダイレクト
F12でデベロッパーツールを起動し、リダイレクトの動作を確認する。
デベロッパーツールを開いたまま、先ほどのリンクを踏んだあと、Networkタブを開き、「q15.ctf.cpaw.site」のHeadersタブを確認する。
Response Headers中のX-flagにてフラグが確認できる。
### Q3
#### 問題文
HTTPはWebページを閲覧する時に使われるネットワークプロトコルである。
ここに、とあるWebページを見た時のパケットキャプチャファイルがある。
このファイルから、見ていたページを復元して欲しい。
http_traffic.pcap
#### 答え
```
cpaw{Y0u_r3st0r3d_7his_p4ge}
```
#### 解説
pcapファイルからhttpを復元する方法をGoogle検索。
以下のコマンドを実行し、wiresharkを起動する。
```
$ wireshark http_traffic.pcap
```
下のページを参考にしながら、データを抽出する。
参考:https://troushoo.blog.fc2.com/blog-entry-157.html
`'network100(1)'`というファイルがあり、このファイルをhtml形式で実行すればよい。
(WSLでLinuxを動かしているため、explorer.exeを使用してブラウザにhtml実行結果を表示させる)
```
$ mv 'network100(1)' main.html
$ explorer.exe main.html
```
画像が表示されず、ボタンを押しても反応なし。
よって一度main.htmlの中身を確認する。
```
$ cat main.html
```
これにより、jsファイルやcssファイルなどの階層が正しくないことが判明したため、対応するディレクトリを作成し、移動させる(もしくはmain.htmlを編集する)。

うまく画像が表示されている。
ボタンを押してみる。

### Q4
#### 問題文
僕(twitter:@porisuteru)はスペシャルフォース2をプレイしています。
とても面白いゲームです。
このゲームでは、僕は何と言う名前でプレイしているでしょう!
フラグはcpaw{僕のゲームアカウント名}です。
#### 答え
```
cpaw{parock}
```
#### 解説
「@porisuteru スペシャルフォース2」でGoogle検索。
一番上に出てきたページをクリックすると、アカウント名が記載された画像が表示される。
(これ正規ルートなんかな?)
### Q5
#### 問題文
このファイルの中にはフラグがあります。探してください。
フラグはすべて小文字です!
file
#### 答え
```
cpaw{mgrep}
```
#### 解説
```
$ file misc100
misc100: pcap capture file, microsecond ts (little-endian) - version 0.0 (linktype#1768711542, capture length 1869357413)
```
とりあえずWiresharkで開こう。

開けないです。
とりあえずmisc100の中身を確認。
```
$ cat misc100
```
いっぱいlovelive!が出てきたぁ...(ラブライブ?)
よく見ると、lovelive!以外にもチラホラ文字列が見える。
てことで、lovelive!の部分を消してみる。
lovelive.py
```python=
with open('misc100') as f:
data = f.read()
data = data.replace('lovelive!', '')
print(data)
```
実行結果
```
Traceback (most recent call last):
File "/home/akane/ctf/L02/lovelive.py", line 2, in <module>
data = f.read()
File "/usr/lib/python3.10/codecs.py", line 322, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd4 in position 0: invalid continuation byte
```
ファイルが開けないエラー発生。
misc100の最初の部分が文字化けしていたことに気づく。
また、misc100はバイナリファイルなので、VSCode上でコピペして無理やりテキストエディタに変換する。
lovelive.py
```python=
with open('misc100.txt') as f:
data = f.read()
data = data.replace('lovelive!', '')
print(data)
```
実行結果
```
e!CCCelive!lovelivPPPovelive!loveAAAe!lovWWWve!{{{elive!loveliMMMelive!lovelGGG!lovelivRRRovelive!lEEElive!PPPelive!}}}
```
loveとlive!が混在しているので、それぞれで消去する。
lovelive.py
```py=
with open('misc100.txt') as f:
data = f.read()
data = data.replace('love', '')
data = data.replace('live!', '')
print(data)
```
実行結果
```
e!CCCelivPPPoveAAAe!lovWWWve!{{{eliMMMelGGG!livRRRovelEEEPPPe}}}
```
まあマシになったけど、まだ残っているのがある。
ここで、lovelive!の文字列以外は3つ連続で続いていることに気づく。
よって、この文字列から3つ繋がった文字のみを取り出して表示するプログラムを作成する。
lovelive.py
```python=
with open('misc100.txt') as f:
data = f.read()
data = data.replace('love', '')
data = data.replace('live!', '')
# string 2 list
str_list = []
for i in data:
str_list.append(i)
# 3つ連続で現れた文字のみリストに格納
flag = False
cpaw_list = []
for i in range(len(str_list)):
if flag == False and str_list[i-1] == str_list[i]:
flag = True
continue
if flag and str_list[i-1] == str_list[i]:
cpaw_list.append(str_list[i])
flag = False
# list 2 string
cpaw = ''.join(cpaw_list)
# 答え
print(cpaw)
```
実行結果
```
CPAW{MGREP}
```
#### 余談
mgrepって出てきたけど、もしかするとそれを使うのが正解かも。
### Q6
#### 問題文
Find the flag in this zip file.
file
#### 答え
```
cpaw{It_is_fun__isn't_it?}
```
#### 解説
zipファイルを展開。
いろいろ探索する。
Find the flag in this zip file.と書いてある以上、このzipファイルの中に答えがあるはず。
- Thumbnailフォルダの中に答えのような画像を見つける。

- xmlファイルとは何かについてGoogle検索する。
- 拡張子のないmimetypeが怪しかったので、そのファイルに書かれている文字列をGoogle検索する。
以下のサイトがトップに現れる。
https://ja.wikipedia.org/wiki/OpenDocument
仕様の部分を読む限り、これと一致する。
ファイルの種類より、「.odg」というのが分かる。
これは勘だが、要は「.zip」の拡張子を「.odg」に変更して開くことでフラグを得ることができるのではないかと考えた。
odgファイルのオンラインビュワーサイトで、「misc100.odg」を開くと、先の画像を確認することができるが、モザイクの部分にカーソルをフォーカスできることに気づく。
それをコピペして、フラグを得る。
オンラインビュワー:https://filext.com/ja/fairu-kakuchoshi/ODG
### Q7
#### 問題文
与えられたC言語のソースコードを読み解いて復号してフラグを手にれましょう。
暗号文:cpaw{ruoYced_ehpigniriks_i_llrg_stae}
crypto100.c
#### 答え
```
cpaw{Your_deciphering_skill_is_great}
```
#### 解説
crypto100.c
```cpp=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]){
// 3番目のコマンドライン引数をint型に変換
int key = atoi(argv[2]);
// 2番目のコマンドライン引数をchar*型として保存
const char* flag = argv[1];
// 解読開始
printf("cpaw{");
int i, j;
for (i = key - 1; i <= strlen(flag); i += key)
{
for (j = i; j >= i - key + 1; j--)
{
printf("%c", flag[j]);
}
}
printf("}\n");
return 0;
}
```
こういうのは、ソースコードとにらめっこするより実行するほうが早い(経験則)。
```
$ gcc -o crypto100.out crypto100.c
$ ./crypto100.out abcdefghijklmn 1
cpaw{abcdefghijklmn}
$ ./crypto100.out abcdefghijklmn 2
cpaw{badcfehgjilknm}
$ ./crypto100.out abcdefghijklmn 3
cpaw{cbafedihglkjnm}
$ ./crypto100.out abcdefghijklmn 4
cpaw{dcbahgfelkji}
```
ここまで実行すると、どういうプログラムなのかが分かるはず。
「ruoYced_ehpigniriks_i_llrg_stae」を眺めると、4文字ずつ反対に読んでいくのが良さそうなので、最終的に以下のコマンドを実行すれば良い。
```
$ ./crypto100.out ruoYced_ehpigniriks_i_llrg_stae 4
cpaw{Your_deciphering_skill_is_great}
```
### Q8
#### 問題文
フラグを出す実行ファイルがあるのだが、プログラム(elfファイル)作成者が出力する関数を書き忘れてしまったらしい…
reverse100
#### 答え
```
cpaw{yakiniku!}
```
#### 解説(もうこれ正規ルートだろ...)
とりあえずいつものコマンド
```
$ file rev100
rev100: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=f94360edd84a940de2b74007d4289705601d618d, not stripped
```
ELFファイルですね(問題文の通り)。
ELFファイルでGoogle検索。
実行形式ファイルというのが分かる。
問題文の「Reversing」というのもあることから、この実行形式ファイルを逆コンパイルし、Cプログラムを作成する問題であると予想できる。
「ELFファイル 逆アセンブル」でGoogle検索する。
参考:https://corgi-lab.com/programming/c-lang/reverse-assemble/
どうやらCプログラムのコンパイル時に「-g」オプションを付けておけば、逆アセンブルしたときにもC言語のソースコードが読めるらしい。
しかし、今回は以下のように実行してもアセンブラしか表示されず、C言語のソースコードは表示されなかった。
```
$ objdump rev100 -S -d
```
といっても情報はこれしかなく、アセンブラを読み取る技術は僕に無いため、ChatGPTに投げることにした(← 天才)。
**You**
以下はオブジェクトファイルを逆アセンブルして得たアセンブリファイルです。
そのファイルを読み、どのような処理を行っているのか説明してください。
また、読み取った結果からそのファイルと同じ動作をするc言語のプログラムを作成してください。
Disassembly of section .init:
0804831c <_init>:
804831c: 53 push %ebx
804831d: 83 ec 08 sub $0x8,%esp
8048320: e8 ab 00 00 00 call 80483d0 <__x86.get_pc_thunk.bx>
...
804860d: 81 c3 f3 19 00 00 add $0x19f3,%ebx
8048613: 83 c4 08 add $0x8,%esp
8048616: 5b pop %ebx
8048617: c3 ret
**ChatGPT**
このアセンブリコードは、main関数があるプログラムです。以下にその処理内容を解説し、C言語のコードを提供します。
まず、.initセクションと.pltセクションはプログラムの初期化に関連しています。.initはプログラムの初期化コード、.pltは手続きリンケージテーブルで、関数の呼び出しを行います。
.textセクションの_startからmainまでの部分が実際のプログラムの本体です。以下はそれらの解説です。
1. _start関数:
- xor %ebp, %ebp:スタックフレームのセットアップで使用される %ebp レジスタをゼロクリアします。
- pop %esi:main関数に渡される引数を %esi レジスタにポップします。
- mov %esp, %ecx:スタックポインタの値を %ecx レジスタに保存します。
- and $0xfffffff0, %esp:スタックアライメントを16バイトに調整します。
- push %eax:main関数に渡す引数として %eax レジスタの値をプッシュします。
- push %esp:スタックポインタの値をプッシュします。
- push %edx:main関数の戻り先のアドレスをスタックにプッシュします。
- push $0x8048600〜push $0x804849d:main関数の引数をスタックにプッシュします。
- call 8048380 <__libc_start_main@plt>:__libc_start_main関数を呼び出します。この関数はプログラムのエントリポイントで、main関数とその引数を受け取ります。
2. main関数 (0x804849d):
- and $0xfffffff0, %esp:スタックアライメントを16バイトに調整します。
- sub $0x50, %esp:ローカル変数のためにスタックから64バイトの領域を確保します。
- mov %gs:0x14, %eax:main関数のプロローグで、スタックのセキュリティ保護情報を取得します。
- mov %eax, 0x4c(%esp):スタック上の変数にセキュリティ保護情報を保存します。
- 一連の文字列ロードとprintfの呼び出し:printfを使って文字列を出力します。
- ループ内のputcharの呼び出し:文字列の各文字を出力します。
- もう一度のprintf呼び出し:ループ終了後の文字列を出力します。
- スタックチェックとプログラムの終了処理。
これらの情報を元に、C言語のコードを作成します。
```cpp=
#include <stdio.h>
int main() {
char str[] = "cpaw{";
int arr[] = {0x63, 0x7b, 0x79, 0x61, 0x6b, 0x69, 0x6e, 0x69, 0x6b, 0x75, 0x21};
printf("cpaw{");
for (int i = 0; i < 11; i++) {
putchar(arr[i]);
}
printf("}\n");
return 0;
}
```
このCプログラムは、与えられたアセンブリコードと同じ動作をします。指定された文字列とASCIIコードを用いて文字を出力し、最終的に "cpaw{cpawyanikubou!}" という文字列を出力します。
神。
しかし、cpaw{cpawyanikubou!}は誤りで、これを入力してもcorrectにはならなかった。
つまり、またChatGPTが誤った答えを出力したのである。
よって、この文字列から似たような文字列を予測し(奇跡)、フラグを得た。
### Q9
#### 問題文
困ったな……どうしよう…….
ぱろっく先生がキャッシュカードをなくしてしまったショックからデータベースに逃げ込んでしまったんだ.
うーん,君SQL書くのうまそうだね.ちょっと僕もWeb問作らなきゃいけないから,連れ戻すのを任せてもいいかな?
多分,ぱろっく先生はそこまで深いところまで逃げ込んで居ないと思うんだけども…….
とりあえず,逃げ込んだ先は以下のURLだよ.
一応,報酬としてフラグを用意してるからよろしくね!
https://ctf.spica.bz/baby_sql/
Caution
・sandbox.spica.bzの80,443番ポート以外への攻撃は絶対にしないようにお願いします.
・あなたが利用しているネットワークへの配慮のためhttpsでの通信を推奨します.
#### 答え
```
cpaw{palloc_escape_from_stage1;(}
```
#### 解説
テーブルの全ての要素を表示させる。
```
SELECT * FROM palloc_home
```
### Q10
#### 問題文
古くから存在するネットワークプロトコルを使った通信では、セキュリティを意識していなかったこともあり、様々な情報が暗号化されていないことが多い。そのため、パケットキャプチャをすることでその情報が簡単に見られてしまう可能性がある。
次のパケットを読んで、FLAGを探せ!
network100.pcap
(2021/04/11: 問題ファイルを更新しました。)
#### 答え
```
cpaw{f4p_sh0u1d_b3_us3d_in_3ncryp4i0n}
```
#### 解説
network100.pcapをwiresharkで解析する。
```
$ wireshark network100.pcap
```
あきらかにユーザ名前とパスワードだろうと思われるログが見つかるので、それを頼りにWinSCPとFTPを用いてログインする。
dummyファイルがあり、このディレクトリ内にflagがあると説明される。
隠しファイルの表示をONにして、隠しファイルを表示させ、フラグを得る。
## Level 3
### Q1
#### 問題文
#### 答え
#### 解説
### Q2
#### 問題文
うーん,ぱろっく先生深くまで逃げ込んでたか.
そこまで難しくは無いと思うんだけども…….
えっ?何の話か分からない?
さてはStage 1をクリアしてないな.
待っているから,先にStage 1をクリアしてからもう一度来てね.
Caution: sandbox.spica.bzの80,443番ポート以外への攻撃は絶対にしないようにお願いします.
#### 答え
```
cpaw{p@ll0c_1n_j@1l3:)}
```
#### 解説
よくあるSQLインジェクションをパスワードに埋め込む。
```
' OR '1'='1
```
### Q3
#### 問題文
x ≡ 32134 (mod 1584891)
x ≡ 193127 (mod 3438478)
x = ?
フラグはcpaw{xの値}です!
#### 答え
```
cpaw{35430270439}
```
#### 解説
```
32134 < 1584891
193127 < 2428478
```
より、それぞれ左の値はxを右の値で割った余りの数ということになる。
つまり、問題文の式は下のように書き換えることができる。
```
x = n1 * 1584891 + 32134
x = n2 * 2428478 + 193127
n1、n2は整数
```
上の二式を満たすような整数xを総当たりで探すプログラムを作成する。
prog.cpp
```cpp=
#include <iostream>
#define N1 1584891
#define N2 3438478
using namespace std;
int main()
{
long long x;
long long i = 0;
while (true)
{
x = i * N1 + 32134;
if (x % N2 == 193127)
{
break;
}
i++;
}
cout << "cpaw{" << x << "}" << endl;
return 0;
}
```
実行結果
```
cpaw{35430270439}
```