Schrodinger's Pad
Writeup for Schrodingers Pad (Crypto) - 1337UP LIVE CTF (2024) 💜
Video walkthrough
Challenge Description
Everyone knows you can't reuse a OTP, but throw in a cat and a box.. Maybe it's secure?
If you know me, you know I hate crypto 😑 I wanted to make a challenge for every category though, so here you go..
Solution
The challenge includes source code, but let's test the basically functionality. Any challenges that include a docker-compose can be started with the ./start.sh script.
nc localhost 1337
Welcome to Schrödinger's Pad!
Due to its quantum, cat-like nature, this cryptosystem can re-use the same key
Thankfully, that means you'll never be able to uncover this secret message :')
Encrypted (cat state=ERROR! 'cat not in box'): 36021a4c0122024f2d06140947160c3f152b2466262b3405125e08342c49105f277a500206163b761e251d1b0408247729595f3f35446e242304313676316b000f201a192d17581f431748627b2c000a0f0379337c11031b00062f6a144e0c143804501353092a0250264e231f4815032310595b2c20111b593f6d1d073e6b133d5d5d7602165905673f3b732f0721215d21551719391a4c5e2c745852471862
Anyway, why don't you try it for yourself?
cryptocat is the best!
Encrypted (cat state=dead): 474541c44a58c8cd55efc44469474f5dc357d8505a7dSome observations:
The encrypted message at the start is different each time we connect
The ciphertext generated from our is also different, despite providing the same input
Source Code Review
Let's get a better understanding what happens when we connect to the server. First thing to note is the key is randomly generate each time we connect (explaining the above observations).
Next, the flag is encrypted using a otp function.
Finally, it takes a plaintext message (up to 160 bytes) from the user and encrypts it.
Let's have a look at the two functions. First is otp
It might look fancy, but it's simply XORing the plaintext with the key. Next is check_cat_box*
It performs some bitwise operations (shift and XOR) depending on the cat_state, which is also randomly determined.
*Note that the flag doesn't go through this function, hence "cat not in box" message
Many Time Pad
One Time Pad's are secure, when the key is truly random. The issues arise when the key is used more than once. That's because XOR is a reversible operation (see warmup: IrrORversible) and with any two pieces of information, we can recover the third.
Since we have some plaintext and the resulting ciphertext, we can XOR them to recover the key. Now, we can recover any other plaintexts that were encrypted with the key, e.g. the flag.
It's made slightly more difficult as a result of the cat/box related operations, but you can manually reverse these or use a script.
Actually, this wasn't my intention for the challenge - as you'll probably see from my solve script and the video walkthrough. I hoped players would recover (p1 ^ p2) from (c1 ^ c2) and then XOR (p1 ^ p2) with p2 to recover p1. It's doable if we remove the user input and just provide two long ciphertexts, but I don't have time to make changes now and the writeup/video is already done. Beside, I told you already I hate crypto 🙃
Solve.py
As mentioned in the last section, the solve script goes the long, but originally intended way. It's easiest just to do c2 ^ p2 = k and then c1 ^ k = p1.
Repeat against remote for the real flag!
Flag: INTIGRITI{d34d_0r_4l1v3}
Last updated
