HTB Dream Diary: Chapter 4 复盘详解
字数 2290 2025-12-06 12:12:25
HTB Dream Diary: Chapter 4 漏洞利用详解
题目概述
题目名称:HTB Dream Diary: Chapter 4
难度等级:INSANE
保护机制:Full RELRO、Stack Canary、NX、PIE
libc版本:2.32(引入指针加密机制)
沙箱策略:黑名单沙箱,禁用execve、open等危险系统调用
逆向分析
初始化函数分析
int (**protect_init())(const char *s) {
seccomp_init(); // 初始化沙箱
boundary_start = (&puts + 0x28F7E); // 设置内存申请边界
boundary_end = (&puts + 0x2957E);
}
沙箱规则分析
通过seccomp-tools dump分析沙箱规则:
- 禁用:execve、execveat、open、creat、fork、vfork等
- 允许:read、write、mprotect、mmap等
核心数据结构
struct page { // 大小0x320字节
__int64 type; // 页面类型:1=只读,2=可读写
char buf_[776]; // 数据缓冲区
__int64 fd; // 前向指针
__int64 bk; // 后向指针
};
功能模块分析
添加页面(add)
- 两种分配方式:malloc(不清空内存)、calloc(清空内存)
- 大小固定为0x320字节
- 通过双向循环链表管理
- 内存范围检查:禁止申请libc的rw段内存
删除页面(delete) - 关键漏洞
if (traverse_and_select() || count != 1) {
// 断链操作
fd = ::current->fd;
bk = ::current->bk;
fd->bk = bk;
bk->fd = fd;
free(::current);
::current = current; // UAF:指针指向已释放内存
}
漏洞点:当count=1时,释放后current指针未清空,产生UAF
编辑页面(edit)
- 只能编辑type=2的可读写页面
- 可对UAF的chunk进行写操作
利用策略
阶段一:信息泄露
堆布局策略
- 申请9个chunk(0x320大小)
- 释放前6个填充tcachebin(7/7)
- 释放第7、8个合并为0x660的unsortedbin chunk
- 释放第9个进入tcachebin
触发sorting机制
关键技术:利用scanf内部缓冲区机制
- scanf初始栈缓冲区大小:0x400
- 输入超过0x400字节触发malloc(0x800)
- 这将把unsortedbin chunk排序到largebin
泄露地址
- 通过malloc申请chunk(保留原有数据)
- 打印内容泄露heap和libc地址
- heap地址:从largebin chunk的fd/bk泄露
- libc地址:从unsortedbin chunk的bk泄露main_arena
阶段二:TSU+攻击
Tcache Stashing Unlink Attack Plus原理
当smallbin不为空且tcache未满时:
// glibc malloc.c 逻辑
while (tcache->counts[tc_idx] < mp_.tcache_count
&& (tc_victim = last(bin)) != bin) {
// 将smallbin chunk转移到tcache
}
通过修改smallbin chunk的bk指针,实现任意地址分配。
攻击tcache_perthread_struct
优势:绕过safe-linking指针加密
- 目标地址:heap_base + 0x200(tcache_perthread_struct位置)
- 条件满足:目标地址+0x18处有可写指针
布局步骤
- 构造smallbin链:A → B → C(C为可控UAF chunk)
- 修改C的bk指向tcache_perthread_struct - 0x10
- 申请small size chunk触发TSU+
- 获得tcache_perthread_struct的控制权
阶段三:劫持free_hook
修改tcache条目
- 控制tcache_perthread_struct后,修改0x330大小的tcache条目
- 将条目指向free_hook - 0x10(因为写操作从+8偏移开始)
COP Gadget利用
mov rdx, [rdi+8] ; 可控:rdi指向chunk,[rdi+8]可控
mov [rsp], rax
call [rdx+0x20] ; 可控跳转
利用链:
- free(chunk) → rdi=chunk_addr
- 通过COP gadget设置rdx
- 调用[rdx+0x20] = setcontext+61进行栈迁移
阶段四:绕过沙箱执行
栈迁移到堆
- 目标地址:heap_base + 0x308
- 布置ROP链调用mprotect修改内存权限
x86/x64架构切换
; 切换至x86模式执行shellcode
push 0x23 ; x86代码段选择子
push x86_entry
retfq
x86_entry:
; x86 shellcode在这里执行
无execve读取flag
Shell内置命令绕过:
echo * # 查看目录文件
read line < flag; echo $line # 读取flag文件
替代方案(如需要shellcode):
- 使用openat+sendfile系统调用
- 避免被沙箱拦截的系统调用
完整利用流程
堆风水布局
- 初始堆布局:9个chunk精心排列
- 触发scanf的malloc(0x800)进行sorting
- 泄露heap和libc基址
攻击序列
- 信息泄露:通过largebin残留数据泄露关键地址
- TSU+攻击:构造smallbin链,修改bk实现任意写
- 劫持控制流:通过tcache_perthread_struct控制tcache,打free_hook
- 栈迁移:COP + setcontext将栈迁移到堆
- 权限修改:ROP调用mprotect使shellcode可执行
- 架构切换:retfq切换到x86模式执行shellcode
- 读取flag:使用Shell内置命令绕过沙箱
技术要点总结
关键技术突破
- scanf内部机制利用:通过输入长度控制触发特定大小malloc
- TSU+攻击优化:直接攻击tcache_perthread_struct绕过指针加密
- COP Gadget应用:创新的控制流转移方式
- 多架构shellcode:x64到x86切换绕过沙箱限制
防护绕过技巧
- Safe-linking绕过:通过结构体攻击避免指针解密
- 沙箱绕过:利用Shell内置命令+架构切换
- 内存保护绕过:精确的堆布局和ROP链构造
扩展思考
漏洞利用的演进
从传统的tcache poisoning到TSU+攻击,体现了对glibc内存管理机制深入理解的重要性。
防御建议
- 加强UAF漏洞的检测和防护
- 对敏感函数指针进行额外保护
- 沙箱规则需要更加精细化
本案例展示了现代pwn题目中多种高级技术的综合应用,为堆漏洞利用提供了重要的技术参考。