记一道强网杯Pwn题——baby_heap
字数 1833 2025-08-20 18:17:53
强网杯Pwn题baby_heap详细解析与利用技术
题目概述
这是一道来自2024年强网杯的Pwn题目,考察的是堆利用技术,结合了UAF漏洞和putenv调用链修改的技术点。题目提供了经典的菜单程序,包含添加、删除、编辑、显示等功能,并设置了沙箱限制。
题目分析
主要函数功能
-
main函数:经典的菜单布局,提供6个选项:
- 添加商品
- 删除商品
- 编辑商品
- 显示商品
- 环境变量操作
- 任意地址写
-
set_IO函数:
- 使用memset清零
_IO_wfile_jumps及其后0x300字节 - 使用mprotect设置
_IO_wfile_jumps_mmap及其后0x1000字节为只读
- 使用memset清零
-
沙箱限制:
- 禁用了execve、open、openat等系统调用
-
堆操作函数:
- add:最多申请5个堆块,大小限制在[0x500,0x600)区间
- delete:存在UAF漏洞
- edit:只有一次修改机会
- show:只有一次展示机会
-
environment函数:
- 提供setenv、getenv、putenv操作
- putenv函数是本题的关键漏洞点
-
write_whatever函数:
- 提供限定地址内的地址写功能
漏洞点分析
- UAF漏洞:delete函数未清空指针,导致释放后仍可使用
- putenv调用链:
putenv -> strchr -> __libc_alloca_cutoff -> strlen -> __add_to_environ - 关键函数位置:strlen函数在libc的.got.plt段中紧挨着
_GLOBAL_OFFSET_TABLE_+16的位置
利用思路
解法一:篡改strlen@got.plt指向(预期解法)
核心思路:
- 利用UAF泄露libc和堆地址
- 构造ROP链实现openat2和sendfile系统调用
- 通过修改GOT表实现控制流劫持
- 利用putenv调用链触发漏洞
详细步骤:
-
泄露地址:
- 通过large bin attack泄露libc地址
- 通过unsorted bin泄露堆地址
-
构造ROP链:
- 使用mprotect修改堆内存权限
- 使用openat2打开文件
- 使用sendfile读取文件内容
-
GOT表修改:
- 修改
_GLOBAL_OFFSET_TABLE_+8指向可控堆地址 - 修改
_GLOBAL_OFFSET_TABLE_+16为栈迁移gadget - 修改strlen@got.plt指向特定地址
- 修改
-
触发漏洞:
- 调用putenv触发修改后的调用链
- 执行ROP链获取flag
关键代码:
# 构造ROP链
New_orw = p64(pop_rdi) + p64(heap - 0x950) + p64(pop_rsi) + p64(0x1000) + p64(pop_rdx_r12) + p64(7) + p64(0) + p64(mprotect) + p64(heap+0x78)
New_orw += asm(shellcraft.pushstr('./flag') + shellcraft.openat2(-100, 'rsp', heap_base+0x3000, 0x30) + shellcraft.sendfile(1, 3, 0, 0x1000))
# 修改GOT表
cmd(6)
p.sendafter(b'Input your target addr \n',p64(GOT_1))
p.send(p64(pop_rsp_13_14_15_rbp) + p64(PLT_GOT_0))
解法二:篡改strncmp@got.plt指向(非预期解法)
核心思路:
- 修改strncmp@got.plt指向puts函数
- 利用putenv调用链中的strncmp调用泄露环境变量
- 从环境变量中获取flag
详细步骤:
- 泄露libc地址
- 获取strncmp@got.plt地址
- 修改strncmp@got.plt指向puts
- 调用putenv触发环境变量打印
关键代码:
# 修改strncmp@got.plt
cmd(6)
p.sendafter(b'Input your target addr \n',p64(strncmp_got))
p.send(p64(puts))
# 触发putenv
cmd(5)
p.sendlineafter(b'Maybe you will be sad !\n',b'2')
技术要点总结
-
UAF利用:
- 通过释放后重用泄露地址
- 结合large bin attack实现信息泄露
-
putenv调用链:
- 理解libc函数调用关系
- 利用strlen在调用链中的关键位置
-
GOT表修改技巧:
- 利用_GLOBAL_OFFSET_TABLE_结构
- 通过修改相邻GOT表项实现控制流劫持
-
沙箱绕过:
- 使用openat2替代被禁用的open/openat
- 使用sendfile读取文件内容
-
ROP链构造:
- 在受限环境下构造有效ROP链
- 使用mprotect修改内存权限
防御建议
-
修复UAF漏洞:
- 释放后及时清空指针
- 使用双重释放检测机制
-
保护GOT表:
- 启用RELRO保护
- 监控GOT表修改行为
-
沙箱加固:
- 限制更多危险系统调用
- 监控非常规系统调用使用
-
环境变量清理:
- 确保比赛环境干净
- 清除敏感环境变量
扩展思考
-
其他可能的利用方式:
- 利用__free_hook等传统hook点
- 结合IO_FILE结构进行利用
-
防御演进:
- 如何防御类似的GOT表修改攻击
- 更严格的沙箱策略设计
-
相关技术延伸:
- House of系列堆利用技术
- 其他环境变量相关漏洞
这道题目展示了现代Pwn题目中堆利用与环境变量操作的结合,对理解libc内部机制和复杂漏洞利用链的构建有很好的学习价值。