24西湖论剑pwn篇
字数 1209 2025-08-22 12:23:12

24西湖论剑PWN篇技术解析与利用教学

目录

  1. C++ PWN漏洞分析
  2. 沙箱Shellcode绕过
  3. 总结与扩展

C++ PWN漏洞分析

漏洞发现

  1. 初始观察

    • 本地执行程序时发现当push数组超过6个元素时,会泄露后面的内存内容
    • IDA反编译显示最大数组数量的变量a2位于栈上且可被覆盖
  2. 关键漏洞点

    • 栈上的数组大小限制变量可以被覆盖为更大的值
    • 这导致可以越界读写栈内存

漏洞利用

  1. 内存泄露

    • 通过覆盖a2为一个大值,可以读取栈上的敏感信息
    • 动态调试发现数组以32位(4字节)为单位写入栈中
  2. libc基址泄露

    • 找到libc_start_main在栈上的偏移位置为数组的第18和19个元素
    • 通过读取这些位置可以计算出libc基址
  3. ROP链构造

    • 利用相同的越界写漏洞向栈上写入ROP链
    • 由于是4字节写入,需要特别注意对齐和顺序
# 示例ROP链构造函数(可用ChatGPT辅助生成)
def build_rop(rop_chain):
    payload = b""
    for addr in rop_chain:
        payload += p32(addr)  # 32位打包
    return payload

ROP链构造

  1. 利用步骤

    • 首先泄露libc基址
    • 计算需要的gadget地址
    • 分4字节一组写入栈中
    • 覆盖返回地址触发ROP链
  2. 注意事项

    • 注意栈偏移计算
    • 考虑栈对齐要求
    • 可能需要栈迁移技术

沙箱Shellcode绕过

限制条件分析

  1. 主要限制

    • count_syscall_instructions函数检查shellcode
    • 禁止出现超过两次连续的0x050f(syscall机器码)
    • read系统调用被禁用
  2. 可用系统调用

    • openat
    • sendfile
    • open
    • mmap
    • write等

方法一:openat+sendfile

  1. 技术原理

    • 使用openat打开文件
    • 使用sendfile直接发送文件内容到标准输出
    • 仅需两次syscall即可完成操作
  2. 优势

    • 符合syscall次数限制
    • 代码简洁高效
    • 在其他限制条件下也经常使用
# 示例exp结构
shellcode = asm('''
    // openat 调用
    // sendfile 调用
''')

方法二:open+mmap+write

  1. 技术原理

    • 前两次使用openmmap正常syscall
    • 第三次write时使用特殊技巧:
      • \x90(nop)对齐
      • 在syscall位置写入高位0x05
      • 通过汇编在RIP寄存器低位补0x0f组成完整syscall
  2. 关键技巧

    • 拆分syscall机器码0x050f为两部分
    • 利用指令流动态组成有效syscall
# 示例exp结构
shellcode = asm('''
    // open 调用
    // mmap 调用
    // 特殊构造的write调用
    // 包含拆分syscall的技巧
''')

总结与扩展

  1. 技术要点总结

    • C++ PWN中注意栈变量覆盖的可能性
    • 32位环境下的ROP构造需要4字节对齐
    • 沙箱绕过时考虑syscall拆分和替代方案
  2. 扩展思考

    • 类似技术可用于其他有syscall限制的场景
    • 可探索更多syscall拆分和动态组合技术
    • 考虑其他系统调用组合实现相同功能
  3. 防御建议

    • 对栈变量进行边界检查
    • 实现更严格的syscall过滤机制
    • 考虑使用seccomp等沙箱技术增强防护
24西湖论剑PWN篇技术解析与利用教学 目录 C++ PWN漏洞分析 漏洞发现 漏洞利用 ROP链构造 沙箱Shellcode绕过 限制条件分析 方法一:openat+sendfile 方法二:open+mmap+write 总结与扩展 C++ PWN漏洞分析 漏洞发现 初始观察 : 本地执行程序时发现当push数组超过6个元素时,会泄露后面的内存内容 IDA反编译显示最大数组数量的变量 a2 位于栈上且可被覆盖 关键漏洞点 : 栈上的数组大小限制变量可以被覆盖为更大的值 这导致可以越界读写栈内存 漏洞利用 内存泄露 : 通过覆盖 a2 为一个大值,可以读取栈上的敏感信息 动态调试发现数组以32位(4字节)为单位写入栈中 libc基址泄露 : 找到 libc_start_main 在栈上的偏移位置为数组的第18和19个元素 通过读取这些位置可以计算出libc基址 ROP链构造 : 利用相同的越界写漏洞向栈上写入ROP链 由于是4字节写入,需要特别注意对齐和顺序 ROP链构造 利用步骤 : 首先泄露libc基址 计算需要的gadget地址 分4字节一组写入栈中 覆盖返回地址触发ROP链 注意事项 : 注意栈偏移计算 考虑栈对齐要求 可能需要栈迁移技术 沙箱Shellcode绕过 限制条件分析 主要限制 : count_syscall_instructions 函数检查shellcode 禁止出现超过两次连续的 0x050f (syscall机器码) read系统调用被禁用 可用系统调用 : openat sendfile open mmap write等 方法一:openat+sendfile 技术原理 : 使用 openat 打开文件 使用 sendfile 直接发送文件内容到标准输出 仅需两次syscall即可完成操作 优势 : 符合syscall次数限制 代码简洁高效 在其他限制条件下也经常使用 方法二:open+mmap+write 技术原理 : 前两次使用 open 和 mmap 正常syscall 第三次 write 时使用特殊技巧: 用 \x90 (nop)对齐 在syscall位置写入高位 0x05 通过汇编在RIP寄存器低位补 0x0f 组成完整syscall 关键技巧 : 拆分syscall机器码 0x050f 为两部分 利用指令流动态组成有效syscall 总结与扩展 技术要点总结 : C++ PWN中注意栈变量覆盖的可能性 32位环境下的ROP构造需要4字节对齐 沙箱绕过时考虑syscall拆分和替代方案 扩展思考 : 类似技术可用于其他有syscall限制的场景 可探索更多syscall拆分和动态组合技术 考虑其他系统调用组合实现相同功能 防御建议 : 对栈变量进行边界检查 实现更严格的syscall过滤机制 考虑使用seccomp等沙箱技术增强防护