glibc中realloc函数源码分析与利用
字数 2020 2025-08-29 08:29:58
glibc中realloc函数源码分析与利用
1. realloc函数概述
realloc函数是C标准库中用于重新分配内存块大小的函数,其原型为:
void *realloc(void *ptr, size_t size);
realloc函数的行为取决于传入的参数组合:
- 当
ptr为NULL时,等同于malloc(size) - 当
size为0且ptr不为NULL时,等同于free(ptr) - 当
ptr不为NULL且size大于0时,尝试调整内存块大小
2. realloc源码分析
2.1 基本流程
realloc函数的核心逻辑在_int_realloc函数中实现,主要处理以下几种情况:
情况1:oldmem为空 (ptr == NULL)
- 直接调用malloc分配新chunk
- 等同于malloc(size)
情况2:oldmem不为空且size == 0
- 调用free释放ptr指向的chunk
- 返回NULL
- 等同于free(ptr)
情况3:oldmem不为空且size > oldsize
- 尝试扩展现有chunk
- 如果相邻高地址有足够空间(top chunk或free chunk),则合并扩展
- 否则分配新chunk并复制数据
情况4:oldmem不为空且size < oldsize
- 尝试分割现有chunk
- 如果剩余空间足够大,则分割并释放剩余部分
- 否则保持原chunk不变
2.2 关键代码路径
- 检查realloc_hook指针(与malloc和free类似)
- 进入
_int_realloc函数,参数为oldsize和nb(请求大小) - 判断下一个chunk是否是top chunk:
- 如果是top chunk且空间足够,则从top chunk分割
- 更新size字段和main_arena的top指针
- 如果相邻chunk是free chunk:
- 检查是否可以合并(unlink操作)
- 合并后分割,释放剩余部分
3. realloc的利用技术
3.1 利用场景
-
从top chunk分割:
- 当请求大小大于原chunk且相邻top chunk有足够空间时
- 可用于构造特定大小的chunk
-
unlink合并操作:
- 当相邻高地址chunk为free状态时
- 可触发unlink操作,造成堆块重叠
- 需要伪造prev_size和size字段
-
off-by-one漏洞利用:
- 通过修改size字段最低字节
- 可构造伪造的chunk结构
3.2 具体利用方法
方法1:利用unlink造成overlapping
-
构造场景:
- chunk1(可控)
- chunk2(目标)
- 通过off-by-one修改chunk1的size字段,使其包含伪造的fake_chunk
-
伪造结构:
- 修改chunk1的size和prev_size字段
- 在chunk2中伪造fake_chunk结构,满足unlink检查
-
触发realloc:
- 对chunk1进行realloc,size大于修改后的size
- 触发unlink操作,合并fake_chunk
- 造成chunk2的fd/bk指针被覆盖
方法2:直接修改size字段
- 构造多个chunk
- 利用漏洞(如off-by-one)修改中间chunk的size字段
- 通过realloc操作获得修改后的chunk
- 覆盖后续chunk的关键字段(如fd/bk)
3.3 例题分析:[广东强网杯 2021 团队组]GirlFriend
-
漏洞点:
- off-by-one漏洞,可修改size字段最低字节
- add操作限制16次
- show函数仅一次机会
-
利用步骤:
- 申请三个chunk
- 利用第一个chunk修改第二个chunk的size字段
- 释放并重新申请,获得修改后的chunk
- 覆盖第三个chunk的fd指针为free_hook
- 申请free_hook并写入setcontext+51进行栈迁移
- 在libc上布置ORW链
-
关键点:
- libc-2.27中tcache仅检查头指针是否为空,不检查count
- 可直接申请到free_hook而不受count限制
4. 防御与绕过
-
unlink检查:
- 现代glibc加强了unlink的双向链表检查
- 需要精心构造fake_chunk满足检查
-
tcache机制:
- libc-2.30后tcache会检查count
- 需要确保tcache中有可用chunk
-
size字段检查:
- 对size字段的合法性检查更严格
- off-by-one利用难度增加
5. 总结
realloc函数的利用关键在于:
- 理解不同参数组合下的行为差异
- 掌握
_int_realloc中的合并与分割逻辑 - 利用unlink操作造成堆块重叠
- 结合其他漏洞(如off-by-one)修改关键字段
与malloc/free相比,realloc的利用更复杂但也更灵活,特别是在只有单个指针控制的场景下,通过精心构造可以绕过一些常规防护措施。