← Back to Writeups
CUSTOMEasyCrypto

Рельсы (Rails)

XESXOR9/10/20262 min read
#crypto#custom#easy#rail-fence-cipher-decryption#pattern-recognition-from-space

Рельсы (Rails)

Platform: hackerlab | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2025-12-25 | Status: Solved Techniques: Rail Fence cipher decryption, Pattern recognition from space-separated groups

Summary

Файл: task.txt C{1fz OYnts30ga DB0itmr1g} Ew1z!

Рельсы (Rails) — HackerLab

Description

Умеете ли Вы читать между строк? Хотя, тут похоже только одна строка...

Файл: task.txt

C{1fz OYnts30ga DB0itmr1g} Ew1z!

Analysis

  1. Task name — "Рельсы" (Rails) — direct hint at Rail Fence cipher (zigzag cipher)

  2. Ciphertext structure:

    • Text is separated by spaces into 4 groups
    • Group 1: C{1fz — 5 characters
    • Group 2: OYnts30ga — 9 characters
    • Group 3: DB0itmr1g} — 10 characters
    • Group 4: Ew1z! — 5 characters
    • Total: 29 characters ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍
  3. Key observation: Spaces separate the text into 4 parts — these are the 4 rails of the cipher!

  4. Distribution verification: For 29 characters and 4 rails:

    • Rail 0 (top): positions 0, 6, 12, 18, 24 → 5 characters ✓
    • Rail 1: positions 1, 5, 7, 11, 13, 17, 19, 23, 25 → 9 characters ✓
    • Rail 2: positions 2, 4, 8, 10, 14, 16, 20, 22, 26, 28 → 10 characters ✓
    • Rail 3 (bottom): positions 3, 9, 15, 21, 27 → 5 characters ✓

Solution

Rail Fence Visualization (4 rails)

Позиция:  0 1 2 3 4 5 6 7 8 9 ...
Рельс 0:  C         O         D ...
Рельс 1:    {     Y   n     B   ...
Рельс 2:      1   t   s   0   i ...
Рельс 3:        f       3       ...

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

Decryption Script

python
#!/usr/bin/env python3
"""Rail Fence cipher decryption"""

def decrypt_rail_fence(cipher, num_rails):
    """Decrypt Rail Fence cipher"""
    n = len(cipher)
    
    # Create fence matrix and mark positions
    fence = [['\n' for _ in range(n)] for _ in range(num_rails)]
    
    # Mark positions in zigzag pattern
    rail, direction = 0, 1
    for i in range(n):
        fence[rail][i] = '*'
        rail += direction
        if rail == num_rails - 1 or rail == 0:
            direction *= -1
    
    # Fill marked positions with cipher characters
    index = 0
    for r in range(num_rails):
        for c in range(n):
            if fence[r][c] == '*' and index < n:
                fence[r][c] = cipher[index]
                index += 1
    
    # Read in zigzag pattern
    result = []
    rail, direction = 0, 1
    for i in range(n):
        result.append(fence[rail][i])
        rail += direction
        if rail == num_rails - 1 or rail == 0:
            direction *= -1
    
    return "".join(result)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍


# Remove spaces (they just separate rails)
ciphertext = "C{1fzOYnts30gaDB0itmr1g}Ew1z!"

# Decrypt with 4 rails
plaintext = decrypt_rail_fence(ciphertext, 4)
print(f"Flag: {plaintext}")

Result

Flag: CODEBY{REDACTED}

Leetspeak decoding: REDACTED → "now it is time for zigzag!"

Character Distribution Formula

For text of length n and k rails:

  • Period = 2*(k-1)
  • Top/bottom rail: ~n/(2*(k-1)) characters
  • Middle rails: ~2n/(2(k-1)) characters ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍