CDDC 2025
Reassemble The Pieces
Network | Qualifier
Extract H.264 video payloads from RTP packets in a .pcap
file using rtp_h264_extractor.lua.

└─$CDDC2025{5tr3@m1ng_53rv1ce35_u53_th3_RT5P_pr0t0c01}
Break the ECDSA
Cryptography | Qualifier
The overall solution is:
Using given signatures to compute the private key using ECDSA Nonce Reuse Attack
Brute-force candidate 12-word BIP-39 mnemonics from the given dictionary, derive their corresponding private keys using
bip32utils
and compare them against the recovered key
from ecdsa.numbertheory import inverse_mod
from itertools import product
import mnemonic
import bip32utils
# Provided constants
r = 81210355722750344493541519494641458710145722871994877785183554697310523407018
h1 = 45643200378651069483892104393394606812504455659831083323743202489147422538955
h2 = 74831345439009646272332597737070016777412939113737083148228963710487431876647
s1 = 110764343964105699917226529930289538481215574456544978805357332521308340464732
s2 = 90138993253633063487274662700800979929978777245182171200537527514756442604713
# SECP256k1 curve order
N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
# Step 1: Recover the private key
numerator = (s2 * h1 - s1 * h2) % N
denominator = inverse_mod(r * ((s1 - s2) % N), N)
private_key = hex((numerator * denominator) % N)
print(f"[+] Recovered Private Key:\n{private_key}")
# 0x9f9068a0cc25f39b9c5fba5bb88d75bc5e4503a8406101a3195dc395194ea690
# Step 2: Brute-force message
words = [
"v1ew", "5tr0ng", "app1e", "fr13nd", "7hank5", "sch00l", "c0d3", "kn0w1edg3", "g00d",
"b4d", "dr34m", "r1v3r", "mou7a1n", "f0r3st", "5kyb1u3", "p14n3t", "c4r", "b1k3", "b00k",
"5tor3", "l4ugh", "sm1l3", "v1ct0ry", "p0w3r", "3n3rgy", "7r4v3l", "p3ac3", "f1gh7", "h0p3",
"4n7", "1i0nkin9", "7ig3r", "p4d0c0in", "0c34n", "w4v3", "5h0r3", "c4v3", "m00n", "5un",
"5tar", "7r33", "fl0w3r", "5e3d", "gr455", "b3", "4ir", "c10ud", "r41n", "5n0w", "5t0rm"
]
template = "BIP-39 SECP256k1 {} 5eed r4nd0m {} g00d 5olve c0ffe {} pe4nut 5mart"
print("[*] Brute-forcing possible message...")
m = mnemonic.Mnemonic('english')
found = False
for w1, w2, w3 in product(words, repeat=3):
msg = template.format(w1, w2, w3)
seed = m.to_seed(msg, passphrase="")
h = bip32utils.BIP32Key.fromEntropy(seed).PrivateKey().hex()
if h == private_key[2:]:
print(w1, w2, w3)
found = True
break
if not found:
print("[-] No match found.")
└─$CDDC2025{p4d0c0in_b3_5tr0ng_(private key in hex)}
Last updated