Rating: 5.0

It is an AES cipher with a 1 byte key randomization and we have a key for a message. There was a hint: xuts refers to 400000th transmission. But it is not necessary, the message can be easily bruteforced.

It looks simple: shift the previous key and try all chars for the last (randomized) byte. To test if the new key is valid, I've checked if the decrypted message contains printable characters (note that there were two false possitives).

For a few cases I wasn't able to judge which key is valid, then I skip this message and brute the next.
The last message (flag) contains some non 7-bit ASCII chars - I've print all posibilities and find it "manually".

EDIT: I've just seen that there were sometimes non ascii chars like in the flag, so the test could be better and then no skipping needed...

Full python code:
```
import string
printset = set(string.printable)

from Crypto import Random
from Crypto.Cipher import AES

def shift(k, n):
return k[-n:] + k[:-n]

class AESCipher:

def __init__( self, key ):
self.key = key

def decrypt(self, enc):
cipher = AES.new(self.key, AES.MODE_ECB)
return cipher.decrypt(enc)


def decode(text, key, first = False):
for b in range(256):
k = shift(key, 1)
k = k[:-1] + chr(b)
cipher = AESCipher(k)
dc = cipher.decrypt(text)
if first:
print dc
# is printable? + some false possitive
if set(dc).issubset(printset) and dc != 'R(?p*H(W1t2j7J;A' and not dc.startswith('9vkB'):
return k, dc

return None, None

key = '52433d7c48262e5c497e435d58442d36'.decode('hex')
tut = 'defdf8e526b7945e19789b9fa533ef7d4c7ee8d2956a99791ea26e9ba64db394' # found by brute forcing all messages

lines = open('Ciphertext.txt').readlines()

for i in range(len(lines)):
if tut == lines[i][:-1]:
j = i - 1
while j >= 0:
text = lines[j][:-1].decode('hex')
k, dc = decode(text, key, j == 0)
if j == 0:
break
# key not found? -> brute next
if k == None:
text = lines[j-1][:-1].decode('hex')
for b in range(256):
k = shift(key, 1)
k = k[:-1] + chr(b)
k, dc = decode(text, k)
if k != None:
j = j - 1
break
if k == None:
raise RuntimeError('not found')

key = k
print j+1, dc, key.encode('hex')
j = j - 1

break
```

The flag:
```
evlz{74!5_5¥573^^_83773Я_83_53('-'Я3}ctf
```