2024 Cyber Apocalypse: Blunt

Challenge Information

AttributeDetails
Event2024 Cyber Apocalypse
CategoryCrypto
ChallengeBlunt
DifficultyEasy

Summary

Blunt exploits a Diffie-Hellman key exchange implementation with a small 32-bit prime modulus. The challenge provides the generator g, prime p, and public keys A and B, enabling recovery of the shared secret and subsequent decryption of the AES-encrypted flag.


Analysis

The encryption source code reveals:

  1. Weak DH Parameters: 32-bit prime (p = 0xdd6cc28d) and generator g = 0x83e21c05
  2. Public Key Exchange: A = 0xcfabb6dd and B = 0xc4a21ba9 are provided
  3. Shared Secret Computation: C = pow(A, b, p) = pow(B, a, p)
  4. AES-256-CBC Encryption:
    • Key derived from SHA256(shared_secret)[:16]
    • Hardcoded IV: b’\xc1V2\xe7\xed\xc7@8\xf9\\xef\x80\xd7\x80L*’
  5. Provided Ciphertext: b’\x94\x99\x01\xd1\xad\x95\xe0\x13\xb3\xacZj{\x97|z\x1a(&\xe8\x01\xe4Y\x08\xc4\xbeN\xcd\xb2*\xe6{‘

Solution

Step 1: Recover Private Key

The vulnerability: with a small prime, we can use modular inverse to recover ‘a’:

from Crypto.Util.number import inverse
p = 0xdd6cc28d
g = 0x83e21c05
A = 0xcfabb6dd
# Recover private key 'a'
a = pow(g, -1, p) * A % p
print(f'a = {a}') # 2766777741

Step 2: Compute Shared Secret

B = 0xc4a21ba9
# Compute shared secret using recovered private key
C = pow(B, a, p)
print(f'Shared secret: {C}') # 1739735275

Step 3: Decrypt the Flag

from Crypto.Util.number import long_to_bytes
from hashlib import sha256
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
# Derive AES key
hash_obj = sha256()
hash_obj.update(long_to_bytes(C))
key = hash_obj.digest()[:16]
# Decryption
iv = b'\xc1V2\xe7\xed\xc7@8\xf9\\\xef\x80\xd7\x80L*'
ciphertext = b'\x94\x99\x01\xd1\xad\x95\xe0\x13\xb3\xacZj{\x97|z\x1a(&\xe8\x01\xe4Y\x08\xc4\xbeN\xcd\xb2*\xe6{'
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_data = unpad(cipher.decrypt(ciphertext), 16)
flag = decrypted_data.decode('utf-8')
print(f'Flag: {flag}')

Key Takeaways

  • Small prime moduli in Diffie-Hellman compromise security entirely
  • Private keys can be recovered through simple mathematical operations when p is weak
  • Always use cryptographically strong parameters (2048+ bit primes)
  • Passive analysis of source code reveals vulnerable implementation patterns