2022年1月に開催されたpicoMini 2022のWrite Upです。
実際に使ったコードはGitHubに置いてあります。CTFの解答なので、可読性は皆無です。気になるところがあったら気軽に訪ねていただければと思います。
runme.py
runme.py
というファイルが配布されます。
python runme.py
として実行したところ、flagが表示されました。
ncme
問題文に nc saturn.picoctf.net 50959
と書かれていたので、実行するとflagが表示されました。
convertme.py
convertme.py
というファイルが配布されます。
実行したところ、
If 50 is in decimal base, what is it in binary base?
Answer:
(10進数における50は2進数でどうなりますか?)ときかれたので、110010と入力するとflagが出力されました。50の部分はランダムのようです。
Codebook
code.py
と codebook.txt
が配布されます。
code.pyを実行するとflagが入手できました。
fixme1.py
fixme1.py
が配布されます。
そのまま実行すると、
File "/Path/to/fixme1.py", line 20
print('That is correct! Here\'s your flag: ' + flag)
IndentationError: unexpected indent
と表示されました。どうやら20行目にエラーがあり、インデントがおかしいようです。テキストエディタでファイルを開くと、20行目の行頭に不要なスペースが入っているのでこれを削除して再度実行するとflagが得られます。
fixme2.py
fixme2.py
が配布されます。
こちらも実行すると、
File "/Path/to/fixme2.py", line 22
if flag = "":
^
SyntaxError: invalid syntax
というエラーが表示されます。22行目において、==
と書くべきところを=
としたのが原因です。修正して再度実行すればflagが得られます。
PW Crack 1
level1.py
と level1.flag.txt.enc
が配布されます。level1.pyを実行するとパスワードの入力を求められました。
テキストエディタでファイルの中身を見ると、
user_pw = input("Please enter correct password for flag: ")
if( user_pw == "1e1a"):
print("Welcome back... your flag, user:")
decryption = str_xor(flag_enc.decode(), user_pw)
print(decryption)
という処理が見えるので、パスワードとして1e1a
を入力すればflagが入手できそうです。
実際に実行すればflagが入手できます。
Glitch Cat
問題文で指定されたサーバーに接続すると
picoCTF{gl17ch_m3_n07_' + chr(0x63) + chr(0x35) + chr(0x36) + chr(0x35) + chr(0x37) + chr(0x66) + chr(0x66) + chr(0x33) + '}'
という応答が返ってきました。
見るからにpythonの文字列なので、
print('picoCTF{gl17ch_m3_n07_' + chr(0x63) + chr(0x35) + chr(0x36) + chr(0x35) + chr(0x37) + chr(0x66) + chr(0x66) + chr(0x33) + '}')
とすることでflagが入手できます。
PW Crack 2
level2.py
と level2.flag.txt.enc
が配布されます。level2.pyを実行すると、再びパスワードの入力を求められました。
level2.pyの中を見ると、
if( user_pw == chr(0x32) + chr(0x65) + chr(0x30) + chr(0x65) ):
print("Welcome back... your flag, user:")
decryption = str_xor(flag_enc.decode(), user_pw)
print(decryption)
という処理が見えます。
chr(0x32) + chr(0x65) + chr(0x30) + chr(0x65)
は 2e0e
なので、これを入力すればflagが表示されます。
HashingJobApp
接続すると、
Please md5 hash the text between quotes, excluding the quotes: 'a full moon'
Answer:
(''で囲まれた単語のmd5値を入力してください)と表示されました。
文字列のmd5値は
import hashlib
print(hashlib.md5(b'a full moon').hexdigest())
で取得できます。md5値を入力すると別の単語で同じ質問をされるので、3会くり返せばflagが表示されます。
Serpentine
配布されたserpentine.py
を実行すると
a) Print encouragement
b) Print flag
c) Quit
ここでbを選択すると、Oops! I must have misplaced the print_flag function! Check my source code!
と言われました。
print_flag
なる関数が存在するようなので、外から関数を呼び出してやります。
from serpentine import print_flag
print_flag()
あとはこのファイルを実行すればflagが入手できます。
PW Crack 3
配布されたlevel3.py
を実行すると、またしてもパスワードを要求されました。level3.pyの末尾には
# The strings below are 7 possibilities for the correct password.
# (Only 1 is correct)
pos_pw_list = ["f09e", "4dcf", "87ab", "dba8", "752e", "3961", "f159"]
と記載されています。どうやらこの7つのどれかが正しいパスワードのようです。
これ以上考えるのが面倒くさいので、7通り全部試せばOKです。7つしか候補が無いほうが悪い。
PW Crack 4
PW Crack 3とほぼ同じ問題ですが、パスワードの候補が100個に増えました。根性で手入力してもいいのですが、流石にだるいので総当りするスクリプトを書きます。
from level4 import pos_pw_list, hash_pw, correct_pw_hash
for pos in pos_pw_list:
pos_hash = hash_pw(pos)
if pos_hash==correct_pw_hash:
print(pos)
パスワードがeacc
であることがわかるので、これをlevel4.pyに入力すればflagが入手できます。
PW Crack 5
PW Crack3, PW Crack 4とほぼ同じですが、今回はdictionary.txt
のどれかがパスワードのようです。
PW Crack 4の時と同じように、スクリプトを書いて総当りを行います。
from level5 import hash_pw, correct_pw_hash
with open("dictionary.txt", "r") as fp:
for pos in fp:
pos = pos.strip() # 行末の改行を削除
pos_hash = hash_pw(pos)
if pos_hash==correct_pw_hash:
print(pos)
パスワードが判明したので、あとはlevel5.pyを実行して入力すればflagが出力されます。