单字节延迟绑定实现rop
字数 1889 2025-08-29 08:30:06
单字节延迟绑定实现ROP攻击技术详解
1. 题目背景与保护措施分析
题目提供了一个有趣的挑战场景:在只能写入单个字节的情况下,利用延迟绑定机制实现完整的ROP攻击链,最终获取shell或实现ORW(Open-Read-Write)操作。
1.1 程序保护机制
- 程序启用了常规保护措施
- GOT表可写
- 无RELRO保护(Partial或No RELRO)
1.2 程序关键特点
- main函数中仅包含exit调用
- 漏洞函数在init函数中被调用
- init函数位于start函数中,在main函数之前执行
2. 漏洞利用基础:ret2dl_resolve技术
2.1 延迟绑定机制概述
当程序第一次调用动态链接函数时:
- 通过PLT表跳转到GOT表
- GOT表会寻找函数真实地址并回填
- 后续调用直接从PLT跳转到GOT再到真实地址
2.2 关键结构体
-
Dyn结构体:描述动态链接信息
d_tag:标记值,指明结构体类型d_un:联合体,存储不同类型信息
-
Sym结构体:描述ELF符号信息
st_name:字符串表索引st_info:符号类型信息st_other:决定link_map参数有效性st_value:符号地址偏移
-
Rel结构体:描述重定位信息
r_offset:加上link_map->l_addr等于GOT表地址r_info:符号索引和类型信息
-
link_map结构体:存储目标函数查询结果
l_addr:目标函数所在lib的基址l_info:Dyn结构体指针数组
2.3 _dl_fixup函数关键逻辑
if (__builtin_expect(ELFW(ST_VISIBILITY)(sym->st_other), 0) == 0) {
// 重定位策略
}
2.4 攻击方式
-
改写.dynamic的DT_STRTAB(仅NO RELRO可行)
- 修改.dynamic中字符串表指针到可控内存
- 伪造函数名实现任意函数调用
-
操纵第二个参数指向伪造的Rel
- 利用_dl_runtime_resolve无越界检查的特性
- 伪造.rel.plt、.dynsym和.dynstr
- 最终调用目标函数
3. 单字节利用技术详解
3.1 初始条件利用
- 程序循环调用漏洞函数
- write函数未被正确填写,每次都会执行延迟绑定
- 通过单字节修改实现循环写入
3.2 改写exit GOT表
-
找到link_map相对于libc的偏移量
- 位于ld文件中
- 在_rtld_global中查找ns_loaded段
-
修改link_map->l_addr
- 计算exit GOT表与write GOT表的偏移
- 写入link_map偏移位置
3.3 泄露libc地址
-
修改stdout的flag字段和write指针
- flag字段改为0xfbad3887
- IO_write_ptr改为0xff
-
触发IO刷新
- 修改l_info[DT_SYMTAB]的LSB指向DT_DEBUG
- 在DT_DEBUG区域伪造"_IO_flush_all"字符串
-
关键步骤:
# 修改l_info[DT_SYMTAB]指向DT_DEBUG write(l_info_DT_SYMTAB_addr, 0xB8) # 单字节修改
3.4 伪造IO结构体
-
恢复write函数GOT表
write(0x2C9338, 0x78) # 恢复原始值 -
伪造IO_FILE结构体
- 直接修改现有结构体
- 设置vtable指针等关键字段
-
修改io_list_all指针
- 指向可控堆块
- 构造完整攻击链
4. 完整利用步骤
- 利用单字节写入修改link_map->l_addr
- 将write的解析重定向到exit
- 构造循环写入条件
- 修改l_info[DT_SYMTAB]指向DT_DEBUG
- 在DT_DEBUG区域伪造"_IO_flush_all"
- 设置stdout的flag和write指针
- 触发IO刷新泄露libc地址
- 恢复write函数GOT表
- 伪造IO_FILE结构体
- 修改io_list_all指针
- 最终获取shell或实现ORW
5. 关键调试技巧
-
查找link_map偏移:
p/x ((struct r_debug *)0x7ffff7ffe118)->r_map p/x ((struct link_map *)0x7ffff7ffe2d0)->l_info[5] -
查找DT_DEBUG地址:
- 在.dynamic段中搜索d_tag为0x15的条目
-
验证修改效果:
- 检查_dl_lookup_symbol_x函数的rdi参数
- 确认解析的函数名是否正确
6. 防御措施
- 启用FULL RELRO保护
- 限制动态链接器的可写内存区域
- 对_dl_runtime_resolve添加边界检查
- 保护link_map关键数据结构
7. 扩展思考
- 在更严格保护下的利用可能性
- 其他单字节写入的利用场景
- 结合堆漏洞的复合利用方式
- 不同glibc版本间的差异处理
通过这种精妙的单字节利用技术,即使在极端受限的条件下,也能构建完整的攻击链,展示了二进制漏洞利用的艺术性和技术深度。