
Copy Fail - CVE-2026-31431 - Implementación robusta en C para operaciones de redteam y pruebas de penetración autorizadas. ⚠️ Aviso legal: Esta herramienta está destinada exclusivamente a investigaciones de seguridad autorizadas, pruebas de penetración autorizadas y análisis defensivo. Úsela en sistemas que posea o para los cuales tenga permiso explícito por escrito para realizar pruebas. El acceso no autorizado a sistemas informáticos es ilegal.
Implementación robusta en C para operaciones de redteam y pruebas de penetración autorizadas.
⚠️ Aviso legal: Esta herramienta está destinada exclusivamente para investigación de seguridad autorizada, pruebas de penetración autorizadas y análisis defensivo. Úsela únicamente en sistemas que posea o para los cuales tenga permiso explícito por escrito. El acceso no autorizado a sistemas informáticos es ilegal.
🚀 El desarrollo principal se ha trasladado a GitLab.
Este repositorio se mantiene activamente aquí. Para incidencias y contribuciones, use GitLab.
Este proyecto es una versión robusta y lista para producción en C del exploit de escalada de privilegios local CVE-2026-31431 ("Copy Fail"), divulgado originalmente por Theori y Xint el 29 de abril de 2026.
La prueba de concepto original estaba escrita en Python y diseñada para demostración de investigación. Esta implementación lo transforma en un kit de herramientas de grado redteam con:
| Atributo | Valor |
|---|---|
| Fecha de divulgación | 29 de abril de 2026 |
| Investigadores | Theori (Jinoh Kang, Yonghwi Jin, Seunghyun Lee), Xint |
| Artículo | https://copy.fail/ |
| PoC original | theori-io/copy-fail-CVE-2026-31431 (Python) |
| Puerto en C (base) | tgies/copy-fail-c por Tony Gies |
| Kernels afectados | Linux 4.14 -- 6.14 (antes del commit de corrección a664bf3d603d) |
| Gravedad | CVSS 7.8 (Alta) -- Escalada de privilegios local |
La vulnerabilidad reside en el subsistema criptográfico AF_ALG del kernel de Linux. La plantilla AEAD authencesn implementa una optimización in situ para el descifrado: cuando el texto cifrado se suministra mediante splice() desde la caché de páginas de un archivo, el kernel reutiliza la misma página como origen y destino.
El flujo del ataque:
/usr/bin/su) en modo solo lecturaauthencesn(hmac(sha256),cbc(aes)) a través de AF_ALGsplice() desde la caché de páginas del archivo objetivoexecve() el objetivo -- el kernel carga páginas mutadas desde la caché, otorga credenciales setuid-rootPunto clave: El inodo en disco nunca se modifica. Solo se muta la caché de páginas en memoria, lo que hace que la detección forense sea significativamente más difícil que en exploits tradicionales de sobrescritura de archivos.
Este proyecto amplía la investigación original con endurecimiento orientado a redteam en nueve módulos.
patch_chunk.c)| Característica | Original | Nuestra Implementación |
|---|---|---|
| Gestión de sockets | Socket nuevo por fragmento | Reutilización de socket (~60% menos llamadas al sistema) |
| Verificación | Ninguna | mmap + memcmp con reintento automático (3 intentos) |
| Escrituras paralelas | Solo secuenciales | Paralelas basadas en fork (hasta 16 procesos) |
| Códigos de error | Éxito/fracaso binario | Granulares: 0=verificado, 1=kernel parcheado, -1=fallo fatal |
| Asignaciones de heap | malloc en ruta crítica | Solo pila (sin fluctuación de asignación) |
target_discovery.c)su, sudo, passwd, pkexec, mount, ping, etc./snap (setuid no tradicional)anti_forensics.c)| Técnica | Propósito |
|---|---|
posix_fadvise(POSIX_FADV_DONTNEED) | Expulsión de caché de páginas por archivo |
echo 3 > /proc/sys/vm/drop_caches | Eliminación global de caché (post-root) |
utimensat() timestomp | Restaurar atime/mtime original |
| Autodestrucción | Sobrescribir binario dropper con ceros antes de exec |
| Borrado de memoria | Puesta a cero volatile de búferes sensibles |
memfd_exec.c)kworker, anon_inode, eventfd (se mezcla en /proc/$pid/fd/)stage1.c)| Canal | Sigilo | Velocidad | Prioridad de Respaldo |
|---|---|---|---|
| Incrustado | Máximo | Instantáneo | Último (airgap) |
| HTTP directo | Medio | <1s | Primero |
| curl/wget del sistema | Bajo | 1-3s | Segundo (soporte HTTPS) |
| DNS TXT | Alto | Lento | Tercero (bypass de firewall) |
stage2_template.c)SIGUSR1 (disparar), SIGUSR2 (estado), SIGTERM (apagar)[kworker/N:0] en ps/topproc_hide.c)/proc/$pid/cmdlineSSH_*, AWS_*, TOKEN*, etc.setsid() + setpgid() para independencia de terminalsignal_trigger.c)| Modo | Comportamiento | Caso de Uso |
|---|---|---|
trigger_oneshot() | Dormir → disparar → ejecutar → salir | Golpe y fuga |
trigger_daemon() | Dormir → disparar → ejecutar → bucle | Implante persistente |
trigger_auto() | Dormir con respaldo de tiempo de espera | Operaciones sin supervisión |
Espera de cero CPU: sigsuspend() en lugar de bucles de sondeo.
sleep_jitter.c)