💯 (unicode magic)
Challenge Data
| Field | Value |
|---|---|
| CTF | Nullcon CTF 2026 |
| Challenge | 💯 (unicode magic) |
| Category | Misc |
| Flag | ENO{EM0J1S_UN1COD3_1S_MAG1C} |
Challenge Description
The only provided file was a README.md which appeared to contain only one emoji, 💯. The file also contained invisible Unicode characters that hid the real message.
Reconnaissance
When a file "contains nothing" but is clearly supposed to hide something, checking the codepoints is usually a very good first step. In this case, reading the UTF-8 content and printing ord() for each character showed values in the ranges U+FE00..U+FE0F and U+E0100..U+E01EF.
Those ranges correspond to Variation Selectors, characters that normally do not appear when displaying text but are still present in the file. The emoji acted as the base, and the selectors that followed were the ones carrying the actual information.
Analysis
The scheme behind the challenge was pretty direct. Each Variation Selector represented a value between 0 and 255, and those values were interpreted as ASCII bytes.
The conversion we needed was this.
U+FE00..U+FE0Fbecame0..15U+E0100..U+E01EFbecame16..255
Once each selector was converted to its numeric value, the only thing left was to concatenate those bytes and recover the hidden text.
There was no strange encryption and no unusual packing. The payload was in the invisible characters around the visible emoji.
Solution
A short Python script was enough to ignore the initial emoji and decode the selectors.
def decode_variation_selectors(text: str) -> str:
payload = text[1:]
values = []
for ch in payload:
cp = ord(ch)
if 0xFE00 <= cp <= 0xFE0F:
values.append(cp - 0xFE00)
elif 0xE0100 <= cp <= 0xE01EF:
values.append(cp - 0xE0100 + 16)
return "".join(chr(v) for v in values)
with open("README.md", "r", encoding="utf-8") as f:
print(decode_variation_selectors(f.read().strip()))
When executed, it printed the flag in cleartext.
Flag
ENO{EM0J1S_UN1COD3_1S_MAG1C}