Your task is to play A difficulty and get at least 70% accuracy in std mode. Submit your replay osr file to server in base64 format.
Solution
As a beginner in osu!, I use the No Fail (mod) to play first and obtain the osr file. Then, I edit the replay using OsuReplayEditor to remove any misses or mods.
Alright, it’s gaming time. SS the top diff and submit your replay to the server in base64 format. (Play nomod, please don’t use mods like DT or HR)
nc chal.osugaming.lol 7278
Solution
First, use Auto (mod) to play it to obtain a perfect osr file (osu!(lazer) does not support exporting auto played osr files, so we need to use osu! Instead). However, even autoplay cannot achieve SS (check the video below).
So I used osu-replay-parser to add a 20ms delay to the auto-played osr, and it worked.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from osrparse import Replay
# parse from a path replay = Replay.from_path("at.osr")
# anti AT detection replay.username = 'ch'
# remove the auto play mods replay.mod_combination = 0
# add some time replay.replay_data[1].time_delta += 20
# write to a new file replay.write_path("at-modified.osr")
Malware
I stumbled upon RedLine Stealer malware while searching for an osu! cheat tool. Interestingly, I had recently reversed it at GCC 2024 .
Crypto
secret-map
Here’s an old, unfinished map of mine (any collabers?). I tried adding an new diff but it seems to have gotten corrupted - can you help me recover it?
In enc.py, the osu file is encrypted using XOR with a random 16-byte key. However, since the osu file starts with osu file format v14, the key can be obtained using it.
1 2 3 4 5 6 7 8 9 10 11
# enc.py import os xor_key = os.urandom(16)
withopen("flag.osu", 'rb') as f: plaintext = f.read()
encrypted_data = bytes([plaintext[i] ^ xor_key[i % len(xor_key)] for i inrange(len(plaintext))])
withopen("flag.osu.enc", 'wb') as f: f.write(encrypted_data)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# sol.py withopen('flag.osu.enc', 'rb') as f: encrypted_data = f.read()
known_pt = b'osu file format v14'[:16] key = bytes([encrypted_data[i] ^ known_pt[i] for i inrange(16)])
defdecrypt(data): returnbytes([data[i] ^ key[i % len(key)] for i inrange(len(data))])
decrypted_data = decrypt(encrypted_data)
withopen('sol.osu', 'wb') as f: f.write(decrypted_data)
After obtaining the osu file, I repackaged it into osz using 7z a -tzip -mm=Deflate -mx=9 example.osz extracted and imported it into osu!. Here are the results:
korean-offline-mafia
I’ve been hardstuck for years, simply not able to rank up… so I decided to try and infiltrate the Korean offline mafia for some help. I’ve gotten so close, getting in contact, but now, to prove I’m part of the group, I need to prove I know every group member’s ID (without giving it away over this insecure communication). The only trouble is… I don’t! Can you help?
from topsecret import n, secret_ids, flag import math, random
assertall([math.gcd(num, n) == 1for num in secret_ids]) assertlen(secret_ids) == 32
vs = [pow(num, 2, n) for num in secret_ids] print('n =', n) print('vs =', vs)
correct = 0
for _ inrange(1000): x = int(input('Pick a random r, give me x = r^2 (mod n): ')) assert x > 0 mask = '{:032b}'.format(random.getrandbits(32)) print("Here's a random mask: ", mask) y = int(input('Now give me r*product of IDs with mask applied: ')) assert y > 0 # i.e: if bit i is 1, include id i in the product--otherwise, don't
val = x for i inrange(32): if mask[i] == '1': val = (val * vs[i]) % n ifpow(y, 2, n) == val: correct += 1 print('Phase', correct, 'of verification complete.') else: correct = 0 print('Verification failed. Try again.')
if correct >= 10: print('Verification succeeded. Welcome.') print(flag) break
Solution
To solve the challenge, simply send n for every verification.
Web
pp-ranking
can you get to the top of the leaderboard? good luck getting past my anticheat…
if (md5 !== score.info.beatmapHashMD5) { thrownewError( "The beatmap and replay do not match! Did you submit the wrong beatmap?", ); } if (score.info._rulesetId !== 0) { thrownewError("Sorry, only standard is supported :("); }
To bypass the anti-cheat mechanism, we can make our score Infinity. This will cause pp = parseInt(newPP) in anticheat.js to become NaN. All comparisons involving NaN will always return false, so we can bypass the anti-cheat mechanism.
I randomly selected a song from here and downloaded the osz and osr (from rank). I then unzipped the osz file to obtain the osu file, modified OverallDifficulty of the osu file to 1000000000, and updated the beatmap hash in the osr to match the new one of the osu file. Finally, I uploaded the modified files to the server and achieved a rank of 1.
By the way, the variable pp can easily become infinity due to the presence of multiple Math.pow functions in the formula.
stream-vs
how good are you at streaming? i made a site to find out! you can even play with friends, and challenge the goat himself https://stream-vs.web.osugaming.lol/
This challenge requires us to beat cookiezi in the game, but cookiezi will always get the exact bpm (see the scoring algorithm below).
// algorithm from https://ckrisirkc.github.io/osuStreamSpeed.js/newmain.js constcalculate = (start, end, clicks) => { const clickArr = [...clicks]; const bpm = Math.round((((clickArr.length / (end - start)) * 60000) / 4) * 100) / 100; const deltas = []; for (let i = 0; i < clickArr.length - 1; i++) { deltas.push(clickArr[i + 1] - clickArr[i]); } const deltaAvg = deltas.reduce((a, b) => a + b, 0) / deltas.length; const variance = deltas .map((v) => (v - deltaAvg) * (v - deltaAvg)) .reduce((a, b) => a + b, 0); const stdev = Math.sqrt(variance / deltas.length);
return { bpm: bpm || 0, ur: stdev * 10 || 0 }; };
// scoring algorithm // first judge by whoever has round(bpm) closest to target bpm, if there is a tie, judge by lower UR /* session.results[session.round] = session.results[session.round].sort((a, b) => { const bpmDeltaA = Math.abs(Math.round(a.bpm) - session.songs[session.round].bpm); const bpmDeltaB = Math.abs(Math.round(b.bpm) - session.songs[session.round].bpm); if (bpmDeltaA !== bpmDeltaB) return bpmDeltaA - bpmDeltaB; return a.ur - b.ur }); */
// make end so that the bpm becomes the same as the target bpm let end = start + ((clicks.size / round_bmp) * 60 * 1000) / 4; recording = false; $("#timer").innerText = `Time remaining: 0s`; // [...] };