# CDDC 2025

## Reassemble The Pieces  <a href="#modal_title" id="modal_title"></a>

<mark style="color:blue;">Network | Qualifier</mark>&#x20;

Extract H.264 video payloads from RTP packets in a `.pcap` file using [rtp\_h264\_extractor.lua](https://github.com/volvet/h264extractor/blob/master/rtp_h264_extractor.lua).

<figure><img src="https://1163145841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4UkbOn8PnZkBCBDx07r4%2Fuploads%2FnQkPnNn3Qw044IjBuceU%2Fimage.png?alt=media&#x26;token=aa163671-9113-49d2-a38c-52638fec7868" alt=""><figcaption><p>Extracted H.264 Video</p></figcaption></figure>

`└─$CDDC2025{5tr3@m1ng_53rv1ce35_u53_th3_RT5P_pr0t0c01}`

## Break the ECDSA <a href="#modal_title" id="modal_title"></a>

<mark style="color:blue;">Cryptography | Qualifier</mark>&#x20;

The overall solution is:

1. Using given signatures to compute the private key using [ECDSA Nonce Reuse Attack](https://notsosecure.com/ecdsa-nonce-reuse-attack)
2. 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

```python
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)}`

