これは、2021/8/21~2021/9/4の期間で開催された、setodaNote CTFの Programing 分野のwriteupです。全体writeupはこちら
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.zip
とpass.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問あったみたい。