Skip to content

Latest commit

 

History

History
275 lines (201 loc) · 8 KB

File metadata and controls

275 lines (201 loc) · 8 KB

seed-sPRiNG

Challenge information

Points: 350
Tags: picoCTF 2019, Binary Exploitation
Author: JOHN HAMMOND

Description:
The most revolutionary game is finally available: seed sPRiNG is open right now! 
seed_spring. 

Connect to it with nc jupiter.challenges.picoctf.org 8311.

Hints:
1. How is that program deciding what the height is?
2. You and the program should sync up!

Challenge link: https://play.picoctf.org/practice/challenge/50

Solution

The CAPITAL letters in the challenge name reveals that a PRNG (PseudoRandom Number Generator) will be involved in the challenge.

Analyse the file

Let's start with some basic analysis of the given file

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2019/Binary_Exploitation/Seed-sPRiNG]
└─$ file seed_spring                                                   
seed_spring: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=7df253108e1bd837fb708dfaab20362525740ccd, not stripped

And why not run the game locally to see what happens?

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2019/Binary_Exploitation/Seed-sPRiNG]
└─$ ./seed_spring

                                                                             
                          #                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!

It seems that you need to do 30 correct guesses to win the game and get the flag.

Decompile and study the code

Next, we decompile the file in Ghidra and study the code.
Import the file in Ghidra and analyze it with the default settings.
The main function of the program looks like this

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");
      fflush(stdout);
      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_00010caa,&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);
}

We see that if we have done 0x1e (that is decimal 30) correct guesses, the flag is shown

<---snip--->
    if (0x1e < local_14) {
      puts("Congratulation! You\'ve won! Here is your flag:\n");
      fflush(stdout);
      get_flag();
      fflush(stdout);
      return 0;
    }
<---snip--->

The seed is set up with the current time

<---snip--->
  local_18 = time((time_t *)0x0);
  srand(local_18);
<---snip--->

That is not so random and we can easily setup a program that predicts the heights.

Create a predicting program

Let's write a small program that predicts and outputs the heights

#include <stdio.h> 
#include <time.h>
#include <stdlib.h> 
  
int main () 
{ 
    int i;
      
    srand(time(0)); 
    
    for (i = 0; i < 30; i++)
    {
        printf("%d\n", rand() & 0xf); 
    }
      
    return 0; 
} 

Now we compile the program called predictor

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2019/Binary_Exploitation/Seed-sPRiNG]
└─$ gcc -o predictor solve.c                

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2019/Binary_Exploitation/Seed-sPRiNG]
└─$ file predictor  
predictor: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=7c12f0e40a930cb1c931a420a237b1c10ed88ffc, for GNU/Linux 3.2.0, not stripped

Get the flag

Finally, we run the script as send the output to the game

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2019/Binary_Exploitation/Seed-sPRiNG]
└─$ chmod +x predictor  

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2019/Binary_Exploitation/Seed-sPRiNG]
└─$ ./predictor | nc jupiter.challenges.picoctf.org 8311 


                                                                             
                          #                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: Congratulation! You've won! Here is your flag:

picoCTF{<REDACTED>}

And there we have the flag.

For additional information, please see the references below.

References