What Are We Working With

We have two things. An encrypted message: a_up4qr_kaiaf0_bujktaz_qm_su4ux_cpbq_ETZ_rhrudm And the Python script that was used to encrypt it:

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))

Pretty much ideal starting point. We know what the output looks like and we know exactly how it was made.


Understanding the Encryption

The script looks a bit weird at first because it is all crammed into one line. I stared at it for a bit before I got it.

Here is what it is actually doing. For every character in the flag, if it is a letter, it shifts it forward in the alphabet by i. And i is just the position of that character starting from 0. So the first letter gets shifted by 0, the second by 1, the third by 2, and so on. Non-letter characters like numbers and underscores are left alone.

That is it. That is the whole thing.


Finding a Tool

My first instinct was to search for an online decoder. This reminded me of a Vigenere cipher so I looked for Vigenere decryption tools. Found a bunch of them but none of them worked for this. Makes sense because this is not quite a standard Vigenere cipher. The key here is literally just the position index, not a repeated keyword.

So no online tool was going to save me here.


Writing the Decryption Script

Since the encryption is just adding i to each letter’s position, reversing it is straightforward. Just subtract i instead.

def dec(ciphertext):
    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(ciphertext)
    )

cipher = "a_up4qr_kaiaf0_bujktaz_qm_su4ux_cpbq_ETZ_rhrudm"
print(dec(cipher))

Spot the difference? I literally just changed + i to - i. That’s it.

Run it and wrap the output in THM{}:

THM{a_sm4ll_crypt0_message_to_st4rt_with_THM_cracks} Done.


Wrapping Up

This one was quick. Having the encryption script handed to you basically means the hard part is already done. All I had to do was read it, understand what it was doing, and flip it around.

The only small wall I hit was assuming there might be an online tool for it. There was not, but writing the fix took about two minutes so it did not matter.