2025CISCN&长城杯半决赛 PWN Prompt详细题解
字数 1622 2025-08-29 08:29:58

2025CISCN&长城杯半决赛 PWN Prompt详细题解

题目概述

这是一个基于Protobuf协议的堆溢出漏洞利用题目,涉及堆块重叠构造、UAF漏洞利用、libc和堆地址泄露、栈地址泄露以及最终通过ORW ROP链获取flag的技术。

初始分析

保护机制检查

首先使用checksec检查程序保护机制,发现开启了seccomp保护,限制了系统调用范围。

逆向分析

使用IDA分析程序,主要关注以下几个关键函数:

  1. main函数

    • 程序使用Protobuf协议进行通信
    • 根据传入的option参数调用不同功能函数
  2. protobuf_unpack函数

    • 首先检查传入的protobuf大小是否匹配
    • 然后调用真正的unpack函数解析数据
  3. add函数

    • 最多创建16个chunk
    • 每个chunk的size限制为不大于0x500
    • 创建时会清空chunk内容,防止指针残留泄露基址
    • 检查传入的content_size是否小于chunk_size,防止堆溢出
  4. delete函数

    • 释放chunk后会将指针置零,没有UAF漏洞
  5. edit函数

    • 存在堆溢出漏洞
    • 发包传入的size可控,可以再次写入任意大小的数据
  6. show函数

    • 使用printf函数打印内容
    • 通过\x00截断打印,可用于泄露地址

漏洞利用思路

  1. 堆溢出漏洞利用

    • 通过edit函数的堆溢出漏洞构造堆块重叠
    • 释放重叠后的chunk,手动构造UAF漏洞
  2. 信息泄露

    • 泄露libc基址
    • 泄露堆地址
    • 泄露栈地址
  3. 最终利用

    • 攻击tcache
    • 构造ORW ROP链获取flag

详细利用步骤

第一步:构造堆块重叠

  1. 创建多个chunk(例如chunk4-chunk7)
  2. 利用edit函数的堆溢出漏洞修改chunk4的size字段为0x1041
    • 这样chunk4就包含了chunk5、chunk6和chunk7
  3. 释放chunk4,使其进入unsorted bin

第二步:泄露libc基址

  1. 申请一个0x400大小的chunk
    • 这会从unsorted bin中分割chunk4
    • chunk5中会残留libc地址
  2. 使用show函数打印chunk5内容
    • 通过printf的\x00截断特性泄露libc地址

第三步:手动构造UAF

  1. 将chunk5、chunk6、chunk7重新申请回来
    • 由于堆块重叠,会出现多个指针指向同一个chunk的情况
  2. 这样就手动构造了UAF漏洞

第四步:泄露堆地址

  1. 利用UAF漏洞:
    • 释放其中一个指针指向的chunk
    • 使用另一个指针打印该chunk内容
  2. 这样可以从堆管理结构中泄露堆地址

第五步:泄露栈地址

  1. 将两个chunk释放到tcache中
    • 例如释放chunk5和chunk6
  2. 修改chunk6的fd指针指向environ附近
    • 不能直接指向environ,因为add函数会清空chunk内容
  3. 申请到environ附近的chunk
    • 填充该chunk内容
  4. 使用printf的\x00截断特性泄露栈地址

第六步:构造ORW ROP链

  1. 再次释放两个可控地址到tcache
  2. 通过UAF修改fd指针指向返回地址
  3. 将返回地址申请出来
  4. 在返回地址上构造ORW ROP链:
    • open - 打开flag文件
    • read - 读取flag内容
    • write - 输出flag内容

最终效果

成功构造完整的利用链,绕过所有保护机制,最终获取flag。

关键点总结

  1. Protobuf协议分析是解题的第一步
  2. edit函数的堆溢出是漏洞根源
  3. 通过堆溢出构造堆块重叠是关键技巧
  4. 手动构造UAF实现信息泄露
  5. 利用printf的\x00截断特性泄露地址
  6. 最终通过ORW ROP链绕过seccomp限制获取flag

防御建议

  1. 严格校验edit函数的size参数
  2. 在free后不仅要置零指针,还应检查double free
  3. 考虑使用更安全的打印函数替代printf
  4. 加强堆管理结构的保护措施
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 加强堆管理结构的保护措施