iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0
自我挑戰組

新手挑戰 picoCTF:資安入門紀錄系列 第 20

PW Crack 4 — 比對雜湊再解密

  • 分享至 

  • xImage
  •  

今天的題目是:
https://ithelp.ithome.com.tw/upload/images/20251001/20178898LybAD5zP63.png
流程跟之前幾題很像:
讀程式找候選密碼 → 用程式內相同的雜湊方式處理候選 → 找出跟提供的 hash 檔相同的那個密碼 → 用該密碼對被 XOR 加密的 flag 檔解密。


解題步驟與思路
一、先把題目檔案下載到 webshell:

wget https://artifacts.picoctf.net/c/19/level4.py
wget https://artifacts.picoctf.net/c/19/level4.flag.txt.enc
wget https://artifacts.picoctf.net/c/19/level4.hash.bin
ls -1

二、檢視 level4.py:
level4.py 大致包含三個重要部分(我把它拆成可理解的段落):

  1. 讀入檔案
    程式會把 level4.flag.txt.enc 與 level4.hash.bin 讀進來
flag_enc = open('level4.flag.txt.enc', 'rb').read()
correct_pw_hash = open('level4.hash.bin', 'rb').read()

rb 表示以 binary 形式讀入(雜湊檔與被加密的檔通常是二進位)。
correct_pw_hash 就是題目提供的「目標 hash bytes」。

  1. str_xor(XOR 邏輯)
    題目連續幾題都用了相同的 str_xor 做法,核心邏輯如下
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(a) ^ ord(b)) for a,b in zip(secret,new_key)])

把 key 的字元循環延伸(repeat)直到跟 secret(密文)一樣長。
逐字元用 ord() 取得 ASCII code,做 XOR(^),再用 chr() 把結果轉回字元。
這就是簡單「流式 XOR」的實作:cipher = plain XOR key,反過來 plain = cipher XOR key 也成立。

  1. hash 比對函式
    程式會把使用者輸入的密碼先做 hash,再跟 correct_pw_hash 比對
import hashlib
def hash_pw(pw_str):
    pw_bytes = bytearray()
    pw_bytes.extend(pw_str.encode())
    m = hashlib.md5()
    m.update(pw_bytes)
    return m.digest()

這題使用的是 MD5(hashlib.md5())。
m.digest() 回傳的是 raw bytes(16 bytes for MD5),剛好能和 level4.hash.bin 直接比對。

  1. 候選密碼清單
    程式末段通常會列出一個 pos_pw_list(這題說有 100 個候選)
pos_pw_list = ["...","...","..."]  # 100 個候選

但我不用暴力全部爆破,而是依程式提供的候選做 hash 比對。


三、比對 hash,找出正確密碼:
我直接把候選自動帶入,並嘗試常見演算法(本題最後是 MD5 命中)。
下面是一段我在 webshell 執行的 Python 程式:

python3 - <<'PY'
import hashlib, re
src = open('level4.py','r',encoding='utf-8').read()
raw = re.search(r'pos_pw_list\s*=\s*\[([^\]]*)\]', src, re.S).group(1)
cands = re.findall(r"""['"]([^'"]+)['"]""", raw)
target = open('level4.hash.bin','rb').read()
for pw in cands:
    if hashlib.md5(pw.encode()).digest() == target:
        print("FOUND:", pw)
        break
PY

系統輸出:程式會直接告訴你是哪一個候選的 MD5 與 level4.hash.bin 相符。
https://ithelp.ithome.com.tw/upload/images/20251001/201788980kyZ4Mfonl.png


四、用找到的密碼執行 XOR 還原 flag:
找到密碼後,我把它當 key 用 str_xor 來解 level4.flag.txt.enc:

python3 - <<'PY'
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(a)^ord(b)) for a,b in zip(secret,new_key))

enc = open('level4.flag.txt.enc','rb').read()
#若 decode() 失敗,可用 latin-1 fallback
try:
    enc_s = enc.decode()
except:
    enc_s = enc.decode('latin-1')

pw = "<the_correct_password>"   # 把這裡換成上一步找到的密碼
print(str_xor(enc_s, pw))
PY

執行結果就是明文 flag:picoCTF{fl45h_5pr1ng1ng_ae0fb77c}
https://ithelp.ithome.com.tw/upload/images/20251001/20178898RulTQOOrI6.png


小心得
「先讀程式」往往勝過「盲目爆破」——很多題目把關鍵線索藏在附檔裡。學會用 Python 快速自動化(把候選丟進 hash 函式),可以省很多時間。

理解基本概念:chr()/ord()、encode()/decode()、XOR、hash digest 長度(MD5=16B、SHA1=20B、SHA256=32B)會很常用。

每題解完把步驟記下,久了你會有自己的「題型速查表」,遇到類似題目就能迅速上手。💪💪


上一篇
PW Crack 3 — 找候選密碼、比對 MD5
系列文
新手挑戰 picoCTF:資安入門紀錄20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言