Ayuda a mejorar código. C sobre Linux.

Iniciado por NeoB, 12 Febrero 2012, 18:02 PM

0 Miembros y 1 Visitante están viendo este tema.

NeoB

Buenas, he estado esta última semana dándole vueltas a la idea de hacer un bruteforce en C, para que ya estoy aprendiendo, animarme un poco. Una de las utilidades de este por ejemplo, sería logearse en un ftp remoto, pero me va MUY LENTO (incluso cuando me intento logear en localhost), y no se que hacer para mejorarlo (ya os he dicho que estoy aprendiendo). ¿Alguna idea? Antes de dejar el código os digo como va: Por ejemplo cuando te pide un comando yo le meto:
Código (bash) [Seleccionar]

lftp ftp://localhost/ -u usuario,

--Aquí va el código que llevo:

/*
 *Nombre: COMB.

 *Autor: NeoB

 *Descrpición: Genera una lista de palabras (con o sin sentido)
   combinando las letras del abecedario, en mayusculas, minúsculas, y números;
   además permite usar esas combinaciones con un comando.
   Para modificar esta lista se puede modificar la variable "abc" (global).

*/

/***LAS LIBRERÍAS***/
#include <stdio.h>
#include <string.h>


/***VARIABLES GLOBALES****/
char *abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; //El abecedario (los caracteres que hay son los que se usarán).
int i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20; //Contadores que usaremos para apuntar a las diferentes posiciones de "abc".
char command[500];
int yescommand;
int tamcommand;


/*******************EL MAIN() Y LAS FUNCIONES DE CONTROL.*********************/
int main()
{
 char option1, option2; int optiontam;  //Para almacenar las opciones que escojamos.  

 printf("\E[0;1m"
        "     ======================================\n"
        "     || COMB - Generador de diccionarios.||\n"
        "     ||     By Juan Escudero Pedrosa.    ||\n"
        "     ======================================\n"
        "Set the length of the strings used:\n"
        "1) use a progressive increase of the string's lenght.\n"
        "2) fixed lenght.\n"
        "3) use range of values for string's lenght.\n"
        "What option has you selected? (1-3):  "
        "\E[00m");
 option1 = getchar(); //Cogemos la opción.
 getchar();  //Es para borrar el stdin, NO SE DEBE DE HACER, pero funciona.

 printf("\E[0;1m"
        "Do you want to use a command with the strings generated? (y/n)  "
        "\E[00m");
 option2 = getchar(); //Cogemos la opción.
 getchar();  //Es para borrar el stdin, NO SE DEBE DE HACER, pero funciona.

 if(option2=='y')
 {
   printf("\E[0;1m"
          "What command do you want to use? (Remember that the word generated will join to the end of the command):  "
          "\E[00m");
   yescommand = 1; //Si yescommand es 1 siginifica que hemos elegido meter comandos.
/*********************************COJEMOS LA CADENA QUE METE***********************************************************/
   fgets(command,500,stdin); //Almacenamos la cadena con un máximo de 500 caracteres.
   char *buscar_n; //La utilizamos para buscar un fin de línea por que queremos cojer solo una línea.
   buscar_n = strchr (command, '\n'); //Buscamos el fin de linea (\n) en command.
   if (buscar_n) //Si lo hay... (no necesita corchetes ('{' y '}') por que solo hacemos una cosa.
   *buscar_n = '\0'; //Lo sustituimos por un final de cadena (\0).
/**********************************************************************************************************************/
   tamcommand = strlen(command); //Lo usamos luego, ya veréis.
 }

 switch(option1)  //Para los valores de lo primero que se nos da a elegir...
 {
   case '1':  //Si elegimos progresiva, vamos llamando. Podemos por ejemplo, cambiar el orden y ponerlo en dos ordenadores.
     cero();
     one();
     two();
     three();
     four();
     five();
   break;

   case '2': //Si elegimos un tamaño predeterminado...
     printf("\E[0;1m"
            "What lenght do you want to use? (0-20):  "
            "\E[00m");
     scanf("%d",&optiontam); //Cojemos el tamaño.
     switch(optiontam)
     {
       case 0: cero(); break;  //Lamamos a cero() (para 0 caracetres):
       case 1: one(); break;  //Llamamos a one() (para 1 caracter)
       case 2: two(); break;  //Llamamos a two() (para 2 caracteres)
       case 3: three(); break;
       case 4: four(); break;
       case 5: five(); break;
       case 6:  break;  //Todavia no lo he puesto...
       case 7:  break;  //Todavia no lo he puesto...
       case 8:  break;  //Todavia no lo he puesto...
       case 9:  break;  //Todavia no lo he puesto...
       case 10: break;  //Todavia no lo he puesto...
       case 11: break;  //Todavia no lo he puesto...
       case 12: break;  //Todavia no lo he puesto...
       case 13: break;  //Todavia no lo he puesto...
       case 14: break;  //Todavia no lo he puesto...
       case 15: break;  //Todavia no lo he puesto...
       case 16: break;  //Todavia no lo he puesto...
       case 17: break;  //Todavia no lo he puesto...
       case 18: break;  //Todavia no lo he puesto...
       case 19: break;  //Todavia no lo he puesto...
       case 20: break;  //Todavia no lo he puesto...
       default: break;  //Todavia no lo he puesto...
     }
   break;
   
   case '3': //Si hemos elegido utilizar un rango de valores...
     setvalues();
   break;

   default:
     printf("\E[0;1m"
            "Unknow option.\n"
            "\E[00m");
     return -1;
   break;
 }
 return 0;
}


int setvalues()
{
 /***EN CONSTRUCCIÓN****/
 return 0;
}



/*
***************HA ESTAS FUNCIONES LAS LLAMAMOS PARA GENERAR LAS PALABRAS********************
***Explico como lo genera en "three()" y en "four()" (para longitudes 3 y 4 respectivamente).
*/

int cero()
{
 char *toexecute;
 char nada = '\0';  //Por si tenemos la p**a suerte de que la password, o para lo que lo utilizemos está en blanco.
 printf("%c\n",nada); //Utilizamos la cadena vacía.
 if(yescommand==1)
 {
   toexecute = command;
   toexecute[tamcommand] = nada;
   system(toexecute);
 }
 return 0;
}


int one()
{
 char *toexecute;
 for (i1=0; i1<=61; i1++)
 {
   char caracter1 = abc[i1];
   printf("%c\n",caracter1);
   if(yescommand==1)
   {
    toexecute = command;
    toexecute[tamcommand] = caracter1;
    system(toexecute);
   }
 }
 return 0;
}


int two()
{
 char *toexecute;
 for (i1=0; i1<=61; i1++)
 {
   char caracter1 = abc[i1];
   for(i2=0; i2<=61; i2++)
   {
     char caracter2 = abc[i2];
     printf("%c%c\n",caracter1,caracter2);
     if(yescommand==1)
     {
         toexecute = command;
         toexecute[tamcommand] = caracter1;
         toexecute[tamcommand + 1] = caracter2;
         system(toexecute);
     }
   }
 }
 return 0;
}


int three()  //Para generar combinaciones de 3 caracteres de longitud.
{
 char *toexecute; //Donde guardamos el comando introducido + las combinaciones generadas.
 for (i1=0; i1<=61; i1++) //Este sería el que más lento cambia de los 3 caracteres.
 {
   char caracter1 = abc[i1]; //"caracter1" apunta primero a "a", luego a "b", luego a "c", etc (ver la variable abc).
   for(i2=0; i2<=61; i2++)
   {
     char caracter2 = abc[i2];
     for(i3=0; i3<=61; i3++) //Este ni lo veríamos pasar de lo rápido que es, pero solo si elegimos no comandos (esto es lo que quiero solucionar).
     {
       char caracter3 = abc[i3];
       printf("%c%c%c\n",caracter1,caracter2,caracter3); //Imprimimos los caracteres, que van variando.
       if(yescommand==1) //Si hemos elegido utilizar un comando...
       {
         toexecute = command; //Ponemos toexecute igual que command, ya que command tiene el comando, pero le tenemos que agregar las palabras generadas.
         toexecute[tamcommand] = caracter1;  //Le vamos agregando las combinaciones (el primer caracter)...
         toexecute[tamcommand + 1] = caracter2;  //Le vamos agregando las combinaciones (el segundo caracter)...
         toexecute[tamcommand + 2] = caracter3;  //Le vamos agregando las combinaciones (el tercer caracter)...
         system(toexecute);  //Ejecutamos "toexecute".
       }
     }
   }
 }
 return 0; //Decimos al main() que todo ha ido bien.
}


int four()
{
 char *toexecute;
 for (i1=0; i1<=61; i1++)
 {
   char caracter1 = abc[i1];
   for(i2=0; i2<=61; i2++)
   {
     char caracter2 = abc[i2];
     for(i3=0; i3<=61; i3++)
     {
       char caracter3 = abc[i3];
       for(i4=0; i4<=61; i4++)
       {
         char caracter4 = abc[i4];
         printf("%c%c%c%c\n",caracter1,caracter2,caracter3,caracter4);
         if(yescommand==1) //Si hemos elegido utilizar un comando...
         {
           toexecute = command; //Ponemos toexecute igual que command.
           toexecute[tamcommand] = caracter1;  //Le vamos agregando las combinaciones (el primer caracter)...
           toexecute[tamcommand + 1] = caracter2;  //Le vamos agregando las combinaciones (el segundo caracter)...
           toexecute[tamcommand + 2] = caracter3;  //Le vamos agregando las combinaciones (el tercer caracter)...
           toexecute[tamcommand + 3] = caracter4;  //Le vamos agregando las combinaciones (el cuarto caracter)...
           system(toexecute);  //Ejecutamos "toexecute".
         }
       }
     }
   }
 }
 return 0;
}


int five()
{
 char *toexecute;
 for (i1=0; i1<=61; i1++)
 {
   char caracter1 = abc[i1];
   for(i2=0; i2<=61; i2++)
   {
     char caracter2 = abc[i2];
     for(i3=0; i3<=61; i3++)
     {
       char caracter3 = abc[i3];
       for(i4=0; i4<=61; i4++)
       {
         char caracter4 = abc[i4];
         for(i5=0; i5<=61; i5++)
         {
           char caracter5 = abc[i5];
           printf("%c%c%c%c%c\n",caracter1,caracter2,caracter3,caracter4,caracter5);
           if(yescommand==1)
           {
           toexecute = command;
           toexecute[tamcommand] = caracter1;
           toexecute[tamcommand + 1] = caracter2;
           toexecute[tamcommand + 2] = caracter3;
           toexecute[tamcommand + 3] = caracter4;
           toexecute[tamcommand + 4] = caracter5;
           system(toexecute);
           }
         }
       }
     }
   }
 }
 return 0;
}


No tengo mucho tiempo para mejorarlo por eso de estudiar, y cuando tengo, no veo que cambiar (detalles importantes, y lo único que he hecho es conseguir logearme en localhost con esta "aaaad" en la opción fijo con 5 caracteres).
He de decir que va muy rápido cuando lo hago sin introducir comandos, pero va al ritmo de 1 por segundo cuando es con comando (porejemplo cuando pongo:  "lftp ftp://localhost/ -u user,". Gracias por adelantado.
(El http:ftp://localhost/ ese sale solo) :o

rir3760

Cita de: NeoB en 12 Febrero 2012, 18:02 PMBuenas, he estado esta última semana dándole vueltas a la idea de hacer un bruteforce en C, para que ya estoy aprendiendo, animarme un poco.
El problema es, al ser tu nivel en el lenguaje todavía bajo, no vas a utilizar todas las facilidades que el lenguaje provee y el programa terminara siendo mas largo (y su desarrollo mas difícil) de lo que debería ser.

Tomar un libro y seguir sus ejemplos (mas ejercicios) no te subirá el nivel de adrenalina pero por algo es la mejor forma de aprender.

Cita de: NeoB en 12 Febrero 2012, 18:02 PMNo tengo mucho tiempo para mejorarlo por eso de estudiar, y cuando tengo, no veo que cambiar (detalles importantes, y lo único que he hecho es conseguir logearme en localhost con esta "aaaad" en la opción fijo con 5 caracteres).
Detalles importantes que cambiar hay muchos, el primero que salta a la vista es:
int i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20;
No hay razón para ello primero porque puedes declarar las variables dentro de las funciones que las utilizan y segundo porque sus nombres no indican nada sobre su uso. Por ejemplo si yo quiero conocer la diferencia entre "i3" e "i5" no queda mas que revisar el código fuente a detalle.


----


Si reducimos el programa al mínimo este consiste en generar palabras en base a un abecedario. Supongamos que este abecedario consta de diez elementos y ellos son:
"0123456789"

Si se desea generar todas las palabras de longitud tres estas son:
000
001
002
003
004
005
006
007
008
009
010

...

999


Como puedes ver con el ejemplo lo que en realidad se hace es procesar de alguna forma cada uno de los números con un numero de dígitos determinado y en una cierta base:

* El numero de dígitos lo indica la longitud de la palabra
* El carácter correspondiente a cada dígito lo dicta tu abecedario
* La base N no es mas que el numero de elementos de tu abecedario.

Hay varias formas de implementarlo, la mas sencilla en mi opinión es emulando un medidor de lo que sea (servicio eléctrico, kilometraje, etc.).

Un ejemplo sencillo en C utilizando un centinela (el ultimo elemento siendo igual al primero en el abecedario) para acortar el programa:
#include <stdio.h>
#include <stdlib.h>

#define MAX_LENGTH  3

void print_words(char const *abc, int length);

int main(void)
{
   char abc[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' /* sentinel */};
   int i;
   
   for (i = 0; i < MAX_LENGTH; i++){
      puts("----");
      print_words(abc, i + 1);
   }
   
   return EXIT_SUCCESS;
}

void print_words(char const *abc, int length)
{
   char *word;
   int i;
   
   if ((word = malloc(length)) == NULL){
      fputs("Women and children first!\n", stderr);
      exit(EXIT_FAILURE);
   }
   
   for (i = 0; i < length; i++)
      word[i] = abc[0];
   printf("Length: %d\n%.*s\n", length, length, word);
   
   while (1){
      i = length;
      while (i-- > 0){
         word[i] = abc[word[i] - abc[0] + 1];
         
         if (word[i] != abc[0])
            break;
      }
     
      if (i == -1)
         break;
      else
         printf("%.*s\n", length, word);
   }
   
   free(word);
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

NeoB