技术社区
安全培训
技术社群
积分商城
先知平台
漏洞库
历史记录
清空历史记录
相关的动态
相关的文章
相关的用户
相关的圈子
相关的话题
注册
登录
手把手带你搞懂堆利用套路
Poseidon
发表于 湖北
二进制安全
249浏览 · 2025-05-20 06:56
返回文档
前言
堆利用一直是 CTF 和安全研究中最具挑战性、同时也最具魅力的方向之一。相较于传统的栈溢出,堆的利用手法更加多样,依赖内存分配器的内部机制,攻击思路往往更具“艺术性”。
我在学习堆利用的过程中,发现很多攻击技术彼此之间既独立又紧密相关,理解一个点常常需要对 glibc 的堆实现有一定的了解。因此,我决定把这些常见的堆利用方式——包括 UAF、fastbin dup 系列(如 into stack、consolidate、reverse into tcache)以及 unsafe unlink 等——整理成这篇笔记,一方面帮助自己梳理知识,另一方面也希望对刚入门或正在深入的同学有所帮助。
这篇文章默认你已经掌握了基本的 C 语言指针操作、glibc 的 malloc/free 使用,以及一些基础的内存漏洞概念。如果你也在学习堆利用,或者正在做相关的 CTF 题,希望这篇内容能为你带来一点启发。
UAF
free之后指针没有清零,结构体内存在函数指针。
简单的说,Use After Free 就是其字面所表达的意思,当一个内存块被释放之后再次被使用。但是其实这里有以下几种情况
●
内存块被释放后,其对应的指针被设置为 NULL , 然后再次使用,自然程序会崩溃。
●
内存块被释放后,其对应的指针没有被设置为 NULL ,然后在它下一次被使用之前,没有代码对这块内存块进行修改,那么
程序很有可能可以正常运转
。
●
内存块被释放后,其对应的指针没有被设置为NULL,但是在它下一次使用之前,有代码对这块内存进行了修改,那么当程序再次使用这块内存时,
就很有可能会出现奇怪的问题
。
而我们一般所指的
Use After Free
漏洞主要是后两种。此外,
我们一般称被释放后没有被设置为NULL的内存指针为dangling pointer。
first_fit
glibc 使用一种first-fit算法去选择一个free-chunk。如果存在一个free-chunk并且足够大(绕过fastbin)的话,malloc会优先选取这个chunk。这种机制就可以在被利用于use after free(简称 uaf) 的情形中.
UAF 漏洞简单来说就是第一次申请的内存释放之后,没有进行内存回收,下次申请的时候还能申请到这一块内存,导致我们可以用以前的内存指针来访问修改过的内存。
程序展示了一个 glibc 堆分配策略,first-fit。在分配内存时,malloc 先到 unsorted bin(或者 fastbins)中查找适合的被 free 的 chunk,如果没有,就会把 unsorted bin 中的所有 chunk 分别放入到所属的 bins 中,然后再去这些 bins 里去寻找适合的 chunk。可以看到第三次 malloc 的地址和第一次相同,即 malloc 找到了第一次 free 掉的 chunk,并把它重新分配。
fastbin_dup
fast bins为单链表存储。fast bins的存储采用后进先出(LIFO)的原则:后free的chunk会被添加到先free的chunk的后面;同理,通过malloc取出chunk时是先去取最新放进去的。free的时候如果是fast bin,就会检查链表顶是不是要释放的chunk_ptr。所以只要链表顶不是该chunk,就可以继续free,从而实现double free。
ptmalloc管理机制中,tcache的优先级是高于fastbin的,但是通过calloc函数申请的内存是跳过tcache的。fastbin dup技巧就是绕过tcache实现2.23版本下面的double free操作。
fastbin_dup_into_stack
通过欺骗malloc 来返回一个我们可控的区域的指针 。
fastbin_dup_consolidate
在分配large chunk的时候,首先会根据chunk的大小来获取对应的 large bin的index,然后判断fast bins中有没有chunk,如果有就调用 malloc_consolidate()合并fast bins中的chunk,然后放到unsorted bin 中。unsorted bin中的chunk 会按照大小放到small或large bins中。
fast_bin_reverse_into_tcache
原理
修改fastbin 释放的chunk的fd指针,指向伪造的chunk地址,实现任意地址覆盖。
在从fast bin中malloc的时候取出一个chunk,会将剩余的chunk放回到tcahce中。而fd指针已经修改为fake_chunk_addr,所以fake_chunk也会进入tcache bin的尾部,再次malloc的时候就会申请出来。
有一点需要注意的是,放入 tcache bin的条件是tcache bin有空余,且fastbin取出后也有剩余。后者的判断方法是取出表头的fd指针指向的下一个chunk,判断是否为空。也就是从头部开始取的,再使用头插法插入 tcache bin。这样的话,排入tcache bin 后chunks的顺序就是与其在fastbin中是相反的,所以叫reverse。
unsafe_unlink
概述
双向链表中移除/添加一个chunk时,会发生断链的操作,这个断链的过程就叫做unlink。
注意事项:unlink不发生在fastbin和smallbin中,所以fastbin和smallbin容易产生漏洞。我们一般是通过已知的全局变量伪造一个已经free的chunk。
chunk在free的时候会进行合并空闲chunk的操作,有向前和向后两种。我们在事先分配的一个chunk中伪造一个空闲chunk——通过修改prev_inuse位来改变prev chunk的状态,再修改fd和bk指针绕过检查,这样高地址的chunk在free的时候就会认为prev chunk是空闲的,从而合并它。合并之后,p的指针会变为p-0x18。
chunk结构图
inuse chunk和free chunk的结构
malloc后返回的地址指向的是不加0x10(10进制的16,即
2*sizeof(size_t)
)的头部数据的地址,而chunks真实的ptr是包含头部数据的地址,即fast bins等中fd指针(或者其他bins中的bk指针)指向malloc_ptr-0x10。
出现场景
malloc
从恰好大小合适的largebin中获取chunk,从比malloc要求大的largebin中取chunk。
malloc_consolidate()函数
用于将 fast bins 中的 chunk 与其物理相邻的chunk合并,并加入 unsorted bin 中。分为高地址(除top chunk)合并和低地址合并。
realloc
向前扩展,合并物理相邻高地址空闲chunk。
free
free之后,与前后空闲的chunk进行合并。
如果chunk不是 mmap生成的,并且物理相邻的前一个或者下一个chunk处于空闲状态,就需要进行合并。同样分为高地址(除top chunk)合并和低地址合并两种。将合并后的 chunk 加入 unsorted bin 的双向循环链表中。如果合并后的 chunk 属于 large bins,将 chunk 的 fd_nextsize 和 bk_nextsize 设置为 NULL,因为在unsorted bin 中这两个字段无用。
tcahe
tcache_poisoning
原理:修改tcache bin 中chunk的next指针,使其被覆盖为任意地址。
概述
tcache 是 glibc 2.26 (ubuntu 17.10) 之后引入的一种技术(see
commit
),目的是提升堆管理的性能。但提升性能的同时舍弃了很多安全检查,也因此有了很多新的利用方式。
结构体
tcache 引入了两个新的结构体,
tcache_entry
和
tcache_perthread_struct
。
这其实和 fastbin 很像,但又不一样。
tcache_entry
tcache_entry
用于链接空闲的 chunk 结构体,其中的
next
指针指向下一个大小相同的 chunk。
需要注意的是这里的 next 指向 chunk 的 user data,而 fastbin 的 fd 指向 chunk 开头的地址。
而且,tcache_entry 会复用空闲 chunk 的 user data 部分。
tcache_perthread_struct
每个 thread 都会维护一个
tcache_perthread_struct
,它是整个 tcache 的管理结构,一共有
TCACHE_MAX_BINS
个计数器和
TCACHE_MAX_BINS
项 tcache_entry,其中
●
tcache_entry
用单向链表的方式链接了相同大小的处于空闲状态(free 后)的 chunk,这一点上和 fastbin 很像。
●
counts
记录了
tcache_entry
链上空闲 chunk 的数目,每条链上最多可以有 7 个 chunk。
tcache_stashing_unlink_attack
原理
malloc遍历unsorted bin找合适chunk的时候,如果不是恰好合适的大小,就会将其放入对应的small bin或者large bin。如果大小是small bin中的chunk,头插法插入对应链表。
calloc并不会首先从tcache bin中取chunk,而是遍历fast bin、small bin、large bin这些。
从small bin中取出一个chunk后,如果tcache bin有空余,会向剩余位置链入small bin中剩下的chunk。但是只检查了尾部一个的bk指针,并没有全部检查。
参考链接:
https://github.com/shellphish/how2heap/blob/master/glibc_2.35/tcache_poisoning.c
https://wiki.wgpsec.org/knowledge/ctf/how2heap.html
https://bbs.kanxue.com/thread-272416.htm#msg_header_h2_7
0
人收藏
0
人喜欢
转载
分享
1
条评论
某人
表情
可输入
255
字
评论
发布投稿
热门文章
1
2025ISCC练武区域赛和决赛pwn以及擂台pwn合集
2
通过Elastic EDR看smbexec并进行二次开发Bypass
3
php代码审计篇 - 信呼OA 前台注入分析一
4
D3CTF-d3kshrm(预期&非预期)题解
5
Tomcat解析XML引入的新颖webshell构造方式
近期热点
一周
月份
季度
1
2025ISCC练武区域赛和决赛pwn以及擂台pwn合集
2
通过Elastic EDR看smbexec并进行二次开发Bypass
3
php代码审计篇 - 信呼OA 前台注入分析一
4
D3CTF-d3kshrm(预期&非预期)题解
5
Tomcat解析XML引入的新颖webshell构造方式
暂无相关信息
暂无相关信息
优秀作者
1
T0daySeeker
贡献值:28700
2
一天
贡献值:24800
3
1674701160110592
贡献值:18000
4
1174735059082055
贡献值:15000
5
Yale
贡献值:14000
6
LeeH
贡献值:10000
7
MeteorKai
贡献值:9000
8
姓*户
贡献值:8600
9
Arcueid
贡献值:8000
10
熊猫正正
贡献值:8000
目录
前言
UAF
first_fit
fastbin_dup
fastbin_dup_into_stack
fastbin_dup_consolidate
fast_bin_reverse_into_tcache
原理
unsafe_unlink
概述
出现场景
tcahe
tcache_poisoning
概述
结构体
tcache_stashing_unlink_attack
原理
转载
标题
作者:
你好
http://www.a.com/asdsabdas
文章
转载
自
复制到剪贴板