CTF pwn题堆入门 -- Tcache bin

本文介绍了CTF中pwn题堆漏洞利用的基础,特别是针对Tcache机制的攻击方式。文章详细讲解了如何绕过Tcache、分配堆到特定地址、泄露内存地址以及利用Tcache bin进行攻击。通过示例代码和调试结果,展示了Tcache的工作原理和在不同场景下的利用技巧,包括tcache poisoning和tcache house of spirit等攻击手段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CTF pwn题堆入门 – Fast bin
CTF pwn题堆入门 – Unsorted bin
CTF pwn题堆入门 – Large bin

序言

  无奈于pwn题中与堆相关的东西实在是比较多,加上到了2021年的现在,ctf比赛中一来就是堆题,还都是新版本libc,对我这种新手中的新手实在不太友好,以此写下这个系列文章,记录自己学习堆漏洞利用过程中的点滴,同时也是个总结吧。结合自己做题的理解,将堆攻击常见的手段和方式按照一定的规律记录下来。
  本文章系列将分成五大块,即tcache bin --> fast bin --> unsorted bin --> small bin --> large bin。

概述

  tcache相对于其余四种bin,是出现的最晚的,在libc2-26中才加入,但现在的题目一般都基于更新版本的libc,tcache肯定是必不可少的一环,而且是最开始的那一环,所以这里先对tcache机制进行一个总结。
  Tcache全名为Thread Local Caching,它为每个线程创建一个缓存,里面包含了一些小堆块。无须对arena上锁既可以使用,所以采用这种机制后分配算法有不错的性能提升。每个线程默认使用64个单链表结构的bins,每个bins最多存放7个chunk,64位机器16字节递增,从0x20到0x410,也就是说位于以上大小的chunk释放后都会先行存入到tcache bin中。对于每个tcache bin单链表,它和fast bin一样都是先进后出,而且prev_inuse标记位都不会被清除,所以tcache bin中的chunk不会被合并,即使和Top chunk相邻。
  另外tcache机制出现后,每次产生堆都会先产生一个0x250大小的堆块,该堆块位于堆的开头,用于记录64个bins的地址(这些地址指向用户数据部分)以及每个bins中chunk数量。在这个0x250大小的堆块中,前0x40个字节用于记录每个bins中chunk数量,每个字节对应一条tcache bin链的数量,从0x20开始到0x410结束,刚好64条链,然后剩下的每8字节记录一条tcache bin链的开头地址,也是从0x20开始到0x410结束。还有一点值得注意的是,tcache bin中的fd指针是指向malloc返回的地址,也就是用户数据部分,而不是像fast bin单链表那样fd指针指向chunk头。

攻击方式

  这里先说一下何时会用到tcache,在有了tcache机制后,无论分配还是释放,操作64位下0x20和0x410大小的chunk,tcache都是首当其冲,直到达到其每种bin的上限7为止。还有一种情况就是fast bin或者small bin返回了一个堆块,且tcache对应大小的bin中未满的话,那么该fast bin或者samll bin链中的堆块会被加入到对应tcache bin中直至其上限。这里值得一提的是,在tcache机制出现后,由于tcache机制首当其冲,很多属于fastbin的安全检查机制都没有被应用,因此在tcache下实现和fastbin一样的攻击原理,相对而言还会更简单些。下面介绍和tcache机制相关的攻击方式,将会按照攻击目的进行分类。

绕过Tcache

  如果你对tcache并不熟悉,或者这道题并不需要利用tcache机制才能实现攻击,那么我们只需要简单的绕过tcache机制就行了。

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


int main()
{
   
    long long *ptr[7];
    long long *a = malloc(0x80);
	// 申请7个,释放7个,填满tcache bin[0x90]
    for (int i=0; i<7; i++)
        ptr[i] = malloc(0x80);
    for (int i=0; i<7; i++)
        free(ptr[i]);
    // 这里再释放a,就会放入到unsorted bin中
    free(a);
    printf("libc addr is %llx\n", (long long)a[0]);

    return 0;
}

tcache bypass
  如上图所示,展示了如何绕过tcache,使用unsorted bin的性质,打印存放于unsorted bin中的libc地址。tcache机制无非就是增加了一层缓存,如果我们还是想使用fast bin/unsorted bin等的性质,那么需要将对应的tcache bin填满,然后再执行相应的操作就可以了。这里需要注意的是,上面代码只是填满了[0x90]这一条tcache bin链表,如果想要自己申请释放的0x20大小的chunk进入到fast bin,那么同样需要先填满tcache bin[0x20]。

分配堆到目的地址

  在堆漏洞利用中,我们很多时候需要将堆块分配到我们想要的地址上去,比如分配到保存堆指针的bss中,或者直接分配到栈空间实现程序流程控制,亦或者还是分配到堆中把堆块重新分割。在tcache中有以下攻击方式可以实现(不加说明则为64位机器,libc-2.26);

tcache poisoning

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


int main()
{
   
    // 在fck处分配堆块
    long long fck;
    printf("fck addr is %p\n", &fck);

    long long * ptr = malloc(0x80);
    printf("malloc ptr addr is %p\n", ptr);
    free(ptr);
    // 只需修改fd指针,申请的大小和当前tcache bin大小相同即可
    ptr[0] = (long long)&fck;
    malloc(0x80);
    printf("the second malloc addr is %p\n", malloc(0x80));

    return 0;
}

tcache_poisoniong
  上图展示了攻击结果,这里同样注意tcache bin中的fd

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值