Tags: crypto
Rating: 5.0
---
Category: CRY | 100 pts - 170 solves
---
# CryMePlx
> Description: Awesome service. Now I don't need to encrypt anything myself! \
> Connect via: `nc chall.rumble.host 2734`
We had a service to netcat with: `nc chall.rumble.host 2734` and the source code to download & unzip. \
Looking at the source code, the program ask for input and then encrypt the flag and the input with AES-CTR-128 mode.
```python
from Crypto.Cipher import AES
from secret import flag
import os
kwargs = {"nonce": os.urandom(8)}
key = os.urandom(16)
def encrypt(msg):
aes = AES.new(key, AES.MODE_CTR, **kwargs)
return aes.encrypt(msg).hex()
print(encrypt(flag))
q = input("Encrypt this string:").encode()
print(encrypt(q))
```
The vulnerability here is that the Nonce is reused for all the encryptions, and as the name says, it should be used only (n)once. \
So, the encryption of flag is done with:
`Ciphertext1 = flag ⊕ AES(Key, Nonce)`
and the encryption of user input:
`Ciphertext2 = input ⊕ AES(Key, Nonce)`
Note that we used the same Nonce and Key pair, so we can say that:
`AES(Key, Nonce) = flag ⊕ Ciphertext1`\
`AES(Key, Nonce) = input ⊕ Ciphertext2`
Therefore:
`flag ⊕ Ciphertext1 = input ⊕ Ciphertext2`\
`flag = input ⊕ Ciphertext2 ⊕ Ciphertext1`\
\
Let's write our exploit:
```python
from pwn import *
import binascii
context.log_level = 'debug'
p = remote('chall.rumble.host', 2734)
enc_flag = binascii.unhexlify(p.recvline().strip())
input = 'A' * len(enc_flag)
p.sendlineafter('Encrypt this string:', input)
enc_input = binascii.unhexlify(p.recvline().strip())
flag = xor(input, enc_input, enc_flag)
log.success(f'{flag=}')
```