seed-sPRiNG

Problem

The most revolutionary game is finally available: seed sPRiNG is open right now! seed_spring. Connect to it with nc 2019shell1.picoctf.com 12269.

Solution

  1. Lets try running the binary:

    ```

                         #                mmmmm  mmmmm    "    mm   m   mmm 

    mmm mmm mmm mmm# mmm # "# # "# mmm #"m # m" "

    " #" # #" # #" "# # " #mmm#" #mmmm" # # #m # # mm

    """m #"""" #"""" # # """m # # "m # # # # # # "mmm" "#mm" "#mm" "#m## "mmm" # # " mm#mm # ## "mmm"

Welcome! The game is easy: you jump on a sPRiNG.
How high will you fly?

LEVEL (1/30)

Guess the height: 5
WRONG! Sorry, better luck next time!
```
  1. Reverse the binary file using Ghidra (cheat sheet). main() function:

     /* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */
    
     undefined4 main(void)
    
     {
     uint local_20;
     uint local_1c;
     uint local_18;
     int local_14;
     undefined *local_10;
    
     local_10 = &stack0x00000004;
     puts("");
     puts("");
     puts("                                                                             ");
     puts("                          #                mmmmm  mmmmm    \"    mm   m   mmm ");
     puts("  mmm    mmm    mmm    mmm#          mmm   #   \"# #   \"# mmm    #\"m  # m\"   \"");
     puts(" #   \"  #\"  #  #\"  #  #\" \"#         #   \"  #mmm#\" #mmmm\"   #    # #m # #   mm");
     puts(
         "  \"\"\"m  #\"\"\"\"  #\"\"\"\"  #   #          \"\"\"m  #      #   \"m   #    #  # # #    #"
         );
     puts(" \"mmm\"  \"#mm\"  \"#mm\"  \"#m##         \"mmm\"  #      #    \" mm#mm  #   ##  \"mmm\"");
     puts("                                                                             ");
     puts("");
     puts("");
     puts("Welcome! The game is easy: you jump on a sPRiNG.");
     puts("How high will you fly?");
     puts("");
     fflush(stdout);
     local_18 = time((time_t *)0x0);
     srand(local_18);
     local_14 = 1;
     while( true ) {
         if (0x1e < local_14) {
         puts("Congratulation! You\'ve won! Here is your flag:\n");
         get_flag();
         fflush(stdout);
         return 0;
         }
         printf("LEVEL (%d/30)\n",local_14);
         puts("");
         local_1c = rand();
         local_1c = local_1c & 0xf;
         printf("Guess the height: ");
         fflush(stdout);
         __isoc99_scanf(&DAT_00010c9a,&local_20);
         fflush(stdin);
         if (local_1c != local_20) break;
         local_14 = local_14 + 1;
     }
     puts("WRONG! Sorry, better luck next time!");
     fflush(stdout);
                         /* WARNING: Subroutine does not return */
     exit(-1);
     }

    The capital letters in the name of this challenge (PRNG) make sense now. That is an abbreviation for pseudo random number generator (srand() in this case), which is what we can abuse to solve this challenge. We need to "guess" 30 "random" numbers in a row to call the get_flag() function and print the flag.

    This program generates a "random" number and then applies a bitwise AND operation between that value and 0xf, so we must do the same in our program.

  2. The program calls srand() and sets the seed to the current time. All the values returned by srand() throughout the program are based on this seed. If we enter the same seed we will receive the same values.

  3. Let's create a program that calls srand(time(0)). Running this program at the same time as seed_spring will produce the same set of "random" numbers. We can feed the output from our program directly into seed_spring.

  4. The solve program will print the first 30 pseudo random numbers with each one followed by a newline so the output can be easily piped into seed_spring. Let's compile solve.c with gcc -g solve.c -o solve.

  5. On the shell server (we need to have the exact same time so we cannot generate out numbers locally) make a solve.c file by copying the solve.c file in this folder, then run the following:

     gcc -g solve.c -o solve
     ./solve | nc localhost 12269

    Output and flag:

    ```

                         #                mmmmm  mmmmm    "    mm   m   mmm 

    mmm mmm mmm mmm# mmm # "# # "# mmm #"m # m" "

    " #" # #" # #" "# # " #mmm#" #mmmm" # # #m # # mm

    """m #"""" #"""" # # """m # # "m # # # # # # "mmm" "#mm" "#mm" "#m## "mmm" # # " mm#mm # ## "mmm"

Welcome! The game is easy: you jump on a sPRiNG.
How high will you fly?

LEVEL (1/30)

Guess the height: LEVEL (2/30)

Guess the height: LEVEL (3/30)

Guess the height: LEVEL (4/30)

Guess the height: LEVEL (5/30)

Guess the height: LEVEL (6/30)

Guess the height: LEVEL (7/30)

Guess the height: LEVEL (8/30)

Guess the height: LEVEL (9/30)

Guess the height: LEVEL (10/30)

Guess the height: LEVEL (11/30)

Guess the height: LEVEL (12/30)

Guess the height: LEVEL (13/30)

Guess the height: LEVEL (14/30)

Guess the height: LEVEL (15/30)

Guess the height: LEVEL (16/30)

Guess the height: LEVEL (17/30)

Guess the height: LEVEL (18/30)

Guess the height: LEVEL (19/30)

Guess the height: LEVEL (20/30)

Guess the height: LEVEL (21/30)

Guess the height: LEVEL (22/30)

Guess the height: LEVEL (23/30)

Guess the height: LEVEL (24/30)

Guess the height: LEVEL (25/30)

Guess the height: LEVEL (26/30)

Guess the height: LEVEL (27/30)

Guess the height: LEVEL (28/30)

Guess the height: LEVEL (29/30)

Guess the height: LEVEL (30/30)

Guess the height: picoCTF{pseudo_random_number_generator_not_so_random_66aacad47c332de30eb8d8170d96b772}Congratulation! You've won! Here is your flag:
```

Flag

picoCTF{pseudo_random_number_generator_not_so_random_66aacad47c332de30eb8d8170d96b772}

Last updated