PW Crack

Q. パスワードをクラックしてflagを入手して

levelX.pyとlevelX.flag.txt.encを受け取って、そこからflagを入手する。

PW Crack 1

level1.py

def level_1_pw_check():
    user_pw = input("Please enter correct password for flag: ")
    if user_pw == "8713":
        print("Welcome back... your flag, user:")
        decryption = str_xor(flag_enc.decode(), user_pw)
        print(decryption)
        return
    print("That password is incorrect")

user_pw == "8713"とあるので、8713を入力する。

Please enter correct password for flag: 8713
Welcome back... your flag, user:
picoCTF{545h_r1ng1ng_1b2fd683}

Flag: picoCTF{545h_r1ng1ng_1b2fd683}

PW Crack 2

level2.py

def level_2_pw_check():
    user_pw = input("Please enter correct password for flag: ")
    if user_pw == chr(0x64) + chr(0x65) + chr(0x37) + chr(0x36):
        print("Welcome back... your flag, user:")
        decryption = str_xor(flag_enc.decode(), user_pw)
        print(decryption)
        return
    print("That password is incorrect")

ASCIIになったのでデコードする。

Please enter correct password for flag: de76
Welcome back... your flag, user:
picoCTF{tr45h_51ng1ng_489dea9a}

Flag: picoCTF{tr45h_51ng1ng_489dea9a}

PW Crack 3

ここではハッシュが登場する。バイナリファイルの中身を確認するため、 stringsやbviを試したが、パスワードの手がかりは見つからなかった。 bviはバイナリエディター。バイナリを文字化けさせずに確認するためのヒントだ。

パスワードの候補はpos_pw_listにまとまっているため、候補を順番に検証する。


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('level3.flag.txt.enc', 'rb').read()
correct_pw_hash = open('level3.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_3_pw_check(password):
    user_pw = password
#    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")


pos_pw_list = ["f09e", "4dcf", "87ab", "dba8", "752e", "3961", "f159"]
for i in pos_pw_list:
    level_3_pw_check(i)


# The strings below are 7 possibilities for the correct password.
#

候補を順番に検証するように書き換えて実行する。

$ uv run level3_solve.py
That password is incorrect
That password is incorrect
Welcome back... your flag, user:
picoCTF{m45h_fl1ng1ng_cd6ed2eb}
That password is incorrect
That password is incorrect
That password is incorrect
That password is incorrect

PW Crack 4

PW Crack 3の候補が100個になっただけで、検証方法は同じ。 ログを確認せず、grepでflagだけを取り出す。

$ uv run level4_solve.py | grep -o "picoCTF{.*}"
picoCTF{fl45h_5pr1ng1ng_ae0fb77c}

Flag: picoCTF{fl45h_5pr1ng1ng_ae0fb77c}

PW Crack 5

パスワードの候補がdictionary.txtにある。

$ cat dictionary.txt | head

0000
0001
0002
0003
0004
0005
0006
0007
0008
0009

read()で一度に読み込むこともできるが、ここではreadline()で1行ずつEOFまで読み込む。 次の処理を追記する。

with open("dictionary.txt", "r") as f:
    while True:
        pw = f.readline()
        if not pw:
            break
        level_5_pw_check(pw.strip("\n"))

改行文字までハッシュの対象にならないよう、strip("\n")で取り除く。

picoCTF{h45h_sl1ng1ng_40f26f81}

Flag: picoCTF{h45h_sl1ng1ng_40f26f81}

以上でPW Crackは終了。