NahamCon CTF 2025 Writeup
Table of Contents

INTRODUCTION⌗
I participated in the NahamCon CTF, with AfriCC-mini-team1
.
Since I didn’t capture many files and screenshots during the event, this write-up will be brief and cover only one challenges I tackled.
SNAD⌗
No, it's not a typo. It's not sand. It's SNAD. There's a difference!
Solution
Upon visiting the site, we notice an interactive particle system that's responsive to mouse movement.
Inspecting the JavaScript code reveals a POST request made to /api/verify-ctf-solution with the following payload:
let t = particles
.filter((e) => e.settled)
.map((e) => ({
x: Math.floor(e.x),
y: Math.floor(e.y),
colorHue: e.colorHue,
}));
let o = await fetch("/api/verify-ctf-solution", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
particleData: t,
}),
});
Initially, manual POST requests return Invalid submission data. Digging deeper, we find a checkFlag()
function that validates particle positions:
function checkFlag() {
if (flagRevealed) return;
let e = 0, t = [];
for (let o of targetPositions) {
let i = false;
for (let r of particles)
if (r.settled) {
let l = dist(r.x, r.y, o.x, o.y),
s = min(abs(r.colorHue - o.colorHue), 360 - abs(r.colorHue - o.colorHue));
if (l < 15 && s < 20) {
i = true;
t.push({
targetPos: `(${o.x}, ${o.y})`,
targetHue: o.colorHue,
particlePos: `(${Math.floor(r.x)}, ${Math.floor(r.y)})`,
particleHue: r.colorHue,
distance: Math.floor(l),
hueDifference: Math.floor(s),
});
break;
}
}
if (i) e++;
}
e >= 7 && ((flagRevealed = true), console.log("🎉 All positions correct! Retrieving flag..."), retrieveFlag());
}
Turns out the key is aligning particles to specific targetPositions with matching colorHue. To spoof this:
Exploit Script
In the browser console, paste this:
function placeCorrectParticles() {
for (let i = 0; i < 7; i++) {
let target = targetPositions[i];
particles.push({
x: target.x + Math.random() * 10 - 5,
y: target.y + Math.random() * 10 - 5,
colorHue: (target.colorHue + Math.random() * 10 - 5 + 360) % 360,
settled: true,
});
}
checkFlag();
}
placeCorrectParticles();
After executing the script, the console logs the flag:
Flag: flag{6ff0c72ad11bf174139e970559d9b5d2}
Catch you in the next hack! Stay curious 🔍