# 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