SteganographyText Steganography
Unicode Steganography
steganographyintermediate
Find and decode data hidden in Unicode homoglyphs, variation selectors, and lookalike characters.
steganographyunicodehomoglyphzero-widthvariation-selectortext
Unicode Steganography
Unicode steganography exploits the vast Unicode character space to hide data in text that appears visually identical to ASCII. The human eye cannot distinguish U+0041 (A) from U+0410 (А, Cyrillic A). By mixing lookalike characters, variation selectors, or zero-width joiners, data can be hidden invisibly in plain text.
Detection Workflow
Detection Steps
Check for non-ASCII characters
with open('suspicious.txt', 'r', encoding='utf-8') as f:
text = f.read()
for i, c in enumerate(text):
if ord(c) > 127:
print(f'Position {i}: U+{ord(c):04X} = {repr(c)}')Identify the technique
U+FE00–U+FE0F→ variation selectorsU+200B,U+200C,U+200D→ zero-width characters- Cyrillic/Greek letters mixed with Latin → homoglyphs
Decode based on technique
Use the appropriate decoder from the tabs below.
Common Techniques
Replacing ASCII letters with visually identical Unicode characters:
# Common homoglyphs (Cyrillic that look like Latin):
# A (U+0041) → А (U+0410)
# a (U+0061) → а (U+0430)
# e (U+0065) → е (U+0435)
# o (U+006F) → о (U+043E)
# p (U+0070) → р (U+0440)
# c (U+0063) → с (U+0441)
cyrillic_lookalikes = {
'А','а','В','Е','е','К','М','Н','О','о','Р','р','С','с','Т','Х','х','У'
}
def decode_homoglyph_binary(text):
binary = ''
for char in text:
if char in cyrillic_lookalikes:
binary += '1'
elif char.isalpha():
binary += '0'
chars = [chr(int(binary[i:i+8], 2)) for i in range(0, len(binary)-7, 8)]
return ''.join(chars)Comprehensive Detector
import unicodedata
def analyze_unicode(text):
print(f"Total chars: {len(text)}")
print(f"ASCII chars: {sum(1 for c in text if ord(c) < 128)}")
print(f"Non-ASCII: {sum(1 for c in text if ord(c) >= 128)}")
for i, c in enumerate(text):
if ord(c) >= 128:
try:
name = unicodedata.name(c)
except ValueError:
name = "UNKNOWN"
print(f" [{i}] U+{ord(c):04X} = {name}")
with open('suspicious.txt', 'r', encoding='utf-8') as f:
analyze_unicode(f.read())CyberChef Approach
- Paste the text into CyberChef
- Apply "Strip Non-Printable Characters"
- Compare output length with original — if different, hidden chars present
- Also try "Encode text" → Unicode code points to see all character values
Checklist
- Python: check
ord(c) > 127for every character - Look for Cyrillic, Greek, or other script lookalikes mixed with Latin
- Check for variation selectors (U+FE00–FE0F)
- Check for zero-width joiners/non-joiners (U+200B–200D)
- CyberChef: "Strip Non-Printable" → compare length before/after
- Try binary decode: ASCII=0, non-ASCII=1 (and vice versa)
-
hexdumpthe file → look for multi-byte UTF-8 sequences
Last updated on