Шепчущий Свиток Клодa (Whispering Scroll of Claude)
Шепчущий Свиток Клодa (Whispering Scroll of Claude)
Platform: caplag | Category: Steganography | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-02-22 | Status: Solved Techniques: binary_encoding, zero_width_unicode_steganography
Summary
Task: find a hidden message in a UTF-8 text file with suspiciously large file size. Solution: extract zero-width Unicode characters (ZWNJ=0, ZWJ=1) from the text, decode 280 bits as 35 ASCII bytes to reveal the flag.
Шепчущий Свиток Клодa (Whispering Scroll of Claude) — caplag
Description
В эпической саге "Герои Кодекса" мудрый маг Claude, сражаясь с генеративным воином GPT в лесах CodeRealm, оставил шепчущий свиток. В нём скрыто тайное послание — заклинание триумфа. Разгадайте секрет, чтобы обрести флаг!
File: scroll.txt — UTF-8 text file, 2037 bytes, containing a Russian-language narrative.
Hint Decoding
| Phrase in description | Meaning |
|---|---|
| "шепчущий свиток" (whispering scroll) | Data hidden in the text file — invisible to the eye |
| "скрытые частоты unicode-эфира" | Zero-width Unicode characters embedded in the text |
| "тайное послание" (secret message) | Binary-encoded flag using invisible characters |
| "набросил вуаль невидимости" | Invisible (zero-width) characters used as the hiding medium |
| |
The critical in-text hint: "Только те, кто настроен на скрытые частоты unicode-эфира, могли разобрать секретное сообщение мага" — directly points to Unicode steganography.
Analysis
Step 1 — Initial recon
The file appears to be a plain Russian text about a battle between the mage Claude and the generative warrior GPT. However, the file size (2037 bytes) is suspiciously large for just 4 short paragraphs of visible text.
bash read-only • copy allowedfile scroll.txt # scroll.txt: UTF-8 Unicode text wc -c scroll.txt # 2037 scroll.txt
Step 2 — Hex dump reveals invisible characters
Examining the hex dump of the file reveals a large block of repeating byte sequences at the end:
bash read-only • copy allowedxxd scroll.txt | tail -20
The output shows a massive block of bytes e2 80 8c and e2 80 8d — these are the UTF-8 encodings of:
- U+200C — ZWNJ (Zero Width Non-Joiner) →
e2 80 8c - U+200D — ZWJ (Zero Width Joiner) →
e2 80 8d
These are invisible Unicode characters — they have zero visual width and render as nothing in text editors and terminals.
Step 3 — Binary encoding identification
Counting the zero-width characters reveals exactly 280 of them, using exactly 2 unique types. This is a classic binary encoding:
- 2 character types → 1 bit per character
- 280 characters ÷ 8 bits/byte = 35 bytes — a perfect match for a flag string like
caplag{...}
Step 4 — Decode
Mapping: ZWNJ (U+200C) = 0, ZWJ (U+200D) = 1
Solution
python read-only • copy allowed#!/usr/bin/env python3 """ Decode zero-width Unicode steganography from scroll.txt. ZWNJ (U+200C) = bit 0, ZWJ (U+200D) = bit 1. """ with open('scroll.txt', 'r', encoding='utf-8') as f: content = f.read() # Extract zero-width characters zw_chars = [c for c in content if c in ('\u200c', '\u200d')] print(f"Found {len(zw_chars)} zero-width characters") print(f"Expected bytes: {len(zw_chars) // 8}") # ZWNJ (U+200C) = 0, ZWJ (U+200D) = 1 bits = ''.join('0' if c == '\u200c' else '1' for c in zw_chars) # Convert bits to ASCII bytes result = '' for i in range(0, len(bits) - 7, 8): byte = bits[i:i+8] result += chr(int(byte, 2)) print(f"Flag: {result}")
Output:
Found 280 zero-width characters
Expected bytes: 35
Flag: caplag{REDACTED}
Key Technique
Zero-Width Unicode Character Steganography — invisible Unicode characters (ZWNJ, ZWJ, zero-width space, etc.) are embedded in normal text to encode a hidden binary message. Each character type represents a bit (0 or 1), and groups of 8 bits decode to ASCII characters.
When to suspect this technique:
- Text file challenge where the visible content seems normal but file size is too large
- Description mentions "hidden", "invisible", "unicode", or "frequencies"
- Hex dump shows repeating
e2 80 8c/e2 80 8d/e2 80 8bbyte patterns - Copy-pasting text produces unexpected behavior or extra whitespace
wc -m(character count) is much larger than visible character count
Common zero-width characters used:
| Character | Code Point | UTF-8 Bytes | Name |
|---|---|---|---|
| ZWNJ | U+200C | e2 80 8c | Zero Width Non-Joiner |
| ZWJ | U+200D | e2 80 8d | Zero Width Joiner |
| ZWSP | U+200B | e2 80 8b | Zero Width Space |
| WJ | U+2060 | e2 81 a0 | Word Joiner |
| FEFF | U+FEFF | ef bb bf | Zero Width No-Break Space (BOM) |
Detection one-liner:
bash read-only • copy allowedxxd scroll.txt | grep -c "e2 80 8[bcd]"