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