Initial research and description

Baby first was one of the easiest pwn challenges at Insomi’hack CTF 2017 and has been solved by many teams.
There was an address ( babyfirst.insomni.hack:2324) and a binary provided in the description.

First, let’s check the binary with a file command:

This is a 64-bit Linux binary, so let’s check which security features are being used with checksec:

After running the application locally, we can see that it cannot read the flag file:
Can't read the flag file!

Unfortunately, the task’s host is offline now (it has been hosted internally, during the CTF only), so I will host it locally for the purpose of this writeup.

The analysis

Let’s open the application with radare2, analyze it with aaa and display all functions with afl:

Ok, radare2 correctly recognized the main function, so we can seek to it with s main and disassemble it with pdf (the output has been cleaned up for better readability):

As we can see, the main function turns off buffering for stdout and stderr, opens a flag.txt file for reading, if it succeeded, calls function fcn.00400930 with the parameters 0x602080, 0x20 and FILE pointer, closes the file, and calls fcn.00400b60.

We’ll now create the flag.txt file with Fake__Flag__For__The__Writeup as content (unfortunately, we have lost the real flag) and host it locally with socat:

Now, connect to it with netcat:

It asks for two strings and then prints this fancy ASCII art. Let’s analyze it more deeply.

A brief analysis of call to fcn.00400930 (with command VV @ fcn.00400930) shows that it reads line up to 0x20 characters long from the flag.txt file to the buffer at 0x602080 and replaces the first occurrence of newline with null byte:

We’ll now analyze the fcn.00400b60 function:

It stores the security cookie on the stack, allocates local buffer of size 0x28 (40) bytes, asks for the name (reads 32 bytes) and copies it to the buffer at 0x602060.
It then asks for another string, reads 0x190 (400) bytes of data to local buffer and copies it to buffer at 0x6020a0. After that it calls the function printing ASCII art and checks the stack cookie.

As we can see, there can be a stack buffer overflow while the second string is being read. Let’s try to write more than 40 bytes:

The original challenge has been configured the same way: it was passing “stack smashing detected” message through the socket. This is why we use socat with pty,stderr,setsid,sigint,sane options to host this binary locally.

The exploit

The “stack smashing detected” message contains the name of the application, which is read from the stack (there is a pointer to this string somewhere on the stack – it was passed as an argv[0] parameter to the main function).
As we can see earlier, PIE is not enabled and the flag is read into the memory offset 0x602080.

If we can overwrite the argv[0] pointer with the address of the buffer containing flag, it will be displayed as an error message.
We could do that by analyzing the stack locally in gdb and calculating approximate offset or by bruteforcing the offset with a simple Python script. Let’s do it with the script this time:

After a while of bruteforcing we get the flag:

Tagged with:


2 Comments » for Insomni’hack 2017: babyfirst
  1. evandrix says:

    Is it possible to upload a copy of the babyfirst binary, so I can follow along your writeup, please?