← Back to Writeups
CUSTOMEasySteganography

Space Created

XESXOR9/2/20262 min read
#steganography#custom#easy#binary_encoding#zero_width_steganography

Space Created

Platform: spbctf | Category: Steganography | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-03-09 | Status: Solved Techniques: binary_encoding, zero_width_steganography

Summary

Task: Text file with short visible content but unusually large size (794 bytes). Solution: Extract zero-width Unicode characters (ZWNJ/ZWJ) and decode as binary (0/1) to reveal the hidden flag.

Space Created — Forensics Kids 2.0

Description

"Do you love Unicode as much as I do?"

File: spc.txt (794 bytes)

Analysis

The file contains a short text "Hey! Do you like stego?" but has a size of 794 bytes — too much for such text.

Hex dump analysis revealed:

  1. UTF-8 BOM at the beginning of the file: EF BB BF
  2. Zero-width Unicode characters hidden between visible characters:
    • E2 80 8C = U+200C (ZWNJ - Zero-Width Non-Joiner)
    • E2 80 8D = U+200D (ZWJ - Zero-Width Joiner)

These characters are invisible when viewing the text normally, but each takes 3 bytes in UTF-8. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Zero-width characters encode binary data:

  • U+200C (ZWNJ) = bit 0
  • U+200D (ZWJ) = bit 1
python
#!/usr/bin/env python3
"""
Zero-width Unicode steganography decoder
Extracts hidden data from ZWNJ/ZWJ characters
"""

with open('spc.txt', 'rb') as f:
    data = f.read()

# Extract zero-width characters
bits = []
i = 0
while i < len(data):
    # Check for U+200C (ZWNJ) - E2 80 8C
    if data[i:i+3] == b'\xe2\x80\x8c':
        bits.append('0')
        i += 3
    # Check for U+200D (ZWJ) - E2 80 8D
    elif data[i:i+3] == b'\xe2\x80\x8d':
        bits.append('1')
        i += 3
    else:
        i += 1
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Convert bits to bytes
binary_string = ''.join(bits)
print(f"Total bits: {len(bits)}")

flag = ''
for i in range(0, len(binary_string), 8):
    byte = binary_string[i:i+8]
    if len(byte) == 8:
        flag += chr(int(byte, 2))

print(f"Flag: {flag}")

Result: 256 bits = 32 bytes = 32 ASCII characters ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍