๐ค UTCTF 2024
Writeups for challenges I solved
There were already a lot of good writeups done and I'm starting this late so these will be a bit low effort.
Cryptography
RSA-256 (627 solves)
Description:
Based on the military-grade encryption offered by AES-256, RSA-256 will usher in a new era of cutting-edge security... or at least, better security than RSA-128.
By Jeriah (@jyu on discord)
Solution:
โโ$ cat vals.txt
N = 77483692467084448965814418730866278616923517800664484047176015901835675610073
e = 65537
c = 43711206624343807006656378470987868686365943634542525258065694164173101323321
# Solution: RsaCtfTool
# https://github.com/RsaCtfTool/RsaCtfTool
โโ$ RsaCtfTool.py -n 77483692467084448965814418730866278616923517800664484047176015901835675610073 -e 65537 --decrypt 43711206624343807006656378470987868686365943634542525258065694164173101323321
private argument is not set, the private key will not be displayed, even if recovered.
['/tmp/tmp66c8hk39']
[*] Testing key /tmp/tmp66c8hk39.
attack initialized...
attack initialized...
[*] Performing mersenne_primes attack on /tmp/tmp66c8hk39.
24%|โโโโโโโโโโโโโโโโโโ | 12/51 [00:00<00:00, 64776.90it/s]
[+] Time elapsed: 0.0162 sec.
[*] Performing factordb attack on /tmp/tmp66c8hk39.
[*] Attack success with factordb method !
[+] Total time elapsed min,max,avg: 0.0162/0.0162/0.0162 sec.
Results for /tmp/tmp66c8hk39:
Decrypted data :
HEX : 0x00000000007574666c61677b6a7573745f73656e645f706c61696e746578747d
INT (big endian) : 48318056036638095126835825247330138638677839744287146849712239741
INT (little endian) : 56744891277200465927677691769438839148620997683319332003939796345463196614656
utf-8 : utflag{just_send_plaintext}
utf-16 : ็ๆดๆ
ฌ็ญง็ช็ณ็ๆนฅๅฝคๆฑฐๆฅก็ฎ็กฅ็ตด
STR : b'\x00\x00\x00\x00\x00utflag{just_send_plaintext}'
Beginner: Anti-dcode.fr (305 solves)
Description:
I've heard that everyone just uses dcode.fr to solve all of their crypto problems. Shameful, really.
This is really just a basic Caesar cipher, with a few extra random characters on either side of the flag. Dcode can handle that, right? >:)
The '{', '}', and '_' characters aren't part of the Caesar cipher, just a-z. As a reminder, all flags start with "utflag{".
By Khael (Malfuncti0nal on Discord).
Solution:
We're given a large file that's rotated some amount of characters. I just went to cyber chef and put in utflag, rotated it one letter at a time and searched for it in the file manually until I found it, was around the 10th attempt or something.
numbers go brrr (228 solves)
Description:
I wrote an amazing encryption service. It is definitely flawless, so I'll encrypt the flag and give it to you.
By jocelyn (@jocelyn3270 on discord)
nc betta.utctf.live 7356
Solution:
As can be seen in the provided main.py, the seed is created from the current time. Therefore assuming our system time is the same as the server, we can just brute force the seed time offset and decode the encrypted flag without even using the "encrypt a message" option.

bits and pieces (218 solves)
Description:
I really really like RSA, so implemented it myself <3.
A two parter.
By jocelyn (@jocelyn3270 on discord)
Solution:
At the beginning of the challenge, only the first one decoded for me with RsaCtfTool.py and I saved it for later. When I came back, all three solutions were uploaded to factordb so it solved all three. Refer to RSA-256 solution, use for all three and concatenate the outputs.
Cryptordle (150 solves)
Description:
Just guess the word in 6 tries. What do you mean it's hard?
By oops (former ISSS officer)
Officer in charge: jyu
nc betta.utctf.live 7496
Solution:
Download a valid wordle list then simulate to get candidates for each phase, solves in 4 or less rounds (got lucky and solved in 2 guesses my last round).

numbers go brrr 2 (126 solves)
Description:
A spiritual successor the first.
By jocelyn (@jocelyn3270 on discord)
nc betta.utctf.live 2435
Solution:
Similar to the part 1 of the challenge, we encrypt a known message and then brute force the seed. We only need to use 1 encryption out of our 250 quota.

simple signature (95 solves)
Description:
The s in rsa stands for secure.
By alex (@kyrili : not the isss officer - someone y'all don't know)
Contact jocelyn (@jocelyn3270 on discord)
nc betta.utctf.live 4374
Solution:
When I was playing around with inputs, I put in 1 and 2 alternating and noticed the keys for both were the same each round, so we can just pass in the encrypted output previously generated.

Forensics
Contracts (387 solves)
Description:
Magical contracts are hard. Occasionally, you sign with the flag instead of your name. It happens.
By Samintell (@samintell on discord)
Solution:
Extract images from the pdf, get the flag.

OSINT 1 (202 solves)
Description:
It seems like companies have document leaks all the time nowadays. I wonder if this company has any.
(NOTE: It turns out there's also an actual company named Kakuu in Japan. The real company is not in scope. Please don't try and hack them.)
By mzone (@mzone on discord)
Solution:
There are already some detailed writeups for these so abridged version here. The website had placeholder links and images, the only thing that stood out were the names of the employees. All but the last one were relatively common names, only the last one was unique (Cole Minerton), he had a youtube channel with a discord link in the description. In the discord, he attaches a company contract with the flag in it.
OSINT 2 (141 solves)
Description:
Can you find where the person you identified in the first challenge lives? Flag format is City,State,Zip. For example, if they live at UT Austin submit Austin,TX,78712.
Do not include any spaces in your submission. The submission is also case sensitive, and works with or without utflag{}.
By mzone (@mzone on discord)
Solution:
The best OSINT site: https://whatsmyname.app
Search for coleminerton, find his Mastodon and see an image he posted on filling up gas before a trip.

Can zoom in the original picture to see New Mexico lottery in the middle and "CIMARRON AVE" on the sign. There are three cities in New Mexico with Cimarron Ave, and the solution ends up being Raton,NM,87740.
OSINT 3 (96 solves)
Description:
Can you find the person's IP address? Flag format is XXX.XXX.XXX.XXX
By mzone (@mzone on discord)
Solution:
When going to his reddit (found through previous link) and specifically with old reddit, we see a wiki link in a community he's a moderator for. In the wiki edit history we can see one of his edits he leaked his IP by not being logged in when making the contribution.
A Very Professional Website (142 solves)
Description:
Web dev skills go brrr
By Caleb (@eden.caleb.a on discord)
Solution:
There's a .git folder (probably needs a light fuzz to find or some basic trial/error), we can extract all the data with a tool. I used gitjacker which didn't download the secret file by default so I had to do a bunch of extra stuff (checking .git/logs/HEAD to find the other hash, manually going to the site to download the zlibs and uncompressing them, etc.), apparently it was possible to get it directly using gitdumper.sh at https://github.com/internetwache/GitTools (I didn't test but probably works).
Study Music (122 solves)
Description:
I listen to this while studying for my exams. https://youtu.be/1Cbaa6dO2Yk By Danny (Danny on Discord).
Note: the audio is the focus of this challenge. The video can be safely ignored.
Solution:
This is a 10 hour video with a looping audio, download a lower quality version of the audio using your site of choice and then open it in sonic visualizer. It takes a while to open and open the spectrogram but under a few minutes on a Kali VM, and at that point we can see a blip where at some point there's something else. Adjust the zoom manually and then the morse code that's played over the clip can be seen visually and transcribed (I also saw other people fed it directly into online morse code audio detectors).
Gibberish (31 solves)
Description:
Help! I'm trying to spy on my lover but they're not typing in any language I'm familiar with!
By mzone (@mzone on discord)
Solution:
We're given a wireshark pcap where we can see usb keypresses for a Razer Huntsman TKL board. Normally it's very straightforward to extract the keypresses, there are many guides online but the first step is something like:
We can then parse that data, although normally only one key is pressed at a time (optionally with a shift modifier which comes earlier), but in this file we see a lot of simultaneous keypresses.

So we need a more custom script. Here's how to extract the chords.
My notes for this one are a bit messy, I was playing around with many versions of the script. I ended up using this I think instead of one that was automatically saving only the full chords by saving the peaks because there were some chords that were more than the 6 characters max (I think up to 8) which requires rolling off some keys earlier and that's only visible by saving all the data.
By the way this chording is for steno typing, and the hint refers to plover. Can google about it but there's a tool that can be downloaded that lets you steno type with a normal keyboard which is how the pcap was made. I ran the above script to get the huge mess of an output and then just looked for some pattern. I found the chord that makes underscore (fgmik[) so I knew where the flag was, and then I just typed it out with plover. There are already good writeups for this so will just call it here.
Insanity Check: Reimagined (24 solves)
Description:
A reimagined version of our iconic Insanity Check: Redux challenge from UTCTF 2023.
The flag is in CTFd this time, but, as always, you'll have to work for it.
(Specifically the CTFd instance hosting utctf.live)
(This challenge does not require any brute-force -- as per the rules of the competition, brute-force tools like dirbuster are not allowed, and will not help you here.)
By Alex (@.alex_._ on Discord)
Solution:
The 2023 challenge had iirc a duck image where only one had the flag stego'd in it and the rest had red herrings in them. Along the same inspiration (and the "iconic" keyword), looking at the website files in the developer tools, there are two favicons (one .ico and one .svg), but the .ico seems like a dead end. The .svg has some interesting stuff in it though.
The pattern between FFFF and FFF6 seems like it's encoding data, and the timestamps are separated by around 0.314 or three times 0.314, and there are occasionaly consecutive FFF6s (either 2 or 4). All this together, we can picture this being morse code, with FFFF being 1 and FFF6 being 0, with two consecutive 0s being a letter separator and four consecutive 0s being a word separator (underscore). Below is my code that automatically converts this to morse code with a wide window for timing variability just in case.
Reverse Engineering
Beginner: Basic Reversing Problem (310 solves)
Description:
So many function calls... but are they that different?
By Khael (@malfuncti0nal on discord)
Solution:
Decompile the attached binary with dogbolt.org.
Many of these functions, extract and then get the flag (gpt can do automatically).
Fruit Deals (239 solves)
Description:
I found a excel sheet with some great deals thanks to some random guy on the internet! Who doesn't trust random people off the internet, especially from email
The flag is the file name that was attempted to be downloaded, wrapped in utflag{} Note: the file imitates malicious behavior. its not malicious, but it will be flagged by AV. you probably shouldn't just run it though.
By Samintell (@samintell on discord)
Solution:
I just opened the attached deals.xlsm in libreoffice calc in kali, enabled macros/editing, added a debug print and moused over it (since it wouldn't print for some reason), flag was banANA... in quotes.

๐ฉธPES-128 (57 solves)
Description:
Introducing the Parallel Encryption Standard PES-128 cipher! It's super high throughput and notable nonrequirement of keys makes it a worthy contender for NIST standardization as a secure PRF.
By Jeriah (@jyu on discord)
Solution:
We're given a PES encryption binary and a flag.enc to decode. We notice that inputs need to be hex and the first byte is always the input first byte with some testing. Assuming it works like other similar forms of encryption where the first byte doesn't change (XOR'ing with next segments/keys like block ciphers), we can brute force the conversion by seeing what inputs result in the output one byte at a time.

Decode the final match in cyber chef (from char code) to get the flag.
Web
Beginner: Off-Brand Cookie Clicker (474 solves)
Description:
I tried to make my own version of cookie clicker, without all of the extra fluff. Can you beat my highscore?
By Khael (@malfuncti0nal on discord)
Solution:
Can look in the javascript to see how the counter is incremented, then just set it manually in the console.

Schrรถdinger (250 solves)
Description:
Hey, my digital cat managed to get into my server and I can't get him out.
The only thing running on the server is a website a colleague of mine made.
Can you find a way to use the website to check if my cat's okay? He'll likely be in the user's home directory.
You'll know he's fine if you find a "flag.txt" file.
By helix (@helix_shift on discord)
Solution:
We can upload a zip file and it will display what the contents are. After some googling, a known vulnerability in this situation is uploading a sym link file so it will print out the contents of what you point it to.
First do a ln -s /etc/passwd file.txt, and then a zip -y file.zip file.txt to create the zip (-y to preserve the symlink). Check the size of the zip file to make sure you aren't uploading /etc/passwd (not a big deal but good practice/thought to have), and then upload it to see the contents of /etc/passwd printed on the server.

There's probably a flag option or something to do it but I just created /home/copenhagen/flag.txt on my machine for the symlink command to succeed then repeated the steps above.

Easy Mergers v0.1 (143 solves)
Description:
Tired of getting your corporate mergers blocked by the FTC? Good news! Just give us your corporate information and let our unpaid interns do the work!
By Samintell (@samintell on discord)
Solution:
We're given a zip file containing the files used on the web server. I did this one towards the start and don't remember too much of it, but I remember running the docker container to test locally and seeing which of the two POST options was potentially vulnerable (either makeCompany or absorbCompany), and then looking into how to set "secret.cmd", where secret is the session, since that's what is run when running absorbCompany. Anyway, here's the solution. Copy the cookie received after accessing the site and put it in solution.sh. The __proto__ lets us define a new variable/value pair.

Home on the Range (71 solves)
Description:
I wrote a custom HTTP server to play with obscure HTTP headers.
By Jonathan (@JBYoshi on discord)
Solution:
The site is a basehttp server that lets us access files, but there's nothing but a hello.html. We're not given the source code for the server but after reading through hints in discord, we know to try to find it with path traversal, and find it at ../../server.py.
This file shows us that the python server reads the flag contents into a variable and then deletes the flag file so the only place the flag is now is in the process memory. Since we can access any files we want with server.py though and since Accept Ranges is enabled, we can access /proc/self/mem and read all the program memory, specifying ranges given by /proc/self/maps so the read doesn't fail.
Unsound (13 solves)
Description:
I decided to roll my own super secure crypto. It's also written in Rust with no unsafe code. If you get past all of that, you have to break through the Wasm sandbox. Good luck...you'll need it.
All web requests replayed on an internal headless browser, which contains the flag. This is necessary since any keys stored in Javascript / Wasm could easily be read by the attacker. Take this into account when attacking this box.
By Aadhithya (@aadhi0319 on discord)
Solution:
At the site we're given an encrypt and decrypt entry field.

Through trial and error, we see the decrypt fails if the input is not a valid base64. Also instead of success, if the original plaintext is between 301 and 600 bytes long, we see those bytes directly printed on the screen (after 600 we just see success again). Since we have a way of displaying text on the page, we can do script injection. A <script> injection doesn't work for some reason but <img> injection does. Therefore we can do cookie exfil to our webhook. This works because all the commands sent in decrypt are also sent to the the internal headless browser running the same thing as mentioned in the description.
Misc
CCV (91 solves)
Description:
I've got some credit cards but I don't which ones are valid. Where did I get them? Uh, that's not important.
Oh, you'll probably need this: dae55498c432545826fb153885bcb06b
By mzone (@mzone on discord)
nc puffer.utctf.live 8625
Solution:
There was a lot of public discussion on this challenge in the discord, someone even posted a link of what needs to be done to verify this credit card data: https://www.linkedin.com/pulse/card-verification-code-cvc-value-cvv-nayoon-cooray/ This depends on having both the csc and cvv, but it's a 10 step process that I replicate in the following solution script.
Last updated
Was this helpful?