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:
- The stream cipher uses XOR:
ciphertext = plaintext XOR keystream - We know the plaintext ("Friday, December 7, 2007") and the corresponding ciphertext
- XOR is reversible:
keystream = ciphertext XOR plaintext - 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 read-only • copy allowedct_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 read-only • copy allowedtarget = 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 read-only • copy allowedimport base64 result = base64.b64encode(forged).decode() print(result) # Submit to server
Full solve script
python read-only • copy allowed#!/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)