← Back to Writeups
CUSTOMMediumCrypto

Semi-ADFGX 18+

XESXOR9/10/20264 min read
#crypto#custom#medium#bigram_frequency_analysis#known_plaintext_attack#pattern_matching

Semi-ADFGX 18+

Platform: grodno_new_year_2026 | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-01-10 | Status: Solved Techniques: bigram_frequency_analysis, known_plaintext_attack, pattern_matching

Summary

Files provided: - Cipher.txt (310 characters) - the ciphertext to decrypt - Intercepted_Codes.txt (860600 characters) - known plaintext for cryptanalysis (Project Gutenberg book "A Farewell to Arms" by Ernest Hemingway)

Semi-ADFGX 18+ - Grodno New Year 2026

Description

Новый год наступил. Поздравляем вас! Флаг в формате grodno{a-z_}

The New Year has arrived. Congratulations! Flag in the format grodno{a-z_}

Files provided:

  • Cipher.txt (310 characters) - the ciphertext to decrypt
  • Intercepted_Codes.txt (860600 characters) - known plaintext for cryptanalysis (Project Gutenberg book "A Farewell to Arms" by Ernest Hemingway)

Analysis

Step 1: Ciphertext Structure

The ciphertext consists of bigrams (pairs of characters):

CECWFYFYRNRWCPRETWRWRNRECWGNRWCWCPRPRWGEREGNGNRNRWTECEGNCAFWCYGECWFWRW...

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Breaking into bigrams:

CE CW FY FY RN RW CP RE TW RW RN RE CW GN RW CW CP RP RW GE RE GN GN RN RN RW ...

Step 2: Identify Character Sets

First characters (rows): C, F, G, R, T (5 characters) Second characters (columns): A, E, N, P, W, Y (6 characters)

This is a 5x6 Polybius square - a modified ADFGX cipher (standard ADFGX uses 5x5). The "18+" in the title hints at this: 5+6+5+2 = 18 (or simply 5*6 = 30 > 26 letters + space).

Step 3: Frequency Analysis

Using the large known plaintext (Intercepted_Codes.txt - Hemingway's "A Farewell to Arms"), I performed frequency analysis on bigrams: ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

python
from collections import Counter

with open('Intercepted_Codes.txt', 'r') as f:
    known = f.read()

# Split into bigrams
bigrams = [known[i:i+2] for i in range(0, len(known)-1, 2)]
freq = Counter(bigrams)

# Top frequencies
for bg, count in freq.most_common(30):
    print(f"{bg}: {count} ({count/len(bigrams)*100:.2f}%)")

Key finding: Bigram RW appears with ~18.6% frequency - this matches the expected frequency of SPACE in English text.

Verification: Average "word" length (characters between RW bigrams) was ~4.37, matching typical English word length. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 4: Build Substitution Mapping

Using frequency analysis and pattern matching with common English words (THE, THIS, AND, etc.):

BigramPlaintextFrequency Rank
RWSPACE1 (18.6%)
REE2
CYT3
CWA4
CNO5
CAI6
CPN7
CEH8
FWS9
GNR10
RPD11
TPL12
TWW13
TAU14
RNY15
GEM16
TNG17
TEC18
FPF19
GYB20
FYP21
GWK22
RYV23
FNJ24
GAX25
RAQ26
FEZ27
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Decryption Script

python
#!/usr/bin/env python3

# Complete bigram to character mapping
mapping = {
    'RW': ' ',  # SPACE
    'RE': 'E', 'CY': 'T', 'CW': 'A', 'CN': 'O', 'CA': 'I',
    'CP': 'N', 'CE': 'H', 'FW': 'S', 'GN': 'R', 'RP': 'D',
    'TP': 'L', 'TW': 'W', 'TA': 'U', 'RN': 'Y', 'GE': 'M',
    'TN': 'G', 'TE': 'C', 'FP': 'F', 'GY': 'B', 'FY': 'P',
    'GW': 'K', 'RY': 'V', 'FN': 'J', 'GA': 'X', 'RA': 'Q',
    'FE': 'Z'
}

def decrypt(ciphertext):
    plaintext = []
    for i in range(0, len(ciphertext), 2):
        bigram = ciphertext[i:i+2]
        if bigram in mapping:
            plaintext.append(mapping[bigram])
        else:
            plaintext.append('?')
    return ''.join(plaintext)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

with open('Cipher.txt', 'r') as f:
    cipher = f.read().strip()

decrypted = decrypt(cipher)
print(f"Decrypted: {decrypted}")

# Convert to flag format (spaces to underscores)
flag = 'grodno{' + decrypted.lower().replace(' ', '_') + '}'
print(f"Flag: {flag}")

Decrypted Message

HAPPY NEW YEAR AND MERRY CHRISTMAS TO ALL REDACTED OF THE NEW YEAR CTF FROM OUR TEAM   WE WOULD BE DELIGHTED TO SEE YOU AT OUR GRAND FINALE IN FEBRUARY

Critical observation: There are THREE consecutive spaces between "TEAM" and "WE" (three RW bigrams in a row: RWRWRW). This must be preserved as three underscores (___) in the flag. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Lessons Learned

  1. Modified ciphers: The "Semi-ADFGX" uses a 5x6 grid instead of standard 5x5, allowing for 30 symbols (26 letters + space + extras)
  2. Space detection: In substitution ciphers, the most frequent symbol is usually SPACE (~18% in English)
  3. Word length verification: Average English word length (~4.5 chars) helps confirm space identification
  4. Preserve exact spacing: Multiple consecutive spaces in the plaintext must be preserved in the flag format ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍