Skip to content

Latest commit

 

History

History

cryptolocker

cryptolocker

The key observation here was that we could guess two bytes of the password, attempt to decrypt the ciphertext, and immediately know if our decryption was valid because we could check if there were 16 bytes of padding. We know that there should be 16 bytes of padding because when we decrypt a ciphertext, we're left with another valid ciphertext, and a valid ciphertext needs to be a multiple of 32. The only time this isn't true is for the last two bytes of the password, where we decode the ciphertext into the flag file. In this case, we remove the check for 16 padding bytes, and print out matches for any valid padding. There was one decryption that resulted in a valid padding of 28, and these were the last two characters

#!/usr/bin/env python3

from AESCipher import *
import hashlib
import string

ciphertext = open('flag.encrypted', 'rb').read()

# These are the characters we recovered. After recovering two characters, we
# would decrypt the ciphertext with those characters before continuing to brute
# force the next two characters. So for example, after discovering that the last
# two bytes of the password were '4D' we would comment in the following two lines.

# ciphertext = AESCipher(hashlib.sha256('4D'.encode('utf-8')).digest()).decrypt(ciphertext)
# ciphertext = AESCipher._unpad(ciphertext)
# ciphertext = AESCipher(hashlib.sha256('WH'.encode('utf-8')).digest()).decrypt(ciphertext)
# ciphertext = AESCipher._unpad(ciphertext)
# ciphertext = AESCipher(hashlib.sha256('52'.encode('utf-8')).digest()).decrypt(ciphertext)
# ciphertext = AESCipher._unpad(ciphertext)

# ciphertext = AESCipher(hashlib.sha256('Sg'.encode('utf-8')).digest()).decrypt(ciphertext)
# ciphertext = AESCipher._unpad(ciphertext)
# open('flag', 'wb').write(ciphertext)

for i in string.printable:
    for j in string.printable:
        s = (i + j).encode('utf8')

        k = hashlib.sha256(s).digest()
        decrypted = AESCipher(k).decrypt(ciphertext)
        last = decrypted[-1]

        valid = True
        for c in decrypted[-last:]:
            if c != last:
                valid = False
                break

        # comment this out for the last two bytes
        if (len(decrypted) - last) % 16 != 0:
            valid = False

        if valid:
            print(s, last)

After decrypting the file, you will have an ODT file that contains the flag: flag{v3ry_b4d_crypt0_l0ck3r}