Writeup:SendanoteCTF "Programing"
Sendanote CTF は 初心者向けの常設CTF です。
常設CTF 自体は世の中に沢山ありますが、その多くは内容が難しかったり、英語だったりすることが多いです。
ですが、Sendanote CTF は 難易度も高くなく、日本語で書かれていて判り易いのでお勧めだと思います。
今日は台風の影響で外出できず暇だったので、Python の復習を兼ねて、"Programing" の問題をやってみました。
1.ZZZIPPP
問題文:
与えられたファイル(flag1000.zip)を解凍する問題。
「flag1000.zip を解凍すると、flag999.zip が現れる」という具合に何度も何度も繰り返し圧縮された zipファイルであるため、手作業で解凍するのは不可能ではないですが、と~っても面倒です。
なので、解凍を自動的にやってくれるスクリプトを書くことにします。
適当なフォルダに、flag1000.zip を1個だけ置き、「フォルダ内のzip を解凍したら元のzipファイルを消す」を zip ファイルが無くなるまでひたすら繰り返せばOK。こんなのは PowerShell で十分です。
while ( ($f = Get-ChildItem *.zip ) -ne $null ) {
Expand-Archive -Path $f.Name -DestinationPath .
Write-Output "[*] file: $f.name extracted."
Remove-Item $f.Name }
実行結果は以下の通り。
最後の flag1.zip を解凍すると flag.txt が現れました。
2.echo_me
問題文:
問題に書いてあるサーバーにアクセスしてみると下図のような表示となりました。"echo me:" の後ろに表示されている数字をひたすら入力していく、という問題のようです。
何回か手入力してみましたが、何度やっても "Correct!" と表示されて、次の数字が表示されます。きっと何回目かにフラグが表示されるのでしょう。
手でやっていられないので、Python で自動的に入力させることにします。
スクリプトは以下の通り。
応答から "echo me:" の後ろの数字を切り出して、そのまま send するだけ。
テストしてみると、最初の接続時のみ 2回に分けて応答が返ってくることがわかったので、最初だけ2度読みしたのが工夫、といえば工夫かも。。。
import socket
host = 'nc.ctf.setodanote.net'
port = 26512
s = socket.create_connection((host,port))
# 最初だけ1行しか応答が来ないので2度読みする。
res = s.recv(1000).decode()
res = s.recv(1000).decode()
print(res)
ans = res.split('\n')[0].split(':')[1].strip()
while 'echo me' in res:
print(ans)
s.send(ans.encode()+b'\n')
res = s.recv(1000).decode()
print(res)
res = s.recv(1000).decode()
print(res)
if 'echo me' in res:
ans = res.split('\n')[1].split(':')[1].strip()
実行結果:
20秒程度の長~いやり取りの末、フラグが表示されました。
3.EZZZIPPP
問題文:
最初に flag1000.zip と pass.txt が与えられ、pass.txt に書かれたパスワードで zip を解凍すると、新たに flag999.zip と pass.txt が出現する、ということの繰り返しになっています。
先ほどと同様 PowerShellで、と思いきや Expand-Archive ではパスワード付 zip の解凍ができない ことが判り、Pythonでスクリプトを書きました。
処理の方法は PowerShell と同様、「フォルダ内のzipファイルを解凍し、もとの zip ファイルと 解凍に使った pass.txt を消す」という処理をひたすら繰り返すだけです。
pythonで zipファイルを処理するときは、zipfile.ZipFile(filename)で最初にオブジェクトを作る必要があることが留意点です。
import os
import glob
import zipfile
target = glob.glob('*.zip')
while (len(target) != 0):
with open('pass.txt') as f:
password = (f.read()).strip().encode()
os.remove('pass.txt')
targetfile = target[0]
with zipfile.ZipFile(targetfile) as zf:
print('[*]: extract: ' ,targetfile, 'pwd=', password)
zf.extractall(pwd=password)
os.remove(targetfile)
target = glob.glob('*.zip')
実行結果:
4.deep_thought
問題文:
サーバーにアクセスしてみると、下図のように「簡単な四則演算の問題が表示され、答えを入力する」ということをひたすら繰り返す問題のようです。
出された問題に自動的に回答する Pythonスクリプトを書くことにします。
先ほどの「echo me」と同様、なぜか最初の1回だけはサーバー側の応答はきまって " [ Q1 ]" のみでした。おそらくサーバー側プログラムのロードに時間がかかっているものと思われるので、初回のみ1秒待ってから受信するようにしました。
"11 + 12" などの問題文の切り出しには、正規表現 '[0-9]+ [\+\-\*|\/] [0-9]+' を使用しました。
import socket
import time
import re
host = 'nc.ctf.setodanote.net'
port = 26511
s = socket.create_connection((host,port))
time.sleep(1) # 初回接続時は起動に時間がかかるみたいなので1秒待つ。
res = s.recv(1000).decode()
check = re.search(r'[0-9]+ [\+\-\*|\/] [0-9]+',res)
while (check != None):
quiz = check.group(0)
ans = str(eval(quiz))
print('[*] quiz :',quiz, ' ans=',ans)
s.send(ans.encode() + b'\n')
res = s.recv(1000) # 最初の応答は 'correct !"なので読み飛ばす。
res = s.recv(1000).decode()
check = re.search(r'[0-9]+ [\+\-\*|\/] [0-9]+',res)
print(res)
実行結果:
10秒弱のやり取りが続いた後、フラグが表示されました。
この記事が気に入ったらサポートをしてみませんか?