> For the complete documentation index, see [llms.txt](https://the-winrars.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://the-winrars.gitbook.io/writeups/2020-writeups/rgbctf/crypto/n-aes.md).

# N-AES

So, at first this seems literally impossible.

The rand\_block function takes a random 1 byte seed(initialising it to the output of `os.urandom(1)` if the argument isnt given) and then generates a 16-byte random block from this.

The encryption is simple - given a stream of seed bytes and a plaintext, iterate through the seed bytes.

On each byte, set the current ciphertext variable to the current ciphertext variable encrypted with the key generated by the random block that is create using `rand_block(cur_byte_of_seed)`

Finally, the challenge is generated like so. A random base64 string is generated using urandom, then encrypted in the algorithm. We get the base64 of the encryption.

```python
def gen_chall(text):
    text = pad(text, BLOCK_SIZE)
    for i in range(128):
        text = AES.new(rand_block(), AES.MODE_ECB).encrypt(text) # VULN

    return b64encode(text)
```

So, what's so fishy about this?

Notice no argument is passed to rand\_block, it simply gets a rand block and encrypts 128 times.

The argument is supposed to be `os.urandom(1)` by default, right? The problem is, everytime you call the function with no argument, the os.urandom(1) isnt regenerated. Instead, the value is first generated when the function is defined and then set to that again and again and again.

Long story short - chall is generated with the same key 128 times. Since it's os.urandom(1), we'll only have to bruteforce 256 possible keys. That can be done easily, and we can check if we've decrypted correctly by checking if the padding matches.

From there, we can simply enter the decrypted ciphertext.

```python
import os
os.environ['TERM'] = 'linux'
os.environ['TERMINFO'] = '/etc/terminfo'
from pwn import *
from base64 import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
from os import urandom
from random import seed,randint
BLOCK_SIZE = 16
def rand_block(key_seed=urandom(1)):
    seed(key_seed)
    return bytes([randint(0, 255) for _ in range(BLOCK_SIZE)])
def gen_chall(text):
    text = pad(text, BLOCK_SIZE)
    for i in range(128):
        text = AES.new(rand_block(), AES.MODE_ECB).encrypt(text)
    return b64encode(text)
p = remote('167.172.123.213', 34567)
enc = p.recvline()[:-1]
#print(enc)
for byte in range(256):
    text = base64.b64decode(enc)
    for i in range(128):
        text = AES.new(rand_block(bytes([byte])), AES.MODE_ECB).decrypt(text)
    try:
        text = unpad(text,16)
        print(base64.b64encode(text))
    except:
        pass
p.interactive()
```

^ script prints out the needed base64, you'll have to manually enter it into the prompt to get the flag from there

## Flag: rgbCTF{i\_d0nt\_7hink\_7his\_d03s\_wh47\_y0u\_7hink\_i7\_d03s}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://the-winrars.gitbook.io/writeups/2020-writeups/rgbctf/crypto/n-aes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
