【Pwn】堆学习之glibc2.31下的tcache机制

0x2 tcache机制

0x1 tcache是什么

· tcache是满足一定条件的chunk被free后首先进入的bin,在2.31版本中一个tcachebin最多存储7个chunk,使用单链表头插法。在64位系统下,不同的tcachebin可存储的chunk的大小范围如下:idx0对应0-24字节,idx1对应25-40字节,idx2对应41-56字节。

0x2 chunk进入tcache的变化

· chunk进入tcache后,user_data的前两个槽位会发生变化。user_data+0x00写为next,指向tcache链表中的下一个chunk,如果链表为空则next也为null;user_data+0x08写为key,指向当前线程的tcache,标志当前chunk位于tcache链表中,也用于辅助double free检测。当前bin的头节点会指向新进入的chunk。注意:chunk进入tcache链表时并不是整个chunk在内存空间中移动,而是user_data的前两个槽位发生变化。chunk进入tcache的逻辑由tcache_put函数负责。

0x3 chunk离开tcache的变化

· chunk离开时,当前bin头节点指向next,即下一个chunk的user_data头。key被清空,标志chunk被使用。

0x4 tcache实例

· 使用如下实例:

#include <stdio.h>
#include <stdlib.h>

int main() {
    setbuf(stdout, NULL);

    char *a = malloc(0x20);
    char *b = malloc(0x20);

    printf("a = %p\n", a);
    printf("b = %p\n", b);

    free(a);
    free(b);

    char *c = malloc(0x20);
    char *d = malloc(0x20);

    printf("c = %p\n", c);
    printf("d = %p\n", d);

    return 0;
}

· 两次malloc后chunk状态:

image

· free(a)后:

image

可以看到a确实进入了tcache。

image

可以看到user_data+0x08变成了指针一样的东西,即key,指向tcache。

· free(b)后:

image

可以看到a与b此时都在tcache中,b的user_data的前两个槽位也都变成了指针,其中user_data+0x00变为next,指向a的user_date,user_data+0x08变为key,指向tcache。此时a与b的位置状态如下:

head-->b-->a-->NULL

· char *c = malloc(0x20)后:

image

可以看到b已经从链表中弹出,且key被清除,标志该chunk已离开链表。

· tcache被塞满的情况(使用如下实例):

#include <stdio.h> 
#include <stdlib.h> 
 
int main() { 
    setbuf(stdout, NULL); 
 
    char *a = malloc(0x20); 
    char *b = malloc(0x20); 
    char *c = malloc(0x20); 
    char *d = malloc(0x20); 
    char *e = malloc(0x20); 
    char *f = malloc(0x20); 
    char *g = malloc(0x20); 
    char *h = malloc(0x20); 
 
 
    free(a); 
    free(b); 
    free(c); 
    free(d); 
    free(e); 
    free(f); 
    free(g); 
    free(h); 
 
    return 0; 
}

· 8次free后:

image

可以看到存储0x30大小的tcachebin被填满,最多存储7个chunk,第8个chunk进入fastbin。

posted @ 2026-03-25 19:36  Lochad  阅读(23)  评论(0)    收藏  举报