菜鸡pwn手对于exit漏洞的探索
字数 1609 2025-08-29 22:41:24
exit漏洞利用技术深入解析
一、漏洞背景与基本原理
exit函数是程序正常退出的重要函数,其内部调用链中存在可利用的漏洞点。传统认知中,exit漏洞利用通常通过exit->__run_exit_handlers->tls_call_dtors路径劫持结构体跳表,但研究发现存在更直接的利用路径。
关键调用链
exit --> __run_exit_handlers --> [取exit_funcs结构体initial数组+0x18偏移位置的加密指针] -> [用fs:[0x30]内容解密指针] --> _dl_fini
二、核心结构体分析
exit_function结构体
这是控制整个流程的核心结构体,包含以下关键成员:
initial:指向控制结构体的指针idx:迭代变量,控制循环次数flavor:分支选择器,决定执行路径
initial结构体
包含实际执行的函数指针和参数:
- 加密的函数指针(通过PTR_DEMANGLE解密)
- 可控制的参数(arg)
- 其他控制流程的成员
三、利用条件
-
内存操作能力:
- 能够任意地址分配内存
- 能够自由读取内存内容(show)
- 能够任意地址写入chunk地址
-
信息泄露能力:
- 能够泄露libc基地址
- 能够篡改/泄露TLS结构体内容
四、利用技术细节
1. 指针控制机制
通过控制exit_function结构体中的initial指针,可以完全控制函数行为:
- 篡改
initial指针指向可控区域 - 控制
idx实现无限循环 - 通过
flavor选择执行分支
2. 函数指针加密机制
函数指针使用TLS中的pointer_chk_guard进行加密:
#define PTR_DEMANGLE(var) \
(var) = (__typeof (var)) ((uintptr_t) (var) >> 0x11) ^ (uintptr_t) (var)
3. 加密密钥获取方式
有两种主要方法获取/控制加密密钥:
-
largebin attack:
- 将堆地址写到
pointer_chk_guard - 使用堆地址计算加密密钥
- 将堆地址写到
-
内存泄露:
- 分配到initial结构体处的chunk
- 泄露原有加密函数指针
- 与真实函数地址计算得到
pointer_chk_guard
4. 参数控制
通过伪造initial结构体可以控制:
- 函数指针(加密后)
- 第一个参数(
arg) - 第二个参数(
status)
五、完整利用流程(POC)
1. 初始准备
- 准备四个chunk,形成两条largebins链
- 释放两个chunk到unsortedbin泄露libc和堆地址
2. 计算加密指针
- 通过堆地址计算加密密钥
- 准备要写入的伪造initial结构体
3. largebin攻击
- 篡改两个largebin头的
bk_nextsize指针- 一个指向TLS->pointer_chk_guard
- 一个指向exit_function
- 将unsortedbin放入largebins完成指针篡改
4. 触发利用
- 调用exit触发漏洞
- 控制流程执行预设函数链(如puts->puts->system)
六、技术难点与限制
-
TLS地址控制:
- largebin attack只能写堆地址到
pointer_chk_guard - 需要额外泄露堆地址
- TLS地址在ASLR下与ld地址偏移固定,泄露复杂
- largebin attack只能写堆地址到
-
initial结构体伪造:
- largebin attack写入的堆块可能包含arena指针
- chunk头的size会影响
idx导致多余循环 - 可能造成环境不稳定
-
ASLR影响:
- TLS地址随机化增加利用难度
- 需要精确计算偏移
七、优化方向
-
更精确的initial控制:
- 寻找更精确的initial结构体写入方式
- 减少不必要的循环
-
密钥获取替代方案:
- 寻找不依赖堆地址的密钥获取方式
- 利用其他泄露方法获取TLS信息
-
稳定性提升:
- 优化伪造结构体内容
- 减少对环境状态的依赖
八、防御措施
-
编译选项:
- 启用FORTIFY_SOURCE
- 使用最新的glibc版本
-
运行时保护:
- 加强ASLR保护
- 监控异常exit行为
-
代码审计:
- 检查exit相关调用链
- 验证关键结构体完整性
本技术提供了在特定条件下的强大利用能力,但实现复杂度较高,需要结合具体环境进行调整和优化。