Writeups
  • Archive
  • 2021
    • CSAW Qualification Round
      • Crypto
        • Gotta Decrypt Them All
    • TMUCTF
      • 435!
      • Common Factor
    • WORMCON 0x01
      • Fake Encryption
      • Rem, Shinobu, Asuna
      • Exclusive
      • Sir Oracle
      • Invisible Cipher
Powered by GitBook
On this page

Was this helpful?

  1. 2021
  2. WORMCON 0x01

Exclusive

#!/usr/bin/env python3
import os

def splitit(n):
	return (n >> 4), (n & 0xF)

def encrypt(n, key1, key2):
	m, l = splitit(n)
	e = ((m ^ key1) << 4) | (l ^ key2)
	return e

FLAG = open('flag.txt').read().lstrip('wormcon{').rstrip('}')
alpha = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_'

assert all(x in alpha for x in FLAG)

otp = int(os.urandom(1).hex(), 16)
otpm, otpl = splitit(otp)

print(f"{otp = }")
cipher = []

for i,ch in enumerate(FLAG):
	if i % 2 == 0:
		enc = encrypt(ord(ch), otpm, otpl)
	else:
		enc = encrypt(ord(ch), otpl, otpm)
	cipher.append(enc)

cipher = bytes(cipher).hex()
print(f'{cipher = }')

open('out.txt','w').write(f'cipher = {cipher}')

Everyone loves XOR because it's easy to use but the cipher becomes vulnerable if you use only a single byte Key. We can easily brute-force the Key and recover our plaintext!

  • Split the otp byte into two halves i.e. otpm = upper nibble(upper 4 bits), otpl = lower nibble(lower 4 bits)

  • Split the plaintext byte into two halves i.e. m = upper nibble, l = lower nibble

  • Makes the XOR encryption and finally joins the ciphertext bytes.

Thus, we can

  • Reverse this and make our decryption function

  • Brute-force the key

  • Try to decrypt the ciphertext and check if all the characters are in the character space or not

Flag: wormcon{x0r_n1bbl3_c1ph3r_15_4_h0m3_br3w3d_c1ph3r}

PreviousRem, Shinobu, AsunaNextSir Oracle

Last updated 3 years ago

Was this helpful?

We already know that otp = int(os.urandom(1).hex(), 16) will generate the 0≤otp≤2550 \leq otp \leq 2550≤otp≤255. The encryption works like this

ciphertext byte={(m⊕otpm)∣∣(l⊕otpl),for even indices(m⊕otpl)∣∣(l⊕otpm),for odd indices where ∣∣ represents bits concatenation\text{ciphertext byte} = \begin{cases} (m \oplus otpm)||(l \oplus otpl), & \text{for even indices} \\ (m \oplus otpl)||(l \oplus otpm), & \text{for odd indices} \end{cases} \\~\\ \text{where $||$ represents bits concatenation}ciphertext byte={(m⊕otpm)∣∣(l⊕otpl),(m⊕otpl)∣∣(l⊕otpm),​for even indicesfor odd indices​ where ∣∣ represents bits concatenation

Solve Script:

solve.py