---
# System prepended metadata

title: Cool Math Games (YBN CTF 2024)
tags: [$RANDOM variable, RANDOM ctf challenge, random module python, RANDOM ctf, prng exploit ctf, ctf, random, RANDOM bash exploit, crypto, misc, ybn, random python exploit, RANDOM bash ctf, RANDOM variable ctf challenge, ybnctf2024, RANDOM variable exploit, prng exploit, RANDOM variable, writeups, RANDOM variable ctf, "random bash\_", ybnctf, RANDOM bash seed, $RANDOM, ybn ctf 2024, ybn ctf writeups, ybn ctf, ctf writeups, "RANDOM bash\_"]

---

# 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:
![image](https://hackmd.io/_uploads/SJmks9j7Jg.png)


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