Tcache Attack中的Tcache dup(基础)

参考资料:PWN入门(3-16-2)-Tcache Attack中的Tcache dup(基础) (yuque.com)

代码来源:Tcache Attack (yuque.com)

附件下载:

链接:https://pan.baidu.com/s/1XtWyhA7_RKL3hTbsLLXpIw
提取码:tywy
–来自百度网盘超级会员V3的分享

漏洞原理

使用libc-2.27.so的源码进行分析

Tcache dup利用的是tcache_put()函数的不严谨:

1
2
3
4
5
6
7
8
9
static __always_inline 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]);
}

从上面的代码可以看出,在libc-2.27版本中没有对tcache_put函数进行检查,也没有对tcache->counts[tc_idx]的检查,在大幅度提高性能的同时安全性也降下来许多。

因为在这个函数中没有任何的检查,所以我们可以对同一个chunk进行多次free,造成cyclical list(循环列表)

与fastbin attack中的double free相似,但是fastbin_attack中检查机制更多。

Demo

举一个例子说明。

源码c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//gcc -g -fno-stack-protector -z execstack -no-pie -z norelro test.c -o test
#include <stdio.h>
#include <stdlib.h>

int main()
{
fprintf(stderr, "先申请一块内存\n");
int *a = malloc(8);

fprintf(stderr, "申请的内存地址是: %p\n", a);
fprintf(stderr, "对这块内存地址 free两次\n");
free(a);
free(a);

fprintf(stderr, "这时候链表是这样的 [ %p, %p ].\n", a, a);
fprintf(stderr, "接下来再去 malloc 两次: [ %p, %p ].\n", malloc(8), malloc(8));
fprintf(stderr, "Finish!!!\n");
return 0;
}

Pwngdb调试

首先在第12行下断点,执行程序,查看内存情况:

image-20230813140619464

然后对这个chunk进行多次free。

在15行下断点,执行程序,查看内存情况:

image-20230813140939079

可以看到再对chunk1进行两次free之后,在tcache中形成了cyclical list,也就是说chunl1中的next指针指向其本身的chunk_data。

然后在17行下断点,执行程序

image-20230813142338323

可以看见tcachebins中为空了,说明执行了两次malloc,分配的就是tcachebins中的堆块。