REVERSE CAPTCHA
Challenge
A "captcha" gate makes you answer ~20 rounds of small computational puzzles in sequence — square roots, the first n digits of π, natural logs, SHA-256 hashes, definite integrals of trig functions, vector components, cone/sphere-ish volumes — before it reveals the flag. Everything needed to compute every answer, including the exact rounding and string formatting the checker expects, ships client-side in the page's own JavaScript.
Solution
Reverse-engineer each puzzle type straight out of the page's JS and reimplement each one bug-for-bug (matching its exact precision/formatting, e.g. toFixed(5)), then drive the actual page's own DOM and form submission in a loop so every intermediate check (timing, state) is satisfied exactly as the real UI would produce it:
function computeAnswer(instruction, title, format) {
if (instruction.startsWith('Please enter the square root of'))
return Math.sqrt(Number(title)).toFixed(5);
if (instruction.startsWith('Please enter the sum of')) {
const n = Number(title.match(/first (\d+) digits/)[1]);
pi ??= generatePi(10000);
return String([...pi.slice(1, n + 1)].reduce((s, d) => s + Number(d), 0));
}
if (instruction.startsWith('Please enter the SHA-256 hash of'))
return { needsHash: true, text: title };
… // natural log, definite integral, vector component, volume …
}
for (let round = 0; round < 20; round++) {
… wait for the next challenge to render …
let answer = computeAnswer(instrEl.textContent, titleEl.textContent, formatEl.textContent);
if (answer?.needsHash) answer = await sha256hex(answer.text);
input.value = answer;
form.dispatchEvent(new Event('submit', { cancelable: true, bubbles: true }));
}
Pasting that loop into the browser console and letting it run through all 20 rounds unattended clears the gate and reveals the flag element.