Rating: 4.0

For this first challenge we are given the following python file
```python
from Crypto.Cipher import AES
import binascii, sys
import hashlib

key = b'T0EyZaLRzQmNe2**'
KEYSIZE = len(key)
assert(KEYSIZE==16)

def pad(message):
p = bytes((KEYSIZE - len(message) % KEYSIZE) * chr(KEYSIZE - len(message) % KEYSIZE),encoding='utf-8')
return message + p

def encrypt(message,passphrase,iv):
aes = AES.new(passphrase, AES.MODE_CBC, iv)
return aes.encrypt(message)

h = hashlib.md5(key).hexdigest()
SECRET = binascii.unhexlify(h)[:10]

with open('flag','rb') as f:
IV = f.read().strip(b'gactf{').strip(b'}')

message = b'AES CBC Mode is commonly used in data encryption. What do you know about it?'+SECRET

print("Encrypted data: ", binascii.hexlify(encrypt(pad(message),key,IV)))

'''
Encrypted data: b'a8**************************b1a923**************************011147**************************6e094e**************************cdb1c7**********a32c412a3e7474e584cd72481dab9dd83141706925d92bdd39e4'
'''
```

Let's have a look at what we have. at the top of the file there is a key `T0EyZaLRzQmNe2**`, the `*` seems to indicate
missing characters so we have a key with 2 missing characters.

Next we hafve a classic padding function, followed by an AES-CBC encrypt. The flag is used as the IV of our encrypted message, and an hash of the key is
appended to the message we are encrypting.

At the end of the file is the output of the encryption, with some missing characters.

First we need to create a function to decrypt a message, given a passphrase and an IV.
```python
def decrypt(message, passphrase, iv):
aes = AES.new(passphrase, AES.MODE_CBC, iv)
return aes.decrypt(message)
```

The next step is to determine the key used to encrypt our message. Luckily we have the last block intact `72481dab9dd83141706925d92bdd39e4`.
During the encryption the previous block was used to encrypt this one, as the encryption is in CBC mode, the previous block is `c7**********a32c412a3e7474e584cd`.
As the length of the encrypted string doesn't change, we now that the last 10 characters are padding, and are 0xA. They are the only characters we need to be able to guess the key

I then tried all combinations of printable characters to find the correct key

```python
import string

def find_key():
keytmp = 'T0EyZaLRzQmNe2{}{}'
for c1 in string.printable:
for c2 in string.printable:
tmp = decrypt(binascii.unhexlify('72481dab9dd83141706925d92bdd39e4'), keytmp.format(c1, c2).encode('utf8'), binascii.unhexlify('0' * 12 + 'a32c412a3e7474e584cd'))
if int(tmp[-2]) < 0x10 and tmp[-1] == tmp[-2] and tmp[-2] == tmp[-3]:
return keytmp.format(c1, c2).encode('utf8')

print(find_key().decode('utf8'))
```

which output `T0EyZaLRzQmNe2pd`. Now that we now the key, we can have the encrypted message:

```python
b'AES CBC Mode is commonly used in data encryption. What do you know about it?\xfc\x89\xb4\xd5\xe2\x0b\xd2\xc6U\xae'
```

Using an arbitrary IV, we can encrypt the message, then use it to get the original encrypted message, and finally the flag

```python
IV = b'yellow_submarine'

arbitrary = binascii.hexlify(encrypt(pad(message), key, IV))
encrypted = 'a8**************************b1a923**************************011147**************************6e094e**************************cdb1c7**********a32c412a3e7474e584cd72481dab9dd83141706925d92bdd39e4'.replace('*', '0')
encrypted = [encrypted[i:i+32] for i in range(0, len(encrypted), 32)]
arbitrary = [arbitrary[i:i+32] for i in range(0, len(arbitrary), 32)]

def guess_block(flag_block, correct_block, correct_iv):
c1 = decrypt(binascii.unhexlify(flag_block), key, binascii.unhexlify(b'0' * 32))
c2 = decrypt(binascii.unhexlify(correct_block), key, binascii.unhexlify(correct_iv))
result = b''
for i in range(16):
result += bytes([c1[i] ^ c2[i]])
return binascii.hexlify(result)

for i in range(1, len(arbitrary) + 1):
if i == len(arbitrary):
e2 = binascii.hexlify(IV)
else:
e2 = arbitrary[-i - 1]
tmp = guess_block(encrypted[-i], arbitrary[-i], e2)
if i == len(arbitrary):
flag = binascii.unhexlify(tmp)
else:
encrypted[-i - 1] = tmp

print(flag.decode('utf8'))
```

```
9j_for_aes_cbc!!
```

Original writeup (https://caillou.eu/2020/gactf/).