miscfreehard

Чай Дракона (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/
lfsr_decryptionebcdic_decodingpython_source_encoding_abuseunicode_escape_newline_injection

Чай Дракона (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:

  1. Server validation: Reads raw bytes → both lines start with # → passes check
  2. Python parsing: Sees # coding: unicode_escape on first line
  3. Re-decoding: Python re-decodes the entire file using unicode_escape codec
  4. Escape expansion: \x0a (hex for newline \n) becomes an actual newline character
  5. After decoding, the file becomes:
# coding: unicode_escape # print(open("/sandbox/flag.txt").read())
  1. 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