This weekend, me and my team D0M BU$TЄR$ played our first CTF, and played osu!gamingctf 2024. We finished in 210th place, with 14/54 challenges solved.
forensics/nathan-on-osu
Here’s an old screenshot of chat logs between sahuang and Nathan on hollow’s Windows machine, but a crucial part of the conversation seems to be cropped out… Can you help to recover the flag from the future?
We are given one file, nathan-on-osu.png
. We need to somehow “uncrop” an image? Searching for “uncrop image vulnerability” gives us a tool called Acropalypse. We can use this tool to uncrop the image, and by simply guessing that the original resolution is 1920x1080, we can view the flag.
crypto/rossau
My friend really likes sending me hidden messages, something about a public key with n = 5912718291679762008847883587848216166109 and e = 876603837240112836821145245971528442417. What is the name of player with the user ID of the private key exponent? (Wrap with osu)
This is an implementation of RSA, which is a way of encrypting messages between each other. Something worth noting is that with RSA, there exists a public key and a private key. We have been given the values and which is part of the public key. , where and are very large prime numbers.
The main reason why RSA is used so much today is that you cannot factor down to its highest prime factors, which is why the modulus (N in this case) usually is so large. In this case, we only have a modulus that is the size 40. This means we can easily factor down to its prime factors, which are , and . We’ll use Euler’s totient function which is:
We can then use the modular inverse to calculate , which is our private key exponent.
Link is https://osu.ppy.sh/users/124493
, which is chocomint’s account.
web/when-you-dont-see-it
welcome to web! there’s a flag somewhere on my osu! profile… https://osu.ppy.sh/users/11118671
We get linked an osu profile, and we can easily find the flag by inspecting the page source, and searching for “the flag”.
A Base64 decode gives us the final flag.
crypto/base727
As this challenge was made using ChatGPT, we can ask ChatGPT to do the reverse. You can’t expect me to decode this by hand, right?
pwn/betterthanu
bet you can’t beat a single one of my plays! nc chal.osugaming.lol 7279
We are given a C file with the challenge.
Our goal is to win against our opponent, but the problem is that somehow we must set our pp
value to be higher than pp + 1
, which obviously is impossible. We can see that the my_pp
value is set to pp + 1
, and if pp <= my_pp
, we lose.
Let’s take a deeper look at the source. We know that the buffer can only take 16 bytes, but the fgets
function allows us to input 100 bytes, which means we can overflow the buffer. This vulnerable fgets
call actually gets called twice, the first one to set the variable pp
to, and the second one, as “last words”.
This actually helps us out, because we can set pp
to 727 for the first call, and for the second function, we can actually overflow the buffer. By “overflowing the buffer”, I mean we can send a lot of garbage into the buffer, and hopefully overwriting the function that checks if pp <= my_pp
, allowing us to win (because we’ve already solved the first constraint by setting pp = 727
).
I made a script to bruteforce potential offsets to “win”. Notice how we send b'A' * i
and incrementing until “Ha” is not in the response, meaning we’ve successfully overwritten the function.
Working offsets are [15, 16]
, so we can send 15 bytes to overflow the buffer.