前回 は、サイバーセキュリティのトレーニングができるサイトを始めてみましたが、少し合わなかったかなって感じでした。
今回も、こりずに、picoCTF という CTF の学習や、コンテストを開催しているサイトがあるので、挑戦してみたいと思います。
それでは、やっていきます。
※2024/10/3:追記
今回は、picoCTF の picoGym で、「Beginner picoMini 2022」の 全13問をやってみました。もし、これから「Beginner picoMini 2022」をやってみようと思う方にお知らせです。問題のタイトルに番号が付いてるものがあります(例:PW Crack 2)。それらの問題については、番号の若い順に解くことをお勧めします。番号が進むにつれて難易度が上がる形になっているためです。
はじめに
「セキュリティ」の記事一覧です。良かったら参考にしてください。
セキュリティの記事一覧
picoCTF の公式サイトは以下です。英語のサイトですが、こちらも、やってる方が多いみたいです。
picoctf.com
それでは、やっていきます。
picoCTFに登録する
公式サイトにアクセスすると、以下の項目が並んでいます。
項目 |
内容 |
詳細 |
Learn |
picoPrimerで知識を習得 |
役に立ちそうな大量のテキストがありました |
Practice |
picoGymとミニコンテストで練習 |
過去のコンテストの内容で練習できるようです |
Compete |
コンテストに参加 |
1年に1、2回開催されているようです、前回は2024年3月に実施されたようです |
Visualize |
サイバーセキュリティのキャリアの紹介 |
カーネギーメロン大学のWebサイトに飛ぶ |
Facilitate |
生徒、または、グループの進捗状況を監視? |
よく分かりません |
Play |
参加して楽しくプレイ |
コンテストと同じ画面に見えます、観客用? |
まずは、Practice(picoGym)に行ってみようと思います。
Practiceのログイン画面
ユーザ名や、E-Mailアドレスを入力して、いくつかの質問に答えて、Sign Up をクリックします。
ユーザ登録画面
確認メールが届くので、届いたら、リンクをクリックすると、完了です。
登録は以上です。
Practice(picoGym)を始めてみる
登録が完了すると、以下のようなトップページが表示されます。左側のフィルタをチェックすると、所望の問題が表示されるようです。
Practice(picoGym)のトップ画面
試しに、「Beginner picoMini 2022」というのがあったので、それでフィルタしてみます。全部で 13問あるようです。最初の方は、Easy の問題が続き、最後の方は、Medium があります。
Beginner picoMini 2022を表示
良さそうな感じなので、「Beginner picoMini 2022」をやってみます。
runme.py
最初は、Pythonスクリプト(runme.py)がダウンロードできて、それを実行するとフラグが表示されるようです。
runme.py問題
PW Crack 2
先に PW Crack 2 が並んでますが、次の問題は PW Crack です。
Pythonスクリプト(level2.py)と暗号化されたパスワードファイル(level2.flag.txt.enc)がダウンロードできます。
PW Crack 2問題
パスワードファイルをバイナリエディタで開くと、31byte でした。
Pythonスクリプトを実行してみると、パスワードを聞かれます。Pythonスクリプトを読むと、入力するパスワードが分かります。簡単でした。
$ python level2.py
Please enter correct password for flag:
PW Crack 1
上の「PW Crack 2」と同じ問題形式です。level1.py と level1.flag.txt.enc がダウンロードできます。
PW Crack 1問題
バイナリファイルは、今度は、30byte でした。Pythonスクリプトを見ると、すぐに答えが分かります。PW Crack 2 より簡単でした。
$ python level1.py
Please enter correct password for flag:
HashingJobApp
次は、インスタンスを起動します。すると、「nc saturn.picoctf.net 53399」と表示されて、15分のカウントダウンが始まります。15分以内に、答える必要があるようです。
HashingJobApp問題
netcat で接続してみます。3回正解すると、フラグが表示されました。
$ nc saturn.picoctf.net 53399
Please md5 hash the text between quotes, excluding the quotes: 'Al Pacino'
Answer:
1c9909508d984c65fb3a2f3b28d27faf
1c9909508d984c65fb3a2f3b28d27faf
Correct.
Please md5 hash the text between quotes, excluding the quotes: 'choir boys'
Answer:
ce6b6964402e279f878ce9cf5e19d14b
ce6b6964402e279f878ce9cf5e19d14b
Correct.
Please md5 hash the text between quotes, excluding the quotes: 'carnival workers'
Answer:
d3818fc79b44a9f961c502fb3a9bd42d
d3818fc79b44a9f961c502fb3a9bd42d
Correct.
Glitch Cat
次の問題もインスタンスを起動する形式です。
Glitch Cat問題
以下のように表示されました。
$ nc saturn.picoctf.net 61936
'picoCTF{gl17ch_m3_n07_' + chr(0x61) + chr(0x34) + chr(0x33) + chr(0x39) + chr(0x32) + chr(0x64) + chr(0x32) + chr(0x65) + '}'
別のターミナルで、以下を実行すればフラグが表示されました。
$ python -c "print('picoCTF{gl17ch_m3_n07_' + chr(0x61) + chr(0x34) + chr(0x33) + chr(0x3
9) + chr(0x32) + chr(0x64) + chr(0x32) + chr(0x65) + '}')"
fixme2.py
Pythonスクリプト(fixme2.py)をダウンロードできます。次の問題が、「fixme1.py」なので、順番を変えてやってみてもいいかもしれません。
fixme2.py問題
Pythonスクリプトを見て、修正すればいいようです。修正すると、Pythonスクリプトを実行できるようになって、フラグが表示されました。
$ python fixme2.py
That is correct! Here's your flag:
fixme1.py
「fixme2.py」と同じ問題形式です。Pythonスクリプト(fixme1.py)をダウンロードできます。
fixme1.py問題
修正できると、Pythonスクリプトを実行できるようになります。修正すると、Pythonスクリプトを実行できるようになって、フラグが表示されました。
$ python fixme1.py
That is correct! Here's your flag:
convertme.py
これもPythonスクリプト(convertme.py)をダウンロードする問題形式です。
convertme.py問題
以下のように質問されます。
$ python convertme.py
If 23 is in decimal base, what is it in binary base?
Answer:
以下で、2進数に変換できます。
$ python -c 'print(f"{bin(23)}")'
0b10111
回答するとフラグが表示されました。
Codebook
Pythonスクリプト(code.py)と、テキストファイル(codebook.txt)をダウンロードできます。
Codebook問題
テキストファイルには、azbycxdwevfugthsirjqkplomn
と書かれていました。
Pythonスクリプトを実行すると、フラグが表示されました。
Serpentine
ここから難易度が Medium になります。Pythonスクリプト(serpentine.py)をダウンロードできます。
Serpentine問題
Pythonスクリプトを見てみると、フラグを表示する関数(print_flag関数)は、どこからも呼ばれていません。main関数の先頭で、print_flag関数を呼び出すようにすると、フラグが表示れました。
Pythonスクリプトを変更したらダメだったかもしれません。それが許されたら、どの問題も簡単になってしまいそうです。もう一度、Pythonスクリプトを見直してみると、print_flag関数の置き場所を間違えたので、ソースをチェックしてください!というメッセージがありました。ソース変更で良かったようです。
PW Crack 5
次も Medium の問題です。4つのファイル(level5.py、level5.flag.txt.enc、level5.hash.bin、dictionary.txt)をダウンロードできます。
PW Crack 5問題
Pythonスクリプト(level5.py)は以下です。
import hashlib
def str_xor(secret, key):
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()
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():
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(), user_pw)
print(decryption)
return
print("That password is incorrect")
level_5_pw_check()
実行すると、パスワードを聞かれるので、正しいパスワードを入力するとフラグが表示されそうです。
パスワードの辞書が提供されているので、それを 1つずつ入力すれば、いつかは正解しますが、辞書には、65536個のパスワードが含まれていました。
Pythonスクリプトを繰り返し実行する Pythonスクリプトを実装すれば良さそうです。pwntools を使います。
import os, sys
from pwn import *
def prologue_python( prog, ss ):
proc = process( ['python', prog] )
print( proc.recv(timeout=1) )
print( ss )
proc.sendline( ss )
ret = proc.recvline()
print( ret )
return proc, ret
fpath = "dictionary.txt"
prog = "level5.py"
with open(fpath) as ff:
for line in ff:
print( f"line={line}" )
proc, ret = prologue_python( prog, line.encode('utf-8') )
if "Welcome" in ret.decode('utf-8'):
break
else:
proc.close()
print( proc.recvline() )
print( proc.recvline() )
print( proc.recvline() )
print( proc.recvline() )
実装して実行しましたが、かなり時間がかかります(2時間ぐらい)。逆順にやった方が絶対早いだろうなと思いましたが、やっぱり、だいぶ後ろの方でヒットしました(笑)。
$ python tmp.py
line=0000
[+] Starting local process '/home/user/20240819/bin/python': pid 209134
b'Please enter correct password for flag: '
b'0000\n'
b'That password is incorrect\n'
[*] Stopped process '/home/user/20240819/bin/python' (pid 209134)
line=0001
[+] Starting local process '/home/user/20240819/bin/python': pid 209136
b'Please enter correct password for flag: '
b'0001\n'
b'That password is incorrect\n'
[*] Stopped process '/home/user/20240819/bin/python' (pid 209136)
line=0002
(以下、省略)
PW Crack 4
次も Medium の問題です。3つのファイル(level4.py、level4.flag.txt.enc、level4.hash.bin)をダウンロードできます。
PW Crack 4問題
上の「PW Crack 5」と似ていて、ちょっと簡単です。前回と同じく、パスワードを入力して、正しければ、フラグが表示されます。前回は、辞書ファイルに 65536個のパスワードの候補が入っていましたが、こちらは、ダウンロードした「level4.py」の中に、100個のパスワード候補がリストに定義されている状態です。
Pythonスクリプト(level4.py)は以下です。
import hashlib
def str_xor(secret, key):
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():
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(), user_pw)
print(decryption)
return
print("That password is incorrect")
level_4_pw_check()
pos_pw_list = ["158f", "1655", "d21e", "4966", "ed69", "1010", "dded", "844c", "40ab", "a948", "156c", "ab7f", "4a5f", "e38c", "ba12", "f7fd", "d780", "4f4d", "5ba1", "96c5", "55b9", "8a67", "d32b", "aa7a", "514b", "e4e1", "1230", "cd19", "d6dd", "b01f", "fd2f", "7587", "86c2", "d7b8", "55a2", "b77c", "7ffe", "4420", "e0ee", "d8fb", "d748", "b0fe", "2a37", "a638", "52db", "51b7", "5526", "40ed", "5356", "6ad4", "2ddd", "177d", "84ae", "cf88", "97a3", "17ad", "7124", "eff2", "e373", "c974", "7689", "b8b2", "e899", "d042", "47d9", "cca9", "ab2a", "de77", "4654", "9ecb", "ab6e", "bb8e", "b76b", "d661", "63f8", "7095", "567e", "b837", "2b80", "ad4f", "c514", "ffa4", "fc37", "7254", "b48b", "d38b", "a02b", "ec6c", "eacc", "8b70", "b03e", "1b36", "81ff", "77e4", "dbe6", "59d9", "fd6a", "5653", "8b95", "d0e5"]
上の「PW Crack 5」で実装した Pythonスクリプトを少し変更します。
import os, sys
from pwn import *
def prologue_python( prog, ss ):
proc = process( ['python', prog] )
print( proc.recv(timeout=1) )
print( ss )
proc.sendline( ss )
ret = proc.recvline()
print( ret )
return proc, ret
prog = "level4.py"
pos_pw_list = ["158f", "1655", "d21e", "4966", "ed69", "1010", "dded", "844c", "40ab", "a948", "156c", "ab7f", "4a5f", "e38c", "ba12", "f7fd", "d780", "4f4d", "5ba1", "96c5", "55b9", "8a67", "d32b", "aa7a", "514b", "e4e1", "1230", "cd19", "d6dd", "b01f", "fd2f", "7587", "86c2", "d7b8", "55a2", "b77c", "7ffe", "4420", "e0ee", "d8fb", "d748", "b0fe", "2a37", "a638", "52db", "51b7", "5526", "40ed", "5356", "6ad4", "2ddd", "177d", "84ae", "cf88", "97a3", "17ad", "7124", "eff2", "e373", "c974", "7689", "b8b2", "e899", "d042", "47d9", "cca9", "ab2a", "de77", "4654", "9ecb", "ab6e", "bb8e", "b76b", "d661", "63f8", "7095", "567e", "b837", "2b80", "ad4f", "c514", "ffa4", "fc37", "7254", "b48b", "d38b", "a02b", "ec6c", "eacc", "8b70", "b03e", "1b36", "81ff", "77e4", "dbe6", "59d9", "fd6a", "5653", "8b95", "d0e5"]
for line in pos_pw_list:
print( f"line={line}" )
proc, ret = prologue_python( prog, line.encode('utf-8') )
if "Welcome" in ret.decode('utf-8'):
break
else:
proc.close()
print( proc.recvline() )
print( proc.recvline() )
print( proc.recvline() )
print( proc.recvline() )
実行します。今度は 1分ぐらいでヒットしました。
$ python tmp.py
line=158f
[+] Starting local process '/home/user/20240819/bin/python': pid 209456
b'Please enter correct password for flag: '
b'158f'
b'That password is incorrect\n'
[*] Stopped process '/home/user/20240819/bin/python' (pid 209456)
line=1655
[+] Starting local process '/home/user/20240819/bin/python': pid 209458
b'Please enter correct password for flag: '
b'1655'
b'That password is incorrect\n'
[*] Stopped process '/home/user/20240819/bin/python' (pid 209458)
line=d21e
[+] Starting local process '/home/user/20240819/bin/python': pid 209460
b'Please enter correct password for flag: '
b'd21e'
b'That password is incorrect\n'
[*] Stopped process '/home/user/20240819/bin/python' (pid 209460)
(以下、省略)
PW Crack 3
次も Medium の問題です。3つのファイルをダウンロードできます。
PW Crack 3問題
内容は、上の「PW Crack 4」と同じ問題で、パスワードの候補がリストに格納されているところも同じで、候補数が 100個から 7個に減っています。
先ほどの Pythonスクリプトを変更します。
import os, sys
from pwn import *
def prologue_python( prog, ss ):
proc = process( ['python', prog] )
print( proc.recv(timeout=1) )
print( ss )
proc.sendline( ss )
ret = proc.recvline()
print( ret )
return proc, ret
prog = "level3.py"
pos_pw_list = ["8799", "d3ab", "1ea2", "acaf", "2295", "a9de", "6f3d"]
for line in pos_pw_list:
print( f"line={line}" )
proc, ret = prologue_python( prog, line.encode('utf-8') )
if "Welcome" in ret.decode('utf-8'):
break
else:
proc.close()
print( proc.recvline() )
print( proc.recvline() )
print( proc.recvline() )
print( proc.recvline() )
実行します。今度はすぐにヒットしました。
$ python tmp.py
line=8799
[+] Starting local process '/home/user/20240819/bin/python': pid 210010
b'Please enter correct password for flag: '
b'8799'
b'That password is incorrect\n'
[*] Stopped process '/home/user/20240819/bin/python' (pid 210010)
line=d3ab
[+] Starting local process '/home/user/20240819/bin/python': pid 210012
b'Please enter correct password for flag: '
b'd3ab'
b'That password is incorrect\n'
[*] Stopped process '/home/user/20240819/bin/python' (pid 210012)
line=1ea2
[+] Starting local process '/home/user/20240819/bin/python': pid 210014
b'Please enter correct password for flag: '
b'1ea2'
b'That password is incorrect\n'
[*] Stopped process '/home/user/20240819/bin/python' (pid 210014)
(以降、省略)
以上で、「Beginner picoMini 2022」の全13問を完了しました!
おわりに
今回は、picoCTF に登録して、その中の picoGym で、「Beginner picoMini 2022」を全問(13問)やりました。
picoCTF は、とても良かったです。シンプルで、分かりやすいシステムで、英語ですが、特に困ったりはしませんでした。
「Beginner picoMini 2022」は、CTF をやったことない方にお勧めでしょうか。逆に、CTF をやったことある方は、早く解くことを目標にやってみてはいかがでしょうか。
最後になりましたが、エンジニアグループのランキングに参加中です。
気楽にポチッとよろしくお願いいたします🙇
今回は以上です!
最後までお読みいただき、ありがとうございました。