見出し画像

Writeup:SendanoteCTF "Programing"

Sendanote CTF は 初心者向けの常設CTF です。
常設CTF 自体は世の中に沢山ありますが、その多くは内容が難しかったり、英語だったりすることが多いです。
ですが、Sendanote CTF は 難易度も高くなく、日本語で書かれていて判り易いのでお勧めだと思います。

今日は台風の影響で外出できず暇だったので、Python の復習を兼ねて、"Programing" の問題をやってみました。 


1.ZZZIPPP

問題文:

あなたはあるファイルの解析作業を依頼されました。何重にも入れ子になった箱のようなファイルのようで、その中に組織にとって重要な機密情報が入っているようです。

https://ctfexh.setodanote.net/challenges#ZZZIPPP-60

与えられたファイル(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

問題文:

山登りが趣味だという同僚が疲れた様子で話しかけてきます。山でヤッホーと声を出せば、いつでもヤッホーと返ってくる。そんなあたりまえを支えるやまびこさんの気持ちって、どんな感じなんでしょうね。その眼には若干の狂気が宿っているようにも思えました。あなたは同僚を狂気から救うため、解析作業を手伝うことにしました。
以下の例のようにサーバにアクセスしてフラグを得てください。
nc nc.ctf.setodanote.net 26512

https://ctfexh.setodanote.net/challenges#echo_me-83

問題に書いてあるサーバーにアクセスしてみると下図のような表示となりました。"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

問題文:

あなたは再びあるファイルの解析作業を依頼されました。何重にも入れ子になった箱のようなファイルですが、今度は鍵までかかっているようです。ファイルを解析し中に封じ込められている機密情報を取得してください。
ファイルを解析してフラグを入手してください。

https://ctfexh.setodanote.net/challenges#EZZZIPPP-61

最初に 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

問題文:

普段は寡黙に働き続けているサーバが不意に話しかけてきました。計算勝負をしましょう。珍しいこともあるものだと思いつつも、あなたはそのサーバからの挑戦を受けることにしました。
以下の例のようにサーバにアクセスしてフラグを得てください。
nc nc.ctf.setodanote.net 26511

https://ctfexh.setodanote.net/challenges#deep_thought-8

サーバーにアクセスしてみると、下図のように「簡単な四則演算の問題が表示され、答えを入力する」ということをひたすら繰り返す問題のようです。

出された問題に自動的に回答する 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秒弱のやり取りが続いた後、フラグが表示されました。


この記事が気に入ったらサポートをしてみませんか?