← Back to Writeups
CUSTOMEasyCrypto

Sub

XESXOR9/10/20262 min read
#crypto#custom#easy#block_permutation_recovery#known_plaintext_attack

Sub

Platform: spbctf | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-03-09 | Status: Solved Techniques: block_permutation_recovery, known_plaintext_attack

Summary

Task: Decrypt ciphertext that appears to use substitution cipher. Solution: Identified it as a block permutation cipher (not substitution), recovered the permutation using known flag prefix spbctf{, and decrypted all 8-character blocks.

Sub — CryptoKids 2.0

Description

Task from the "substitution and permutation" category (crybasic_sub). Given an encrypted text that needs to be decrypted.

Ciphertext:

fncpbt{s eou_n_te n_hoce'_ o__zivti _aarymvp rs_hepos s}jo_ett

Analysis

Despite the name "substitution", this is actually a permutation cipher, not a substitution cipher.

Key observations:

  1. Ciphertext length = 64 characters (divisible by 8)
  2. Known flag prefix: spbctf{ (7 characters)
  3. First 8 characters of ciphertext: fncpbt{s
  4. All characters from spbctf{ are present in fncpbt{s — this is a permutation, not a substitution! ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Position mapping (plaintext → ciphertext):

plaintext:  s p b c t f { ?
position:   0 1 2 3 4 5 6 7

ciphertext: f n c p b t { s
position:   0 1 2 3 4 5 6 7

Where each plaintext character ended up in ciphertext:

  • s (pos 0 in plain) → located at pos 7 in cipher
  • p (pos 1 in plain) → located at pos 3 in cipher
  • b (pos 2 in plain) → located at pos 4 in cipher
  • c (pos 3 in plain) → located at pos 2 in cipher
  • t (pos 4 in plain) → located at pos 5 in cipher
  • f (pos 5 in plain) → located at pos 0 in cipher
  • { (pos 6 in plain) → located at pos 6 in cipher ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Encryption permutation: [5, 3, 4, 2, 1, 0, 6, 7] (where to take the character for each cipher position)

For decryption, we need the inverse permutation: [7, 3, 4, 2, 5, 0, 6, 1]

  • plaintext[0] = ciphertext[7]
  • plaintext[1] = ciphertext[3]
  • etc.

Solution

python
#!/usr/bin/env python3
"""
CryptoKids 2.0 - Sub
Block permutation cipher with block size 8
"""

ciphertext = "fncpbt{s eou_n_te n_hoce'_ o__zivti _aarymvp rs_hepos s}jo_ett"

# Decryption permutation derived from known plaintext "spbctf{"
# plaintext[i] = ciphertext[perm[i]]
perm = [7, 3, 4, 2, 5, 0, 6, 1]
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

block_size = 8
plaintext = ""

for i in range(0, len(ciphertext), block_size):
    block = ciphertext[i:i+block_size]
    decrypted_block = ""
    for j in range(block_size):
        decrypted_block += block[perm[j]]
    plaintext += decrypted_block

print(plaintext)
# spbctf{REDACTED}

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