crackmes.one - Sexy 1337 writeup (zh-TW)

題目連結: https://crackmes.one/crackme/6715466c9b533b4c22bd18bb
1) 先看 main
:決定要追的兩個函式
從 main
可以一次抓到三個關鍵事實:
generate_password(local_48, "sexy1337")
⇒ 有一個「以固定種子產生密碼」的步驟encrypt_decrypt(local_48, 0xffffffaa)
與encrypt_decrypt(local_88, 0xffffffaa)
⇒ 同一把 key(0xAA)分別作用在「正確密碼」與「使用者輸入」上strcmp(local_88, local_48)
⇒ 最終比較發生在兩次加密(XOR)之後。
結論:先去看「密碼怎麼被產生」→ generate_password
;再回來驗證「同鑰 XOR 的效果」→ encrypt_decrypt
。
2) 追 generate_password
:算出「密碼明文」
for (i = 0; i < strlen(seed); i++) {
dst[i] = seed[i] + 3;
}
dst[len] = '\0';
- 種子是固定字串:
"sexy1337"
- 逐字元 +3(ASCII Caesar shift)
手算:
- s→v、e→h、x→{、y→|、1→4、3→6、3→6、7→:
- 得到密碼明文:
vh{|466:
到這裡,我們已經知道「正確密碼的未 XOR 版本」。
3) 看 encrypt_decrypt
:確認「同鑰 XOR」的等價性
for (...) {
buf[i] ^= 0xAA; // 0xffffffaa 的低 8 位即 0xAA
}
main
對 兩邊都做 ^ 0xAA
後再 strcmp
。
XOR 的性質:a == b ⇔ (a ^ k) == (b ^ k)
。
因此「兩邊都 XOR 同一把鑰」等價於直接比較原文。
推論:我們只要在輸入框裡輸入剛剛算出的明文(vh{|466:
),就會與「產生後亦 XOR 的密碼」在 XOR 後相等。
4) 回到 main
:收斂成最終輸入
main
的剩餘細節只是讀字串、去掉換行,然後 strcmp
。
既然比較等價於比較原文,我們的最終輸入就是:
vh{|466:
總結
- 從
main
發現「先生成密碼、雙方同鑰 XOR、最後 strcmp」的流程 - 進
generate_password
算出明文密碼vh{|466:
- 用
encrypt_decrypt
的「同鑰 XOR 等價比較原文」確認邏輯 - 回到
main
下結論:直接輸入vh{|466:
即可通關
經驗分享
上面提到的程式碼,是經過ghidra反編譯過的程式碼,所以我們是透過分析反編譯的程式碼解出這題喔!