Back to Posts

Pentest Cyprus 2016: Giratina Write-up

Posted in Pentest Cyprus 2016 Written by Marios Nicolaides (styx00)

Hey girls and guys! Following a request for write-ups from Circles (excellent job organizing the CTF by the way), we’re going to analyze how we captured Giratina (in the form of a flag). Without further ado, let’s begin!

The description of the challenge from the player board is the following:

“Giratina exploits some times while playing asciipoke :)”

The keyword “exploit”, as well as the fact that the challenge was in the “Exploit” category, gives us a strong indication that we need to exploit a Buffer Overflow vulnerability to get our flag.

Step 1: Identification

First things first! We need to find where the asciipoke (whatever that is) is hiding.

The first place to look is the pokestore and the PlayMon interface. Having a quick look at the pokestore, there is no sign of Giratina or asciipoke. It’s time to look in the PlayMon interface. By logging in the PlayMon interface using the credentials “user:user”, it appears that asciipoke is a 32-bit ELF file located at “/home/user/games/”.

Alt

Let’s run asciipoke and try to figure out what we need to do to get the flag and capture Giratina! The program asks for a Pokemon name and expects one of the following: blastoise, bulbasaur, charizard, pikachu and wartortle. When we type one of the aforementioned Pokemon names, the asciipoke program outputs the figure of the Pokemon in the form of ASCII art, hence the name “asciipoke”. By providing a long string (100 A’s), the program crashes due to a segmentation fault.

Alt

It’s time to investigate what caused the crash and what’s happening behind the scenes. Running asciipoke using GDB (GNU Debugger), we see that there is a buffer overflow vulnerability due to insufficient bounds checking. If you look closely below, you will see that the EBP and EIP registers are filled with 0x41414141 (AAAA) which indicates that our input has overwritten them.

Alt

By using the following command we can disassemble asciipoke to view the executable in assembly form.

objdump -D asciipoke -M intel

Scrolling down to the main method, we see that it makes a call to the read_input function which is probably the function responsible for handling our input. By investigating the read_input function we see that the it uses the scanf library function to read input from stdin (see 08048827) and that the input buffer starts 28 bytes before EBP (1c in hex is 28 in decimal). This means that the program reserves 28 bytes for the input buffer.

080487e3: lea eax, [ebp-0x1c]

For the hexadecimal-to-decimal conversion we used tconv, a custom wrapper script we developed for the CTF (we couldn’t find anything that wasn’t overkill for our purposes). For more info about tconv checkout https://github.com/runesec/tconv (we welcome forks and pull requests).

Alt

Now we know that 28 bytes are reserved for the input buffer which is just before the Base Pointer of the read_input function. This means that the next 4 bytes will be stored in the EBP and the next 4 bytes will override the return address (i.e., the address that the EIP register will jump to when it completes the function. So we can now control the flow of execution but we still haven’t figured out what we need to do to get the flag! Let’s fire up gdb to see the functions of asciipoke.

Alt

It appears that there is a function called pokemon_found which is not called during program execution. The name of the function is particularly suspicious, so let’s disassemble the asciipoke binary again (using objdump as we did earlier) and have a look at the pokemon_found function. We can see that it uses the fopen() library function which is used to open files. Considering that there is a file called asciipoke_flag in the same directory with asciipoke, it is reasonable to believe that asciipoke opens the asciipoke_flag file when the pokemon_found function is executed.

Alt

Maybe we should try to manipulate the program to call the pokemon_found function and see what happens!

Step 2: Plan attack

We need to craft a payload which will override the return address in an attempt to redirect the flow of execution and execute the pokemon_found function which is located at 0x080485fb.

Before crafting our payload, it is important to remember that our machine is little-endian which means that we need to reverse the order of the bytes of the pokemon_function address, i.e., \xfb\x85\x04\x08. This can be easily done using tconv as illustrated below.

Reverse the endianness using tconv

Now, we need to fill the input buffer which is 28 bytes long, plus the next 4 bytes which is the EBP, plus the next 4 bytes which is the return address we want to override. Our payload should look something similar to the following:

Alt

Step 3: Execute

Let’s pipe our payload directly into the asciipoke binary and see what happens.

Alt

Giratina captured!

Hope you found the above useful. If you have any questions, drop us a comment on Facebook or Twitter.

Read Next

Pentest Cyprus 2016: Charizard Write-up