This is short writeup on the Decode Me challenge of the first CryptoCTF.
The following string has to be decoded into a flag somehow:
D: mb xwhvxw mlnX 4X6AhPLAR4eupSRJ6FLt8AgE6JsLdBRxq57L8IeMyBRHp6IGsmgFIB5E :ztey xam lb lbaH
The first thing that comes to mind is that some sort of substitution cipher was being used in the first place. A cipher of this kind is the Caesar cipher which is also known as ROT. Fiddling around with this cipher and a key of 7
yields:
K: ti edoced tsuE 4E6HoWSHY4lbwZYQ6MSa8HnL6QzSkIYex57S8PlTfIYOw6PNztnMPI5L :galf eht si sihO
And reversed:
Ohis is the flag: L5IPMntzNP6wOYIfTlP8S75xeYIkSzQ6LnH8aSM6QYZwbl4YHSWoH6E4 Eust decode it :K
The odd thing is that some characters, the O
in Ohis
, the E
in Eust
and the smiley and the end of the line seem broken. Playing around with other keys and ciphers like Affine cipher or Vigenère didn’t work. Also just decoding the alleged flag with Base64 and other encodings didn’t produce anything useful.
While trying to fix the corrupted characters, it has been observed that with a ROT key of 12
, the corrupted characters seem to be included correctly in the plaintext when merging it with the result with key 7
:
Tmnx nx ymj kqfl: Q5NURsyeSU6bTDNkYqU8X75cjDNpXeV6QsM8fXR6VDEbgq4DMXBtM6J4 Jzxy ijhtij ny :P
Base64 decoding this prints:
CTF̞INL3db<_\3i]zB<}tzT1pm3x%
This at least starts with the CTF
string…
The assumption that has been made is that the alleged flag is encoded with Base64. It’s known that all flags start with the CCTF{
string in this particular CTF, so Base64 encoding this prints: Q0NURns=
as reference. Therefore the encoded flag has to start with this string or a substring of it.
The decryption result with key 12
starts with Q5NUR
which is quite similar to the string that’s being searched for. Let’s line up both decryption results:
L5IPMntzNP6wOYIfTlP8S75xeYIkSzQ6LnH8aSM6QYZwbl4YHSWoH6E4 (key 7)
Q5NURsyeSU6bTDNkYqU8X75cjDNpXeV6QsM8fXR6VDEbgq4DMXBtM6J4 (key 12)
It was striking that the numbers weren’t rotated when decrypting the string with CyberChef. According to the reference above, the second character has to be a zero but it’s a five. So I’ve decided to just add 5
to every number that’s present in the second decryption result (second line in the listing above):
Q0NURsyeSU1bTDNkYqU3X20cjDNpXeV1QsM3fXR1VDEbgq9DMXBtM1J9
And Base64-decoded:
CCTF̞IM[L3db7_m3i]uB7}tuT11pm3R}
Looks better but not good enough.
An additional thing to notice is that they string decrypted with 7
has all lowercase characters correct. The 12
one has all uppercase characters correct - the T
, J
and P
. So the idea was to merge these strings together: Use the lowercase characters from the 7
one, the uppercase ones from the 12
string and also rotate the numbers as shown before. This yields:
Q0NURntzSU1wTDNfYlU3X20xeDNkXzV1QnM3aXR1VDEwbl9DMXBoM1J9
And Base64-decoded:
CCTF{sIMpL3_bU7_m1x3d_5uBs7ituT10n_C1ph3R}
What to take away from this? I don’t know. Maybe that
Base64Encode(CCTF{) = Q0NURns=
Base64Decode(Q0NURnt=) = CCTF{
So this means that there are various inputs for Base64 decoding that decode to the same string.