Use the tree to jump between collections without leaving the reader.

archive Select writeup Open tree
NullconCTF2026/WriteupEmoji.en.md READ_ONLY

💯 (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+FE0F became 0..15
  • U+E0100..U+E01EF became 16..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}