\[Writeup\]Daily AlpacaHack #Find XOR key ================================================== 概要 -- paca? 初心者向けヒント - xorは、同じ値をxorすると0になる性質があります。例えば、A xor B = C ならば、C xor A = B となります。 - 知っている情報から、keyを決定できないでしょうか? [https://alpacahack-prod.s3.ap-northeast-1.amazonaws.com/f4934f9e-b0ca-4c50-a051-21fe8ce7251f/find-xor-key.tar.gz](https://alpacahack-prod.s3.ap-northeast-1.amazonaws.com/f4934f9e-b0ca-4c50-a051-21fe8ce7251f/find-xor-key.tar.gz) 与えられたPythonスクリプト prob.pyと実行結果 output.txt から、XOR暗号の鍵を特定しフラグを復元する。 解析 -- prob.pyのコードを確認すると、以下の特徴がある。 - 鍵は string.ascii\_letters(英字)からランダムに選ばれた7バイトである。 - フラグの先頭は必ず Alpaca{ で始まる。 - itertools.cycle(key) を用いて、フラグ全体に対して7バイトの鍵を繰り返し適用してXORしている。 - XOR暗号の性質 C = P \\oplus K から、逆演算 K = C \\oplus P が成り立つ。 既知の平文(Alpaca{)はちょうど7バイトであるため、これと暗号文の先頭7バイトをXORすれば、鍵を完全に特定できる。 以下のスクリプトを作成し、フラグを復元した。 ```python from itertools import cycle c_hex = "031b13072d280a2c1816392f3b041d07020d2f1619232817153b24141d000c3925281a3704161b" c = bytes.fromhex(c_hex) # 既知のプレフィックス(7バイト) known_p = b"Alpaca{" # 1. 鍵の特定: K = C ^ P key = bytes([c1 ^ c2 for c1, c2 in zip(c[:7], known_p)]) # 2. 復号: P = C ^ K flag = bytes([c1 ^ c2 for c1, c2 in zip(c, cycle(key))]) print(f"Key: {key.decode()}") print(f"Flag: {flag.decode()}") ``` ``` Key: keykeyk Flag: Alpaca{x0r_15_v3ry_345y_f0r_y0u_7h4nk_y0u} ``` Flag: ----- ``` Alpaca{x0r_15_v3ry_345y_f0r_y0u_7h4nk_y0u} ``` 考察 -- 鍵の長さが固定で、かつ平文の一部が既知(Known Plaintext Attack)であれば、単純なXOR暗号は容易に突破可能である。今回の鍵 keykeyk は、内部的には key という単語の繰り返しであったことが推測される。