コース目次 / 第2章
エンコードの、玉ねぎ
rot13・base64・hexの3重にエンコードされた文字列を生成します。エンコードが暗号ではなく鍵を必要としないことを確認し、逆順に1枚ずつはがして復元します。
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章です。
この章はまだ完了していません。
保存できませんでした(プライベートブラウズ中かもしれません)。この端末に進捗は残りませんが、先へは進めます。