Narnia(binary exploitation) walkthrough
Hey amazing hackers,
welcome back to my blog-post and with an another challenge. Today, i am going to walkthrough “Narnia” at overthewire. I hope you will like this blog and if so… Please do not forget to share, like, and support my Medium. Lets dive into it.
Narnia is a wargame that has been rescued from the demise of intruded.net, previously hosted on narnia.intruded.net. Big thanks to adc, morla and reth for their help in resurrecting this game!
What follows below is the original description of narnia, copied from intruded.net:
Summary:
Difficulty: 2/10
Levels: 10
Platform: Linux/x86
Level 0
After logging in you should be able to see these files:
I am going to look the source code of this file to have better understanding what this file does.
In order to solve this challenge we need to change the value with 0x41414141 to 0xdeadbeef
There is a security issue by scanf() because buf[20] is initialized to 20 characters however, we are able to add 4 more characters which allows us to buffer the flow.
We are going to use python to splash 24 characters:)
Awesome, it seems to work. We will be able to modify BBBB to “litte endian”
Little endian: An argument for little-endian order is that as you increase a numeric value, you may need to add digits to the left. For example, a higher non-exponential number has more digits. Thus, an addition of two numbers often requires moving all the digits of a big-endian ordered number in storage. This addition moves everything to the right. source(https://www.techtarget.com/searchnetworking/definition/big-endian-and-little-endian)
Lets modify it.
I struggled with this one, because it did not pop the shell, after a while i recognized that it was depreciated so we should add “;cat”
Bam it works!!! go to the next level…
Level 1
Before executing this file, we need to check the source code so as to understand what kind of problem I can be facing.
It seems we ought to export EGG because as you can read of this file it says;
if “EGG” is empty then → “give me something to execute at the env-variable EGG” and then it will exit with exit() function
else:
If we export a shellcode for example, we might be able to get the shell , and found something on “exploit-db”
You can find the CVE: Linux/x86 — execve(/bin/sh) + NOT Encoded Shellcode (27 bytes)
I will use random shellcode to be able to get the shell prompted
source : https://www.exploit-db.com/exploits/44594
As you can see it works !!!
Level 2
First of all, in order to complete this challenge we need to view the source code of “narnia2.c”
It holds 128 characters, thus it means if put extra chars it will be overflowed.
And also we will be able to break the execution flow.
We tried to add 132*A chars, and as you can see “segmentation fault”
I was going to use “gdb” to view the memory at line “main+68” we see a call function “printf” I am willing to manipulate this function.
I set a breakpoint at “main+68” address of “0x804848f” just as usual, i wanted to print “104*\x90" NOP but what does NOP mean ?
NOP: A no operation or “no-op” instruction in an assembly language is an instruction that does not implement any operation. IT pros or others might refer to this as a blank instruction or placeholder.
source(https://www.techopedia.com/definition/11989/no-operation-nop)
and shellcode was being used. I used Linux/x86 — execve(/bin/sh) Shellcode (28 bytes) because we lnow that this machine is x86(32 bit) machine.
link of this shellcode: https://www.exploit-db.com/exploits/43716
I used “0xffffd864” as NOP → 0x90909090 lets put everything together.
We got a shell but we need to run this outside of GDB.
And boom we used the command which we used before.
command : ./narnia2 $(python -c ‘print 104 * “\x90” + “\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80” + “\x64\xd8\xff\xff”’)
level 3
After logging in to level 3, we are facing a file called “narnia3”. I ran this program.
Nothing suspicious. It says that my file “will be sent contents of file 2 /dev/null” Now ı get fascinated to view this code.
We have “ofile[16]”, “ifile[32]” it seems that if we are able to manipulate “ifile” to buffer this “char” we might be able to get shell ? lets run “gdb”
Could you see “main+93” called “open@plt” I am going to set a breakpoint at that line
I ran “hacker” to test if something being changed. We still see “/dev/null” so we could not overwrite it.
x/s $eax
x: address
s: string
eax: is the 32-bit, “int” size register.
Lets use more characters
Boom! it works. We overwritten the security flow successfully.
I will use this outside of gdb.
We should use “symbolic linked directory”
- mkdir -p /tmp/HACHACHACHACHACHACHACHACHAC/tmp
- ln -s /etc/narnia_pass/narnia4 /tmp/HACHACHACHACHACHACHACHACHAC/tmp/ab
- touch /tmp/ab
- chmod 777 /tmp/ab
- ./narnia3 /tmp/HACHACHACHACHACHACHACHACHAC/tmp/ab
6. cat /tmp/ab
After doing this process step by step you will be able to get the next password.
Level 4
We do the same process, which we did before.
hmm…. output nothing ? lets see why this happened
In order to analyze the source code, i am willing to use vim editor
Hmm… Okay.
It seems like that we will be able to buffer the memory
It can be a segmentation error when i put more than 254 chars.
“char buffer[254]” lets give a try
Awesome as you can see “segmentation error has occurred”
As usual, i will run this file in “gdb”.
I am going to set a breakpoint after strcpy() function.
Do you remember: Linux/x86 — execve(/bin/sh) Shellcode (28 bytes) shellcode
source : https://www.exploit-db.com/exploits/43716
We are going to use this shellcode but we need to calculate the size of that “buffer” 256
lenght= 264
that means we should add 4 bytes to buffer the flow.
we were using NOP \x90 → $(python -c ‘print 236 * “\x90” + “\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80” + 4 * “B”’)
We can randomly choose a memory. I shall use “0xffffd4bc” It looks like →
$(python -c ‘print 236 * “\x90” + “\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80” + 4 * “\xbc\xd4\xff\xff”’)
Awesome it works. It has the same methodology what in level 2 gave to but this one has not been given any output.
I am going to use the same shellcode out of gdb
Boom got the password!!
Level 5
Before executing this file ı would like to view the source code.
We are seeing that char buf[64] is defined as character. And i also thus that means we need to be able to manipulate “i” to get the shell
because reaching i == 500 means we will ge the shell.
everything looks good now lets do our job.
We just put “a” character and we got a hint from the OS. This is much better to get the shell because we know the memory address of i. I assume that this challenge provide us to exploit it with format string bug.
What is a format string bug
A format string bug occurs when user-supplied data is included in the format specification string of one of the “printf” family of function, including
- printf
- fprintf
- nprintf
- snprintf
- vfprintf
- vprintf
- vsprintf
- vsprintf
- vsnprintf
next to a we put an address “%x”
hmm suspicious we added %100x means “100 memory address+ %1\$n”
$n : These variables correspond to the arguments with which a script was invoked.
i was counted to 104 thus we 100 + 4 awesome!! We are going to add 496 because 496 + 4 byte = 500
Boom we are “nania6”
I found an awesome blog format string exploit → https://axcheron.github.io/exploit-101-format-strings/
level 6
As usual, we need to analyze the code before executing the file.
Very interesting. We see that “fp” pointer points to “&puts” and argv[1] , argv[2] copied into b1 and b2 respectively, to better analyze this file we will run “gdb”
We set a breakpoint at “main+319”
We set a breakpoint at “main+319 ” and after we ran our code “DDDD CCCC” DDDD represents = 0x44444444 and CCCC represents = 0x43434343
We are seeing that “EAX” memory has “0x8048430” the address of puts() is higher on the stack so, we might be able to overwrite it. Let’s give a try…
The idea behind of this methodology is to overwrite system() return address.
Awesome it works. I am going to try this shell out of “gdb”
BOOM! we got our password.
level 7
As usual so as to understand the executable file we need to view the source code.
As we knew before that, snprintf occurs a format string vulnerability.
We have pointer function called (ptrf) so we need to manipulate this function to overwrite the memory “goodfunction” to “hackedfunction” let’s give a try….
Luckily, we do need to use “gdb” because the memory is already given “0x8048724” so what we did, exact the same flow what by narian level 5 has happened. We just overwritten the memory with %x%n
%s : → input type “pointer” output type → string
%d : → input type “value” output type → decimal
%n : → input type “pointer” output type → number of bytes written so far
%x : → input type “value” output type → hexdecimal
%u : → input type “value” output type → unsigned decimal.
At this point we need to calculate “0x8048724” to overwrite it.
or….
You can use your linux kung-fu :)
now let’s put this together..
Boom! it works
By the way, i recommend you to read “hacking the art of exploitation and shellcode” you will fully understand this methodology.
level 8 (the final boss)
Hmm… firstly, i tried to enter “test” and after that was going to try “100” A characters.
at the end of A you will see 8 and then garbage values……? strange let’s view this code.
We have “func()” called char *b, char bok[20] and we see that “b” value is equal to blah.
memset(): The memset() function sets the first count bytes of dest to the value c. The value of c is converted to an unsigned character.
it seems that, we have a for loop which starts at 0 until it reaches blah[i] and copied to bok[i].
We have seen that bok has max of 20 characters thus let’s try to overflow it with 21 characters.
First of all, we need to disassemble func() you just need to enter these commands respectively:
- gdb ./navian8
- set disassembly-flavor inter so as to understand more clearly
- disass func
after these commands; we will try some overflow attack such as, as you can see we decreased “0xffffd889” to “0xffffd888” awesome we can check via “x/16wx ” $esp because after func() we are calling $esp stack.
We will check the following dump, the address “0x0804048a7 “is in fact the return address to main() at the following line “0x0804048a7” <repeats 23 times> which adds $esp 0x04 to main().
As you can see above.
We are going to restore the orginal pointer to our string. “0xffffd88a”
we shall add 1 byte at “0xffffd88a”
Awesome.
Actually at the last level I got stuck…..:(
I found an awesome walkthrough of this challenge. I am still a nooberrrr hahah I have to learn so much things. I super apolologize to unable solve this last level . I have cheated this level but still did not understand very well
I put the link below where you can watch and be informed about this level..
Link → https://youtu.be/nAMznri1EMQ
Summary
As I mentioned, you will be informed when you watch that video of level 8:)
First of all, thanks for reading this blog. If you are interested in such things, please follow me and subscribe… and share with your friends.
Ahmet Göker | Exploit researcher | malware Researcher| Cryptanalyst | CTF player | Reverse Engineering
You can follow me on:
Linkedin: https://www.linkedin.com/in/ahmetg%C3%B6ker/
Twitter: https://twitter.com/TurkishHoodie_
Youtube: https://www.youtube.com/c/TurkishHoodie
Github: https://github.com/DarkGhost010
references:
The shellcoder’s handbook
Hacking: the art of exploitation 2nd edition