Penetration testing

Protostar: Finals – Remote Heap Unlink Exploitation

January 31, 2018 by Sahil Dhar

In this article, the two final challenges of Protostar will be solved, and these are the remote Format String and the Heap Unlink Exploitation vulnerabilities.


These levels introduce the hurdles of debugging and developing exploits for the remote Format String and the Heap Unlink vulnerabilities. These will be further examined to see how they can be debugged and reverse engineered at the binary level to understand what input is to be expected.


The VM used in this article can be downloaded from here.

Final 0

This level takes us back to the simple format string vulnerability, but this time, our target is a remote server. Before examining how to reverse-engineer the binary, let us first understand the inner workings of it by seeing how it interacts with Netcat.

Note: The application does not seem to respond to any of our input as in the previous format string challenges where we able to see the output. This is illustrated below:

The source code for this level can be found here.

After analyzing the disassembly of the binary, it was determined that the application uses four functions apart from the main function. These are getipport, parser, trim and logit with the following functionalities:

getipport(): Records the connected client information.

parser(): parse user input for a specific format and log it syslog using the logit function

trim(): removes the carriage return and line feed characters from user input.

logit(): logs eth user input to the system’s syslog.

From the syslog documentation, the syslog function takes on separate two arguments: one is the priority (used for specifying the debug level), and the other is the format specifier. This is illustrated below:

By looking at the disassembly of the logit function, it can determine that the snprintf first copies the formatted string into a buffer at [$ebp-0x208]. The same string is then passed into a format specifier argument of the syslog function leading to a format string vulnerability. This is demonstrated in the screenshot below:

The screenshot below shows the formatted string that is used by the snprintf function at the 0x8049ee4 level. The result of the formatted string after calling the function is stored in the $eax function. This is then fed as the second argument to the syslog function.

The following screenshot displays the result of the injected format string. It can also be accessed at /var/log/syslog, as seen below:

After the root cause and the entry point for the vulnerability has been discovered, the process of writing a remote exploit can now begin for the same. The process of writing this exploit for this level remains exactly same as the one discussed here.

After some trial and error, the following exploit has been created where the GOT entry is being overwritten for the strchr function in the same system, which is illustrated below:

As shown in the screenshot below, executing the exploit shown in the above screenshot gives a root shell on the remote machine.

Final 2

This is the final challenge of the Protostar VM. At this level, the Heap Overflow vulnerability will be examined where it will be exploiting the malloc algorithm from the memory chunks on located on the heap.

Note: The exploitation process for this challenge remains the same as of the one discussed here. From this point onwards, it will be examined how the application logic fails, resulting in the creation of the fake heap memory chunks. In turn, this ultimately leads to remote code execution.


In this section, the fundamental details on how the data should look like before it reaches the vulnerable function will be reviewed. The application implements a search and replaces functionality, where it expects that the user data should start with a syntax of “FSRD.”

It then looks for the last occurring forward slash “/” character; and from there, it starts searching for the word “ROOT.” It replaces everything starting with the word “/ROOT” till the last forward slash “/,” as well as the data after forward slash “/CCCCCCCCCC.”

This activity is performed by searching backward,
i.e., before the word “ROOT” in the input provided by the user for a forward slash “/.” If one instance is found, it then stops the search and performs the replace function.

The screenshot below shows how the user input is manipulated by the application before and after the search and replace functions are executed:

Now comes the part where the replace logic fails because it will keep checking backward for a forward slash “/” to inject the replaced string. If one more forward slash is added to the input, the application will not replace anything, and the data in the heap memory will remain intact.

In the heap unlink exploitation, we need to unlink the fake chunk preceded with one more chunk to host the shellcode. In this case, using the FSRD/ROOT command is infeasible in the input.

Thus, the second request of FSRDROOT/<size><address> will be sent, and the logic will merely remove the FSRDROOT. This is because a forward slash has been used before in the FSRDROOT command from a previous backward search request. This is illustrated in the screenshot below:

The screenshot below shows the state of the heap memory before and after the “Search Replace” functionality is executed. It is important to note that the data in the heap memory remains the same.

Using the above approach, two fake chunks can thus be injected into the heap memory which leads to the remote code execution on the system. This is done by exploiting the way the malloc unlinks the heap chunks. For the sake of efficiency, a. gdbinit script was created to automate the debugging process, as illustrated below:

The. gdbinit script shown in the above screenshot puts a breakpoint before and after the memmove() function is executed; and thus, it demonstrates the state of the heap.

The screenshot below demonstrates the final exploit code utilized to gain the code execution for this challenge:

This exploit sends two requests to the server for creating two fake chunks. For example, one of them injects a two-stage shellcode, and the other one overwrites the (write() GOT
– 0xc) entry with the address of the first stage shellcode.

The screenshot below illustrates the content of the first and second request in heap memory:

It is important to note that after tricking the malloc() into freeing the fake heap chunk, the GOT address of write() is successfully overwritten with the pointer to the respective shellcode.

Executing the exploit code shown above yields a remote root shell on the server as shown in the below screenshot:


Posted: January 31, 2018
Sahil Dhar
View Profile

Sahil Dhar is an Information Security Enthusiast having more than two years of hands-on experience in Application Security, Penetration Testing, Vulnerability Assessments and Server Config Reviews. He has also been acknowledged and rewarded by various organizations like Google, Apple, Microsoft, Adobe, Barracuda, Pinterest, Symantec, Oracle etc for finding vulnerabilities in their online services.