Cipher’s Secret Message – CTF Writeup

Platform: TryHackMe
Instructions:
One of the Ciphers’ secret messages was recovered from an old system alongside the encryption algorithm, but we are unable to decode it.
Order: Can you help void to decode the message?
Message: a_up4qr_kaiaf0_bujktaz_qm_su4ux_cpbq_ETZ_rhrudm
Encryption algorithm:
from secret import FLAG
def enc(plaintext):
return "".join(
chr((ord(c) - (base := ord('A') if c.isupper() else ord('a')) + i) % 26 + base)
if c.isalpha() else c
for i, c in enumerate(plaintext)
)
with open("message.txt", "w") as f:
f.write(enc(FLAG))
This one seems like a fun problem! The beauty of encryption is that how these algorithms for encryption work are publicly available.
Thereby, what makes them secure is simply the super clever math behind them.I doubt this provided encryption will hold up as well as widely used algorithms. Lets analyze how it works:
- The function takes in a string
plaintext
- For each character in the string, take the unicode code point (converts the string into a corresponding integer)
- If the character is uppercase, we set the value of the base operator to the ordinal value of ‘A’ (65) if it is lowercase we set the base to the ordinal value of lowercase ‘a’ (97).
- Subtract the base
- Add the position of the character in the string
i
to this difference - Then %26 to shift
- Add the base value back
- Convert this numerical value into a character, if it is alphabetic, otherwise we just input the character as it is in the string
- Join the results of this subroutine together
This code is a little tough to read, as it is essentially one long subroutine of a ternary operators! However essentially, this is performing a caesar cipher shift on alphanumeric characters, otherwise it leaves the character as is.
Here is a more basic equation:
(ord(c) - base + i) % 26 + base
So lets craft up an algorithm to undo this! Essentially all we have to do, since this is a position shift cipher, is just subtract by the i instead of adding by it.
We get the following code in python, which I have written in a slightly different format than the code that was encoded for clarities sake:
def decrypt(encoded_text: str):
# A list to store all of our converted characters
chars = []
for i, c in enumerate(encoded_text):
base = 0
# Choose our base, 65 if c is uppercase, otherwise we set it to 87
if c.isupper():
base = ord("A")
else:
base = ord("a")
# Reverse the calculation by calling minus i
decoded_c = chr((ord(c) - base - i) % 26 + base)
# If the decoded character is alphabetic, we add that,
# otherwise we add the original c
if c.isalpha():
chars.append(decoded_c)
else:
chars.append(c)
# Join it all together:
return "".join(chars)
Running this function with our encoded text, we get our flag!