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
The CAPITAL letters in the challenge name reveals that a PRNG (PseudoRandom Number Generator) will be involved in the challenge.
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.
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.
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
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.