Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-31431-cleaned — Proof-of-concept exploit for CVE-2026-31431, a Linux kernel local privilege escalation via splice() and crafted socket options, enabling arbitrary kernel memory write to overwrite setuid binaries. | Kitploit
Tools/GitHubGitHub/galoryber/cve-2026-31431-cleaned
Privilege EscalationExploit FrameworksVulnerability AnalysisExploitationBinary Exploitation
GitHubgaloryber/cve-2026-31431-cleaned

CVE-2026-31431-cleaned

Proof-of-concept exploit for CVE-2026-31431, a Linux kernel local privilege escalation via splice() and crafted socket options, enabling arbitrary kernel memory write to overwrite setuid binaries.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository
13 months agoNot yet reviewed

copyFail.py — CVE Exploit Analysis Report

Summary

copyFail.py is a proof-of-concept (PoC) exploit that demonstrates a local privilege escalation vulnerability in the Linux kernel. By abusing the splice() system call in combination with crafted socket options, the exploit gains the ability to corrupt arbitrary kernel memory. It uses this capability to overwrite any setuid binary on disk with a custom ELF executable, then runs the tampered binary to obtain elevated privileges.

Attack type: Local privilege escalation (LPE) Impact: Full root shell access (when targeting setuid-root binaries) Complexity: Low (single script, no external dependencies)

Usage:

root@kitploit:~
./copyFail_cleaned.py [target_binary]   # default: /usr/bin/su

The original PoC hardcoded /usr/bin/su, but the underlying kernel vulnerability applies to any file — the attacker can overwrite any setuid binary they choose. The cleaned version accepts an optional command-line argument to specify the target, making this behavior explicit.


What the Vulnerability Is

The Linux kernel provides a splice() system call that copies data between two file descriptors entirely inside the kernel — without copying data into userspace first. This is called "zero-copy I/O" and is used for performance in high-throughput applications like web servers and reverse proxies.

The vulnerability arises because the kernel does not properly validate the internal state of certain socket structures when splice() is used on PACKET sockets that have been configured with unsupported protocol-level socket options. By carefully crafting these options, an attacker can corrupt kernel pointers, and then use splice() to redirect kernel memory writes to arbitrary locations.

In simple terms: the kernel has a shortcut for moving data around internally, and this exploit tricks that shortcut into writing data in the wrong place — specifically, into the in-memory copy of a system binary.


How the Exploit Works (High-Level)

The exploit follows a clear sequence of steps:

1. Set Up a Malformed Socket

The exploit creates a raw PACKET socket (AF_PACKET / SOCK_RAW) and binds it to intentionally malformed addresses. It then calls setsockopt() using SOL_PNIO (protocol level 279), which is a Solaris-level constant that Linux does not recognize.

Why this matters: When the kernel encounters an unsupported protocol level in setsockopt(), it falls through to a generic handler that doesn't validate the data properly. This leaves kernel memory in an inconsistent, exploitable state.

2. Corrupt Kernel Pointers with sendmsg()

After establishing a socket connection via accept(), the exploit sends crafted ancillary (control) messages using sendmsg(). These messages have deliberately mismatched length headers — some claim to be shorter than they are, others claim to be longer.

Why this matters: The kernel's control message parser uses these lengths for pointer arithmetic. Mismatched lengths cause the parser to read or write beyond intended boundaries, corrupting adjacent kernel structures — specifically, pointers that splice() will later follow.

3. Redirect splice() to Overwrite Arbitrary Memory

The exploit creates a pipe and calls splice() twice:

  • First, it splices data from /usr/bin/su into the pipe.
  • Then, it splices from the pipe into the corrupted socket.

Why this matters: The splice() call follows the corrupted kernel pointers planted in Step 2, causing it to write data to an attacker-chosen kernel memory address instead of the socket buffer. This gives the exploit an arbitrary kernel memory write primitive.

4. Repeat for Each Chunk of Shellcode

The exploit's payload is a 160-byte ELF executable (see below). Each call to the exploit function writes exactly 4 bytes. So the main loop runs 40 times (160 / 4 = 40), each time:

  • Creating a fresh socket
  • Corrupting kernel state
  • Writing 4 bytes of shellcode
  • Cleaning up

After all 40 iterations, the first 160 bytes of /usr/bin/su have been overwritten.

5. Execute the Tampered Binary

Finally, the exploit runs os.system("su"). The kernel loads the modified /usr/bin/su from its page cache (which now contains the attacker's shellcode instead of the real su binary), and the shellcode executes.


The Shellcode Payload

The embedded payload decompresses to a 160-byte x86-64 ELF executable containing this shellcode:

root@kitploit:~
; Attempt syscall 105 (execveat) — may not be available on older kernels
xor  eax, eax
xor  edi, edi
mov  al, 0x69          ; syscall 105
syscall

; Fallback: syscall 59 (execve) — the reliable path
lea  rdi, [rip+0xf]    ; RDI = pointer to "/bin/sh"
xor  esi, esi           ; RSI = NULL (envp)
push 0x3b               ; syscall 59 number
pop  eax
cdq                     ; RDX = NULL (argv)
syscall

; Exit cleanly
xor  edi, edi
push 0x3c               ; syscall 60 (exit)
pop  eax
syscall

; Data section: "/bin/sh\0\0\0"

What it does: Spawns /bin/sh with no arguments, inheriting the privileges of the process that ran su. If the exploit runs as root (or with capabilities that grant su root access), the resulting shell is a root shell.

What it does NOT do:

  • No reverse shell or network callback
  • No persistence mechanism (cron, systemd, SSH key, etc.)
  • No credential theft or data exfiltration
  • No process hiding or anti-forensics

This is a straightforward one-shot privilege escalation, consistent with a research PoC.


Technical Details

Key Linux Constants Used

File Structure

root@kitploit:~
copyFail.py
├── hex_to_bytes()         — hex string decoder
├── exploit_splice()       — core exploit (socket setup + corruption + splice)
│   ├── Phase 1: Create PACKET socket, bind, setsockopt (SOL_PNIO)
│   ├── Phase 2: accept() connection
│   ├── Phase 3: sendmsg() with crafted ancillary messages
│   ├── Phase 4: pipe() + splice() to corrupt kernel memory
│   └── Phase 5: recv() attempt (solidifies corruption)
└── Main loop:
    ├── Open /usr/bin/su (read-only)
    ├── Decompress embedded payload (zlib → 160-byte ELF)
    ├── Loop: inject 4 bytes per iteration (40 iterations total)
    └── Execute tampered su → root shell

Why Read-Only?

The exploit opens /usr/bin/su with O_RDONLY (read-only). It doesn't need write access because the corruption happens through the kernel page cache — the in-memory copy of the file that the kernel uses before flushing changes to disk. The splice()-based write bypasses normal file permissions entirely, going straight to kernel memory.


Detection and Mitigation

Indicators of Compromise

  • Modified /usr/bin/su binary (compare hash against package manager)
  • Anomalous PACKET socket creation by non-root processes
  • Unexpected setsockopt() calls with unknown protocol levels
  • splice() syscalls on non-regular file descriptors

Mitigations

  • Apply the kernel patch for this CVE when available
  • Use sysctl to restrict AF_PACKET socket creation by unprivileged users
  • Enable kernel hardening options (CONFIG_FORTIFY_SOURCE, CONFIG_STACKPROTECTOR)
  • Monitor file integrity of critical binaries (AIDE, OSSEC, Tripwire)

References

  • Original PoC: copyFail.py (as distributed)
  • Annotated version: copyFail_cleaned.py (same directory)
  • Relevant kernel subsystems: net/packet/, fs/splice.c, net/core/sock.c

This report is for security research and defensive analysis purposes only.

Download Tool
ConstantValuePurpose in Exploit
AF_PACKET17Raw packet socket family
SOCK_RAW3Raw socket type
SOL_PNIO279Unsupported protocol level (Solaris)
MSG_DONTWAIT0x400Non-blocking sendmsg flag