hgame2025 week1 pwn题解
字数 1207 2025-08-22 12:23:24

HGAME2025 Week1 PWN题解教学文档

1. counting petals

程序分析

  • 保护全开
  • init函数中以当前时间戳作为随机数种子
  • 生成的"随机数"可预测

漏洞点

  1. 数组下标溢出:
    • 数组下标最大只到16
    • 如果输入16,则会出现16+1=17的下标,导致数组溢出

利用思路

  1. 绕过随机数检查:

    • 奇数 &1=1,偶数 &1=0
    • 随机数%30后是偶数则输入1,奇数则输入0保证不break
  2. 泄露libc地址:

    • 第一次输入0x0000001300000013覆盖数组下标
    • 利用数组打印功能泄露libc地址
  3. ROP链构造:

    • 第二次输入0x0000001200000016覆盖返回地址
    • 构造ROP链获取shell

调试技巧

  • 使用gdb查看溢出后的内存布局
  • 注意数组下标17处的数据内容

2. format

程序分析

  • 保护基本没开
  • 存在格式化字符串漏洞
  • 每次只能输入3个字节

漏洞点

  1. 整数溢出:

    • main函数中v5是有符号比较
    • vuln函数中是unsigned int类型
    • 输入负数在vuln中会变成巨大数
  2. 格式化字符串漏洞:

    • 受限的3字节输入

利用思路

  1. 初始尝试:

    • 用%p泄露栈地址(受限)
  2. 改进思路:

    • 第一次栈溢出控制rbp为输入的栈地址
    • 返回后利用格式化字符串泄露libc地址
  3. 最终利用:

    • 溢出执行system('/bin/sh')
    • 注意scanf缓冲区会吞掉一个字符

调试要点

  • 注意输入输出异常情况
  • 精确计算输入长度

3. ezstack

程序环境

  • 开启沙箱,禁用execve和execveat
  • 需要通过ORW获取flag
  • 程序作为TCP服务器运行,监听9999端口

程序功能

  • htons设置套接字(0.0.0.0:9999)
  • bind绑定套接字
  • listen监听端口
  • accept等待客户端连接

调试方法

  1. 先运行vuln程序
  2. 通过nc 0.0.0.0 9999连接
  3. gdb调试时需要先启动程序,再写脚本连接

漏洞利用挑战

  • printf和read的第一个参数通过套接字描述符设置
  • 无法直接返回vuln函数

利用思路

  1. 栈迁移:

    • 寻找内容带描述符的空间
    • 迁移到该空间再次执行write/read
  2. 泄露地址:

    • 使用gdb查找套接字描述符
    • 利用"gift"伪造描述符
  3. 分阶段利用:

    • 第一次迁移执行read
    • 设置rsi为write的got表地址
    • 调用write泄露libc地址
    • 再次调用read布置ORW链

关键点

  • 多次栈迁移时注意rbp值的变化
  • 精确控制每次迁移的目标位置
  • 注意程序运行方式的特殊性

总结

这三道题目涵盖了多种PWN技术:

  1. counting petals:数组溢出+ROP
  2. format:格式化字符串+整数溢出
  3. ezstack:沙箱绕过+栈迁移+ORW

每道题都有其独特之处,特别是ezstack的调试方式和利用方法值得深入研究。在实际解题时,需要结合gdb调试,精确控制内存布局和程序流。

HGAME2025 Week1 PWN题解教学文档 1. counting petals 程序分析 保护全开 init函数中以当前时间戳作为随机数种子 生成的"随机数"可预测 漏洞点 数组下标溢出: 数组下标最大只到16 如果输入16,则会出现16+1=17的下标,导致数组溢出 利用思路 绕过随机数检查: 奇数 &1=1,偶数 &1=0 随机数%30后是偶数则输入1,奇数则输入0保证不break 泄露libc地址: 第一次输入0x0000001300000013覆盖数组下标 利用数组打印功能泄露libc地址 ROP链构造: 第二次输入0x0000001200000016覆盖返回地址 构造ROP链获取shell 调试技巧 使用gdb查看溢出后的内存布局 注意数组下标17处的数据内容 2. format 程序分析 保护基本没开 存在格式化字符串漏洞 每次只能输入3个字节 漏洞点 整数溢出: main函数中v5是有符号比较 vuln函数中是unsigned int类型 输入负数在vuln中会变成巨大数 格式化字符串漏洞: 受限的3字节输入 利用思路 初始尝试: 用%p泄露栈地址(受限) 改进思路: 第一次栈溢出控制rbp为输入的栈地址 返回后利用格式化字符串泄露libc地址 最终利用: 溢出执行system('/bin/sh') 注意scanf缓冲区会吞掉一个字符 调试要点 注意输入输出异常情况 精确计算输入长度 3. ezstack 程序环境 开启沙箱,禁用execve和execveat 需要通过ORW获取flag 程序作为TCP服务器运行,监听9999端口 程序功能 htons设置套接字(0.0.0.0:9999) bind绑定套接字 listen监听端口 accept等待客户端连接 调试方法 先运行vuln程序 通过 nc 0.0.0.0 9999 连接 gdb调试时需要先启动程序,再写脚本连接 漏洞利用挑战 printf和read的第一个参数通过套接字描述符设置 无法直接返回vuln函数 利用思路 栈迁移: 寻找内容带描述符的空间 迁移到该空间再次执行write/read 泄露地址: 使用gdb查找套接字描述符 利用"gift"伪造描述符 分阶段利用: 第一次迁移执行read 设置rsi为write的got表地址 调用write泄露libc地址 再次调用read布置ORW链 关键点 多次栈迁移时注意rbp值的变化 精确控制每次迁移的目标位置 注意程序运行方式的特殊性 总结 这三道题目涵盖了多种PWN技术: counting petals:数组溢出+ROP format:格式化字符串+整数溢出 ezstack:沙箱绕过+栈迁移+ORW 每道题都有其独特之处,特别是ezstack的调试方式和利用方法值得深入研究。在实际解题时,需要结合gdb调试,精确控制内存布局和程序流。