tcache attack

tcache attack

tcache double free

double free可以通过对同一块内存free两次,实现任意地址写。当libc版本在2.26以上时,free的块优先放入tcache,malloc也优先从tcache中取,性能更好。但是安全检查变弱了。

static void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
  tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
  assert (tc_idx < TCACHE_MAX_BINS);
  e->next = tcache->entries[tc_idx];
  tcache->entries[tc_idx] = e;
  ++(tcache->counts[tc_idx]);
}

tcache free代码如上,只校验了tc_idx的值是否到达TCACHE_MAX_BINS(7),并没有其他的检查,相比fastbin或者其它bin的double free,tcache double free更加简单。

double free 原理

如果程序存在某些漏洞可以对同一个地址free两次,则存在double free。比如,在调用free函数后,不把指针变量置NULL,或者不检查该内存是否被free过了。
如果存在,对于tcache,那么通常的利用步骤是:

  1. double free 地址A,让A进入tcache,并A的fd指针指向自己。(tcache[7]: A----->A)
  2. 调用malloc,将A分配出来,这时tcache中还有一个A(tcache[7]: A);
  3. 伪造tcache中的A,修改A的fd为free函数或者print函数got表中地址,或者hook地址,或者任意地址。这样让free函数地址插入到了tcache中;(tcache[7]: A—>__free_hook)
  4. 再调用一次malloc,将tcache剩余的一个A分配出来。
  5. 最后调用malloc的时候,就能将__free_hook的地址分配出来了。实现任意地址写。
  6. 最后我们可以向__free_hook地址中(或者其它任意地址)写入system函数或者one_gadget地址。调用free的时候就能跳转到one_gadget去实现程序流控制;

例题

tcache-uaf-attack
用ctfwiki的例题做讲解
题目漏洞点在malloc的地方,存在一个null-byte-overflow的漏洞:

if ( sz )
  {
    while ( 1 )
    {
      read(0, &malloc_p[i], 1uLL);
      if ( sz - 1 < i || !malloc_p[i] || malloc_p[i] == '\n' )
        break;
      ++i;
    }
    malloc_p[i] = 0;
    malloc_p[sz] = 0;                           // null-byte-overflow
  }

可以将下一个chunk头的p_inuse位置零,实现double free。
大体思路:

 1. 题目libc版本为2.27,存在tcache。需要转换为unsorted bin的double free;
 2. 泄露libc地址,需要使用unsorted bin泄露,先把tcache填满,然后构造unsorted bins:
 	A->B->C, C有main_arena的地址,将C 分配出来,打印,注意不覆盖bk;
 3. 程序流控制:需要利用null-byteo-verflow实现double free,实现任意地址写:
 	a. 在之前构造的unsorted bin链基础上,将ABC分配出来,分配B时,利用漏洞溢出修改A的头部p_inuse位;
 	b. 重新free C和A,由于A的p_inuse为0,会触发chunk合并,将ABC合成一个大free chunk(B还在使用中);
 	c. 使用malloc功能,重新将B分配出来,这样,表中就有两个B chunk。
 	d. 这时候使用free功能就能将B free两次,触发double free
 	e. 然后将B分配出来,写入free_hook地址,再分配一次B,就能将free_hook分配出来(详情见double free原理),我们写入one_gadget地址。

附录

  1. __free_hook:

    它是libc free函数中使用的一个全局变量:
unsigned __int64 __fastcall free(unsigned __int64 *a1)
{
...
    if ( _free_hook )
      {
        _free_hook(a1, retaddr);
        return __readfsqword(0x28u) ^ v77;
      }
...
}

如果free_hook不为0,则直接跳转到free_hook的函数,通常用于堆利用时,got表无法修改时的情况(开启了RELRO)。可以将free_hook存的值修改为system,可实现控制程序流。

malloc_hook类似。

libc2.27—>ubuntu18


2.123

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值