中高生向けのpicoCTF の更に初心者向けの mini CTF Beginner picoMini 2022 が2022年1月10日 8:00pm GMT ~ 2月4日 8:00pm GMT で開催されました。名前の通りちゃんととっても初心者向けで、全部解けた人も多いかと思いますがwriteupを残しておきます。
python問題が結構多めで、セキュリティ要素はかなり弱めだった印象です。
こちら私のスコアグラフ。起きてすぐ取り組んだけど351位でした。
期間が終わっても下記のpicoGymからプレイできるので、もし興味を持たれた方がいらっしゃいましたら是非トライしてみてください!
[General Skills] runme.py
Run the runme.py script to get the flag. Download the script with your browser or with wget in the webshell.
python scriptが配布されます。中にflagが書いてあったけど、多分pythonスクリプトを実行させる問題。
#!/usr/bin/python3 ################################################################################ # Python script which just prints the flag ################################################################################ flag ='picoCTF{run_s4n1ty_run}' print(flag)
なるほどかなり初心者向けだ。
[General Skills] ncme
Connect to a remote computer using nc and get the flag.
$ nc saturn.picoctf.net 57688
言われたとおり接続してみます。
$ nc saturn.picoctf.net 57688 picoCTF{s4n1ty_c4t}
[General Skills] convertme.py
Run the Python script and convert the given number from decimal to binary to get the flag.
またpython scriptが配布されます。
import random def str_xor(secret, key): #extend key to secret length new_key = key i = 0 while len(new_key) < len(secret): new_key = new_key + key[i] i = (i + 1) % len(key) return "".join([chr(ord(secret_c) ^ ord(new_key_c)) for (secret_c,new_key_c) in zip(secret,new_key)]) flag_enc = chr(0x15) + chr(0x07) + chr(0x08) + chr(0x06) + chr(0x27) + chr(0x21) + chr(0x23) + chr(0x15) + chr(0x5f) + chr(0x05) + chr(0x08) + chr(0x2a) + chr(0x1c) + chr(0x5e) + chr(0x1e) + chr(0x1b) + chr(0x3b) + chr(0x17) + chr(0x51) + chr(0x5b) + chr(0x58) + chr(0x5c) + chr(0x3b) + chr(0x10) + chr(0x57) + chr(0x0f) + chr(0x5e) + chr(0x51) + chr(0x5c) + chr(0x46) + chr(0x53) + chr(0x13) num = random.choice(range(10,101)) print('If ' + str(num) + ' is in decimal base, what is it in binary base?') ans = input('Answer: ') try: ans_num = int(ans, base=2) if ans_num == num: flag = str_xor(flag_enc, 'enkidu') print('That is correct! Here\'s your flag: ' + flag) else: print(str(ans_num) + ' and ' + str(num) + ' are not equal.') except ValueError: print('That isn\'t a binary number. Binary numbers contain only 1\'s and 0\'s')
今回はflagをそのまま書いてはないので、実行してみます。
$ python convertme.py If 26 is in decimal base, what is it in binary base? Answer: 11010 That is correct! Here's your flag: picoCTF{4ll_y0ur_b4535_e2a58836}
2進数に直した値を答えさせる問題でした。今回はお手軽に、CyberChefの To Base フィルタを使って解きました。
[General Skills] Codebook
Run the Python script
code.py
in the same directory ascodebook.txt
.
問題文にある2つのファイルが配布されるので、同じディレクトリで実行してみます。
$ python code.py picoCTF{c0d3b00k_455157_8100c7c1}
[General Skills] fixme1.py
Fix the syntax error in this Python script to print the flag.
python scriptが配布されます。エラーが出るから直してくれとのこと。まずは実行してみます。
$ python fixme1.py File "fixme1.py", line 20 print('That is correct! Here\'s your flag: ' + flag) ^ IndentationError: unexpected indent
インデントエラー。よく出るよね。indentいらないところなので、削除して再実行。
$ python fixme1.py That is correct! Here's your flag: picoCTF{1nd3nt1ty_cr1515_09ee727a}
[General Skills] fixme2.py
Fix the syntax error in the Python script to print the flag.
こっちもまずは実行してみます。
$ python fixme2.py File "fixme2.py", line 22 if flag = "": ^ SyntaxError: invalid syntax
イコールの書き方は =
ではなくて ==
なので修正して再実行。
$ python fixme2.py That is correct! Here's your flag: picoCTF{3qu4l1ty_n0t_4551gnm3nt_4863e11b}
[General Skills] PW Crack 1
Can you crack the password to get the flag? Download the password checker here and you'll need the encrypted flag in the same directory too.
level1.flag.txt.enc
と level1.py
が配布されます。
### THIS FUNCTION WILL NOT HELP YOU FIND THE FLAG --LT ######################## def str_xor(secret, key): #extend key to secret length new_key = key i = 0 while len(new_key) < len(secret): new_key = new_key + key[i] i = (i + 1) % len(key) return "".join([chr(ord(secret_c) ^ ord(new_key_c)) for (secret_c,new_key_c) in zip(secret,new_key)]) ############################################################################### flag_enc = open('level1.flag.txt.enc', 'rb').read() def level_1_pw_check(): user_pw = input("Please enter correct password for flag: ") if( user_pw == "691d"): print("Welcome back... your flag, user:") decryption = str_xor(flag_enc.decode(), user_pw) print(decryption) return print("That password is incorrect") level_1_pw_check()
まずは実行してみると、
$ python level1.py Please enter correct password for flag: That password is incorrect
passwordがいるらしい。コードを読んでみると、パスワードは 691d
なのでこれを入れる。
$ python level1.py Please enter correct password for flag: 691d Welcome back... your flag, user: picoCTF{545h_r1ng1ng_56891419}
[General Skills] Glitch Cat
Our flag printing service has started glitching!
$ nc saturn.picoctf.net 52026
接続してみます。
$ nc saturn.picoctf.net 52026 'picoCTF{gl17ch_m3_n07_' + chr(0x62) + chr(0x65) + chr(0x63) + chr(0x66) + chr(0x33) + chr(0x38) + chr(0x36) + chr(0x31) + '}'
おお、hexからasciiへ変換が必要。今回もCyberChefの From Hex フィルタを使って変換。
[General Skills] PW Crack 2
Can you crack the password to get the flag? Download the password checker here and you'll need the encrypted flag in the same directory too.
今度は level2.flag.txt.enc
と level2.py
が配布されます。
pythonの方にまたpasswordが書いてあるので、これをasciiに直します。
user_pw = input("Please enter correct password for flag: ") if( user_pw == chr(0x34) + chr(0x65) + chr(0x63) + chr(0x39) ):
-> 4ec9
がpassword。あとは実行してpasswordを入れるだけ。
$ python level2.py Please enter correct password for flag: 4ec9 Welcome back... your flag, user: picoCTF{tr45h_51ng1ng_9701e681}
[General Skills] HashingJobApp
If you want to hash with the best, beat this test!
nc saturn.picoctf.net 65352
接続してみると、指定された単語のmd5を計算して答える問題が。またCyberChefの MD5
フィルタを使った。
$ nc saturn.picoctf.net 65352 Please md5 hash the text between quotes, excluding the quotes: 'Joan of Arc' Answer: 19ba425a542946fcf13228d9ddd53139 19ba425a542946fcf13228d9ddd53139 Correct. Please md5 hash the text between quotes, excluding the quotes: 'Clint Eastwood' Answer: b84954cb41831fa842dd69f6e1836b6e b84954cb41831fa842dd69f6e1836b6e Correct. Please md5 hash the text between quotes, excluding the quotes: 'grave robbers' Answer: bf48d2ac4e5d0532912c8e8e0998645f bf48d2ac4e5d0532912c8e8e0998645f Correct. picoCTF{4ppl1c4710n_r3c31v3d_674c1de2}
ちなみに、macでコマンドラインでmd5
を計算するときは
$ echo -n "Joan of Arc" | md5 19ba425a542946fcf13228d9ddd53139
こんな感じ。-n
option で改行をしないようにするのを忘れないように。
[General Skills] Serpentine
Find the flag in the Python script!
pythonスクリプトが配布されます。長かったので読む前に実行してみた。
$ python serpentine.py Y .-^-. / \ .- ~ ~ -. () () / _ _ `. _ _ _ \_ _/ / / \ \ . ~ _ _ ~ . | | / / \ \ .' .~ ~-. `. | | / / ) ) / / `.`. \ \_ _/ / / / / / `' \_ _ _.' / / ( ( / / \ \ / / \ \ / / ) ) ( ( / / `. `. .' / `. ~ - - - - ~ .' ~ . _ _ _ _ . ~ Welcome to the serpentine encourager! a) Print encouragement b) Print flag c) Quit What would you like to do? (a/b/c)
flagを表示してほしかったので b
を選択すると、
Oops! I must have misplaced the print_flag function! Check my source code!
とのこと。ソースコードを見てみます。
while True: print('a) Print encouragement') print('b) Print flag') print('c) Quit\n') choice = input('What would you like to do? (a/b/c) ') if choice == 'a': print_encouragement() elif choice == 'b': print('\nOops! I must have misplaced the print_flag function! Check my source code!\n\n') elif choice == 'c': sys.exit(0) else: print('\nI did not understand "' + choice + '", input only "a", "b" or "c"\n\n')
この choice == 'b'
のところに、print_flag()
を持ってきてあげれば良さそう。
書き換えて実行すると
What would you like to do? (a/b/c) b picoCTF{7h3_r04d_l355_7r4v3l3d_8e47d128}
[General Skills] PW Crack 3
Can you crack the password to get the flag?
Download the password checker here and you'll need the encrypted flag and the hash in the same directory too.
There are 7 potential passwords with 1 being correct. You can find these by examining the password checker script.
今回は level3.py
, level3.flag.txt.enc
, level3.hash.bin
が配布されます。
pythonのスクリプトを見てみると、level3.hash.bin
にpasswordのhashがあり、これを戻したものがpassword何だけどもhashは一応不可逆なのでpasswordに戻せない。
問題文にもある通り、スクリプトの最後の方にある7つのpassword候補を全部試してあっているものを探すのが早い。
$ python level3.py Please enter correct password for flag: 1ea2 Welcome back... your flag, user: picoCTF{m45h_fl1ng1ng_6f98a49f}
3つ目が正解でした。
[General Skills] PW Crack 4
Can you crack the password to get the flag?
Download the password checker here and you'll need the encrypted flag and the hash in the same directory too.
There are 100 potential passwords with only 1 being correct. You can find these by examining the password checker script.
level4.py
, level4.hash.bin
, level4.flag.txt.enc
が配布されます。
ほぼlevel3の問題と同じだけど、候補が7つではなく100個。これはscriptを書いたほうが良さそう。
元のスクリプトを少し書き換えて
import hashlib # The strings below are 100 possibilities for the correct password. # (Only 1 is correct) pos_pw_list = ["6b3e", "989c", "4b17", "d06f", "f495", "6ea1", "44e4", "1d45", "3e1a", "b0b4", "8c65", "3276", "c496", "9d3d", "2476", "6ef4", "6b7f", "c184", "c2a8", "9708", "7bea", "9a2d", "4a22", "93ae", "826b", "9a50", "8b39", "5410", "a86c", "3760", "6426", "ec8e", "c294", "a909", "cbc6", "2e75", "f137", "9cb3", "79e7", "469f", "a9f9", "3e37", "b33e", "3f31", "4b27", "2f06", "cc2f", "d9e4", "2de7", "7328", "b4d4", "8e74", "a677", "b139", "9c74", "8ea4", "36f6", "613b", "7a7a", "5710", "838c", "44d5", "7190", "99d9", "c0a6", "b218", "3223", "477e", "38e5", "19b4", "3267", "2287", "b947", "a8d0", "fd9c", "e99c", "d8b7", "4c82", "b289", "332b", "bba5", "716d", "653e", "eb5d", "ad77", "ad3a", "3922", "7565", "947d", "928c", "2937", "823f", "f362", "79cf", "4582", "c0d0", "ed20", "d89a", "129c", "4e81"] ### THIS FUNCTION WILL NOT HELP YOU FIND THE FLAG --LT ######################## def str_xor(secret, key): #extend key to secret length new_key = key i = 0 while len(new_key) < len(secret): new_key = new_key + key[i] i = (i + 1) % len(key) return "".join([chr(ord(secret_c) ^ ord(new_key_c)) for (secret_c,new_key_c) in zip(secret,new_key)]) ############################################################################### flag_enc = open('level4.flag.txt.enc', 'rb').read() correct_pw_hash = open('level4.hash.bin', 'rb').read() def hash_pw(pw_str): pw_bytes = bytearray() pw_bytes.extend(pw_str.encode()) m = hashlib.md5() m.update(pw_bytes) return m.digest() def level_4_pw_check(pw): # user_pw = input("Please enter correct password for flag: ") # user_pw_hash = hash_pw(user_pw) # if( user_pw_hash == correct_pw_hash ): print("Welcome back... your flag, user:") decryption = str_xor(flag_enc.decode(), pw) print(decryption) return print("That password is incorrect") def choose_pw(): for p in pos_pw_list: if hash_pw(p) == correct_pw_hash: return p pw = choose_pw() level_4_pw_check(pw)
実行結果
$ python level4.py Welcome back... your flag, user: picoCTF{fl45h_5pr1ng1ng_89490f2d}
[General Skills] PW Crack 5
Can you crack the password to get the flag?
Download the password checker here and you'll need the encrypted flag and the hash in the same directory too. Here's a dictionary with all possible passwords based on the password conventions we've seen so far.
今度は100個ではなくdictionay(65536行)で配布されます。level4同じように全部試してあげればOK。
import hashlib ### THIS FUNCTION WILL NOT HELP YOU FIND THE FLAG --LT ######################## def str_xor(secret, key): #extend key to secret length new_key = key i = 0 while len(new_key) < len(secret): new_key = new_key + key[i] i = (i + 1) % len(key) return "".join([chr(ord(secret_c) ^ ord(new_key_c)) for (secret_c,new_key_c) in zip(secret,new_key)]) ############################################################################### flag_enc = open('level5.flag.txt.enc', 'rb').read() correct_pw_hash = open('level5.hash.bin', 'rb').read() dictionary = open('dictionary.txt', 'r').readlines() def hash_pw(pw_str): pw_bytes = bytearray() pw_bytes.extend(pw_str.encode()) m = hashlib.md5() m.update(pw_bytes) return m.digest() def level_5_pw_check(pw): # user_pw = input("Please enter correct password for flag: ") # user_pw_hash = hash_pw(user_pw) # if( user_pw_hash == correct_pw_hash ): print("Welcome back... your flag, user:") decryption = str_xor(flag_enc.decode(), pw) print(decryption) return print("That password is incorrect") def find_pw(): for d in dictionary: d = d.strip() if hash_pw(d) == correct_pw_hash: return d pw = find_pw() level_5_pw_check(pw)
実行結果
$ python level5.py Welcome back... your flag, user: picoCTF{h45h_sl1ng1ng_2f021ce9}