exit_hook攻击利用
字数 1460 2025-08-20 18:17:41

exit_hook攻击利用技术详解

概述

exit_hook攻击是一种针对glibc动态链接器机制的利用技术,通过劫持程序退出时的处理流程来实现代码执行。本文将详细分析该技术的原理、利用条件、实现方法以及实际案例。

适用版本

  • 适用于glibc-2.34之前的版本
  • glibc-2.34及以后版本已失效

利用条件

  1. 内存写入能力

    • 至少需要一次任意地址写入能力
    • 理想情况下需要两次任意地址写入能力
  2. 程序退出条件

    • 程序可以显式触发exit函数
    • 或者主函数由libc_start_main启动且可正常退出,从而调用到_dl_fini函数

技术原理分析

退出流程分析

当程序退出时,会调用exit函数,其执行流程如下:

  1. exit函数调用__run_exit_handlers
  2. __run_exit_handlers进一步调用_dl_fini函数
  3. _dl_fini函数会访问_rtld_global结构体中的两个关键函数指针:
    • rtld_lock_default_lock_recursive
    • rtld_lock_default_unlock_recursive

关键数据结构

_rtld_global结构体(位于ld.so中)包含以下关键字段:

  • rtld_lock_default_lock_recursive (偏移0xf08)
  • rtld_lock_default_unlock_recursive (偏移0xf10)
  • _dl_load_lock (偏移0x908) - 可作为参数存储区

攻击方式

  1. 一次任意写

    • 直接将rtld_lock_default_lock_recursive修改为one_gadget地址
    • 成功率取决于one_gadget的约束条件
  2. 两次任意写(更可靠):

    • 第一次写:修改rtld_lock_default_lock_recursive为system函数地址
    • 第二次写:修改_dl_load_lock为"/bin/sh\x00"字符串
    • 程序退出时会执行system("/bin/sh")

实际案例分析

案例1:The fastest man

利用步骤

  1. 绕过密码验证(发现base64编码中有key)

  2. 获取libc基地址

  3. 计算关键地址:

    ld_base = libc_base + 0x213000
    _rtld_global = ld_base + ld.sym['_rtld_global']
    _dl_rtld_lock_recursive = _rtld_global + 0xf08
    
  4. 将one_gadget写入_dl_rtld_lock_recursive

EXP关键代码

ru('give me a address:')
sl(str(_dl_rtld_lock_recursive))
sla('give me a value:',str(ogg))  # ogg为one_gadget地址

案例2:2023蓝帽杯半决赛-uaf

利用特点

  • 通过UAF漏洞结合程序提供的任意写机会
  • 直接修改exit_hook实现利用

EXP关键代码

adm('shu',2)  # 触发任意写
_rtld_global = libc_base+0x226060
_dl_rtld_lock_recursive = _rtld_global + 0xf08
ru('WRITE MODE: ')
s(p64(_dl_rtld_lock_recursive))
og = libc_base + 0xe6c7e  # one_gadget
s(p64(og))

案例3:WMCTF2023-blindless

特殊场景

  • 无信息泄露,需要爆破3位地址(1/4096概率)
  • 通过mmap分配大内存实现越界写

利用步骤

  1. 申请超大内存触发mmap
  2. 计算_rtld_global相关地址
  3. 构造payload写入system和"/bin/sh"

EXP关键代码

payload = b'@' + p32(argv0 - 0x10) + write(b'/bin/sh\x00')
payload += b'@' + p32(rtld_lock - argv0 - 8) + write(b'\x90\x02\x46') #system

防御措施

  1. 升级到glibc-2.34或更高版本
  2. 加强内存写保护机制
  3. 监控关键函数指针的修改行为

参考链接

  1. exit hook - 狒狒猩橙 - 博客园
  2. WMCTF2023 pwn 部分wp - 知乎

总结

exit_hook攻击是一种在特定glibc版本下有效的利用技术,特别适合在有任意写能力但缺乏信息泄露的场景。通过深入理解动态链接器的内部机制,攻击者可以绕过多种保护措施实现代码执行。防御方面应及时升级系统库,并加强对关键内存区域的保护。

exit_ hook攻击利用技术详解 概述 exit_ hook攻击是一种针对glibc动态链接器机制的利用技术,通过劫持程序退出时的处理流程来实现代码执行。本文将详细分析该技术的原理、利用条件、实现方法以及实际案例。 适用版本 适用于glibc-2.34之前的版本 glibc-2.34及以后版本已失效 利用条件 内存写入能力 : 至少需要一次任意地址写入能力 理想情况下需要两次任意地址写入能力 程序退出条件 : 程序可以显式触发exit函数 或者主函数由libc_ start_ main启动且可正常退出,从而调用到_ dl_ fini函数 技术原理分析 退出流程分析 当程序退出时,会调用exit函数,其执行流程如下: exit函数调用 __run_exit_handlers __run_exit_handlers 进一步调用 _dl_fini 函数 _dl_fini 函数会访问 _rtld_global 结构体中的两个关键函数指针: rtld_lock_default_lock_recursive rtld_lock_default_unlock_recursive 关键数据结构 _rtld_global 结构体(位于ld.so中)包含以下关键字段: rtld_lock_default_lock_recursive (偏移0xf08) rtld_lock_default_unlock_recursive (偏移0xf10) _dl_load_lock (偏移0x908) - 可作为参数存储区 攻击方式 一次任意写 : 直接将 rtld_lock_default_lock_recursive 修改为one_ gadget地址 成功率取决于one_ gadget的约束条件 两次任意写 (更可靠): 第一次写:修改 rtld_lock_default_lock_recursive 为system函数地址 第二次写:修改 _dl_load_lock 为"/bin/sh\x00"字符串 程序退出时会执行 system("/bin/sh") 实际案例分析 案例1:The fastest man 利用步骤 : 绕过密码验证(发现base64编码中有key) 获取libc基地址 计算关键地址: 将one_ gadget写入 _dl_rtld_lock_recursive EXP关键代码 : 案例2:2023蓝帽杯半决赛-uaf 利用特点 : 通过UAF漏洞结合程序提供的任意写机会 直接修改exit_ hook实现利用 EXP关键代码 : 案例3:WMCTF2023-blindless 特殊场景 : 无信息泄露,需要爆破3位地址(1/4096概率) 通过mmap分配大内存实现越界写 利用步骤 : 申请超大内存触发mmap 计算 _rtld_global 相关地址 构造payload写入system和"/bin/sh" EXP关键代码 : 防御措施 升级到glibc-2.34或更高版本 加强内存写保护机制 监控关键函数指针的修改行为 参考链接 exit hook - 狒狒猩橙 - 博客园 WMCTF2023 pwn 部分wp - 知乎 总结 exit_ hook攻击是一种在特定glibc版本下有效的利用技术,特别适合在有任意写能力但缺乏信息泄露的场景。通过深入理解动态链接器的内部机制,攻击者可以绕过多种保护措施实现代码执行。防御方面应及时升级系统库,并加强对关键内存区域的保护。