tcache double free
本讲将介绍tcache在2.27到2.35libc中的检测机制和double free绕过(前置知识,tcache的fd指向的是user data区域,而fastbin的fd指向prev_size区域)
libc2.26-libc2.2
在tcache刚出来的版本glibc2.26的时候存在严重的安全问题,就是在free时没有添加任何的安全策略,可以随心所欲的进行double free,不过
libc2.27-0ubuntu1.4之后
在glibc2.27(= 0ubuntu1.4 )之后添加了新的机制,也就是在chunk的bk指针位置放入了key,在每一次free时会检查当前chunk的bk指针所在的位置。
我们来看看源码包怎么检测的吧
但是要绕过这个检测也很简单,如果存在UAF或者堆覆盖等等漏洞,可以修改到bk位置即可达成绕过让e->key == tcache不成立
例如:
libc2.32
在glibc-2.32引入了Safe-Linking机制,应用于tcache与fastbins中在 glibc 2.32 中引入了一个简单的异或加密机制
我们来看看远吗:
static __always_inline void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
/* Mark this chunk as “in the tcache” so the test in _int_free will
detect a double free. */
e->key = tcache;
e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
tcache->entries[tc_idx] = e;
++(tcache->counts[tc_idx]);
}
可以看到经glibc-2.32更新后,e->next不再是直接指向原来的tcache头指针,而是指向了经PROTECT_PTR处理过的指针,查看PROTECT_PTR定义:
#define PROTECT_PTR(pos, ptr)
((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
我们来实际测试下
编译后使用gdb调试
当我们free掉两个堆块的时候,tcache中有两个free chunk,fd的指针的地址分别是0x55555555a2e0 和 0x5555555592a0
而fd里面的内容分别是0x555555559和0x55500000c7fa
计算一下:
第一个tcache
第二个tcache
正好是fd里面的内容0x555555559和0x55500000c7fa
tcache_entry->next中存放的chunk地址为 next的地址右移12位与当前tcache_entry地址进行异或运算后所得到的值, 这就要求我们在利用 tcache_entry 进行任意地址写之前 需要我们提前泄漏出相应 chunk 的地址,并且加以计算,当我们malloc第一个chunk的时候,当前地址位NULL(NULL在C语言的宏定义中表示为0),下一个chunk的地址就是堆地址,移12位之后异或,得到的就是heap_base所以实际上对堆基址的泄露更加简单了
原文始发于微信公众号(由由学习吧):glibc堆第二讲tcache double free
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论