Username : narnia7
Password : ahkiaziphu
SSH : narnia.labs.overthewire.org:2226
To solve this level, we first ssh into the narnia server using the credentials provided above. Let’s have a look at the executable for this level and its source code.
As we can see above, the executable contains four functions main(), vuln(), hackedfunction(), and goodfunction().
The executable expects an argument from the user and passes it to vuln() function. The vuln() function as the name suggests is a vulnerable function. It uses a pointer to call goodfunction() which prints a statement and exits. The function of interest is hackedfunction() as we can see that function contains a system call to execute shell.
From a high level, this level seems very similar to Level 5 as we need to exploit it using string format vulnerability. If we can replace the value of pointer ‘ptrf’ to the address of hackedfunction() we can gain access to the shell. Let’s look at the inner working of the executable.
On starting the program, I set a breakpoint to right before the vuln() function is called to view the stack contents.
As we can see the executable pushes the address of the location which contains the content of the argument passed. The contents of this address are then copied to the buffer created in the vuln() function.
Another breakpoint has been set right after the snprintf() function is called within vuln().
As we can see above, the address and the copied content of the address are 6 words away from each other. Therefore, If we exploit the program using string format vulnerability, we can replace the 6th word with the address where we want our values written.
As this is a variation of string format vulnerability that I had to learn, I solved this problem in two different ways:
- Writing 2 bytes at a time
- Writing the entire word at a time
As we learned earlier, we can use the %u specifier to increase the width of the string, thus writing an arbitrary number of bytes in a location by using the %n specifier. Let’s use this technique to replace contents of the pointer ptrf to point to the location of hackedfunction() instead of goodfunction(). The executable prints the location of the pointer function and as we can see, the address that it points to is the address of goodfunction(). Therefore, if we modify the 6th word in the argument to point to the address of ptrf pointer and use %u and %n format specifier, we would be able to change the value to the address of hackedfunction().
As we can see above, by exploiting the string format vulnerability, we are able to right a random value at a location of our choice. In the case above, by writing 104 bytes (4 bytes of address and 100 bytes of %x), we are able to replace the value at the location “0xffffd67c” with 0x68 (104 in decimal). Let’s use this technique to replace the value with 0x8048706 which equates to 134514438 in decimal.
As we can see above, the executable prints the password to the next round as the value at the ptrf address is changed to the address of hackedfunction(). Note: 134514434 value is provided to the %u parameter as the address is 4 bytes long.
The method described above is easier and convenient, however, I also wanted to demonstrate another method of exploiting this by using short writes (2 bytes long each). It is very similar to the above method, however, instead of writing an entire word, it breaks the number to be overwritten into 2 different parts. The address to be written is 0x8048706. 0x804 (Higher bytes) is 2052 in decimals and 0x8706 (Lower bytes) is 34566 in decimals. Therefore, if we write the first 2 bytes in the higher address space and the last two bytes in the lower address space, we can achieve the same output as writing one single word.
As we can see above, by doing 2 different writes, one at the lower address (0xffffd65c) and one at the higher address (0xffffd65e) we were able to replace the value to the address of function hackedfunction().
Username : narnia8
Password : mohthuphog
SSH : narnia.labs.overthewire.org:2226