Sub
Sub
Platform: CUSTOM | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: block_permutation_recovery, known_plaintext_attack
Summary
Walkthrough of the CUSTOM Crypto Sub. 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{, a
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:
- Ciphertext length = 64 characters (divisible by 8)
- Known flag prefix:
spbctf{(7 characters) - First 8 characters of ciphertext:
fncpbt{s - All characters from
spbctf{are present infncpbt{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 cipherp(pos 1 in plain) → located at pos 3 in cipherb(pos 2 in plain) → located at pos 4 in cipherc(pos 3 in plain) → located at pos 2 in ciphert(pos 4 in plain) → located at pos 5 in cipherf(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 read-only • copy allowed#!/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}
Key Takeaways / Lessons
- Mastering block_permutation_recovery, known_plaintext_attack was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-03-09 • CUSTOM • Sub • Difficulty: Easy