setodaNote CTF Exhibition Writeup (Programming)
Programming - ZZZIPPP
あなたはあるファイルの解析作業を依頼されました。何重にも入れ子になった箱のようなファイルのようで、その中に組織にとって重要な機密情報が入っているようです。
添付されたファイルを解析してフラグを入手してください。
問題にはflag1000.zip
が添付されており、その中にはflag999.zip
が、さらにその中にはflag888.zip
が…という状態です。
PythonでZIPファイルを解凍していくコードを書きます。
import zipfile
import os
current_zip = "flag1000.zip"
while True:
# ZIPファイルの解凍先フォルダ
folder = os.path.splitext(current_zip)[0]
# ZIPファイルを解凍
with zipfile.ZipFile(current_zip, "r") as file:
file.extractall(folder)
# 解凍後のフォルダに格納されているファイル名を取得
file_names = os.listdir(folder)
# ZIPファイルが格納されていた場合はcurrent_zipにZIPファイルのパスを格納して処理を繰り返す
if file_names[0].endswith(".zip"):
current_zip = os.path.join(folder, file_names[0])
# ZIPファイル以外が格納されていた場合はフォルダのパスを出力して終了
else:
print(f"Path: {folder}")
break
$ python unzip_old.py
Traceback (most recent call last):
File "F:\CTF\setodaNote CTF Exhibition\Programming\ZZZIPPP\unzip_old.py", line 12, in <module>
file.extractall(folder)
File "D:\Users\judenfly\AppData\Local\Programs\Python\Python312\Lib\zipfile\__init__.py", line 1744, in extractall
self._extract_member(zipinfo, path, pwd)
File "D:\Users\judenfly\AppData\Local\Programs\Python\Python312\Lib\zipfile\__init__.py", line 1793, in _extract_member
os.makedirs(upperdirs)
File "<frozen os>", line 225, in makedirs
FileNotFoundError: [WinError 206] ファイル名または拡張子が長すぎます。: 'flag1000\\flag999\\flag998\\flag997\\flag996\\flag995\\flag994\\flag993\\flag992\\flag991\\flag990\\flag989\\flag988\\flag987\\flag986\\flag985\\flag984\\flag983\\flag982\\flag981\\flag980\\flag979\\flag978\\flag977\\flag976'
$
Windowsのパスは既定で260文字まで[1]という制限をすっかり忘れていました…。
各ZIPファイルを常に同一のフォルダ内で解凍するようコードを修正します。
import zipfile
import os
current_zip = "F:\\CTF\\setodaNote CTF Exhibition\\Programming\\ZZZIPPP\\flag1000.zip"
folder = "F:\\CTF\\setodaNote CTF Exhibition\\Programming\\ZZZIPPP\\result\\"
while True:
# ZIPファイルを解凍
with zipfile.ZipFile(current_zip, "r") as file:
file.extractall(folder)
# ZIPファイルを解凍したら削除
if os.path.exists(current_zip):
os.remove(current_zip)
# 解凍後のフォルダに格納されているファイル名を取得
file_names = os.listdir(folder)
# ZIPファイルが格納されていた場合はcurrent_zipにZIPファイルのパスを格納して処理を繰り返す
if file_names[0].endswith(".zip"):
current_zip = os.path.join(folder, file_names[0])
# ZIPファイル以外が格納されていた場合は終了
else:
break
$ python unzip.py
$
実行が完了するとfolder
で指定したフォルダにflag.txt
が格納されており、そのテキストファイルにflagが記載されています。
正答:flag{loop-zip-1989-zip-loop}
Programming - echo_me
山登りが趣味だという同僚が疲れた様子で話しかけてきます。山でヤッホーと声を出せば、いつでもヤッホーと返ってくる。そんなあたりまえを支えるやまびこさんの気持ちって、どんな感じなんでしょうね。その眼には若干の狂気が宿っているようにも思えました。あなたは同僚を狂気から救うため、解析作業を手伝うことにしました。
以下の例のようにサーバにアクセスしてフラグを得てください。
nc nc.ctf.setodanote.net 26512
この設問では用意されたサーバにアクセスして答えます。接続先は以下の通りです。
- Server: nc.ctf.setodanote.net
- Port: 26512
まず、サーバに接続して動作を確認します。
$ nc nc.ctf.setodanote.net 26512
==========
echo me: 374551
==========
374551
Correct!
==========
echo me: 562204
==========
562204
Correct!
==========
echo me: 488611
==========
488611
Correct!
==========
echo me: 666918
==========
^C
$
「echo me」の後に表示される数字を入力すればよいのですが、どこまで続ければよいのか分からないので、Pythonでコードを書いて自動化します。
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# サーバに接続
s.connect(("nc.ctf.setodanote.net", 26512))
while True:
# サーバから受信したデータ
data = s.recv(1024).decode("utf-8")
# サーバが接続を切った場合は終了
if not data:
break
# サーバから受信したデータを出力
print(data)
# 「echo me」の後に表示される数字をサーバに送信
lines = data.split("\n")
for line in lines:
if "echo me:" in line:
number = line.split("echo me: ")[1].strip()
s.sendall(f"{number}\n".encode("utf-8"))
$ python echo.py
==========
echo me: 842071
==========
Correct!
==========
echo me: 839218
==========
Correct!
==========
echo me: 748336
==========
Correct!
~省略~
==========
echo me: 37300568
==========
Correct!
flag{Hellow_yamabiko_Yoo-hoo!}
$
正答:flag{Hellow_yamabiko_Yoo-hoo!}
Programming - EZZZIPPP
あなたは再びあるファイルの解析作業を依頼されました。何重にも入れ子になった箱のようなファイルですが、今度は鍵までかかっているようです。ファイルを解析し中に封じ込められている機密情報を取得してください。
ファイルを解析してフラグを入手してください。
問題にはflag1000.zip
とpass.txt
が添付されており、その中にはflag999.zip
とpass.txt
が、さらにその中にはflag888.zip
とpass.txt
が…という状態です。
どうやらpass.txt
には同フォルダ内のZIPファイルのパスワードが書いてあるようなので、Pythonでパスワード付きZIPファイルを解凍していくコードを書きます。
import zipfile
import os
current_zip = "F:\\CTF\\setodaNote CTF Exhibition\\Programming\\EZZZIPPP\\flag1000.zip"
folder = "F:\\CTF\\setodaNote CTF Exhibition\\Programming\\EZZZIPPP\\result\\"
while True:
# パスワードを取得
password_file = os.path.join(os.path.dirname(current_zip), "pass.txt")
with open(password_file, "r") as f:
password = f.read().strip().encode("utf-8")
# ZIPファイルを解凍
with zipfile.ZipFile(current_zip, "r") as file:
file.extractall(folder, pwd=password)
# 解凍したらZIPファイルを削除
if os.path.exists(current_zip):
os.remove(current_zip)
# 解凍後のフォルダに格納されているファイル名を取得
file_names = os.listdir(folder)
# ZIPファイルが格納されていた場合はcurrent_zipにZIPファイルのパスを格納して処理を繰り返す
zip_files = [f for f in file_names if f.endswith(".zip")]
if zip_files:
current_zip = os.path.join(folder, zip_files[0])
else:
break
$ python unzip_pass.py
$
実行が完了するとfolder
で指定したフォルダにflag.txt
が格納されており、そのテキストファイルにflagが記載されています。
正答:flag{bdf574f15645df736df13daef06128b8}
Programming - deep_thought
普段は寡黙に働き続けているサーバが不意に話しかけてきました。計算勝負をしましょう。珍しいこともあるものだと思いつつも、あなたはそのサーバからの挑戦を受けることにしました。
以下の例のようにサーバにアクセスしてフラグを得てください。
nc nc.ctf.setodanote.net 26511
この設問では用意されたサーバにアクセスして答えます。接続先は以下の通りです。
- Server: nc.ctf.setodanote.net
- Port: 26511
まず、サーバに接続して動作を確認します。
$ nc nc.ctf.setodanote.net 26511
[ Q1 ]
1 + 2
3
Correct!
[ Q2 ]
3 + 7
10
Correct!
[ Q3 ]
4 - 7
-3
Correct!
[ Q4 ]
18 - 10
8
Correct!
[ Q5 ]
16 + 18
34
Correct!
[ Q6 ]
36 + 14
50
Correct!
[ Q7 ]
34 + 49
83
Correct!
[ Q8 ]
22 + 28
50
Correct!
[ Q9 ]
60 - 30
30
Correct!
[ Q10 ]
72 + 65
^C
$
表示される計算式の答えを入力すればよいのですが、どこまで続ければよいのか分からないので、Pythonでコードを書いて自動化します。
import socket
import re
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# サーバに接続
s.connect(("nc.ctf.setodanote.net", 26511))
while True:
# サーバから受信したデータ
data = s.recv(1024).decode("utf-8")
# サーバが接続を切った場合は終了
if not data:
break
# サーバから受信したデータを出力
print(data)
# 数式を計算してサーバに送信
lines = data.split("\n")
for line in lines:
match = re.match(r"^\d+.*", line)
if match:
expression = match.group(0).strip()
number = eval(expression)
s.sendall(f"{number}\n".encode("utf-8"))
$ python deep_thought.py
[ Q1 ]
1 + 1
Correct!
[ Q2 ]
4 + 6
Correct!
[ Q3 ]
9 + 4
Correct!
~省略~
[ Q50 ]
1541 + 1638
Correct!
flag{__42__}
$
正答:flag{__42__}
Discussion