← Back to Writeups
CUSTOMMediumCrypto

Forger

XESXOR9/10/20262 min read
#crypto#custom#medium#keystream_recovery#known_plaintext_attack#message_forging

Forger

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

Summary

Task: PHP page shows XOR-encrypted date with known plaintext. Solution: Recover keystream via XOR, forge target message, submit as base64.

Forger — crypto-kids20 (forkbomb.ru)

Description

The task provides a PHP page "Crypto Date" that shows:

  • A random date encrypted with a stream cipher (XOR): "Friday, December 7, 2007" → hex "700e076a37c8c1c7d748dd6dab93271e0d7baf7b3b7ca8f5"
  • We need to provide BASE64-encoded data that decrypts to "Look_mom_i_am_an_admin_ahaha"

Task ID: crysym_forger

Analysis

This is a classic known-plaintext attack on a stream cipher.

Key observations:

  1. The stream cipher uses XOR: ciphertext = plaintext XOR keystream
  2. We know the plaintext ("Friday, December 7, 2007") and the corresponding ciphertext
  3. XOR is reversible: keystream = ciphertext XOR plaintext
  4. Knowing the keystream, we can encrypt any message of the same length ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Vulnerability: keystream reuse — a fatal flaw for stream ciphers.

Solution

Step 1: Extracting the keystream

python
ct_hex = "700e076a37c8c1c7d748dd6dab93271e0d7baf7b3b7ca8f5"
ct = bytes.fromhex(ct_hex)
pt = b"Friday, December 7, 2007"

# XOR ciphertext with plaintext gives keystream
keystream = bytes(c ^ p for c, p in zip(ct, pt))

Step 2: Encrypting the target message

python
target = b"Look_mom_i_am_an_admin_ahaha"

# XOR target with keystream
forged = bytes(k ^ t for k, t in zip(keystream, target))

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

Step 3: Base64 encoding and submission

python
import base64
result = base64.b64encode(forged).decode()
print(result)  # Submit to server

Full solve script

python
#!/usr/bin/env python3
"""
Forger - crypto-kids20 (forkbomb.ru)
Known-plaintext attack on XOR stream cipher
"""

import base64

# Data from the task
ct_hex = "700e076a37c8c1c7d748dd6dab93271e0d7baf7b3b7ca8f5"
ct = bytes.fromhex(ct_hex)
pt = b"Friday, December 7, 2007"

# Step 1: Recover keystream
keystream = bytes(c ^ p for c, p in zip(ct, pt))
print(f"Keystream (hex): {keystream.hex()}")
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Step 2: Encrypt target message
target = b"Look_mom_i_am_an_admin_ahaha"
forged = bytes(k ^ t for k, t in zip(keystream, target))
print(f"Forged ciphertext (hex): {forged.hex()}")

# Step 3: Base64 encoding
result = base64.b64encode(forged).decode()
print(f"Base64 payload: {result}")

# Submit result to server to get the flag

Theory

Why this works

For a stream cipher:

C1 = P1 XOR K
C2 = P2 XOR K

If we know P1 and C1:

K = C1 XOR P1
C2 = P2 XOR K = P2 XOR (C1 XOR P1)

Defense

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

  • Never use the same keystream twice
  • Use a nonce/IV for each message
  • Apply authenticated encryption (AES-GCM, ChaCha20-Poly1305) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍