← Back to Writeups
CUSTOMMediumCrypto

Странный код (Strange Code)

XESXOR9/2/20266 min read
#crypto#custom#medium#base64_case_bruteforce#printable_ascii_constraint_fil#vigenere_decryption#vigenere_known_plaintext_attac

Странный код (Strange Code)

Platform: CUSTOM | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: base64_case_bruteforce, printable_ascii_constraint_filtering, vigenere_decryption, vigenere_known_plaintext_attack

Summary

Walkthrough of the CUSTOM Crypto Странный код (Strange Code). Task: a Python file encrypted with Vigenère cipher — structure preserved but keywords unrecognizable. Solution: identify Vigenère key 'code' via known-plaintext (Python keywords), decrypt the script,

Description

У меня что-то со зрением или это новый язык программирования?

English summary: A zip file strange_code.zip contains code.py — a file that looks like Python code but with all letters shifted/substituted. The structure (indentation, colons, parentheses, quotes, equals signs) is preserved, but keywords are unrecognizable. The goal is to figure out the cipher, decrypt the code, and extract the flag.

Analysis

Step 1: Examine the encrypted code

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

The file code.py contains:

kassth wmos dw z

wptqfw fcgh64 eu p64



i = "u09gfxnbs000wp83crixznixznujurqqvt8zvn80l0patrq9"

i = d64.p64giecgi(h).rhgqrh()

g = "ecqktoww!\p"

rhj r(h, g=0.2):

    jqf f mp h:

        svkbw(g, gbg='', jnivl=vfxi)

        z.goigd(g)



t(e+s)

Key observations:

  • Python-like structure is intact: import-like statements, function definition with def-like keyword, for-like loop, print-like call
  • Only alphabetic characters are affected; digits, spaces, symbols, and newlines are unchanged
  • All letters are lowercase ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 2: Identify the cipher via known plaintext

Matching ciphertext keywords to Python keywords:

CiphertextPlaintextLength
kassthimport6
wptqfwimport6
rhjdef3
svkbwprint3
jqffor3

Computing shifts (ciphertext - plaintext mod 26) for each alphabetic character position:

PositionCipherPlainShiftKey letter
0ki2c
1am14o
2sp3d
3so4e
4tr2c
5ht14o
............repeating
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The shift pattern 2, 14, 3, 4 repeats — this is a Vigenère cipher with key "code" (c=2, o=14, d=3, e=4). The key cycles over alphabetic characters only; non-alpha characters are passed through without advancing the key position.

Step 3: Decrypt the code

Applying Vigenère decryption with key "code" recovers the original Python script:

python
import time as x

import base64 as b64



f = "q09erujze000tl83adftxzftxzrfsdnmtf8wrl80x0mwrdn9"

e = b64.b64decode(f).decode()

c = "congrats!\n"

def p(t, d=0.2):
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

    for c in t:

        print(c, end='', flush=True)

        x.sleep(d)



p(c+e)

The script decodes a base64 string and prints "congrats!" followed by the decoded flag with a typewriter effect.

Step 4: Recover the base64 string's case

Critical problem: The Vigenère cipher operates mod 26 within the lowercase alphabet, so ALL letters in the encrypted file became lowercase. But base64 is case-sensitive — A-Z encodes values 0-25, while a-z encodes values 26-51. The cipher destroyed the original case information. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution: Split the 48-character base64 string into 12 groups of 4 characters. Each 4-char group decodes independently to 3 bytes. For each group, brute-force all case combinations of alphabetic characters (2^n where n = number of alpha chars in the group, max 2^4 = 16 per group) and keep only those producing valid printable ASCII bytes.

Additional constraints from the known flag format CODEBY{...}:

  • Groups 0-1 (bytes 0-5): must decode to CODEBY
  • Group 2 (byte 6): must start with {
  • Group 11 (byte 35): must end with } ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 5: Case recovery results

GroupLowercaseCorrect caseDecoded
0q09eQ09ECOD
1rujzRUJZEBY
2e000e000{M4
3tl83Tl83N_7
4adftaDFTh1S
5xzftXzFT_1S
6xzrfXzRf4
7sdnmSDNMH3L
8tf8wTF8wL_0
9rl80Rl80F_4
10x0mwX0Mw_C0
11rdn9RDN9D3}

Correct base64 string: Q09ERUJZe000Tl83aDFTXzFTXzRfSDNMTF8wRl80X0MwRDN9 ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

python
#!/usr/bin/env python3
"""
Solve script for "Strange Code" (Hackerlab)
Vigenère cipher on Python code + base64 case recovery
"""
import base64
import itertools

# Read the encrypted code
with open("code.py", "r") as f:
    ciphertext = f.read()

# Step 1: Vigenère decryption with key "code", cycling on alpha chars only
key = "code"
key_shifts = [ord(c) - ord('a') for c in key]  # [2, 14, 3, 4]

def decrypt_vigenere(text, key_shifts):
    result = []
    alpha_idx = 0
    for ch in text:
        if ch.isalpha():
            shift = key_shifts[alpha_idx % len(key_shifts)]
            if ch.islower():
                dec = chr((ord(ch) - ord('a') - shift) % 26 + ord('a'))
            else:
                dec = chr((ord(ch) - ord('A') - shift) % 26 + ord('A'))
            result.append(dec)
            alpha_idx += 1
        else:
            result.append(ch)
    return ''.join(result)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

plaintext = decrypt_vigenere(ciphertext, key_shifts)
print("Decrypted code:")
print(plaintext)

# Step 2: Extract the base64 string from the decrypted code
import re
b64_match = re.search(r'"([A-Za-z0-9+/=]+)"', plaintext)
b64_lower = b64_match.group(1)
print(f"\nBase64 string (all lowercase): {b64_lower}")

# Step 3: Recover case by brute-forcing each 4-char group
# Each group of 4 base64 chars decodes to 3 bytes independently
groups = [b64_lower[i:i+4] for i in range(0, len(b64_lower), 4)]
recovered = ""
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

for gi, group in enumerate(groups):
    alpha_pos = [i for i, c in enumerate(group) if c.isalpha()]
    candidates = []
    for combo in itertools.product([False, True], repeat=len(alpha_pos)):
        chars = list(group)
        for idx, upper in enumerate(combo):
            if upper:
                chars[alpha_pos[idx]] = chars[alpha_pos[idx]].upper()
        variant = ''.join(chars)
        try:
            # Pad for independent decoding
            decoded = base64.b64decode(variant + '==')[:3]
            if all(0x20 <= b <= 0x7E for b in decoded):
                candidates.append((variant, decoded))
        except Exception:
            pass
    
    if len(candidates) == 1:
        recovered += candidates[0][0]
    else:
        # Apply flag format constraints
        best = candidates[0][0] if candidates else group
        for variant, decoded in candidates:
            text = decoded.decode('ascii', errors='replace')
            # Group 0-1: CODEBY, Group 2: starts with {, Group 11: ends with }
            if gi == 0 and text == "COD":
                best = variant; break
            elif gi == 1 and text == "EBY":
                best = variant; break
            elif gi == 2 and text.startswith("{"):
                best = variant; break
            elif gi == 11 and text.endswith("}"):
                best = variant; break
        recovered += best
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

print(f"\nRecovered base64: {recovered}")
flag = base64.b64decode(recovered).decode()
print(f"Flag: {flag}")

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

Key Takeaways / Lessons

  • Mastering base64_case_bruteforce, printable_ascii_constraint_filtering, vigenere_decryption, vigenere_known_plaintext_attack was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-04-05 • CUSTOM • Странный код (Strange Code) • Difficulty: Medium