N0PS CTF 2025 - Key Exchange Writeup
Category: CrypTopia
Challenge Name: Key Exchange
Flag: ✅ N0PS{d1fFi3_h31lm4n_k3y_XcH4ng3}
Author: algorab
Challenge Description
We’re given a connection endpoint to a secret service belonging to CrypTopia:
nc 0.cloud.chals.io 26625
The challenge implies that if we manage to speak the right language to this service, it will reward us with the flag. The format is N0PS{...}
. No additional hints — just the address and an attached Python script.
Naturally, I started by connecting to the server using netcat to see what kind of response it gives:
nc 0.cloud.chals.io 26625
As expected, I was greeted with a screen full of binary garbage. This was a clear sign that the server is expecting a binary-level protocol, not plain text.
. The file was named main.py
given , and it contained the core logic running on the server.
Code Breakdown
The script performs a Diffie-Hellman key exchange followed by AES encryption of a flag file. Here's a brief summary:
- The server generates a safe prime
p
and a generatorg
. - It calculates
k_a = g^a mod p
wherea
is a random private key. - It sends
p
,g
, andk_a
to the client. - The client is expected to respond with
k_b = g^b mod p
. - Both parties compute the shared secret key
k = g^(ab) mod p
. - The server uses
SHA-256(k)
as an AES key to encrypt the flag and send it back.
Realization
What we had here was a textbook example of a Diffie-Hellman key exchange implemented in a CTF setting. The goal is to mirror the server’s steps, perform the math on our side, and decrypt the flag ourselves.
To solve it, I needed to:
- Parse the 1024-byte
p
,g
, andk_a
values sent by the server. - Generate a private
b
, computek_b
, and send it back. - Receive the AES-encrypted flag.
- Derive the same shared key and decrypt the ciphertext.
Building the Exploit Script
To automate this, I wrote a Python script using socket
, Crypto
, and hashlib
libraries. One important note: the server sends 1024 bytes, not bits — I initially messed this up and got all zeroes for p
, g
, and k_a
.
Once that was corrected, everything lined up.
Decryption & Discovery
After decryption, the data didn't look like text, so I ran:
file decrypted_flag.bin
And saw this:
PNG image data, 4267 x 4267, 8-bit/color RGBA
converted it to the png file
mv decrypted_flag.bin flag.png
Bingo. The flag was embedded inside an image.
decrypted_flag.bin: PNG image data, 4267 x 4267, 8-bit/color RGBA
I opened the file and found the flag painted on top of a shiny treasure chest.
? Final Flag
N0PS{d1fFi3_h31lm4n_k3y_XcH4ng3}
Team N0C71S