Como ya se indicó en un artículo anterior donde compilábamos nuestro kernel, los diferentes parámetros del kernel se pueden compilar dentro del propio kernel o como módulo, el hacerlo como módulo nos dará una mayor flexibilidad ya que se puede cargar el módulo con diferentes parámetros pero por otro lado nos expone a los temidos rootkits.
En esta ocasión aprenderemos a compilar un módulo de lo mas sencillo cuya única misión es imprimir un mensaje en los logs del sistema, lo se no es gran cosa pero bastará como iniciación a la programación de módulos.
Los módulos se encuentran en un directorio determinado, /lib/modules/version/ los principales comandos utilizados para su gestión son los siguientes:
- depmod -a: Genera el fichero /lib/modules/version/modules.dep donde se indican las dependencias de los módulos.
- insmod: Carga un módulo sin comprobar dependencias, si existen dependencias hay que cargarlas en el orden correcto manualmente y es necesario indicarle la localización exacta del módulo
- modprobe: Carga el módulo teniendo en cuenta las dependencias, busca en el directorio por defecto para cargar los módulos
- rmmod: Descarga el módulo
Todo módulo consta como mínimo de dos partes:
- init_module –> main() Se ejecuta en la carga del módulo: insmod, modprobe
- cleanup_module –> Se ejecuta en la descarga del módulo: rmmod
En nuestro ejemplo simplemente imprimiremos mediante syslog un mensaje en la carga de módulo y otro en la descarga:
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.
");
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.
");
}
Creamos un makefile para poder compilarlo:
obj-m += my_module.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
NOTA: Las tabulaciones del make son muy importantes, si se edita con Vi se puede apreciar como cambia de color al tabular
Compilamos:
make -C /lib/modules/3.16.5-gentoo-Kr0m-ceph-xfs-xen/build M=/home/XXXX modules
make[1]: Entering directory '/usr/src/linux-3.16.5-gentoo'
CC [M] /home/XXXX/my_module.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/XXXX/my_module.mod.o
LD [M] /home/XXXX/my_module.ko
make[1]: Leaving directory '/usr/src/linux-3.16.5-gentoo'
Ya podemos cargar el módulo pero antes dejaremos un tail en los logs del sistema para comprobar que se ha cargado con éxito:
En otro terminal cargamos el módulo:
my_module 812 0
En la consola con el tail veremos:
Nov 18 21:46:30 localhost kernel: [981248.867904] Hello world 1.
Si lo descargamos:
En la consola con el tail veremos:
Nov 18 21:49:08 localhost kernel: [981407.803926] Goodbye world 1.
Esto puede ser un primer paso hacia la programación de nuestro propio rootkit ;)