jailCTF 2024 - parseltongue
Challenge
入力は printable ASCII 文字のみ許可され、バイトコードとして解釈・実行される。
import disimport sys
code = input("Enter your code: ")
# printable ASCII のみ許可for c in code: if ord(c) < 0x20 or ord(c) > 0x7e: print("Invalid character") sys.exit(1)
# バイトコードとして実行exec(compile(code, '<input>', 'exec'))Solution
printable ASCII オペコード
printable ASCII 範囲 (0x20-0x7e) 内のオペコードを使用:
| オペコード | 値 | 文字 |
|---|---|---|
| LOAD_FAST | 124 | | |
| STORE_FAST | 125 | } |
| LOAD_CONST | 100 | d |
| RETURN_VALUE | 83 | S |
| POP_TOP | 1 | 範囲外 |
バイトコード構築
# Python 3.12 のバイトコード形式# 各命令は2バイト (opcode, arg)
# printable 文字のみで構成bytecode = b'd\x00S\x00' # LOAD_CONST 0, RETURN_VALUE実際のペイロード
# 文字列として入力可能なバイトコードpayload = "d\x00|\x00S\x00"Technical Details
Python 3.11+ ではバイトコード形式が変更され:
- 可変長命令
- CACHE 命令の追加
- specialized instructions
これらを考慮してペイロードを構築する必要がある。
Alternative Solutions
別解1: LOAD_NAME との組み合わせ
# LOAD_NAME (101 = 'e') を使用# printable 範囲内Flag
jail{...}
References
- jailCTF 2024 Official
- Python dis module documentation