This was the first CTF competitions that I actively participated in, and also as a member of b01lers. I kept this writeup private for a while, because I wanted to use one of the challenges as a homework problem for the class I was TAing this semester (CS 426). Now that the semester is over, I can finally publish this writeup here!
The competition website seems no longer online, but fortunately I have all the challenges and my solutions saved.
The two main vulnerabilities here are: \( q \) is only 512 bits and the program reveals (too much) information about \( p \) and \( q \). Initially, I was trying to see if I can solve this by expanding \( (p+q)^e \), then play with it along with \( (pq)^e \) and \( (p / q)^e \). But in the end, they are all 'encrypted' and it might be difficult to figure out \( p \) and \( q \) directly from those without having to take the 65537th root of something. Then I noticed that the program does not 'encrypt' \( p-q \) and \( p \;\text{ mod } q \).
Let \( d = p-q \) and \( r = p \;\text{ mod } q \). Since \( p > q \) and \( 0 < r < q \), there exists an integer \( k \) such that \( p = qk + r \), or equivalently \( r = p - qk \). Then we can cancel \( p \) as follows:
\[ d - r = (p - q) - (p - qk) = qk - q = q(k - 1) \]
Being able to cancel \( p \) is a good sign, because \( p \) was a 1024-bit integer which is large enough to make our life hard, whereas \( q \) is only a 512-bit integer. So the first thing I did tried was see if I can factorize this directly, hoping that I was lucky and got a \( k-1 \) that is nice enough to factorize fast.
Well, I was not lucky enough and this takes forever. This probably was as expected, because \( d \) is an 1024-bit integer which can be large enough for a laptop like mine.
Though this program is nice enough that it lets you re-generate one of the primes of your choice. We were able to cancel \( p \) anyway, so I can intentionally re-generate \( p \), cancel it again, and get another multiple of \( q \). Let \( p' \) be re-genereated \( p \). Then we do the math again: Let \( d' = p' - q \), \( r' = p' - qk' \) for some integer \( k' \), then \( d' - r' = q(k' - 1) \). This again is too large to factorize, but it is not large enough to run the extended Euclidean algorithm over and calculate the GCD.
\[ \gcd(d - r, d' - r') = q \gcd(k - 1, k' - 1) \]
This should be easier to factorize than \( q(k - 1) \) or \( q(k' - 1) \) for sure. It turns out I am just lucky enough here.
I somehow managed to get \( k \) and \( k' \) such that \( \gcd(k-1, k'-1) = 1 \). The q_maybe in the code above is hence the \( q \) that we were looking for! We are basically done here then, the rest follows from the typical textbook RSA algorithm.
Curious readers here might ask: will \( \gcd(k-1, k'-1) = 1 \) for all \( p \) and \( q \) in this problem? I have tested it a few more times and the answer obviously is no. But regardless, \( \gcd(k-1, k'-1) \) should be smaller than \( k-1 \) and \( k'-1 \), so \( q \gcd(k-1, k'-1) \) definitely should be easier to factorize than \( q(k-1) \) and \( q(k'-1) \). If you are that paranoid, you can factorize it (maybe break if it takes too long) and find the 512-bit prime number among its prime factors yourself. Something like this:
For the sake of completeness, here is the full solution script, for your reference:
sol.py (Click to expand)
brokenimg (Forensics)
This challenge was pretty cute. You are given a PDF file of a love letter: chall.pdf. You will soon realize that this letter is to sweet (?) for a CTF competition (I am obviously joking here, but hey, I'm sure you'd agree), something might have been hidden inside.
Upon checking its metadata (I just used cat chall.pdf on terminal), I found this inside the entry for the file description:
This looks like an URL, given how the second and third numbers (164) are the same and eighth and ninth numbers (57) are the same (URLs start with https://). So I tried this.
Well that wasn't very nice of him. Let's let that boy cook then.
Anyway, going into that link gives us this weird looking picture that appears to be tilted by someone intentionally for the purpose of obfuscation, or actually making people tilted (pun intended).
Fortunately, there is an online tool that skews pictures https://www.luxa.org/image/tcp1p_2023/skew. What a great world we live in today! Upon unskewing by skewing the skewed picture (pun intended a little bit), I got this:
Looks like one of those Wojak memes! After carefully transcribing the text below two Wojak characters (this can be more non-trivial than you think... xP)