Game of Chance is a misc challenge that was part of the 2022 Jade CTF. To get the flag, we had to find a way to win the game of chance.

File

#!/usr/bin/env python3

import random
from secret import FLAG
import pyfiglet


result = pyfiglet.figlet_format("Game Of Chance")
print(result)
print()

name=input("What is your name: ")
try:
    seed=int(input("How old are you: "))
except:
    print("Bruh whot?")
    exit()

print()
print(f"Welcome! {name}")
print("Lets play a game!")
print()
score=0
random.seed(seed)

tries=0
while(tries<32):
    x=random.randint(0,255)
    print(f"Current score: {score}")
    if(x%2==0):
        print("""Options:
        1) Increment your score
        2) Exit
        > """,end="")
        try:
            option=int(input())
        except:
            print("Umm?!")
            exit()
        if(option==1):
            score+=1
        elif(option==2):
            print("Thanks for playing!")
            exit()
        else:
            print("Huh?!")
            exit()
    else:
        print("""Options:
        1) Decrement your score
        2) Exit
        >""",end="")
        try:
            option=int(input())
        except:
            print("Umm?!")
            exit()
        if(option==1):
            score-=1
        elif(option==2):
            print("Thanks for playing!")
            exit()
        else:
            print("Huh?!")
            exit()
    if(score>=32):
        print()
        print("Congratulations! You lucky AF boi")
        print(FLAG)
        exit()
    tries+=1
    
print()
print("Seems like you didn't make it")
print("Better luck next time")

Vulnerability

The name variable is only used in the welcome message, but the seed variable initializes the random number generator! We can use this to our advantage.

Solution

The game is pretty simple, we can increment or decrement our score depending on the random number generated. If we get a number that is even, we can increment our score, and if we get a number that is odd, we have to decrement our score. To win the game and get the flag, we have to increment our score 32 times with only 32 tries!

The same seed, we will get us the same random numbers. Finding a seed (age input) that will give us 32 even numbers in a row is the only way to win the game. We can use a brute force approach to find the seed, but it will take a lot of time. We can use multiprocessing to speed up the process.

#!/usr/bin/env python3
import sys
import random
from multiprocessing import cpu_count
from multiprocessing import Pool
from multiprocessing.dummy import Pool as ThreadPool

def task(r):
    r1 = r * search_range
    r2 = r1 + search_range + 1000
    if r2 > maxSeed:
        r2 = maxSeed
    print(f"Process {r+1} started: range {r1} to {r2}")
    for i in range(r1, r2):
        good_scores = []
        random.seed(i)
        for _ in range(32):
            score = random.randint(0,255)
            if score % 2 == 0:
                good_scores.append(score)
                if len(good_scores) == 32:
                    return i
            else:
                break
        i += 1


numOfCpus = cpu_count()
print("Number of CPUs:", numOfCpus)

maxSeed = sys.maxsize
print("Max seed:", maxSeed)
search_range = maxSeed // numOfCpus
print("Search range:", search_range)

with Pool(processes=numOfCpus) as pool:
    results = pool.imap_unordered(task, range(numOfCpus))
    pool.close()

    for r in results:
        if r:
            pool.terminate()
            print(r)
            break
    pool.join()

Output:

$ time ./solve.py          
Number of CPUs: 32
Max seed: 9223372036854775807
Search range: 288230376151711743
Process 1 started: range 0 to 288230376151712743
Process 2 started: range 288230376151711743 to 576460752303424486
Process 3 started: range 576460752303423486 to 864691128455136229
Process 4 started: range 864691128455135229 to 1152921504606847972
Process 5 started: range 1152921504606846972 to 1441151880758559715
Process 6 started: range 1441151880758558715 to 1729382256910271458
Process 7 started: range 1729382256910270458 to 2017612633061983201
Process 8 started: range 2017612633061982201 to 2305843009213694944
Process 9 started: range 2305843009213693944 to 2594073385365406687
Process 10 started: range 2594073385365405687 to 2882303761517118430
Process 11 started: range 2882303761517117430 to 3170534137668830173
Process 12 started: range 3170534137668829173 to 3458764513820541916
Process 13 started: range 3458764513820540916 to 3746994889972253659
Process 14 started: range 3746994889972252659 to 4035225266123965402
Process 15 started: range 4035225266123964402 to 4323455642275677145
Process 16 started: range 4323455642275676145 to 4611686018427388888
Process 17 started: range 4611686018427387888 to 4899916394579100631
Process 18 started: range 4899916394579099631 to 5188146770730812374
Process 19 started: range 5188146770730811374 to 5476377146882524117
Process 20 started: range 5476377146882523117 to 5764607523034235860
Process 21 started: range 5764607523034234860 to 6052837899185947603
Process 22 started: range 6052837899185946603 to 6341068275337659346
Process 23 started: range 6341068275337658346 to 6629298651489371089
Process 24 started: range 6629298651489370089 to 6917529027641082832
Process 25 started: range 6917529027641081832 to 7205759403792794575
Process 26 started: range 7205759403792793575 to 7493989779944506318
Process 27 started: range 7493989779944505318 to 7782220156096218061
Process 28 started: range 7782220156096217061 to 8070450532247929804
Process 29 started: range 8070450532247928804 to 8358680908399641547
Process 30 started: range 8358680908399640547 to 8646911284551353290
Process 31 started: range 8646911284551352290 to 8935141660703065033
Process 32 started: range 8935141660703064033 to 9223372036854775807
5188146770740757344

real	146,63s
user	4668,24s
sys	0,50s
cpu	3184%

Execution

Use a name of your choice but 5188146770740757344 as age/seed:

$ nc 34.76.206.46 10011                 
  ____                         ___   __    ____ _                          
 / ___| __ _ _ __ ___   ___   / _ \ / _|  / ___| |__   __ _ _ __   ___ ___ 
| |  _ / _` | '_ ` _ \ / _ \ | | | | |_  | |   | '_ \ / _` | '_ \ / __/ _ \
| |_| | (_| | | | | | |  __/ | |_| |  _| | |___| | | | (_| | | | | (_|  __/
 \____|\__,_|_| |_| |_|\___|  \___/|_|    \____|_| |_|\__,_|_| |_|\___\___|
                                                                           


What is your name: p2o
How old are you: 5188146770740757344

Welcome! p2o
Lets play a game!

Current score: 0
Options:
        1) Increment your score
        2) Exit
        > 1
Current score: 1
...
Current score: 30
Options:
        1) Increment your score
        2) Exit
        > 1
Current score: 31
Options:
        1) Increment your score
        2) Exit
        > 1

Congratulations! You lucky AF boi
jadeCTF{y0u_lucky_or_whot?!}

Flag

The flag is “jadeCTF{y0u_lucky_or_whot?!}”.