A couple of times ago, a new challenge was released on the vulnhub website. Because it wass really interesting, I decided to blog it. You can find the challenge here: https://ctf-team.vulnhub.com/rop-primer/
Let’s have a look 🙂
First of all, the virtual machine has been deployed under VirtualBox. After finding the IP address, let’s begin with nmap:
an@chm:~/Pentest/Tools$ nmap 192.168.56.103 Starting Nmap 6.46 ( http://nmap.org ) at 2015-04-22 14:04 CEST Nmap scan report for 192.168.56.103 Host is up (0.00060s latency). Not shown: 997 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 8888/tcp open sun-answerbook Nmap done: 1 IP address (1 host up) scanned in 0.04 seconds
The web server contains all information about this challenge:
This challenge has to be performed locally through SSH.
A local program named level0 can be executed from the level0 home directory:
level0@rop:~$ ./level0 [+] ROP tutorial level0 [+] What's your name? Antoine [+] Bet you can't ROP me, Antoine!
Let’s try to obtain some error:
level0@rop:~$ ./level0 [+] ROP tutorial level0 [+] What's your name? uilhnuiojzui&/%(&()J=/)(=KJK/()=ZNIHuiomziouz=)()=Kpuio.jivtrtü+bvät#vphrv#tr [+] Bet you can't ROP me, uilhnuiojzui&/%(&()J=/)(=KJK/()=ZNIHuiomziouz=)()=Kpuio.jivtrtü+bvät#vphrv#tr! Segmentation fault
Ok apparently parameters are not properly casted.
I analyzed the comportment with gdb (the peda plugin has been added): level0@rop:~$ gdb level0
In order to identify the impact of this error on the stack, I used a pattern generated with peda:
Now, the EIP is 0x41414641. With this value, I am able to determine the position of the EIP:
EIP found at offset 44. I decided to generate a complete shellcode and include it:
I created an exploit file with this shellcode:
an@chm:~$ perl -e 'print "A"x44 . "B"x4 . "\x90"x500 . "\x31\xc0\x50\x68\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80"' > shellcode.bin
With gdb, I injected this shellcode.bin in the program input to analyze the result:
The EIP is 0x42424242. The good news is the EIP has been properly overwritten by the 42424242.
I can try to perform a ret2libc.
Return-to-libc attack (ret2libc):
I need the address of the bash and the system function. To find the bash, I am looking around the ESP:
I have the bash address. Now, I am looking for the system() address:
The system() address cannot be found. The ret2libc seems to be not possible.
Return oriented programming (rop):
Back to the initial exploit:
an@chm:~$ perl -e 'print "A"x44 . "B"x4' > min.bin
I reproduced the exploit with gdb. As previously, the EIP has been replaced:
In order to perform a ROP, I need a gadget.
In this challenge I used the leave() function in the main. I put a breakpoint on this address to analyze the stack. Before the crash:
I made a step to see the stack after the leave() function:
What can we conclude?
- ESP 0xbffff5c0
- EBP 0xbffff5f8
- ESP 0xbffff5fc
- EBP 0x41414141
I wrote a python script “exploit.py” to use the main leave() call:
Ok, I still have the EIP at 42 🙂
Now I am looking for the mprotect/read call addresses and the mapped memory on the stack:
With these addresses, I adapted the previous script:
Now, I executed once again the exploit and see the difference in the mapped memory:
Good news, now we have a memory space mapped in rwxp!
In the same gdb session, I am looking for the POP POP POP RET – pop3ret gadget:
Sounds good! Let’s modify one more time the python script to include these addresses:
The EIP is 0x41414141! Perfect 🙂
The end is not so far away!
Let’s modified the python script for the last time with the real ret address:
Perfect, we don’t have any segmentation fault!
Now , let’s add a shell: http://shell-storm.org/shellcode/files/shellcode-606.php