Чай Дракона (Dragon Tea)
alfactf
Task: Multi-stage challenge with LFSR encryption, hidden EBCDIC data, and Python comment-only execution sandbox. Solution: Reverse password check, decode cp500 EBCDIC, abuse unicode_escape encoding to inject newlines into comments.
$ ls tags/ techniques/
Чай Дракона (Dragon Tea) — AlfaCTF
Description
Ваши коллеги прикатили на велосипедах из Японии и наконец-то раздобыли в префектуре Сидзуока древний рецепт тайного чая императора-дракона. К сожалению, он также оказался на древнеяпонском.
Помогите разобрать его, и мы наконец вкусим этот живительный напиток, дающий +100 к ловкости и −10 к унынию.
Свиток с рецептом: https://alfactf.ru/files/tearecipe_7a49aae.py
Multi-stage challenge: decrypt LFSR-encrypted data, find hidden EBCDIC-encoded script, then bypass a Python sandbox that only allows comment lines.
Analysis
Part 1: LFSR Encryption Analysis
The provided Python file tearecipe_7a49aae.py contains:
#!/usr/bin/env python3 # brewing: ht409 (Hina Takahashi), encryption: yo660 (Yuto Ogawa), vibecoding: cp500 (Chihiro Punaki), original tea recipe: gs001 (Genryu Saito) import sys d1, d2, reg, taps, n = b'\x18Pf\xc7\xee\x0f-.\x8fBv 0\x9b\xb8\xf1\xb1\xb6G\x86Q\x9aFj\xdb\xee\x08 c\x89\rr#e\x8e\xfd\xf5\xf8\xe4\\\xd3U\xd5Rn\xc7\xaf\tl!\x98\x07hsd\x9f\xf9\xa7\xef\xec', b'\x02Tc\xca\xe7\x10)c\x8e\x07~!0\x9d\xed\xe2\xa7\xb0\x1e\x9d\x08\xd5en\xc2\xed]-c\x99\x0bo', 170, 0x88, 8 if len(sys.argv) <= 1: data = d1 # FAIL elif bytes([n + 1 for n in sys.argv[1].encode()]).upper() != b'IJSBLFHPNB': data = d1 # FAIL else: data = d2 # SUCCESS
Password check reversal:
- Check:
bytes([n + 1 for n in sys.argv[1].encode()]).upper() != b'IJSBLFHPNB' - Each byte is incremented by 1, then uppercased
- Reverse: subtract 1 from each byte of
IJSBLFHPNB I-1=H, J-1=I, S-1=R, B-1=A, L-1=K, F-1=E, H-1=G, P-1=O, N-1=M, B-1=A- Password:
HIRAKEGOMA(開けゴマ = "Sesame, open!" in Japanese)
Part 2: Hidden EBCDIC Data
The comment mentions vibecoding: cp500 (Chihiro Punaki) — a hint at EBCDIC encoding (cp500).
After the visible Python code, there's hidden binary data. Extracting and decoding with cp500:
# Extract bytes after the visible code with open('tearecipe_7a49aae.py', 'rb') as f: data = f.read() # Find hidden data and decode as cp500 (EBCDIC) hidden = data[visible_end:] decoded = hidden.decode('cp500')
The hidden script requires password himetahimitsu (秘めた秘密 = "hidden secret" in Japanese).
Running with correct password reveals URL: https://tokyosage-yu9baicvn.alfactf.ru/
Part 3: Comments-Only Python Sandbox
The web service accepts Python files but validates that every line starts with # or is empty.
Hint on page: "Только написав программу из одних комментариев, познаешь ты секрет" (Only by writing a program of only comments will you know the secret)
Solution
The unicode_escape Trick
Python's source encoding declaration can be abused to bypass the comment check:
# coding: unicode_escape # \x0aprint(open("/sandbox/flag.txt").read())
How it works:
- Server validation: Reads raw bytes → both lines start with
#→ passes check - Python parsing: Sees
# coding: unicode_escapeon first line - Re-decoding: Python re-decodes the entire file using unicode_escape codec
- Escape expansion:
\x0a(hex for newline\n) becomes an actual newline character - After decoding, the file becomes:
# coding: unicode_escape # print(open("/sandbox/flag.txt").read())
- Execution: The
print()statement is now on its own line (not a comment) and executes!
Final Exploit
# coding: unicode_escape # \x0aprint(open("/sandbox/flag.txt").read())
Upload this file to the service → flag is printed.
$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar
Similar writeups
- [web][Pro]O.H.F.U.K.— spbctf
- [forensics][Pro]Переработки стоит держать в секрете (Overtime Should Be Kept Secret)— hackerlab
- [reverse][Pro]Змеиная магия (Snake Magic)— hackerlab
- [pwn][Pro]Древний замок мага (Ancient Magician Castle)— duckerz
- [stego][Pro]Шепчущий Свиток Клодa (Whispering Scroll of Claude)— caplag