ペネトレーションテスト&バグバウンティ
CTF(Capture The Flag)のCryptoカテゴリでは、XOR(エクスクルーシブオア)暗号の問題が出題されます。
ここでは、XOR暗号の仕組みや、CTFでの出題例・攻略方法をわかりやすく説明していきますね。
XOR演算とは
XOR(排他的論理和)とは、ビット同士を比較して「異なれば1、同じなら0」になる演算です。
Aが"0"で、Bが"0"なら、A xor Bは"0"
Aが"1"で、Bが"0"なら、A xor Bは"1"
Aが"0"で、Bが"1"なら、A xor Bは"1"
Aが"1"で、Bが"1"なら、A xor Bは"0"
XORは、暗号文の状態から平文の状態に変化した後、元の状態に戻ることができる性質があり
暗号文 xor 鍵 = 平文
平文 xor 鍵 = 暗号文
と、同じ鍵で復号できるのが特徴です。
なぜXOR暗号は使われるのか
・計算が非常にシンプル。(高速)
・暗号・マルウェア・バイナリ操作で頻出。
・CTFでの「初歩的な暗号」としてちょうど合っている問題。
ただし、短い鍵やパターンのあるデータに対しては脆弱です。
CTFでの典型的な出題パターン
・パターン 特徴 攻略法
1.単一バイトXOR 1文字だけの鍵で暗号化 総当たり(0から255)で解読
2.繰り返しXOR 短い鍵を繰り返して使う 鍵長を推測し復号
3.XOR + Base64 Base64後にXOR 順番に復号
4.XOR + 既知平文 一部の平文がわかる 鍵を逆算できる
単一バイトXORを総当たりより
1.暗号文
(例):cipher_hex = "6c666b6d517e6f797e72657857"
これは何の鍵でXORされたか分からない。
そこで、全ての鍵(0~255)を試す総当たりをします。
2.Pythonで解読のスクリプトを作成しましょう。
nanoエディターを立ち上げます。
nano xor_cipher.py
3.下記のソースを入力します。(コピペしてくださいね)
# この行は、16進数で書かれた文字列"6c666b6d517e6f797e7572657857"を、バイナリ(バイト列)に変換します。
cipher = bytes.fromhex("6c666b6d517e6f797e72657857")
# `key` を 0~255(全256通りの1バイト)で1つずつ試します。
# これは「どの1バイトの鍵が使われたのか」を総当たりするためです。
for key in range(256):
# 暗号文の各バイトbに対して、鍵 key と XOR演算(^)を実行します。
decrypted = bytes([b ^ key for b in cipher])
try:
# 復号結果(バイト列)を、文字列として表示しようとします。
print(f"Key {key:3}: {decrypted.decode()}")
# デコードに失敗した(意味のある文字列にならなかった)場合は、スキップして次の鍵へ。
except UnicodeDecodeError:
continue
このスクリプトは
(1)16進数からバイト列に変換
(2)すべての鍵を使ってXOR復号
(3)出力が読める文字列になったところをチェック
となります。
4.書き終えたら、以下の手順で保存してエディタを終了します。
Ctrl + O → Enter(保存)
Ctrl + X(終了)
5.ファイルを保存したら、次のように実行します。
python3 xor_cipher.py
6.出力例とフラグの見つけ方
以下のように出力されます。
出力結果の中から"flag"が見つかりました。
Key 10: flag[testxor]
このように意味ある文字列"flag..."が出れば正解です。
ハッカーは、CTFでXOR暗号の仕組みと復号の基本テクニックを学ぶのまとめ
「XORを制する者はCryptoを制す」と言われているそうです。
XOR暗号は単純ですが、CTFで頻繁に使われる重要なテーマです。
基本:XORの仕組みと性質を理解
実践:Pythonで復号スクリプトを書く
応用:既知平文や繰り返し鍵への応用
この方法は、CTFだけでなくマルウェア解析やリバースエンジニアリングにも応用できそうですね。