Do you want to use dark theme?

The Hare And The Tortoise 

Misc, 350 points.

Challenge

Do you know Jean de La Fontaine? A friend of mine created a program mimicking the hare and the tortoise. He told me that smart tortoises always wins. I want you to be that tortoise. Connect with ssh [email protected]. Password : tortoise

Source Codes

main.c semaphores.h

Walkthrough

After connecting to the server with SSH, we observe that there is a compiled binary and a flag.txt, plus the source codes of the target binary (linked above). The target binary is a setuid binary. This means we can only read the flag by running the binary.

[email protected]_hare_and_the_tortoise$ ls -l

-r-------- 1 hare hare   77 May 11 09:04 flag.txt
-r--r--r-- 1 root root 2360 May 11 09:04 main.c
-r--r--r-- 1 root root  687 May 11 09:04 semaphores.h
-r-sr-xr-x 1 hare hare 2754 May 11 09:04 the_hare_and_the_tortoise

when we run the program, we get 

[email protected]_hare_and_the_tortoise$ ./the_hare_and_the_tortoise flag.txt
The tortoise, progressing slowly... : "s"
The hare says : "Do you ever get anywhere?"
The tortoise, progressing slowly... : "h"
The tortoise, progressing slowly... : "k"
The tortoise, progressing slowly... : "C"
The tortoise, progressing slowly... : "T"
The tortoise, progressing slowly... : "F"
The hare says : "Hurry up tortoise !"
The tortoise, progressing slowly... : "{"
The tortoise, progressing slowly... : "r"
The tortoise, progressing slowly... : "4"
The tortoise, progressing slowly... : "c"
Killed

Inspecting the source code, we find that the hare process, after setting all the semaphores, sets an alarm to be 5 seconds later. When it receives the SIGALRM, it kills the tortoise process. Intuitively, we want to bypass the timer by trapping the signal. However, this doesn't work because the program overwrites the alarm handler. Due to the nature of a SUID program, we cannot replace libc with LD_PRELOAD or hook it up with gdb. So there is only one way left to intercept the signal: kill the hare process with SIGKILL. 

It might seems as if we have to write a program to time everything carefully so that we send SIGKILL immediately after the "Hurry up tortoise" shows up. However, since we have 5 seconds to do it, we can actually start a different ssh session, run ps aux | grep the_hare_and_the_tortoise, and send the hare process a SIGKILL manually. The PID of the hare process is always larger because it is the child process. This sounds like it requires some very quick actions, but with the help of bash's history completion, I got it on the third try. 

The tortoise, progressing slowly... : "s"
The hare says : "Do you ever get anywhere?"
The tortoise, progressing slowly... : "h"
The tortoise, progressing slowly... : "k"
The tortoise, progressing slowly... : "C"
The tortoise, progressing slowly... : "T"
The tortoise, progressing slowly... : "F"
The hare says : "Hurry up tortoise !"
The tortoise, progressing slowly... : "{"
The tortoise, progressing slowly... : "r"
The tortoise, progressing slowly... : "4"
The tortoise, progressing slowly... : "c"
The tortoise, progressing slowly... : "3"
The tortoise, progressing slowly... : "5"
The tortoise, progressing slowly... : "_"
The tortoise, progressing slowly... : "4"
The tortoise, progressing slowly... : "r"
The tortoise, progressing slowly... : "3"
The tortoise, progressing slowly... : "_"
The tortoise, progressing slowly... : "3"
The tortoise, progressing slowly... : "a"
The tortoise, progressing slowly... : "s"
The tortoise, progressing slowly... : "i"
The tortoise, progressing slowly... : "3"
The tortoise, progressing slowly... : "r"
The tortoise, progressing slowly... : "_"
The tortoise, progressing slowly... : "w"
The tortoise, progressing slowly... : "h"
The tortoise, progressing slowly... : "3"
The tortoise, progressing slowly... : "n"
The tortoise, progressing slowly... : "_"
The tortoise, progressing slowly... : "y"
The tortoise, progressing slowly... : "0"
The tortoise, progressing slowly... : "u"
The tortoise, progressing slowly... : "_"
The tortoise, progressing slowly... : "4"
The tortoise, progressing slowly... : "r"
The tortoise, progressing slowly... : "3"
The tortoise, progressing slowly... : "_"
The tortoise, progressing slowly... : "a"
The tortoise, progressing slowly... : "l"
The tortoise, progressing slowly... : "0"
The tortoise, progressing slowly... : "n"
The tortoise, progressing slowly... : "e"
The tortoise, progressing slowly... : "_"
The tortoise, progressing slowly... : "6"
The tortoise, progressing slowly... : "a"
The tortoise, progressing slowly... : "2"
The tortoise, progressing slowly... : "6"
The tortoise, progressing slowly... : "a"
The tortoise, progressing slowly... : "2"
The tortoise, progressing slowly... : "6"
The tortoise, progressing slowly... : "c"
The tortoise, progressing slowly... : "5"
The tortoise, progressing slowly... : "7"
The tortoise, progressing slowly... : "f"
The tortoise, progressing slowly... : "0"
The tortoise, progressing slowly... : "0"
The tortoise, progressing slowly... : "1"
The tortoise, progressing slowly... : "2"
The tortoise, progressing slowly... : "e"
The tortoise, progressing slowly... : "d"
The tortoise, progressing slowly... : "6"
The tortoise, progressing slowly... : "6"
The tortoise, progressing slowly... : "a"
The tortoise, progressing slowly... : "b"
The tortoise, progressing slowly... : "8"
The tortoise, progressing slowly... : "c"
The tortoise, progressing slowly... : "2"
The tortoise, progressing slowly... : "0"
The tortoise, progressing slowly... : "e"
The tortoise, progressing slowly... : "5"
The tortoise, progressing slowly... : "3"
The tortoise, progressing slowly... : "8"
The tortoise, progressing slowly... : "a"
The tortoise, progressing slowly... : "0"
The tortoise, progressing slowly... : "4"
The tortoise, progressing slowly... : "}"
The tortoise, progressing slowly... : "}"
Slow but steady wins the race!

After parsing the output, we get the flag.

shkCTF{r4c35_4r3_3asi3r_wh3n_y0u_4r3_al0ne_6a26a26c57f0012ed66ab8c20e538a04}