← Back to Writeups
CUSTOMMediumCrypto

Japanese Script

XESXOR9/10/20263 min read
#crypto#custom#medium#frequency_analysis#homophone_interpretation#monoalphabetic_substitution_de

Japanese Script

Platform: hackerlab | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-04-04 | Status: Solved Techniques: frequency_analysis, homophone_interpretation, monoalphabetic_substitution_decrypt

Summary

Task: a long ciphertext built from Japanese-looking Unicode symbols with frequent ノ separators. Solution: first recover English text with monoalphabetic substitution, then treat rare vowel homophones as a second layer that encodes leetspeak digits inside the apparent flag.

Japanese Script — Hackerlab

Description

Японские письмена Формат флага: CODEBY{...}

The archive contained task.txt with a long ciphertext made of hiragana-, katakana-, and kanji-looking Unicode symbols. A very common separator ノ quickly suggested token or word boundaries rather than a continuous stream cipher.

Analysis

The first useful observation was the frequency of ノ. It appeared so often, and in such natural positions, that it behaved like a space or word separator. Once the text was split on that symbol, the challenge started looking like a classical substitution problem rather than an exotic encoding. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

A monoalphabetic substitution was enough to recover coherent English prose. This was the main first layer of the task. During substitution work, symbol variants also showed up in ways that matched case-like or homophonic behavior, which hinted that not all symbols mapped one-to-one in a simple alphabet.

The recovered plaintext contained a very visible flag-like string:

text
CODEBY{sequence_analysis_is_not_too_complicated}

However, that string was a decoy. The surrounding plaintext explicitly indicated that this was not the final answer and should not be submitted as-is. That meant the readable English text still contained another hidden layer. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The second layer came from rare homophonic variants of vowels inside the plaintext. Most vowels were written normally, but some uncommon variants appeared in selected positions and encoded digit substitutions:

  • rare e -> 3
  • rare a -> 4
  • rare i -> 1
  • rare o -> 0

So the plaintext was not only readable text; it also embedded a leetspeak transformation. Applying those marked vowel variants to the decoy clue converted it into the real accepted flag.

Solution

  1. Inspect the ciphertext and count common symbols.
  2. Notice that ノ behaves like a separator, effectively giving word boundaries.
  3. Solve the first layer as a monoalphabetic substitution until the text becomes readable English prose.
  4. Extract the apparent flag-like string CODEBY{sequence_analysis_is_not_too_complicated}.
  5. Read the surrounding message carefully and notice it is a decoy, not the final flag.
  6. Identify the second layer: rare vowel homophones encode digits.
  7. Replace marked vowels using e->3, a->4, i->1, o->0.
  8. Apply that transformation to the decoy clue to obtain the final flag. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍
python
#!/usr/bin/env python3
decoy = "CODEBY{sequence_analysis_is_not_too_complicated}"

# Second-layer interpretation recovered from rare homophonic vowel variants
leet_map = str.maketrans({
    "e": "3",
    "a": "4",
    "i": "1",
    "o": "0",
})

inner = decoy[len("CODEBY{"):-1]
flag = f"CODEBY{{{inner.translate(leet_map)}}}"
print(flag)

# CODEBY{REDACTED}

Solver Notes

  • A readable plaintext is not always the end of the challenge; treat obvious flags with suspicion if the text comments on itself.
  • Frequent separator symbols are strong reconnaissance anchors in substitution tasks.
  • Homophonic variants can hide metadata even after the main decryption succeeds.
  • When a plaintext clue looks almost correct, check whether typography, alternate glyphs, or repeated character classes encode a second channel. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍