An ransomware attack has taken place, encrypting millions of files on thousands of workstation in a large financial institution.

The defenders have managed to retrieve the script used to encrypt all of the files, however it appears it's AES encryption, which is considered unbreakable if correctly implemented.

Defenders also managed to discover a remote service which appears to be used for the attackers to allow file decryption, however we don't know how long this service will be available and in order to decrypt all of those millions of files a more feasible solution is required like retrieving the main decryption key

Retrieve the decryption key.

Encryption script: script_delivery.py

Decryption service: nc 10.XX.32.133 12345

The flag consists of two parts that you need to combine! Total length 32chars.

Connecting to decryption service, provides an option to choose one of two keys and decrypt ciphertext to plaintext.

```
$ nc 10.XX.32.133 12345
You have 2 keys to choose from:
=> 1
1) Decrypt content
2) Choose a different key
3) Exit
```

Looking at the source code, decryption is done using AES with CBC block cipher mode. There are multiple issues with implemented cryptography, - IV is used as key and IV reuse. That breaks the security of AES CBC, e.g., CWE-329, CWE-1204.

```
while True:
print("1) Decrypt content")
print("2) Choose a different key")
print("3) Exit")
choice = str(raw_input("=> "))
encrypt_message(key, key)
if choice == "1":
decrypt_message(key, key)
elif choice == "2":
key = new_key()
else:
exit()
```

```
def decrypt_message(key, IV):
print("Hex data for decryption")
ctxt = raw_input("=> ")
ctxt = ctxt.decode('hex')
if (len(ctxt) % 16) != 0:
print "Specify a proper length"
return
cipher = AES.new(key, AES.MODE_CBC, IV)
ptxt = cipher.decrypt(ctxt)
print ptxt.encode('hex')
```

Looking back at CBC mode decryption:

Mathematical formula for CBC mode decryption:

Looking at first two plaintexts, the first plaintext `P`

would be _{1}`decrypt(C`

or _{1}) xor C_{0}`decrypt(C`

.
Second plaintext _{1}) xor IV`P`

would be _{2}`decrypt(C`

.
_{2}) xor C_{1}

Providing the same ciphertext for `C`

and _{1}`C`

as _{2}`C`

, decrypted plaintexts would be:_{x}

`P`

_{1} = decrypt(C_{x}) xor IV

`P`

_{2} = decrypt(C_{x}) xor C_{x}

If `P`

and _{1}`P`

is xor-ed, _{2}`IV`

can be retrieved. Because xor-ing equal values results in 0 and xor-ing anything with 0 is the same value.

`P`

_{1} xor P_{2} = decrypt(C_{x}) xor IV xor decrypt(C_{x}) xor C_{x}

`P`

_{1} xor P_{2} = ~~decrypt(C~~ xor IV xor _{x})~~decrypt(C~~ xor C_{x})_{x}

`P`

_{1} xor P_{2} = IV xor C_{x}

This can be simplified if `C`

is chosen as _{x}`0`

.

`P`

_{1} xor P_{2} = IV

Therefore, by providing two blocks of (zero-ed) ciphertext, returned `P`

and _{1}`P`

xored with each other would be equal to _{1}`IV`

.

Retrieve `P`

and _{1}`P`

for first key.
_{1}

```
$ nc 10.XX.32.133 12345
You have 2 keys to choose from:
=> 1
1) Decrypt content
2) Choose a different key
3) Exit
=> 1
Hex data for decryption
=> 0000000000000000000000000000000000000000000000000000000000000000
b1b2666f04fb0304dd176f06b6874bca8183545c30ce6568bc705f3784b47fff
```

Calculate first key's `IV`

.

```
$ python3 -c 'print("".join([chr(a^b) for a,b in zip(bytes.fromhex("b1b2666f04fb0304dd176f06b6874bca"), bytes.fromhex("8183545c30ce6568bc705f3784b47fff"))]))'
012345flag012345
```

Retrieve `P`

and _{1}`P`

for second key.
_{1}

```
$ nc 10.XX.32.133 12345
You have 2 keys to choose from:
=> 2
1) Decrypt content
2) Choose a different key
3) Exit
=> 1
Hex data for decryption
=> 0000000000000000000000000000000000000000000000000000000000000000
51a0c3cc75e8c9a4609bfc5fdae120c16496f4f44cd8afc801fcc969edd919f1
```

Calculate second key's `IV`

.

```
$ python3 -c 'print("".join([chr(a^b) for a,b in zip(bytes.fromhex("51a0c3cc75e8c9a4609bfc5fdae120c1"), bytes.fromhex("6496f4f44cd8afc801fcc969edd919f1"))]))'
567890flag567890
```

As the `IV`

is same as key, therefore first key is `012345flag012345`

and second key is `567890flag567890`

.

The flag is 012345flag012345567890flag567890.