Writeup DGA - CTF - Involucrypt 1

This article describes my solution for the 100-point challenge called “Involucrypt 1”.


Pendant une investigation numérique sur un disque dur, vous trouvez un fichier chiffré en utilisant un algorithme propriétaire.

Heureusement, le script utilisé pour chiffrer et déchiffrer se trouve dans le même dossier, mais vous ne disposez pas de la clé. Bon courage !

If you want to test yourself, crypt.py file is available here and involucrypt1 is available here.


According to the description of this challenge, the crypt.py file contains a proprietary algorithm that encrypted the involucrypt1 file. The crypt.py file contains a mersenne_rng class which seems to be an implementation of the pseudo-random number generator Mersenne Twister. This class generates a pseudo-random number. Then there are two functions keystream(seeds, length, base=None) and encrypt(string, key).

By analyzing the code and playing with the script, we can see that the encryption key only takes 3 characters: if we execute the script with a key of 3 characters or more, the decryption result is the same.

cat involucrypt1 | python2 crypt.py 1 | wc -c
cat involucrypt1 | python2 crypt.py 12 | wc -c
cat involucrypt1 | python2 crypt.py 123 | wc -c
cat involucrypt1 | python2 crypt.py 1234 | wc -c
cat involucrypt1 | python2 crypt.py 12345 | wc -c

Now that we know that the key is only 3 characters long, we can write a brute force script to find the key and thus decipher the message.

Having tried this script in Python 3, it doesn’t work very well due to a character encoding problem, so I created a virtual environment to run my script in Python 2.

virtualenv2 crypt1
created virtual environment CPython2.7.18.final.0-64 in 73ms
  creator CPython2Posix(dest=/home/ap/crypt1, clear=False, global=False)
  seeder FromAppData(download=False, pip=bundle, wheel=bundle, setuptools=bundle, via=copy, app_data_dir=/home/ap/.local/share/virtualenv)
    added seed packages: pip==20.2.4, setuptools==44.1.1, wheel==0.35.1
  activators PythonActivator,CShellActivator,FishActivator,PowerShellActivator,BashActivator
cd crypt1/
source bin/activate.fish
f = open("involucrypt1", "r")
file = f.read()

def bruteforce(file):
    for i in list(string.ascii_lowercase):
        for j in list(string.ascii_lowercase):
            for k in list(string.ascii_lowercase):
                key = i + j + k
                result = encrypt(file, key)
                if "flag" in result:
                    print (result)
		    print ("The key is: " + key)


I added this script at the end of the crypt.py file to be able to use the encrypt() function directly. You must also import the string library (import string) at the very top of the file to be able to use the ascii_lowercase method. I also removed the part that allows to launch the script automatically (if __name__ == "__main__":).

By executing this script, the result is displayed in less than 30 seconds.

(crypt1) python crypt.py
The flag is: TheKeyIsTooDamnWeak!

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

The key is: ane

The flag to validate this change appears as well as the decryption key.