前言
终于抽出时间对glibc动态内存管理部分源码进行初略的探究,试着从源码和动调来分析free函数执行过程和一些pwn的攻击技巧,分析的不是很全面,有错误的地方望提出指正,共同进步。ps:欢迎白帽子们关注 涂鸦智能安全响应中心。
Free in fastbin
正常情况下的free in fastbin
测试代码
Free -> libc_free,正常进入 free(p1)时,free_hook为空,修改free_hook为onegadget或者其他payload 可以任意执行
非mmap空间,进入 int_free()
Chunk_size的检查
Chunk_size <= 0x80 进入 fastbin的处理
对相邻下一块chunk进行size的对齐检查
Fastbin 建立 与串联链表 部分
触发double free 异常
free(p1);
free(p1);
此时free_chunk与 old相等 导致报错
Double free绕过方式
测试代码
Double free p1需要先释放另一个满足此fastbin size的堆块,修改old
运行结果
再次申请一个fastbin size的chunk,修改chunk的fd指针后,完成use after free,控制fastbin的申请区域
Use after free
代码
释放堆块后未对指针置空,并且能修改指针的情况下,可以直接use after free
运行结果:
之后第二次的malloc(0x20 ~ 0x2f)的申请 可以请求到构造的fake_chunk地址上。
Malloc in fastbin
测试代码
Fastbin 处理代码 位于 int_malloc(),类似于int_free()中fastbin处理,是一个相互的逆过程
fastbins链表结构为 main_arena + 0x10 -> p2 -> p1->0
对于取出fastbins表头的校验
之后对fastbin[0x20]表进行替换列表头的操作
之后对取出chunk的size进行检测(伪造size需要满足size移位之后等于对应的idx,即 若idx=7时fake_size应满足 0x70 ~ 0x7f)
程序运行结果
Free in unsortedbins
第一次进行free_in_unsortedbin
测试代码
由free() -> __int_free(),不满足之前对于fastbin的检测后,接着进行下面的逻辑判断,对于top_chunk的保护以及size是否对齐的判断
之后进入 unsortedbin 的处理部分(涉及 chunk overlap绕过技巧)
之后进入 unsortedbin 的链表处理,此时 fwd == bck,之后进行unsortedbin双链表的串联
此时的链表示意图,为了方便展示将fwd 和 bck分开放置
堆块向前overlapping
测试代码
通过置空prev_inuse 设置fake prev_size 欺骗unsortedbins的合并堆块机制
构造合适的prev_size 可以使堆块合并在已经被free的unsortedbin上,吞并未被释放的p2,p3
fake_prev_size = size_p1 + size_p2 + size_p3 = 0xb0 + 0x20 + 0x20 = 0xf0
之后重写写上size+ prev_size 的chunk头和下一块堆块的prev_size后,完成堆块的吞并
之后再申请出制定大小的堆块后,可以用于构造fastbin中的use after free
Unlink
测试代码
How2heap/glibc-2.23/unsafe_unlink.c
Unlink触发过程,伪造上一个堆块已被释放
unlink函数源代码
构造的堆块
Gdb没有挂载到unlink函数 直接分析汇编代码对应源码
p->prev_size 是否为0
builtin_expect (P->fd_nextsize->bk_nextsize != P, 0)
builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)
之后汇编代码逻辑
目标地址 0x601068(P->fd_nextsize -> bk_nextsize P->bk_nextsize -> fd_nextsize 为同一地址)
目标地址先被写上 p->bk_nextsize(0x601058)
接着写上 p->fd_nextsize(0x601050)
1.伪造 被释放堆块的prev_inuse和prev_size
2.伪造被释放堆块的prev_chunk 的 fd_nextsize 和 bk_nextsize
3.fd_nextsize = target – 0x18 bk_nextsize = target – 0x10,目标地址target 被写上 fd_nextsize
Malloc in unsortedbins
正常处理逻辑
测试代码
对 0x128 的unsortedbins 申请 0x100的chunk
unsortedbin 申请chunk代码段在 _int_malloc()函数中
运行效果:清空unsortedbins的操作为在 main_arena中清空 bins 表
之后 通过bck赋值变量fwd
改变申请的堆块的fd和bk指针
申请出的chunk被串入双链表
之后将申请出的chunk写上正确的size,并将剩余的bin串入 unsortedbins 并且写上size
Remainder 堆块的设置
House_of_lore
若双链表的bk指针被篡改指向伪造区域,并且在伪造的区域满足fd指针等于victim,申请到的堆地址将可控
测试代码:
how2heap/glibc-2.23/house_of_lore.c
先利用正常情况free一个smallbin进入 unsortedbins
此时双链表正常,之后篡改 unsortedbin的bk指针
之后进入 _int_malloc()的处理的校验逻辑
伪造的堆块被串联进入 bin
再次申请smallbins,申请到了伪造区域
本文作者:Jambolt@涂鸦智能安全实验室
漏洞悬赏计划:涂鸦智能安全响应中心(https://src.tuya.com) 欢迎白帽子来探索。
招聘内推计划:涵盖安全开发、安全测试、代码审计、安全合规等所有方面的岗位,简历投递sec@tuya.com,请注明来源。
发表评论
您还未登录,请先登录。
登录