(500 pts, 1 solve)
Solver: T0022 - HKUST Member 2
Description:
I am so excited having a chance talking to Alice. She told me to calm down - and sent me an encrypted secret.
nc tertiary.pwnable.hk 50013
Okay. So seems that this is a RSA-2048 crypto challenge and there are few commands avaliable.
Let's see what we have for the RSA now. We could get , the public key from the output of the program. We could also get , the ciphertext of the flag. How about the public key exponent ? If we search for the function online, it will set as default. However, we don't have the private key exponent nor the original secret message , which is the thing that we want!
What we have now is enough for doing encryption because , but we can't do decryption because which we don't have in our hand.
However, there is one thing that concerns us. After sending the encrypted message, it would tells us if the decrypted message is ended with a .
(dot). We could't get any other information about the decrypted message, but just if it ends with a dot. We could consider this as an oracle function and this would be our starting point as there is no other things in this challenge that we can use for exploit.
Also, by sending the encrypted flag back to Alice, the oracle function tells us that the original message ends with a dot too. Of course as expected, because Alice is a polite girl, right?
Knowing whether the last byte is a dot - kind of similar to RSA LSB oracle attack! (Reference: CTF-Wiki) Where the difference is that for RSA LSB oracle attack, the oracle function returns the value of the last byte to us. However, this time, the function just returns whether it is a dot or not. How could we get the original message with just little information?! It seems impossible!
Nothing is impossible.
Someone
Ok. Well. This task should be similar to RSA LSB oracle attack though. Let's get some idea from the RSA LSB oracle attack.
What we could get is that, the first step of most of the RSA oracle attacks follow these steps.
Therefore, when the server tries to decrypt , it will get instead of the original message .
And now we can somehow manipulate what the server will get after it decrypts a ciphertext. Let's put the encrypted secret message as the ciphertext . What value of should be chosen? What are we going to do?
In fact, usually the original message is much much smaller than . Therefore, still results so that the server could get back the original message.
What if we set the value of very large, making just slightly bigger than ? In another way, finding the minimum(can be slightly larger) that satisfies
This can be written as like the following, where is the remainder with and
Tada! We could then find once we find the specfic that satisfies the equation!
Assume increasing the value of from one by one, each time sending to the server, how could we know when the value of exceeds ? We know that the server will do everytime, but the has no effect when . At the moment , the server will get as the message. Is it possible to detect this moment? YES!
Here's the time for the oracle function works. The byte representation of .
is 0x2e
. If we multiply 0x2e
with 0x81
, we get 0x172e
. The last byte is still 0x2e
! So this means if we set any value of with the last byte be 0x81
, the server should also get with the last byte be 0x2e
and the oracle function will return true. UNLESS, for the moment that , the last byte of (0x2e
) will minus the last byte of . As the last byte of will never be 0x00
( is always odd), the resultant byte must not equals to 0x2e
and the orcale function will return false.
Therefore, by testing values of in ascending order that end with the byte 0x81
(E.G. 0x181
, 0xA81
, 0x12381
), at the moment that the orcale function suddenly return false, that value would be the one that we want.
Before starting to find the value of , there is one small problem that we have to solve, actually we could not increment the value of one by one to try (i.e. 0x181
, 0x281
, 0x381
…). As , the target value of would be very large(more than 100 bytes) and it would take billion of years to find ! Luckily, this is not difficult to solve.
Repeatly append 0xf
to 0x81
as until the oracle function return false (e.g. 0xf81
, 0xff81
, 0xfff81
…), denote it as . When the oracle function return false, it means that the value of is greater than the value you previously tried and smaller than .
Choose as the value of . Start from the leftmost digit of , for a digit, decrease it by 1 until the oracle function returns true (or the digit reaches 0). If the oracle function returns true, increase the digit back by 1. Then proceed to do the same procedure for the next digit on the right. This makes always larger then , while making as minimum as possible.
Therefore, here is the final code:
We finally got the secret message: Hey, congratulations on solving the challenge. But please hkcert20{c4lm_d0wn_4nd_s0lv3_th3_ch4llen9e}.
CTF
, HKCert20CTF