好奇心の足跡

飽きっぽくすぐ他のことをしてしまうので、忘れないため・形にして頭に残すための備忘録。

setodaNote CTF writeup [Programing]

これは、2021/8/21~2021/9/4の期間で開催された、setodaNote CTFの Programing 分野のwriteupです。全体writeupはこちら

tech.kusuwada.com

ZZZIPPP (80)

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

添付されたファイルを解析してフラグを入手してください。

添付されたファイルを解凍すると、flag1000.zipというファイルが。
MacOSのFinder上で迂闊にダブルクリックしてしまったところ、flagxxx.zipとカウントダウンが始まり、おそらく1000回のunzipが勝手に走り始めてしまった。
プログラムで1000回解凍するやつを書いて実行するのが想定解っぽいけど、このまま待っててもflagが出そうなので放置して就寝。ちなみにunzip後の元ファイルは親切にも消してくれているので、ゴミも増えなさそう。おやすみなさい。

...

寝る前に解凍終わってた。最後はflag.txtが出現。

$ cat flag.txt 
flag{loop-zip-1989-zip-loop}

echo_me (120)

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

以下にアクセスしてフラグを得てください。

nc 10.1.1.10 12020

この設問では Linux ターミナルを使用します。 https://ctf.setodanote.net/webshell/

上記、CTFで用意されたターミナルからしかつながらないようなので、webshellにログインしてncコマンドを打ってみます。

$ nc 10.1.1.10 12020
==========
echo me: 92183493
==========
92183493
Correct!

==========
echo me: 67474967
==========
67474967
Correct!

...

こんな感じで、echo me: xxxxxx と言われた数字を打ち込み続ける問題。
10個くらい手動でやっても終わらなかったので、プログラムを組みます。webshellに入ってたpythonのversionが2.7.18なので、2系のpythonで。

#!/usr/bin/env python2
# -*- coding:utf-8 -*-

import socket

host = '10.1.1.10'
port = 12020

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    try:
        while 1:
            rcv = s.recv(1024).rstrip().replace('\n','').replace('==========','').replace('Correct!','')
            print repr(rcv)
            if rcv != '':
                q = (rcv)[9:].rstrip()
                print repr('answer: ' + q)
                s.send(q + '\n')
    except Exception as e:
        print(e)
except socket.error:
    print('socket error.')

このプログラム止まらないので(笑)、実行結果をテキストに吐いて後でgrepしてflagを探すことにします。

実行結果

$ python solve.py > log.txt
$ ctrl+C (強制終了)
$ grep flag log.txt
'flag{Hellow_yamabiko_Yoo-hoo!}'

EZZZIPPP (150)

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

ファイルを解析してフラグを入手してください。

今度はZZZIPPPのときの過ちを侵さないよう、慎重に。配布ファイルを解凍すると、同じくflag1000.zipと、今回はpass.txtというpasswordが記載されたtextが配布されています。
zipの方を回答してみるとpasswordが求められ、pass.txtの内容を入れると解凍。新しくflag999.zippass.txtが出現し、passwordが新しいものに置き換わります。
これはプログラムして自動でパスワードを入れて解凍させていくのが良さそう。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import subprocess

file_zip = "flag"
file_pass = "pass.txt"

def exec_command(cmd):
    print(cmd)
    try:
        res = subprocess.check_output(cmd)
    except Exception as e:
        print(e)
        raise("finish")
    return res

counter = 0
while True:
    filename = file_zip + str(1000-counter) + '.zip'
    password = (exec_command(['cat', file_pass])).decode('utf-8').strip()
    exec_command(['rm', file_pass])
    exec_command(['unzip', '-P', password, filename])
    exec_command(['rm', filename])
    print('counter: ' + str(counter))
    counter += 1

エラーで止まって終わるというお行儀の悪いプログラムですが、最終的にまたflag.txtが出現しました。

$ cat flag.txt
flag{bdf574f15645df736df13daef06128b8}

deep_thought (250)

計算勝負をしましょう。普段は寡黙に働き続けているサーバが不意に話しかけてきました。あなたは珍しいこともあるものだと思いつつも、そのサーバからの挑戦を受けることにしました。

以下にアクセスしてフラグを得てください。

nc 10.1.1.10 12010

この設問では Linux ターミナルを使用します。 https://ctf.setodanote.net/webshell/

またwebshell上でncしてみます。

$ nc 10.1.1.10 12010
[ Q1 ]
3 + 4
7
Correct!

[ Q2 ]
2 + 5
7
Correct!
...

こんな感じの計算問題が続くようです。人力でQ9までやって間違えた。雑魚。

#!/usr/bin/env python2
# -*- coding:utf-8 -*-

import socket
import re

host = '10.1.1.10'
port = 12010

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    try:
        while 1:
            rcv = s.recv(1024).rstrip().replace('\n','').replace('Correct!','')
            rcv = re.sub(r"\[.*\]", "", rcv)
            if rcv != '':
                print repr(rcv)
                q = eval(rcv)
                print repr('answer: ' + str(q))
                s.send(str(q) + '\n')
    except Exception as e:
        print(e)
except socket.error:
    print('socket error.')

文字列の式をeval()に与えるとそのまま計算してくれるので、これと前の問題の"echome"で作ったスクリプトを流用しました。今回はflagが出るとプログラムが止まるのでそのまま実行。

$ python solve.py 
'5 + 1'
'answer: 6'
'3 + 5'
'answer: 8'
'6 + 7'
~(中略)~
'1060 - 1790'
'answer: -730'
'1687 - 1557'
'answer: 130'
'2399 - 1214'
'answer: 1185'
'flag{__42__}'

50問あったみたい。