Skip to main content

Transformation picoCTF 2021 Solution

Reverse engineer a custom encoding scheme that packs multiple characters into Unicode code points.

Published: April 2, 2026Updated: August 13, 2026

Description

I wonder what this really is... The file enc displays as seemingly random Unicode characters.

Download the enc file.

bash
wget <url>/enc

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Identify the encoding scheme
    Observation
    The enc file displays as Unicode characters with code points well above 127, not readable ASCII. So the original bytes were packed together into wider integers rather than stored as they were.
    Open enc in a text editor or print it - it contains Unicode characters with code points well above 127. This is a clue that multiple ASCII bytes were packed together. The encoding is: char = (ord(a) << 8) + ord(b), combining two consecutive ASCII bytes into one Unicode code point.
    Learn more

    Standard ASCII characters have code points from 0 to 127, fitting in 7 bits. A Unicode code point, however, can represent values up to 1,114,111. The encoding used here treats two ASCII bytes as the high byte and low byte of a 16-bit integer, producing a single Unicode character - effectively compressing two characters into one.

    This is not a standard encoding like UTF-16; it is a custom scheme. Looking at the code points of the characters in enc and noticing they are all in the range 0x2000 to 0x7e7e (printable ASCII pairs) is the main clue.

  2. Step 2Reverse the encoding
    Observation
    The scheme packs two ASCII bytes into one Unicode code point by bit-shifting. Applying the inverse to each character, a right shift by 8 and a mask against 0xff, rebuilds the original plaintext.
    For each Unicode character c in enc, extract the high byte with (ord(c) >> 8) and the low byte with (ord(c) & 0xff). Convert each byte back to a character and concatenate - this reconstructs the original ASCII string containing the flag.
    python
    python3 -c "
    enc = open('enc').read().strip()
    print(''.join([chr(ord(c) >> 8) + chr(ord(c) & 0xff) for c in enc]))
    "

    Expected output

    picoCTF{16_bits_inst34d_of_8_...}
    What didn't work first

    Tried: Opening enc in a hex editor and running strings or xxd to extract ASCII text directly

    The file is valid UTF-8, so strings and xxd show the encoded Unicode bytes rather than the packed ASCII pairs. No flag characters appear, because every original pair was merged into one high-code-point glyph. The Python bit extraction is what reconstructs the ASCII.

    Tried: Decoding the file as base64 or with Python's codecs.decode(data, 'utf-8') expecting a standard encoding

    UTF-8 decoding succeeds and hands back the same Unicode string you already had; it never unpacks the byte pairs. This is not base64 or any standard codec, but a custom scheme where each glyph bit-packs two ASCII bytes. The wrong decoding layer just gives meaningless Unicode text.

    Learn more

    The shift-right operator >> 8 drops the lower 8 bits, leaving the original high byte. The bitwise AND & 0xff masks to only the lower 8 bits, recovering the low byte. These are standard bit manipulation operations for unpacking multi-byte values - used extensively in binary format parsing and network protocol decoding.

    The challenge title "Transformation" refers to the encoding transformation applied to the plaintext. Reversing a transformation requires understanding the original operation - here a straightforward bit-packing scheme with no randomness or key.

Interactive tools
  • Base64 & Base32 DecoderDecode Base64 and Base32 strings with auto-detection. Multi-layer mode unwraps nested encodings automatically.
  • Recipe ChainStack decoders into a pipeline: Base64, hex, ROT, XOR, Morse, URL, Atbash, Vigenère, and more. Magic mode auto-discovers the chain. Bookmark the URL to save it.
  • Number Base ConverterConvert numbers between binary, octal, decimal, and hexadecimal instantly. Enter any value and see all four bases update in real time.

Flag

Reveal flag

picoCTF{16_bits_inst34d_of_8_...}

The encoding pairs consecutive ASCII bytes into a single Unicode code point - reverse by extracting the high byte (>>8) and low byte (&0xff) separately.

Key takeaway

Custom bit-packing disguises data by repacking bytes into wider integer types, and the transformation always reverses once you know the scheme. The step that matters is noticing the output code points cluster in a predictable numeric range, here 0x2000 to 0x7e7e, which reveals the structure without reverse-engineering any source. The same reasoning works on proprietary binary protocols, obfuscated shellcode, and any encoding whose character distribution looks wrong for natural text.

Related reading

Useful tools for Reverse Engineering

Where to go next