# Cool Math Games
Pseudo-Random Number Generator (PRNG) Exploitation CTF Challenge (YBN CTF 2024)
### Challenge Details
> Title: Cool Math Games \
> Description: The intern got bored, and created a guessing game for the rest of the team to solve. So far, no one has solved all 160 challenges. \
> Attachments: `https://ctf.ybn.sg/files/4126628025029abaee365d2a50693f10/server.py`, `https://ctf.ybn.sg/files/9f2356eacac75fa3edd10e76f03dda15/startup.sh`\
> Instance: `nc tcp.ybn.sg 28480`
### Writeup
In `startup.sh`, we have:
```sh
#!/bin/bash
sudo apt install socat -y
sudo apt install python3 -y
seed=$RANDOM
export seed # Credits to Jabriel for the idea
export FLAG="YBN24{this_is_a_fake_flag}"
pip install -r requirements.txt
socat -dd TCP-LISTEN:1337,fork,reuseaddr EXEC:"python server.py"
```
And in `server.py`:
```py
from string import ascii_lowercase, ascii_uppercase, digits
import os
import random
RAND_SEED = os.getenv("seed")
random.seed(int(RAND_SEED))
def generate_random_string():
return "".join([random.choice(ascii_lowercase + ascii_uppercase + digits) for _ in range(32)])
rounds = 160
print(f"Welcome to my game! Your user ID is \"{generate_random_string()}\"")
print("Complete all the rounds of this game, and you win the flag! Good luck!")
for i in range(rounds):
print('*'*8, f"Round {i+1}", '*'*8)
answer_string = generate_random_string()
guess = str(input("Enter the string: "))
if guess != answer_string:
print("Sorry, but your response was wrong. Out!")
exit()
print()
print(f"Congratulations! Here is your flag: {os.getenv('FLAG')}")
```
What this does is that it gets a seed from Bash's `$RANDOM`, sets it as the seed value.
The key thing here is that `$RANDOM` returns a value from 0 to 32767 (as per https://tldp.org/LDP/abs/html/randomvar.html). \
Therefore, we can easily loop through all possible values and check if the result of `generate_random_string()` matches with the user ID.
If they have, we can say that we have found the seed, and can thus predict the next 160 "random" strings.
We can also use `pwntools` which is a library that (amongst other things) allows you to connect to an ip and port like you would with netcat, but programmatically. \
I came up with this solve script.
```py
from pwn import *
from string import ascii_lowercase, ascii_uppercase, digits
import random
def generate_random_string():
return "".join([random.choice(ascii_lowercase + ascii_uppercase + digits) for _ in range(32)])
def brute(user_id):
for i in range(0, 32767):
random.seed(int(i))
if user_id == generate_random_string():
print(f"Found seed: {i}")
return i
print("Could not find seed. Exiting...")
exit()
conn = remote("tcp.ybn.sg", 28480)
user_id = conn.recvline().lstrip(b'Welcome to my game! Your user ID is "').rstrip(b'"\n')
user_id = user_id.decode()
print(f"user_id: {user_id}")
brute(user_id)
while True:
try:
conn.sendlineafter(b": ", generate_random_string().encode())
except EOFError as e:
print(e)
break
print(conn.recvrepeat(timeout=4))
```
`brute(user_id)` takes in a user_id, enumerates through all values from 0 to 32767, seeds `random` with it, and checks if seed is correct, implementing the logic discussed before.
Thus, we have:

Flag:
:::spoiler Flag
YBN24{wH0_kN0w5_8a5H_R4nD0m_w4sn7_s0_rAnD0m_4ft3r_4ll}
:::
\
\
\
Main Writeups Page: https://hackmd.io/@ctf-lol/ybnctf2024