Category: Reverse Engineering
Difficulty: Easy
Points: 20
Description
An encrypted file enc is provided. A comment in the source reveals the encoding scheme. The task is to reverse it.
Overview
- The flag is encoded by packing each pair of ASCII characters into a single Unicode code point.
- The encoding shifts the first character left by 8 bits and adds the second character, producing a 16-bit value stored as one Unicode character.
- Decoding unpacks each Unicode character back into two ASCII bytes.
Background: Bit Packing
- ASCII characters occupy one byte (8 bits), with values in the range 0-127.
- A Unicode code point can represent values up to
0x10FFFF, well above 16 bits. - Shifting the first byte left by 8 and OR-ing in the second byte creates a single 16-bit integer that stores both characters:
chr((ord(a) << 8) | ord(b)). - This halves the character count of the encoded string, making it visually unrecognizable.
Solution
Step 1: Read the Encoding Comment
- The source file contains an explicit comment describing the encoding:
# code : ''.join([chr((ord(flag[i]) << 8) + ord(flag[i + 1])) for i in range(0, len(flag), 2)])
- Reading this tells us that pairs of characters are packed into single Unicode code points.
Step 2: Reverse the Encoding
- For each character
din the encoded file, extract the high byte with a right shift of 8 bits, and the low byte from the UTF-16 big-endian encoding.
result = ""
for d in data:
result += chr(ord(d) >> 8) # high byte: first original char
result += chr(d.encode("utf-16be")[-1]) # low byte: second original char
ord(d) >> 8extracts the top 8 bits (the first original character).d.encode("utf-16be")[-1]extracts the bottom 8 bits as a byte (the second original character).
Flag
picoCTF{16_bits_inst34d_of_8_26684c20}