25 octubre 2011

Análisis de Jynx (Linux Rootkit)

Últimamente poco se había innovado en el campo de los Rootkits para sistemas Linux, muy atrás quedaron los tiempos en los que 'adore' (LKM) o 'SuckIT' (parcheo de la memoria en caliente) marcaban el paso en cuanto a rootkits para sistemas Linux.

Poco a poco el Kernel de Linux ha ido evolucionando y haciendo bastante mas compleja la labor de modificarlo para esos fines, así que actualmente la forma mas efectiva de instalar un rootkit en un sistema Linux es ir hacia la parte 'userland'

De esta clase de rootkits existen dos tipos, o bien los que cambian los típicos binarios del sistema asociados a obtener información (ps y amigos) y los rootkits más sofisticados que inyectan una librería en los procesos.

Desde hace tiempo han existido rootkits que actuaban de esa forma, pero habían permanecido un tanto ocultos, hace relativamente poco se ha hecho pública una implementación completa y funcional de un rootkit con capacidad para infectar un sistema Linux actual, su nombre: Jynx

Este tipo de rootkits actúan inyectando una librería compartida (.so) en todos los procesos del sistema.

Aun a riesgo de que un purista encuentre objeciones, podemos decir que este tipo de vectores en Linux serían análogos al 'API Hooking' en Windows, las librerías .so serían el análogo a las Dlls y el fichero /etc/ld.so.preload sería el análogo a la clave de registro

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

En resumen, lo que hacen este tipo de rootkits es añadir una línea en el fichero /etc/ld.so.preload apuntando hacia la librería del rootkit en la que se encuentran 're-escritas' ciertas funciones asociadas a la obtención de información del sistema. Luego, será el propio sistema Linux el que se encargue de hacer que cada proceso creado en el sistema lleve cargada esa librería con las funciones alteradas. La única salvedad son los binarios compilados de forma estática.

Si miramos en el fichero ld_poison.c de Jynx podemos ver claramente que funciones del sistema van a ser re-escritas:

static int (*old_fxstat)(int ver, int fildes, struct stat *buf);
static int (*old_fxstat64)(int ver, int fildes, struct stat64 *buf);
static int (*old_lxstat)(int ver, const char *file, struct stat *buf);
static int (*old_lxstat64)(int ver, const char *file, struct stat64 *buf);
static int (*old_open)(const char *pathname, int flags, mode_t mode);
static int (*old_rmdir)(const char *pathname);
static int (*old_unlink)(const char *pathname);
static int (*old_unlinkat)(int dirfd, const char *pathname, int flags);
static int (*old_xstat)(int ver, const char *path, struct stat *buf);
static int (*old_xstat64)(int ver, const char *path, struct stat64 *buf);

static DIR *(*old_fdopendir)(int fd);
static DIR *(*old_opendir)(const char *name);

static struct dirent *(*old_readdir)(DIR *dir);
static struct dirent64 *(*old_readdir64)(DIR *dir);

Y ahora un ejemplo real, he infectado con este rootkit un sistema linux ocultando dos procesos a la vista de ps y derivados, he creado un proceso bash y otro nc ocultos.

[campus@... ~]$ ./nc -l 9000

Si interrogamos a ps en busca de procesos nc:

[root@... ~]# ps aux | grep -i nc
[root@... ~]#

El comando ps no ve nada.

Ahora vamos a usar Unhide para detectar estos procesos. De entrada, si Unhide está compilado estáticamente (como se recomienda en el manual) es totalmente inmune a esta clase de rootkits, no obstante vamos a usar una versión de Unhide compilada de forma normal debido a que -lamentablemente- la mayoría de distribuciones Linux lo empaquetan así.

Empezamos con un escaneo empleando syscalls

[root@... unhide-20110113]# ./unhide-linux26 sys
Unhide 20110113
http://www.unhide-forensics.info
[*]Searching for Hidden processes through getpriority() scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through getpgid() scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through getsid() scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through sched_getaffinity() scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through sched_getparam() scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through sched_getscheduler() scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through sched_rr_get_interval() scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through kill(..,0) scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through  comparison of results of system calls

[*]Searching for Hidden processes through sysinfo() scanning

HIDDEN Processes Found: 2       sysinfo.procs = 143   ps_count = 142

¡¡ Bingo !! los procesos son detectados, el comando identificado y también la ruta en la que se encuentra.

Ahora vamos a probar un escaneo empleando los tests proc

[root@... unhide-20110113]# ./unhide-linux26 procall
Unhide 20110113
http://www.unhide-forensics.info
[*]Searching for Hidden processes through /proc stat scanning

[*]Searching for Hidden processes through /proc chdir scanning

Found HIDDEN PID: 1616  Exe: "/bin/bash"

Found HIDDEN PID: 1654  Exe: "/home/campus/nc"

[*]Searching for Hidden processes through /proc opendir scanning

[*]Searching for Hidden thread through /proc/pid/task readdir scanning

En este caso el rootkit ha bloqueado y ocultado la presencia de los procesos ante stat, readdir, opendir y readdir pero como Unhide también emplea chdir ha caído en ese test.

Conclusión: Este tipo de rootkits son bastante efectivos a la hora de hacer su trabajo, pero no son infalibles.

4 comments :

Foo dijo...

me gusta :D

Ole - dijo...

Gracias por la referencia a phrack de como parchear la memoria!!! Leyendo en 3, 2, 1...

t31m0 dijo...

Buena analize
 

Jagy124 dijo...

Muy buen articulo picha,
pero como se configura el jynx
ya se que en el config.h
pero:
#define MAGIC_DIR "xochi" <== aqui un nonbre para un directorio oculto ???? y donde se crea en root  en home o tengo que poner la ruta completa???#define MAGIC_GID 90#define CONFIG_FILE "ld.so.preload"#define APP_NAME "bc" <== El programa a ocultar??? lo cambio por Ejem: nc ??#define MAGIC_ACK 0xdead#define MAGIC_SEQ 0xbeef    <== Con esto podemos activar remotamente nuestro comando????

Muchas GRACIAS.