尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

【学习记录】Week14(二):沙箱机制深度剖析与进阶 ORW 绕过体系

【学习记录】Week14(二):沙箱机制深度剖析与进阶 ORW 绕过体系
📅 发布时间:2026/7/6 4:22:00

写在前面:在上一篇中,我们建立了信息泄露的系统化方法论,并学习了 ORW(Open-Read-Write)的基础 ROP 构造。然而,出题人的防守并非一成不变。当简单的open也被沙箱拦截时,基础的 ORW 链便会失效。今天,我们将深入剖析 Linux 的沙箱机制,学习如何使用seccomp-tools逆向分析规则,并掌握进阶的 ORW 绕过手法,如openat与/proc/self/mem魔法。

📑 目录

  1. 沙箱溯源:Seccomp 与 BPF 机制简介
  2. 破译密码:使用seccomp-tools分析沙箱规则
  3. 进阶 ORW:当open被禁时的openat替换
  4. 深水区绕过:/proc/self/mem魔法读取
  5. 总结与下篇预告

1. 沙箱溯源:Seccomp 与 BPF 机制简介

在 Linux 中,Seccomp(Secure Computing Mode)是一种用于限制进程可用系统调用的内核机制。现代 CTF 中的沙箱通常基于prctl(PR_SET_NO_NEW_PRIVS, 1)和seccomp(SECCOMP_MODE_FILTER, ...)实现。

其核心是BPF (Berkeley Packet Filter)。BPF 最初用于网络数据包过滤,后来被引入到系统调用过滤中。出题人会编写一段 BPF 字节码,告诉内核:“如果进程请求的系统调用号是 X,则放行;如果是 Y,则杀死进程”。

由于 BPF 规则是以字节码形式加载到内核的,我们在用户态无法直接 patch 掉它。因此,我们必须先逆向分析这段字节码,找出它的“盲区”。

2. 破译密码:使用seccomp-tools分析沙箱规则

手动逆向 BPF 字节码极其痛苦。感谢安全社区,我们拥有神器seccomp-tools。
假设题目附件是./pwn,我们执行:

seccomp-tools dump ./pwn

它会将内核中的 BPF 规则反编译为易读的伪代码。我们经常会看到如下输出:

场景 A:基础沙箱(只禁 execve)

line 1: ALLOW syscalls: open, read, write, mmap, mprotect... line 2: KILL syscalls: execve (59), execveat (322)

*应对策略*:使用上一篇讲的基础 ORW 即可。

场景 B:进阶沙箱(禁用 open)

line 1: ALLOW syscalls: read, write, mmap, mprotect... line 2: KILL syscalls: execve, open (2)

*应对策略*:open被杀,但openat往往幸存。

场景 C:地狱级沙箱(禁用所有 open 家族)

line 1: ALLOW syscalls: read, write, mmap, mprotect... line 2: KILL syscalls: execve, open (2), openat (257)

*应对策略*:无法打开新文件,但可以利用/proc/self/mem配合write实现任意地址读写。

3. 进阶 ORW:当open被禁时的openat替换

open的系统调用号是 2,而openat是 257。它们的功能几乎一样,区别在于openat需要额外指定一个目录文件描述符dirfd。

3.1 openat 的函数原型

int openat(int dirfd, const char *pathname, int flags);
  • 如果pathname是绝对路径(如/flag),则dirfd参数会被忽略。
  • 因此,我们只需将dirfd设置为任意值(通常设为AT_FDCWD(-100) 或 0),即可完全等价于open。

3.2 ROP 链修改

只需将基础 ORW 中的open部分替换为openat:

// openat("/flag", 0) -> sys_openat = 257 pop rdi; ret; -100; // rdi = AT_FDCWD (-100) pop rsi; ret; bss_addr; // rsi = "/flag" 字符串地址 pop rdx; ret; 0; // rdx = O_RDONLY pop rax; ret; 257; // rax = 257 (sys_openat) syscall; ret;

后续的read和write完全不变。这就是为什么出题人必须把open和openat一起禁掉,否则沙箱形同虚设。

4. 深水区绕过:/proc/self/mem魔法读取

当open和openat全部阵亡,我们无法获取新的文件描述符。但幸运的是,程序启动时默认打开了三个流:stdin(0),stdout(1),stderr(2)。更重要的是,Linux 提供了一个特殊的虚拟文件:/proc/self/mem。

4.1 核心思想

/proc/self/mem是当前进程内存的镜像。对这个文件进行lseek和read/write,等同于直接读写进程自身的内存!
然而,/proc/self/mem并不是一个常规文件,它无法直接被open打开(即使没禁用 open,也可能因为权限问题失败)。但它通常已经被打开了,在文件描述符表中吗?不,它没有。
等等,如果连openat都不能用,怎么打开它?

4.2 终极魔法:利用write绕过限制

如果沙箱允许openat,我们可以打开/proc/self/mem。但如果连openat都禁了呢?
此时如果允许write和lseek(系统调用号 8):

  1. 我们通过 ROP 调用openat打开/proc/self/mem… 不行,禁用了。
  2. 真正的魔法(无 open 场景):如果题目允许write,且我们有一个指向 libc 中__free_hook或类似可写区域的指针,我们可以直接写入 shellcode?不,NX 开启。
  3. 修正魔法(结合 mprotect):如果沙箱允许mprotect和write,且允许open(但不允许openat),这太矛盾了。

真实的/proc/self/mem利用场景:
通常发生在:允许open或openat,但不允许直接读flag(例如通过正则过滤了路径名,或者read被限制只能读取特定 fd)。
更极端的场景:允许openat打开/proc/self/mem,然后利用lseek偏移到目标内存,再用write覆盖内存!

具体流程:

  1. openat("/proc/self/mem", O_RDWR)-> 返回 fd = 3
  2. lseek(3, target_addr, SEEK_SET)-> 将文件指针移动到我们想写的目标地址(如__free_hook或栈上的返回地址)
  3. write(3, payload, len)-> 将 payload 写入目标地址!
    这种手法可以绕过某些对write系统调用参数有严格检查的沙箱,因为我们写的“文件”是内存本身。

4.3 如果连 openat 都没有,只有 read/write 怎么办?

这是最极端的无 libc 场景或极严沙箱。通常需要利用mprotect将内存改为可执行,然后写入 shellcode 执行(这需要mprotect未被禁)。如果mprotect也被禁,则可能需要利用内核漏洞(超出本周讨论范围)。

5. 总结与下篇预告

5.1 核心知识点总结

  1. Seccomp 与 BPF:理解沙箱的底层原理,沙箱规则是加载到内核的,用户态无法绕过,只能寻找规则的盲区。
  2. seccomp-tools:实战必备工具,打题第一步必先 dump 沙箱规则。
  3. openat替换:最基础的绕过姿势,利用dirfd = AT_FDCWD完美替代open。
  4. /proc/self/mem:将内存视为文件,通过lseek+write实现极其隐蔽的任意地址写,绕过对系统调用参数的直接检查。

5.2 下篇预告

在解决了沙箱与 ORW 之后,下一篇我们将转向另一个实战痛点:无 Libc 环境与ret2mprotect进阶应用。

  • 当题目不给 libc,且远程环境未知时,如何利用ret2dlresolve或ret2mprotect破局?
  • 如何在没有pop rdx; ret等 gadget 时,利用__libc_csu_init构造万能 ROP?
  • got2plt劫持在 Partial RELRO 下的妙用。

结语:沙箱不是不可逾越的高墙,而是一道带缝隙的过滤网。出题人受限于系统调用之间的依赖关系,永远无法完全封死读写内存的途径。掌握openat和/proc/self/mem,你就掌握了在沙箱中“穿墙”的咒语。

相关新闻

  • 湿地生态好不好,不能只看绿不绿
  • 从零学习Kafka:调优
  • Node.js-Phase 1 学习总结:CLI 文件管理系统

最新新闻

  • AI规划能力测试:从推箱子游戏看世界模型与推理技术
  • FanControl:从零开始打造你的个性化风扇控制系统
  • Waifu2x-Extension-GUI完整指南:AI媒体增强实战教程
  • 小智MCP一键部署客户端(windows极简方案)
  • 从模糊到高清:使用Waifu2x-Extension-GUI实现AI超分辨率与视频补帧的终极指南
  • MNIST 与 Fashion-MNIST 数据集对比:2 种经典基准在 3 类模型上的泛化性分析

日新闻

  • AI智能体安全防护框架AgentGuard:从原理到实战部署指南
  • KMX63与PIC18F26K40硬件组合及低功耗设计实践
  • 基于YOLO13改进的门体检测模型:C3k2模块与PoolingFormer技术解析

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号