> For the complete documentation index, see [llms.txt](https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/cybersecurityrumble-ctf/crymeplx.md).

# Crymeplx

CRY | 100 pts - 170 solves

> 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))
```

This's how AES CTR works:

<figure><img src="https://3525522742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5W0dBJgjI9bjS7hNDvKF%2Fuploads%2Fgit-blob-76601fb87fdd24b267cc1b20afe8639140a13a7e%2FCtr_encryption.png?alt=media" alt=""><figcaption></figcaption></figure>

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=}')
```
