jebidiah-anthony
write-ups and what not
Dr. J’s Group Test Randomizer #1
PART 1 : CHALLENGE DESCRIPTION
Dr. J is back with another group test, and he patched his prng so we
can't predict the next number based on the previous one! Can still
you help Leaf predict the next output of the prng?
nc shell.2019.nactf.com 31258
PART 2 : GIVEN FILES
[>] class-randomizer-1.c
PART 3 : PROGRAM FLOW
- A seed is initialized:
uint64_t seed = 0; void init_seed() { uint64_t r1 = (uint64_t) randombytes_random(); uint64_t r2 = (uint64_t) randombytes_random(); seed = (r1 << 32) + r2; }
NOTE(S):
- The generated seed has a maximum value of
0xffffffff
.
- The generated seed has a maximum value of
- An actions menu is presented to the user:
printf("\nWelcome to Dr. J's Random Number Generator v2! A vulnerability involving " "predictability of outputs has been patched. \n" "[r] Print a new random number \n" "[g] Guess the next four random numbers and receive the flag! \n" "[q] Quit \n\n");
[r]
generates a new random number:uint64_t nextRand() { // Keep the 8 middle digits from 5 to 12 (inclusive) and square. seed = getDigits(seed, 5, 12); seed *= seed; return getDigits(seed, 13, 16); }
NOTE(S):
- The 5th to the 8th digits from the right of the seed is squared.
- The squared number is now the new seed.
- This time, the “random” number generated is no longer the new seed.
- It is now The 13th to the 16th digits (from the right) or the leading digits of the new seed.
-
[g]
lets the user guess the next four “random” numbers to get the flag. [q]
lets the user exit the program.
PART 4 : GETTING THE FLAG
- Write a script that approximates the initial middle value used to generate the first number:
from math import sqrt from sys import argv def approximateMiddleValue(num): # In order to generate the next "random" numbers, the seed curr = int(num) # used to generate the first number should be known. root = int(sqrt(curr)*100) # # The first number generated is the 13th-16th digits (from return root*(10**4), (root+100)*(10**4) # the right) or basically the leading digits of the middle # square value of the initial or current seed. def getNextRand(seed): # mid = str(seed)[-12:-4] # The initial or seed's middle value used to generate the m_s = int(mid)**2 # first number could be approximated by taking the square # root of the first number multiplied by a hundred to return m_s, str(m_s)[:-12] # increase its precision then rounding it down. All this # times 10^4 should be quite near the initial seed value. min_val,max_val = approximateMiddleValue(argv[1]) # # With the limited number of middle values to work with, for i in range(min_val, max_val): # bruteforcing the initial seed and generating new numbers seed = i**2 # should no longer be a problem. if str(seed)[:-12] == argv[1]: # seed,num = getNextRand(seed) # This code requires three succeeding numbers generated to if num == argv[2]: # make sure that the program returns accurate results. for x in range(5): seed,num = getNextRand(seed) if x==0 and num!=argv[3]: break elif x!=0: print(num) if x==5: break
- Run the PRNG and generate three (3) “random” numbers:
$ nc shell.2019.nactf.com 31258 Welcome to Dr. J's Random Number Generator v2! A vulnerability involving predictability of outputs has been patched. [r] Print a new random number [g] Guess the next four random numbers and receive the flag! [q] Quit $ > r 95 $ > r 5453 $ > r 2112 $ >
- Run the python script above to generate the next four numbers:
$ python3 class-randomizer-1.py 95 5453 2112 1498 5923 50 123
- Go back to the running PRNG and submit the next four numbers generated by te script:
$ > g Guess the next four random numbers for a flag! Dr. Strange sees fourteen million six hundred and five possibilies... and you only guess correctly in one. Good luck! Enter your first guess: $ > 1498 Yeah, yeah, one correct guess is easy. Enter your second guess: $ > 5923 Okay, you're lucky... You won't be able to guess right a third time. Enter your third guess: $ > 50 Wow. I'll admit I'm impressed. This is the final test. Enter your fourth guess: $ > 123 Oh no... we're in the endgame now... Here's your flag: nactf{th3_b35t_pr3d1ct0r_0f_fu7ur3_b3h4v10r_15_p4st_b3h4v10r}