2025CISCN&长城杯半决赛 PWN Prompt详细题解
字数 1622 2025-08-29 08:29:58
2025CISCN&长城杯半决赛 PWN Prompt详细题解
题目概述
这是一个基于Protobuf协议的堆溢出漏洞利用题目,涉及堆块重叠构造、UAF漏洞利用、libc和堆地址泄露、栈地址泄露以及最终通过ORW ROP链获取flag的技术。
初始分析
保护机制检查
首先使用checksec检查程序保护机制,发现开启了seccomp保护,限制了系统调用范围。
逆向分析
使用IDA分析程序,主要关注以下几个关键函数:
-
main函数:
- 程序使用Protobuf协议进行通信
- 根据传入的option参数调用不同功能函数
-
protobuf_unpack函数:
- 首先检查传入的protobuf大小是否匹配
- 然后调用真正的unpack函数解析数据
-
add函数:
- 最多创建16个chunk
- 每个chunk的size限制为不大于0x500
- 创建时会清空chunk内容,防止指针残留泄露基址
- 检查传入的content_size是否小于chunk_size,防止堆溢出
-
delete函数:
- 释放chunk后会将指针置零,没有UAF漏洞
-
edit函数:
- 存在堆溢出漏洞
- 发包传入的size可控,可以再次写入任意大小的数据
-
show函数:
- 使用printf函数打印内容
- 通过\x00截断打印,可用于泄露地址
漏洞利用思路
-
堆溢出漏洞利用:
- 通过edit函数的堆溢出漏洞构造堆块重叠
- 释放重叠后的chunk,手动构造UAF漏洞
-
信息泄露:
- 泄露libc基址
- 泄露堆地址
- 泄露栈地址
-
最终利用:
- 攻击tcache
- 构造ORW ROP链获取flag
详细利用步骤
第一步:构造堆块重叠
- 创建多个chunk(例如chunk4-chunk7)
- 利用edit函数的堆溢出漏洞修改chunk4的size字段为0x1041
- 这样chunk4就包含了chunk5、chunk6和chunk7
- 释放chunk4,使其进入unsorted bin
第二步:泄露libc基址
- 申请一个0x400大小的chunk
- 这会从unsorted bin中分割chunk4
- chunk5中会残留libc地址
- 使用show函数打印chunk5内容
- 通过printf的\x00截断特性泄露libc地址
第三步:手动构造UAF
- 将chunk5、chunk6、chunk7重新申请回来
- 由于堆块重叠,会出现多个指针指向同一个chunk的情况
- 这样就手动构造了UAF漏洞
第四步:泄露堆地址
- 利用UAF漏洞:
- 释放其中一个指针指向的chunk
- 使用另一个指针打印该chunk内容
- 这样可以从堆管理结构中泄露堆地址
第五步:泄露栈地址
- 将两个chunk释放到tcache中
- 例如释放chunk5和chunk6
- 修改chunk6的fd指针指向environ附近
- 不能直接指向environ,因为add函数会清空chunk内容
- 申请到environ附近的chunk
- 填充该chunk内容
- 使用printf的\x00截断特性泄露栈地址
第六步:构造ORW ROP链
- 再次释放两个可控地址到tcache
- 通过UAF修改fd指针指向返回地址
- 将返回地址申请出来
- 在返回地址上构造ORW ROP链:
- open - 打开flag文件
- read - 读取flag内容
- write - 输出flag内容
最终效果
成功构造完整的利用链,绕过所有保护机制,最终获取flag。
关键点总结
- Protobuf协议分析是解题的第一步
- edit函数的堆溢出是漏洞根源
- 通过堆溢出构造堆块重叠是关键技巧
- 手动构造UAF实现信息泄露
- 利用printf的\x00截断特性泄露地址
- 最终通过ORW ROP链绕过seccomp限制获取flag
防御建议
- 严格校验edit函数的size参数
- 在free后不仅要置零指针,还应检查double free
- 考虑使用更安全的打印函数替代printf
- 加强堆管理结构的保护措施