高级ROP之SROP利用
字数 2387 2025-08-19 12:41:42
SROP (Sigreturn Oriented Programming) 利用技术详解
1. SROP 基础知识
1.1 SROP 概念
SROP (Sigreturn Oriented Programming) 是一种利用 sigreturn 系统调用的高级ROP攻击技术。其核心原理是通过伪造 Signal Frame 来控制程序执行流程。
1.2 Signal 机制原理
Signal 机制是类 Unix 系统中进程间通信的一种方法,也称为软中断信号。其工作流程如下:
- 内核向进程发送 signal,进程被挂起进入内核态
- 内核保存进程上下文(所有寄存器压入栈中),包括:
- Signal 信息
- 指向
sigreturn的系统调用地址
- 跳转到注册的 signal handler 处理 signal
- signal handler 返回后,执行
sigreturn系统调用恢复保存的上下文
1.3 Signal Frame 结构
Signal Frame 包含以下关键部分:
- ucontext 结构(保存的寄存器值)
- siginfo 结构(signal 信息)
sigreturn系统调用地址
32位和64位系统的 sigreturn 调用号:
- 32位:119 (0x77)
- 64位:15 (0xf)
2. SROP 利用条件
要成功利用 SROP 攻击,需要满足以下条件:
- 栈溢出:能够控制栈的内容
- 控制 rax 寄存器:能够设置 rax 为
sigreturn的系统调用号 - syscall 可用:存在
syscall指令或函数 - 足够的栈空间:能够布置伪造的 Signal Frame
3. SROP 攻击步骤
3.1 基本攻击流程
- 通过栈溢出劫持返回地址
- 构造 SROP 链:
- 控制 rax 寄存器为
sigreturn的系统调用号 - 执行
syscall进入sigreturn系统调用
- 控制 rax 寄存器为
- 精心构造栈布局,使
sigreturn系统调用后的 pop 指令能够控制各寄存器
3.2 获取 shell 的寄存器设置
要执行 execve("/bin/sh", 0, 0),需要设置以下寄存器:
- rax → 59 (
execve的系统调用号) - rdi → "/bin/sh" 字符串地址
- rsi → 0
- rdx → 0
- rip →
syscall指令地址
4. SROP 链构造
当需要多次系统调用时(如沙箱环境下需要 open/read/write),可以构造 SROP 链:
- 通过设置 rsp 寄存器,使一个 SROP 结束后自动进入下一个 SROP
- 每个 SROP 负责一个特定的系统调用
- 链式调用直到完成所有需要的操作
5. 工具使用
pwntools 提供了方便的 SROP 构造工具 SigreturnFrame():
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr
在 payload 中使用 bytes(frame) 将其转换为字节序列。
6. 注意事项
6.1 syscall 的两种形式
-
syscall 函数:
- 在 IDA 中显示为
call _syscall - 需要遵循寄存器传参规则
- 构造时需要考虑函数调用约定
- 在 IDA 中显示为
-
syscall 指令:
- 在 IDA 中显示为
syscall机器码 (0F 05) - 通常以
sys_read、sys_write等伪代码形式出现 - 直接执行系统调用,无需额外处理
- 在 IDA 中显示为
6.2 栈空间不足的解决方案
当溢出空间不足时,可以采用栈迁移技术:
- 利用有限的溢出空间修改 rsp
- 将栈迁移到更大的空间(如 .bss 段)
- 在新的栈空间布置完整的 SROP 链
7. 实战案例分析
7.1 案例1:2023江西省赛初赛pwn2
漏洞点:
char buf[16];
sys_read(0, buf, 0x200uLL); // 明显的栈溢出
利用步骤:
- 利用溢出控制返回地址
- 设置 rax 为 15 (
sigreturn调用号) - 构造 Signal Frame 执行
execve("/bin/sh", 0, 0)
关键点:
- 通过栈迁移将控制流转移到 .bss 段
- 分阶段构造 SROP 链(先 read 再 execve)
7.2 案例2:第六届安洵杯网络安全挑战赛pwn2
特殊条件:
- 开启了沙箱保护(仅允许 read/write/open/chmod/rt_sigreturn/exit_group)
- 输入长度有限(需要栈迁移)
利用步骤:
- 利用有限的溢出空间进行栈迁移
- 将栈迁移到 .bss 段的大空间
- 构造三段式 SROP 链:
- open("./flag", 0, 0)
- read(3, buf, 0x50) // 3 是打开的文件描述符
- write(1, buf, 0x50) // 1 是标准输出
关键点:
- 通过调试确定 rsp 的正确位置
- 确保每个 SROP 结束后 rsp 指向下一个 SROP 的起始点
- 处理文件描述符的传递
8. 调试技巧
-
使用 gdb 调试时,可以在关键位置设置断点:
gdb.attach(io, 'b *0x40136e') -
观察栈布局和寄存器变化,确保 Signal Frame 被正确解析
-
对于复杂的 SROP 链,可以分段调试,确保每一段都能正确执行
9. 防御措施
- 启用栈保护机制(如 Canary)
- 限制
sigreturn系统调用的使用 - 使用地址随机化(ASLR)增加预测难度
- 对敏感系统调用进行过滤
10. 总结
SROP 是一种强大的攻击技术,它通过伪造 Signal Frame 实现了对程序完全控制。相比传统 ROP,SROP 具有以下优势:
- 一次性设置所有寄存器,减少 gadget 需求
- 可以构造复杂的调用链
- 在沙箱环境下尤其有效
掌握 SROP 技术需要深入理解 signal 机制和系统调用约定,通过实际案例练习可以更好地掌握这一技术。