A?
A?
Platform: TaipanByte | Category: Misc | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-02-14 | Status: Solved Techniques: combining_mark_substitution, known_plaintext_attack, leet_speak_recognition, unicode_nfd_decomposition
Summary
The task provides a string of Unicode characters where each character is the letter 'A' with various diacritical marks:
A? — TaipanByte
Description
The task provides a string of Unicode characters where each character is the letter 'A' with various diacritical marks:
ĀȦ{ÃA̧Ȃ3@Ǎ_A̧1A̯A̰3Ȃ_A̱3A̧0A̱3Ȃ}
The task name "A?" hints that all characters are related to the letter A.
Flag format: TB{...}
Analysis
1. NFD Decomposition
Each modified character under NFD decomposition (Normalization Form Decomposition) breaks down into:
- Base character:
A(U+0041) - Combining diacritical mark: a character from the U+0300–U+036F range
Literal characters ({, }, _, 3, @, 1, 0) remain unchanged — they don't contain combining marks.
2. Substitution Cipher
Each combining mark encodes a specific letter. This is a classic substitution cipher where the key is the mapping table "combining mark → letter".
3. Known-Plaintext Attack
Knowing the flag format TB{...}, the first two characters give us:
Ā= A + U+0304 (COMBINING MACRON) → TȦ= A + U+0307 (COMBINING DOT ABOVE) → B
4. Mapping Table
| Symbol | NFD | Combining Mark | Codepoint | Name | Letter |
|---|---|---|---|---|---|
| Ā | A + ◌̄ | COMBINING MACRON | U+0304 | MACRON | T |
| Ȧ | A + ◌̇ | COMBINING DOT ABOVE | U+0307 | DOT ABOVE | B |
| Ã | A + ◌̃ | COMBINING TILDE | U+0303 | TILDE | s |
| A̧ | A + ◌̧ | COMBINING CEDILLA | U+0327 | CEDILLA | c |
| Ȃ | A + ◌̑ | COMBINING INVERTED BREVE | U+0311 | INVERTED BREVE | r |
| Ǎ | A + ◌̌ | COMBINING CARON | U+030C | CARON | m |
| A̯ | A + ◌̯ | COMBINING INVERTED BREVE BELOW | U+032F | INVERTED BREVE BELOW | p |
| A̰ | A + ◌̰ | COMBINING TILDE BELOW | U+0330 | TILDE BELOW | h |
| A̱ | A + ◌̱ | COMBINING MACRON BELOW | U+0331 | MACRON BELOW | d |
| |
5. Decoding Step by Step
The string splits into three words (separated by _):
- ÃA̧Ȃ3@Ǎ → s-c-r-3-@-m →
scr3@m(scream) - A̧1A̯A̰3Ȃ → c-1-p-h-3-r →
c1ph3r(cipher) - A̱3A̧0A̱3Ȃ → d-3-c-0-d-3-r →
d3c0d3r(decoder)
Cross-validation: the same combining mark always yields the same letter:
- CEDILLA (U+0327) →
c— appears in scr3@m, c1ph3r, d3c0d3r ✓ - INVERTED BREVE (U+0311) →
r— appears in scr3@m, c1ph3r, d3c0d3r ✓ - MACRON BELOW (U+0331) →
d— appears in d3c0d3r (twice) ✓
Solution
python read-only • copy allowed#!/usr/bin/env python3 """ A? — TaipanByte CTF Unicode combining diacritical marks substitution cipher decoder. """ import unicodedata # Encrypted string encoded = "ĀȦ{ÃA̧Ȃ3@Ǎ_A̧1A̯A̰3Ȃ_A̱3A̧0A̱3Ȃ}" # Substitution table: combining mark codepoint → letter # Derived through known-plaintext (TB{...}) and word analysis substitution = { 0x0304: 'T', # COMBINING MACRON 0x0307: 'B', # COMBINING DOT ABOVE 0x0303: 's', # COMBINING TILDE 0x0327: 'c', # COMBINING CEDILLA 0x0311: 'r', # COMBINING INVERTED BREVE 0x030C: 'm', # COMBINING CARON 0x032F: 'p', # COMBINING INVERTED BREVE BELOW 0x0330: 'h', # COMBINING TILDE BELOW 0x0331: 'd', # COMBINING MACRON BELOW } # NFD decomposition and decoding nfd = unicodedata.normalize('NFD', encoded) result = [] skip_next = False for i, ch in enumerate(nfd): if skip_next: skip_next = False continue cp = ord(ch) # If this is a combining mark (U+0300-U+036F) — substitute the letter if 0x0300 <= cp <= 0x036F: if cp in substitution: result.append(substitution[cp]) else: result.append(f'[U+{cp:04X}]') # If this is base 'A' and next char is a combining mark, skip 'A' elif ch == 'A' and i + 1 < len(nfd) and 0x0300 <= ord(nfd[i + 1]) <= 0x036F: continue # 'A' is the base character, will be processed via combining mark else: # Literal character (digits, brackets, underscores) result.append(ch) flag = ''.join(result) print(f"Flag: {flag}") # Flag: TB{REDACTED}