# h3 time ## Downloading the binary file [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → wget https://github.com/guyinatuxedo/nightmare/raw/master/modules/09-bad_seed/h3_time/time --2021-03-07 12:51:05-- https://github.com/guyinatuxedo/nightmare/raw/master/modules/09-bad_seed/h3_time/time Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt' Resolving github.com (github.com)... 140.82.121.3 Connecting to github.com (github.com)|140.82.121.3|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/09-bad_seed/h3_time/time [following] --2021-03-07 12:51:05-- https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/09-bad_seed/h3_time/time Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.108.133, 185.199.110.133, ... Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 8864 (8.7K) [application/octet-stream] Saving to: ‘time’ time 100%[================================================================>] 8.66K --.-KB/s in 0.006s 2021-03-07 12:51:06 (1.41 MB/s) - ‘time’ saved [8864/8864] [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → file time time: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=4972fe3e2914c74bc97f0623f0c4643c40300dab, not stripped [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → chmod +x time ` ![]() ## Solution First let's take a look at the binary with pwn checksec as well as running it: [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → pwn checksec time; ./time [*] '/home/nothing/binexp/3/time/time' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000) Welcome to the number guessing game! I'm thinking of a number. Can you guess it? Guess right and you get a flag! Enter your number: 1234 Your guess was 1234. Looking for 34981616. Sorry. Try again, wrong guess! [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → ./time Welcome to the number guessing game! I'm thinking of a number. Can you guess it? Guess right and you get a flag! Enter your number: 4321 Your guess was 4321. Looking for 994945792. Sorry. Try again, wrong guess! So here we see that we have a 64bit binary. When we run it, it prompts us to guess a number. Let's check what ghidra finds on that binary: undefined8 main(void) { time_t tVar1; long in_FS_OFFSET; uint local_18; uint local_14; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); tVar1 = time((time_t *)0x0); srand((uint)tVar1); local_14 = rand(); puts("Welcome to the number guessing game!"); puts("I\'m thinking of a number. Can you guess it?"); puts("Guess right and you get a flag!"); printf("Enter your number: "); fflush(stdout); __isoc99_scanf(&DAT;_00400bbc,&local;_18); printf("Your guess was %u.\n",(ulong)local_18); printf("Looking for %u.\n",(ulong)local_14); fflush(stdout); if (local_14 == local_18) { puts("You won. Guess was right! Here\'s your flag:"); giveFlag(); } else { puts("Sorry. Try again, wrong guess!"); } fflush(stdout); if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return 0; } Here we see something interesting, first of all the **rand** function which should give a random number, as well as the scanf call with the %u format string stored in local_18. Basically the main function creates a random number, then prompts us for some number to store into local_18, and then it checks if the 2 numbers are the same. If they are we enter the giveFlag function: void giveFlag(void) { FILE *__stream; long in_FS_OFFSET; char local_118 [264]; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); memset(local_118,0,0x100); __stream = fopen("/home/h3/flag.txt","r"); if (__stream == (FILE *)0x0) { puts("Flag file not found! Contact an H3 admin for assistance."); } else { fgets(local_118,0x100,__stream); fclose(__stream); puts(local_118); } if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return; } Here we see that this function reads and prints out the flag file from **/home/h3/flag.txt** What we need to figure out is what the output of the **rand** function will be. Thing is, the output of the ran dunction is not actually random. The output is based off a value called a 'seed' which it uses to determine what number sequence to generate. SO if we can get the same seed, we can get **rand** to generate the same sequence of numbers. Looking at the decompiled code, we see the following: tVar1 = time((time_t *)0x0); srand((uint)tVar1); Here we see tVar1 gets the current time as a seed, therefore we can write a C program that uses the current time as a seed, and output a digit and redirect the output to the target: [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → vim exploit.c #include<****stdio.h> #include <****time.h> #include <****stdlib.h> #include <****stdint.h> #include <****string.h> int main() { uint32_t rand_num; srand(time(0)); //seed with current time rand_num = rand(); uint32_t ans; printf("%d\n", rand_num); } [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → gcc exploit.c -o exploit [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → ./exploit 1779237112 [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → ./exploit 1476399991 [ 192.168.0.18/24 ] [ /dev/pts/25 ] [binexp/3/time] → ./exploit | ./time Welcome to the number guessing game! I'm thinking of a number. Can you guess it? Guess right and you get a flag! Enter your number: Your guess was 1333337650. Looking for 1333337650. You won. Guess was right! Here's your flag: ${g0tt3m_boyz} And that's it ! We managed to print the flag. ## Title text ` ![]() ## Title text ` ![]()