glibc2.29堆溢出tcache的利用方式及原理

本文详细介绍了glibc2.29中堆溢出利用tcache的原理和方法,包括tcache poisoning、tcache perthread corruption和tcache house of spirit。通过分析malloc和free的源码,揭示了tcache机制的潜在安全问题,给出了漏洞利用示例,并强调了了解最新libc源码的重要性。
摘要由CSDN通过智能技术生成

glibc2.29 堆溢出tcache的利用方式及原理

Dancing With Heap 与堆共舞

二进制学习之旅

参考资料:
ctf-pwn https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/tcache_attack/#tcache-poisoning
glibc wiki https://sourceware.org/glibc/wiki/MallocInternals
glibc document http://www.gnu.org/software/libc/documentation.html
glibc2.29 source http://ftp.gnu.org/gnu/glibc/glibc-2.29.tar.gz

写在前面:
tcache 和 fastbin在free中并没有被清除inuse标志,所以他们被认为是处于使用状态,不会被合并,普通chunk被添加到unsorted bin,直到malloc时有机会使用它们,才会放入normal bin

libc经常更新,安全小白刚开始入门pwn了解堆溢出的资料有很多比较过时,于是查阅资料,写博客记录,分享知识给其他需要的同学。建议阅读libc最新源码以了解关于堆分配器的新机制,或是利用方式。

机器的测试结果,与利用方式均受机器字长的影响,关于malloc源码的概述和特殊结构体以及宏可以参考我的其他相关博客

tcache poisoning

tcache机制允许,将空闲的chunk以链表的形式缓存在线程各自tcache的bin中。下一次malloc时可以优先在tcache中寻找符合的chunk并提取出来。他缺少充分的安全检查,如果有机会构造内部chunk数据结构的特殊字段,我们可以有机会获得任意想要的地址。
###tcache_entry

typedef struct tcache_entry
{
	//指向chunk当中的用户内存区,第一个变量是一个指针,指向tcache的下一个chunk,
	//就是单链表访问
  struct tcache_entry *next;
  /* 这个字段是用来检测双重free释放的  */
  struct tcache_perthread_struct *key;
} tcache_entry;

在malloc中对tcache几乎没有什么检查,如果能给有机会覆写tcache中的next字段并且将next字段,覆写为任意指定的的地址,malloc就会直接返回这个地址的指针给应用程序,之后便可以恶意利用这个地址的内容,写入也好,读取也好。
来稍微看下malloc中tcache流程

void *
__libc_malloc (size_t bytes)
{
	.......

	#if USE_TCACHE
  //检查bytes合法性,并获取请求的标准chunk大小
  checked_request2size (bytes, tbytes);
  //获得tcache对应请求大小bin的索引
  size_t tc_idx = csize2tidx (tbytes);
//如果没有初始化tcache,那么我们初始化tcache
  MAYBE_INIT_TCACHE ();

  DIAG_PUSH_NEEDS_COMMENT;
  //检查tcache给定索引是否有chunk满足条件,有就直接取出来
  //索引大小不能超过index,并且tcache存在,并且tcache对应索引有块,初始化时不为0
  if (tc_idx < mp_.tcache_bins
      /*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */
      && tcache
      && tcache->entries[tc_idx] != NULL)
    {
      return tcache_get (tc_idx);//获取tcache
    }
  DIAG_POP_NEEDS_COMMENT;
	#endif

	.......

}

来看下获取tcache的宏

static __always_inline void *
tcache_get (size_t tc_idx)
{
tcache_entry *e = tcache->entries[tc_idx];
  //idx防止越界
  assert (tc_idx < TCACHE_MAX_BINS);
  //确实有块
  assert (tcache->entries[tc_idx] > 0);
  //取出第一个块
  tcache->entries[tc_idx] = e->next;
  //计数减少
  --(tcache->counts[tc_idx]);
  //key设置为null
  e->key = NULL;
  //返回chunk
  return (void *) e;
}

这个宏只做了请求索引越界,确定bin中有块的检测,malloc中也做了请求大小检测,请求索引检测,没有别的操作,检测完后他就简单从tcache对应大小的entry中取出头部第一个chunk,返回他的地址给应用程序。

再来看一下free中是怎么处理添加chunk到tcache的
不同于malloc_libc_free对外的接口不直接处理tcache,而是在_int_free这个模块内部例程中处理有关tcache的操作

static void//arena     chunk ptr      lock state
_int_free (mstate av, mchunkptr p,
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值