Rating: 5.0

## Solution

### Quick Explanation

We exploit the pseudo random number generator used, which is the __Mersenne Twister__. We are then able to predict the next key used and get the flag.

### Full Solution

I have omitted the parts of `server.py` that are not really necessary.

```python
import random

class ThreadedServer(object):
def getKey(self, r):
return str(r.getrandbits(32)).rjust(16, '0')

def listenToClient(self, client, address):
client_flag = self.flag
r = random.Random()
key = self.getKey(r)
client_flag = self.encrypt(key, client_flag)
while True:
try:
client.send('Please insert the decryption key:\n')
key_guess = client.recv(16)
if key_guess == key:
client.send('Correct! Your flag is: ' + self.decrypt(key, client_flag) + '\n')
else:
client.send('Wrong! The key was: ' + key + '\n')
client_flag = self.decrypt(key, client_flag)
key = self.getKey(r)
client_flag = self.encrypt(key, client_flag)
```

We get two insights:

1. A single instance of `random.Random()` is used per connection
2. Bits generated are eventually leaked to us

The [documentation](https://docs.python.org/2/library/random.html) of python's `random` module states:

> Python uses the Mersenne Twister as the core generator... However, being completely deterministic, it is not suitable for all purposes, and is completely unsuitable for cryptographic purposes.

We use eboda's [MTRecover](https://github.com/eboda/mersenne-twister-recover/blob/master/MTRecover.py) to do this, and we get the flag.

```
Correct! Your flag is: noxCTF{41w4ys_us3_cryp70_s3cur3d_PRNGs}
```

__For implementation see the link__

Original writeup (https://github.com/pberba/ctf-solutions/tree/master/20180907_nox/plot_twist).