コース目次 / 第2章

エンコードの、玉ねぎ

rot13・base64・hexの3重にエンコードされた文字列を生成します。エンコードが暗号ではなく鍵を必要としないことを確認し、逆順に1枚ずつはがして復元します。

第2章 / 全4章目安 約10分この章のゴール: 多重エンコードを見分け、逆順にほどいて復元できるようになる

3重に、エンコードする

encode_chain.py として保存します。

import base64, codecs

flag = "flag{peel_the_encoding_onion}"
step1 = codecs.encode(flag, 'rot13')          # 1枚目: rot13
step2 = base64.b64encode(step1.encode()).decode()  # 2枚目: base64
step3 = step2.encode().hex()                  # 3枚目: hex

print(step3)
python3 encode_chain.py
63336c756448746a636e4a3558326431636c39795958426963585a686446396959585a695958303d

これが、配布される文字列です。

エンコードは、暗号ではない

rot13・base64・hexは、どれも「読みにくい表現に変換する」だけの符号化であり、鍵を必要としません。変換のルールさえ知っていれば、誰でも逆方向に戻せます。mini-ctf-cryptoで扱ったXOR暗号やAESとは違い、「解けない」ようにするための仕組みではないという点が重要です。CTFのmiscでは、こうしたエンコードを見た目から判別する力が問われます。

見分け方のヒント——hexは0-9とa-fだけの文字列。base64はA-Z/a-z/0-9と+ / =で構成され、長さが4の倍数になりがち。rot13は英字だけを規則的にずらすので、記号や数字はそのまま残ります。

逆順に、はがす

decode_chain.py として保存します。エンコードした順と逆——hex→base64→rot13の順にほどきます。

import base64, codecs

encoded = "63336c756448746a636e4a3558326431636c39795958426963585a686446396959585a695958303d"

step1 = bytes.fromhex(encoded).decode()   # hexを戻す
step2 = base64.b64decode(step1).decode()  # base64を戻す
step3 = codecs.decode(step2, 'rot13')     # rot13を戻す

print(step3)
python3 decode_chain.py
flag{peel_the_encoding_onion}

復元できました。「玉ねぎの皮をむく」ように、外側(最後に施されたエンコード)から順にはがしていくのが基本です。見た目のパターンからエンコード方式を推測する練習は、実際のCTFのmisc問題でも頻繁に役立ちます。

こうなっていればOK

卒業まであと1章です。

この章はまだ完了していません。