Update upstream source from tag 'upstream/1.6.5'
Update to upstream version '1.6.5'
with Debian dir 1651acc292407323acadfef15f3d62f5738dfa1f
Sophie Brun
6 years ago
13 | 13 | Reaver versioning was updated to **1.6.x** in order to identify the new cycle. |
14 | 14 | All stable relases since the first beta version of reaver 1.6 can be downloaded from our [Releases](https://github.com/t6x/reaver-wps-fork-t6x/releases) page. |
15 | 15 | * More information about the Pixie Dust attack (including **which APs are vulnerable**) can be found in [pixiewps repository](https://github.com/wiire/pixiewps), |
16 | [pixie dust thread in Kali forum)](https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack) & [Dominique Bongard's full disclosure](https://docs.google.com/spreadsheets/d/1tSlbqVQ59kGn8hgmwcPTHUECQ3o9YhXR91A_p7Nnj5Y/edit?usp=sharing) | |
16 | [pixie dust thread (in Kali forum)](https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)) & [Dominique Bongard's full disclosure](https://docs.google.com/spreadsheets/d/1tSlbqVQ59kGn8hgmwcPTHUECQ3o9YhXR91A_p7Nnj5Y/edit?usp=sharing) | |
17 | 17 | |
18 | 18 | - - - |
19 | 19 | |
67 | 67 | |
68 | 68 | # Reaver Usage |
69 | 69 | |
70 | ```Reaver v1.6.4 WiFi Protected Setup Attack Tool | |
70 | ``` | |
71 | 71 | Copyright (c) 2011, Tactical Network Solutions, Craig Heffner <[email protected]> |
72 | 72 | |
73 | 73 | Required Arguments: |
78 | 78 | -m, --mac=<mac> MAC of the host system |
79 | 79 | -e, --essid=<ssid> ESSID of the target AP |
80 | 80 | -c, --channel=<channel> Set the 802.11 channel for the interface (implies -f) |
81 | -o, --out-file=<file> Send output to a log file [stdout] | |
82 | 81 | -s, --session=<file> Restore a previous session file |
83 | 82 | -C, --exec=<command> Execute the supplied command upon successful pin recovery |
84 | -D, --daemonize Daemonize reaver | |
85 | 83 | -f, --fixed Disable channel hopping |
86 | 84 | -5, --5ghz Use 5GHz 802.11 channels |
87 | 85 | -v, --verbose Display non-critical warnings (-vv or -vvv for more) |
103 | 101 | -L, --ignore-locks Ignore locked state reported by the target AP |
104 | 102 | -E, --eap-terminate Terminate each WPS session with an EAP FAIL packet |
105 | 103 | -J, --timeout-is-nack Treat timeout as NACK (DIR-300/320) |
104 | -F, --ignore-fcs Ignore frame checksum errors | |
106 | 105 | -w, --win7 Mimic a Windows 7 registrar [False] |
107 | 106 | -K, --pixie-dust Run pixiedust attack |
108 | 107 | -Z Run pixiedust attack |
109 | 108 | |
110 | 109 | Example: |
111 | ./reaver -i wlan0mon -b 00:90:4C:C1:AC:21 -vv | |
110 | reaver -i wlan0mon -b 00:90:4C:C1:AC:21 -vv | |
112 | 111 | ``` |
113 | 112 | |
114 | 113 | Options description and examples of use can be found in the [Readme from Craig Heffner](https://github.com/t6x/reaver-wps-fork-t6x/blob/master/docs/README.REAVER). Here comes a description of the new options introduced since then: |
123 | 122 | # Wash Usage |
124 | 123 | |
125 | 124 | ``` |
126 | Wash v1.6.3 WiFi Protected Setup Scan Tool | |
127 | 125 | Copyright (c) 2011, Tactical Network Solutions, Craig Heffner |
128 | 126 | |
129 | 127 | Required Arguments: |
132 | 130 | |
133 | 131 | Optional Arguments: |
134 | 132 | -c, --channel=<num> Channel to listen on [auto] |
135 | -o, --out-file=<file> Write data to file | |
136 | 133 | -n, --probes=<num> Maximum number of probes to send to each AP in scan mode [15] |
137 | -D, --daemonize Daemonize wash | |
134 | -F, --ignore-fcs Ignore frame checksum errors | |
135 | -2, --2ghz Use 2.4GHz 802.11 channels | |
138 | 136 | -5, --5ghz Use 5GHz 802.11 channels |
139 | 137 | -s, --scan Use scan mode |
140 | 138 | -u, --survey Use survey mode [default] |
147 | 145 | ``` |
148 | 146 | |
149 | 147 | A detailed description of the options with concrete syntax examples can be found in [Craig Heffner's wash readme](https://github.com/t6x/reaver-wps-fork-t6x/blob/master/docs/README.WASH). |
150 | About the new options: | |
148 | About the new options and features: | |
151 | 149 | ## -a // --all |
152 | 150 | The option `-a` of Wash will list all access points, including those without WPS enabled. |
153 | 151 | ## -j // --json |
154 | 152 | The extended WPS information (serial, model...) from the AP probe answer will be printed in the terminal (in json format) |
155 | ||
153 | ## "Vendor" column | |
154 | Wash now displays the manufacturer of the wifi chipset from the Acces Points in order to know if they are vulnerable to pixie dust attack. | |
155 | ## Stdout can be piped | |
156 | 156 | Notice that wash output can be piped into other commands. For more information see the wiki article [Everything about the new options from wash](https://github.com/t6x/reaver-wps-fork-t6x/wiki/Everything-about-the-new-options-from-wash) |
157 | 157 | |
158 | 158 | # Acknowledgements |
0 | .TH Reaver "1" "29 December, 2011" "1.3" | |
1 | .SH NAME | |
2 | .P | |
3 | .B Reaver | |
4 | - WPS Cracker | |
5 | .SH SYNOPSIS | |
6 | .P | |
7 | .B reaver -i <interface> -b <target bssid> -vv | |
8 | .SH DESCRIPTION | |
9 | .P | |
10 | Reaver implements a brute force attack against WiFi Protected Setup which can crack the WPS pin of an access point in a matter of hours and subsequently recover the WPA/WPA2 passphrase. | |
11 | .P | |
12 | Specifically, Reaver targets the registrar functionality of WPS, which is flawed in that it only takes 11,000 attempts to guess the correct WPS pin in order to become a WPS registrar. Once registred as a registrar with the access point, the access point will give you the WPA passphrase. | |
13 | .SH OPTIONS | |
14 | .P | |
15 | .RS | |
16 | .B -m, --mac=<mac> | |
17 | .RS | |
18 | MAC of the host system (should be resolved automatically) | |
19 | .RE | |
20 | .RE | |
21 | .P | |
22 | .RS | |
23 | .B -e, --essid=<ssid> | |
24 | .RS | |
25 | ESSID of the target AP. Unless cloaked, this will be resolved automatically. | |
26 | .RE | |
27 | .RE | |
28 | .P | |
29 | .RS | |
30 | .B -c, --channel=<channel> | |
31 | .RS | |
32 | Set the 802.11 channel for the interface (implies -f) | |
33 | .RE | |
34 | .RE | |
35 | .P | |
36 | .RS | |
37 | .B -o, --out-file=<file> | |
38 | .RS | |
39 | Send output to a log file [default: stdout] | |
40 | .RE | |
41 | .RE | |
42 | .P | |
43 | .RS | |
44 | .B -f, --fixed | |
45 | .RS | |
46 | Disable channel hopping | |
47 | .RE | |
48 | .RE | |
49 | .P | |
50 | .RS | |
51 | .B -5, --5ghz | |
52 | .RS | |
53 | Use 5GHz 802.11 channels | |
54 | .RE | |
55 | .RE | |
56 | .P | |
57 | .RS | |
58 | .B -v, --verbose | |
59 | .RS | |
60 | Display non-critical warnings (-vv for more) | |
61 | .RE | |
62 | .RE | |
63 | .P | |
64 | .RS | |
65 | .B -q, --quiet | |
66 | .RS | |
67 | Only display critical messages | |
68 | .RE | |
69 | .RE | |
70 | .P | |
71 | .RS | |
72 | .B -i, --interface=<wlan> | |
73 | .RS | |
74 | Name of the monitor-mode interface to use | |
75 | .RE | |
76 | .RE | |
77 | .P | |
78 | .RS | |
79 | .B -b, --bssid=<mac> | |
80 | .RS | |
81 | BSSID of the target AP | |
82 | .RE | |
83 | .RE | |
84 | .P | |
85 | .RS | |
86 | .B -p, --pin=<wps pin> | |
87 | .RS | |
88 | Use the specified WPS pin | |
89 | .RE | |
90 | .RE | |
91 | .P | |
92 | .RS | |
93 | .B -h, --help | |
94 | .RS | |
95 | Show help | |
96 | .RE | |
97 | .RE | |
98 | .SH AUTHOR | |
99 | .P | |
100 | This manual page was written by Craig Heffner <[email protected]>, Tactical Network Solutions. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. |
47 | 47 | static void deauthenticate(void); |
48 | 48 | static void authenticate(void); |
49 | 49 | static void associate(void); |
50 | static int check_fcs(const unsigned char *packet, size_t len); | |
51 | ||
50 | 52 | |
51 | 53 | /*Reads the next packet from pcap_next() and validates the FCS. */ |
52 | 54 | unsigned char *next_packet(struct pcap_pkthdr *header) |
53 | 55 | { |
54 | 56 | const unsigned char *packet = NULL; |
55 | 57 | struct pcap_pkthdr *pkt_header; |
58 | static int warning_shown = 0; | |
56 | 59 | int status; |
57 | 60 | |
58 | 61 | /* Loop until we get a valid packet, or until we run out of packets */ |
62 | 65 | |
63 | 66 | memcpy(header, pkt_header, sizeof(*header)); |
64 | 67 | |
65 | if(get_validate_fcs() && !check_fcs(packet, header->len)) | |
68 | if(get_validate_fcs() && !check_fcs(packet, header->len)) { | |
69 | if(!warning_shown) | |
70 | cprintf(INFO, "[!] Found packet with bad FCS, skipping...\n"); | |
71 | warning_shown = 1; | |
66 | 72 | continue; |
73 | } | |
67 | 74 | |
68 | 75 | break; |
69 | 76 | } |
602 | 609 | } |
603 | 610 | |
604 | 611 | /* Validates a packet's reported FCS value */ |
605 | int check_fcs(const unsigned char *packet, size_t len) | |
606 | { | |
612 | static int check_fcs(const unsigned char *packet, size_t len) | |
613 | { | |
614 | if(!has_rt_header()) return 1; | |
615 | ||
607 | 616 | uint32_t offset = 0, match = 0; |
608 | 617 | uint32_t fcs = 0, fcs_calc = 0; |
609 | 618 | struct radio_tap_header *rt_header = NULL; |
612 | 621 | { |
613 | 622 | |
614 | 623 | /* FCS is not calculated over the radio tap header */ |
615 | if(has_rt_header() && len >= sizeof(*rt_header)) | |
624 | if(len >= sizeof(*rt_header)) | |
616 | 625 | { |
617 | 626 | uint32_t presentflags, flags; |
618 | 627 | if(!rt_get_presentflags(packet, len, &presentflags, &offset)) |
81 | 81 | int parse_beacon_tags(const unsigned char *data, size_t len); |
82 | 82 | unsigned char *parse_ie_data(const unsigned char *data, size_t len, uint8_t tag_number, size_t *ie_len, size_t *ie_offset); |
83 | 83 | int is_target(struct dot11_frame_header *frame_header); |
84 | int check_fcs(const unsigned char *packet, size_t len); | |
85 | 84 | int has_rt_header(void); |
86 | 85 | unsigned char *radio_header(const unsigned char *packet, size_t len); |
87 | 86 |
48 | 48 | int long_opt_index = 0; |
49 | 49 | char bssid[MAC_ADDR_LEN] = { 0 }; |
50 | 50 | char mac[MAC_ADDR_LEN] = { 0 }; |
51 | char *short_options = "b:e:m:i:t:d:c:T:x:r:g:l:o:p:s:C:KZA5ELfnqvDShwN6J"; | |
51 | char *short_options = "b:e:m:i:t:d:c:T:x:r:g:l:p:s:C:KZA5ELfnqvDShwN6JF"; | |
52 | 52 | struct option long_options[] = { |
53 | 53 | { "pixie-dust", no_argument, NULL, 'K' }, |
54 | 54 | { "interface", required_argument, NULL, 'i' }, |
64 | 64 | { "session", required_argument, NULL, 's' }, |
65 | 65 | { "recurring-delay", required_argument, NULL, 'r' }, |
66 | 66 | { "max-attempts", required_argument, NULL, 'g' }, |
67 | { "out-file", required_argument, NULL, 'o' }, | |
68 | 67 | { "pin", required_argument, NULL, 'p' }, |
69 | 68 | { "exec", required_argument, NULL, 'C' }, |
70 | 69 | { "no-associate", no_argument, NULL, 'A' }, |
73 | 72 | { "eap-terminate", no_argument, NULL, 'E' }, |
74 | 73 | { "dh-small", no_argument, NULL, 'S' }, |
75 | 74 | { "fixed", no_argument, NULL, 'f' }, |
76 | { "daemonize", no_argument, NULL, 'D' }, | |
77 | 75 | { "5ghz", no_argument, NULL, '5' }, |
78 | 76 | { "repeat-m6", no_argument, NULL, '6' }, |
79 | 77 | { "nack", no_argument, NULL, 'n' }, |
82 | 80 | { "win7", no_argument, NULL, 'w' }, |
83 | 81 | { "help", no_argument, NULL, 'h' }, |
84 | 82 | { "timeout-is-nack", no_argument, NULL, 'J' }, |
83 | { "ignore-fcs", no_argument, NULL, 'F' }, | |
85 | 84 | { 0, 0, 0, 0 } |
86 | 85 | }; |
87 | 86 | |
147 | 146 | case 'L': |
148 | 147 | set_ignore_locks(1); |
149 | 148 | break; |
150 | case 'o': | |
151 | set_log_file(fopen(optarg, "w")); | |
152 | break; | |
153 | 149 | case 'x': |
154 | 150 | set_fail_delay(atoi(optarg)); |
155 | 151 | break; |
159 | 155 | case 'g': |
160 | 156 | set_max_pin_attempts(atoi(optarg)); |
161 | 157 | break; |
162 | case 'D': | |
163 | daemonize(); | |
164 | break; | |
165 | 158 | case 'E': |
166 | 159 | set_eap_terminate(1); |
167 | 160 | break; |
188 | 181 | break; |
189 | 182 | case 'N': |
190 | 183 | set_oo_send_nack(0); |
184 | break; | |
185 | case 'F': | |
186 | set_validate_fcs(0); | |
191 | 187 | break; |
192 | 188 | default: |
193 | 189 | ret_val = EXIT_FAILURE; |
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.4. | |
2 | # Generated by GNU Autoconf 2.69 for reaver 1.6.5. | |
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.4' | |
580 | PACKAGE_STRING='reaver 1.6.4' | |
579 | PACKAGE_VERSION='1.6.5' | |
580 | PACKAGE_STRING='reaver 1.6.5' | |
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.4 to adapt to many kinds of systems. | |
1225 | \`configure' configures reaver 1.6.5 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.4:";; | |
1286 | short | recursive ) echo "Configuration of reaver 1.6.5:";; | |
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.4 | |
1374 | reaver configure 1.6.5 | |
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.4, which was | |
1672 | It was created by reaver $as_me 1.6.5, which was | |
1673 | 1673 | generated by GNU Autoconf 2.69. Invocation command line was |
1674 | 1674 | |
1675 | 1675 | $ $0 $@ |
3886 | 3886 | # report actual input values of CONFIG_FILES etc. instead of their |
3887 | 3887 | # values after options handling. |
3888 | 3888 | ac_log=" |
3889 | This file was extended by reaver $as_me 1.6.4, which was | |
3889 | This file was extended by reaver $as_me 1.6.5, which was | |
3890 | 3890 | generated by GNU Autoconf 2.69. Invocation command line was |
3891 | 3891 | |
3892 | 3892 | CONFIG_FILES = $CONFIG_FILES |
3939 | 3939 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
3940 | 3940 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
3941 | 3941 | ac_cs_version="\\ |
3942 | reaver config.status 1.6.4 | |
3942 | reaver config.status 1.6.5 | |
3943 | 3943 | configured by $0, generated by GNU Autoconf 2.69, |
3944 | 3944 | with options \\"\$ac_cs_config\\" |
3945 | 3945 |
98 | 98 | } |
99 | 99 | #endif |
100 | 100 | |
101 | /* | |
101 | /* | |
102 | 102 | * Goes to the next 802.11 channel. |
103 | 103 | * This is mostly required for APs that hop channels, which usually hop between channels 1, 6, and 11. |
104 | 104 | * We just hop channels until we successfully associate with the AP. |
106 | 106 | */ |
107 | 107 | int next_channel() |
108 | 108 | { |
109 | #define BG_CHANNELS 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 | |
110 | #define AN_CHANNELS 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 183, 184, 185, 187, 188, 189, 192, 196 | |
111 | ||
109 | 112 | static int i; |
110 | int n = 0; | |
111 | int bg_channels[] = BG_CHANNELS; | |
112 | int an_channels[] = AN_CHANNELS; | |
113 | int *channels = NULL; | |
113 | static const short bg_channels[] = {BG_CHANNELS}; | |
114 | static const short an_channels[] = {AN_CHANNELS}; | |
115 | static const short bgan_channels[] = {BG_CHANNELS, AN_CHANNELS}; | |
116 | static const int band_chan_count[] = { | |
117 | [BG_BAND] = sizeof(bg_channels)/sizeof(bg_channels[0]), | |
118 | [AN_BAND] = sizeof(an_channels)/sizeof(an_channels[0]), | |
119 | [BG_BAND|AN_BAND] = sizeof(bgan_channels)/sizeof(bgan_channels[0]), | |
120 | }; | |
121 | static const short* band_select[] = { | |
122 | [BG_BAND] = bg_channels, | |
123 | [AN_BAND] = an_channels, | |
124 | [BG_BAND|AN_BAND] = bgan_channels, | |
125 | }; | |
114 | 126 | |
115 | /* Select the appropriate channels for the target 802.11 band */ | |
116 | if(get_wifi_band() == AN_BAND) | |
117 | { | |
118 | channels = (int *) &an_channels; | |
119 | n = sizeof(an_channels) / sizeof(int); | |
120 | } | |
121 | else | |
122 | { | |
123 | channels = (int *) &bg_channels; | |
124 | n = sizeof(bg_channels) / sizeof(int); | |
125 | } | |
127 | int band = get_wifi_band(); | |
128 | const short *channels = band_select[band]; | |
129 | int n = band_chan_count[band]; | |
126 | 130 | |
127 | 131 | /* Only switch channels if fixed channel operation is disabled */ |
128 | 132 | if(!get_fixed_channel()) |
129 | 133 | { |
130 | i++; | |
134 | i++; | |
135 | if((i >= n) || i < 0) i = 0; | |
136 | return change_channel(channels[i]); | |
137 | } | |
131 | 138 | |
132 | if((i >= n) || i < 0) | |
133 | { | |
134 | i = 0; | |
135 | } | |
136 | ||
137 | return change_channel(channels[i]); | |
138 | } | |
139 | ||
140 | 139 | return 0; |
141 | 140 | } |
142 | 141 |
33 | 33 | #ifndef IFACE_H |
34 | 34 | #define IFACE_H |
35 | 35 | |
36 | #define BG_BAND 0 | |
37 | #define AN_BAND 1 | |
38 | ||
39 | #define BG_CHANNELS { 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 } | |
40 | #define AN_CHANNELS { 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 183, 184, 185, 187, 188, 189, 192, 196 } | |
36 | #define BG_BAND (1 << 0) | |
37 | #define AN_BAND (1 << 1) | |
41 | 38 | |
42 | 39 | int read_iface_mac(); |
43 | 40 | int next_channel(); |
148 | 148 | if(!status) return handle; |
149 | 149 | } |
150 | 150 | cprintf(CRITICAL, "[X] ERROR: pcap_activate status %d\n", status); |
151 | if(status == PCAP_ERROR_NO_SUCH_DEVICE) | |
152 | cprintf(CRITICAL, "[X] PCAP: no such device\n"); | |
153 | /* TODO : print nice error message for other codes */ | |
151 | static const char *pcap_errmsg[] = { | |
152 | [1] = "generic error code", | |
153 | [2] = "loop terminated by pcap_breakloop", | |
154 | [3] = "the capture needs to be activated", | |
155 | [4] = "the operation can't be performed on already activated captures", | |
156 | [5] = "no such device exists", | |
157 | [6] = "this device doesn't support rfmon (monitor) mode", | |
158 | [7] = "operation supported only in monitor mode", | |
159 | [8] = "no permission to open the device", | |
160 | [9] = "interface isn't up", | |
161 | [10]= "this device doesn't support setting the time stamp type", | |
162 | [11]= "you don't have permission to capture in promiscuous mode", | |
163 | [12]= "the requested time stamp precision is not supported", | |
164 | }; | |
165 | if(status < 0 && status > -13) | |
166 | cprintf(CRITICAL, "[X] PCAP: %s\n", pcap_errmsg[-status]); | |
154 | 167 | pcap_close(handle); |
155 | 168 | handle = 0; |
156 | 169 | } |
85 | 85 | fflush(get_log_file()); |
86 | 86 | } |
87 | 87 | |
88 | /* Daemonizes the process */ | |
89 | void daemonize(void) | |
90 | { | |
91 | if(fork() > 0) | |
92 | { | |
93 | exit(EXIT_SUCCESS); | |
94 | } | |
95 | ||
96 | if(chdir("/") == 0) | |
97 | { | |
98 | setsid(); | |
99 | umask(0); | |
100 | ||
101 | if(fork() > 0) | |
102 | { | |
103 | exit(EXIT_SUCCESS); | |
104 | } | |
105 | } | |
106 | } | |
107 | ||
108 | 88 | /* Closes libpcap during sleep period to avoid stale packet data in pcap buffer */ |
109 | 89 | void pcap_sleep(int seconds) |
110 | 90 | { |
25 | 25 | p->pke, p->ehash1, p->ehash2, p->authkey, p->enonce, |
26 | 26 | dh_small ? "-S" : "-r" , dh_small ? "" : p->pkr); |
27 | 27 | printf("executing %s\n", cmd); |
28 | system(cmd); | |
29 | exit(0); | |
28 | exit(system(cmd)); | |
30 | 29 | } |
31 | 30 | PIXIE_FREE(authkey); |
32 | 31 | PIXIE_FREE(pkr); |
378 | 378 | return new; |
379 | 379 | } |
380 | 380 | |
381 | int verifyssid(const unsigned char *s) | |
382 | { | |
383 | int i; | |
384 | unsigned char c; | |
385 | ||
386 | if(!s || strlen(s)>32) { //32 characters | |
387 | return 0; | |
388 | } | |
389 | ||
390 | for (i = 0; (c = s[i++]);) { | |
391 | if ((c & 0x80) == 0) {//ascii flag | |
392 | if(c < 0x20 || c == 0x7f) { | |
393 | return 0; | |
394 | } | |
395 | } else if ((c & 0xe0) == 0xc0) {//utf8 flag | |
396 | if ((s[i++] & 0xc0) != 0x80) { | |
397 | return 0; | |
398 | } | |
399 | } else if ((c & 0xf0) == 0xe0) {//utf8 flag | |
400 | if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) { | |
401 | return 0; | |
402 | } | |
403 | } else if ((c & 0xf8) == 0xf0) {//utf8 flag | |
404 | if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) { | |
405 | return 0; | |
406 | } | |
407 | } else { | |
408 | return 0; | |
409 | } | |
410 | } | |
411 | return 1; | |
412 | } |
447 | 447 | int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, |
448 | 448 | size_t len); |
449 | 449 | char* sanitize_string(const char *s); |
450 | int verifyssid(const unsigned char *s); | |
450 | 451 | |
451 | 452 | #ifdef CONFIG_NATIVE_WINDOWS |
452 | 453 | void wpa_unicode2ascii_inplace(TCHAR *str); |
126 | 126 | # error "Sorry, we couldn't detect endiannes for your system! Please set -DENDIANNESS_LE=1 or 0 using your CPPFLAGS/CFLAGS and open an issue for your system on https://github.com/rofl0r/endianness.h - Thanks!" |
127 | 127 | #endif |
128 | 128 | |
129 | #ifdef ENDIANNESS_DEBUG | |
130 | # if ENDIANNESS_LE == 1 | |
131 | # warning "Detected Little Endian target CPU" | |
132 | # endif | |
133 | # if ENDIANNESS_BE == 1 | |
134 | # warning "Detected BIG Endian target CPU" | |
135 | # endif | |
136 | #endif | |
137 | ||
129 | 138 | #include <stdint.h> |
130 | 139 | #include <limits.h> |
131 | 140 | |
210 | 219 | return result; |
211 | 220 | } |
212 | 221 | |
213 | #ifdef ENDIANNESS_LE | |
222 | #if ENDIANNESS_LE+0 == 1 | |
214 | 223 | # define end_htobe16(x) end_bswap16(x) |
215 | 224 | # define end_be16toh(x) end_bswap16(x) |
216 | 225 | # define end_htobe32(x) end_bswap32(x) |
223 | 232 | # define end_le32toh(x) (uint32_t)(x) |
224 | 233 | # define end_htole64(x) (uint64_t)(x) |
225 | 234 | # define end_le64toh(x) (uint64_t)(x) |
226 | #elif ENDIANNESS_BE | |
235 | #elif ENDIANNESS_BE+0 == 1 | |
227 | 236 | # define end_htobe16(x) (uint16_t)(x) |
228 | 237 | # define end_be16toh(x) (uint16_t)(x) |
229 | 238 | # define end_htobe32(x) (uint32_t)(x) |
18 | 18 | {"\x00\x1c\x51", "CelenoCo"}, /* Celeno Communications */ |
19 | 19 | {"\x00\x50\x43", "MarvellS"}, /* Marvell Semiconductor, Inc. */ |
20 | 20 | {"\x00\x26\x86", "Quantenn"}, /* Quantenna */ |
21 | {"\x00\x09\x86", "LantiqML"}, /* Lantiq/MetaLink */ | |
21 | 22 | {"\x00\x50\xf2", "Microsof"} /* Microsoft */ |
22 | 23 | }; |
23 | 24 |
0 | 0 | #!/bin/sh |
1 | 1 | |
2 | BINDIR=$(dirname $(readlink -f "$0")) | |
2 | argv0=$(echo "$0" | sed -e 's,\\,/,g') | |
3 | BINDIR=$(dirname "$(readlink "$0" || echo "$argv0")") | |
3 | 4 | |
4 | 5 | if test -d "$BINDIR"/../.git ; then |
5 | 6 | if type git >/dev/null 2>&1 ; then |
151 | 151 | fprintf(stderr, "\t-m, --mac=<mac> MAC of the host system\n"); |
152 | 152 | fprintf(stderr, "\t-e, --essid=<ssid> ESSID of the target AP\n"); |
153 | 153 | fprintf(stderr, "\t-c, --channel=<channel> Set the 802.11 channel for the interface (implies -f)\n"); |
154 | fprintf(stderr, "\t-o, --out-file=<file> Send output to a log file [stdout]\n"); | |
155 | 154 | fprintf(stderr, "\t-s, --session=<file> Restore a previous session file\n"); |
156 | 155 | fprintf(stderr, "\t-C, --exec=<command> Execute the supplied command upon successful pin recovery\n"); |
157 | fprintf(stderr, "\t-D, --daemonize Daemonize reaver\n"); | |
158 | 156 | fprintf(stderr, "\t-f, --fixed Disable channel hopping\n"); |
159 | 157 | fprintf(stderr, "\t-5, --5ghz Use 5GHz 802.11 channels\n"); |
160 | 158 | //fprintf(stderr, "\t-6, --repeat-m6 Send M6 again upon duplicated M5 reception\n"); |
177 | 175 | fprintf(stderr, "\t-L, --ignore-locks Ignore locked state reported by the target AP\n"); |
178 | 176 | fprintf(stderr, "\t-E, --eap-terminate Terminate each WPS session with an EAP FAIL packet\n"); |
179 | 177 | fprintf(stderr, "\t-J, --timeout-is-nack Treat timeout as NACK (DIR-300/320)\n"); |
178 | fprintf(stderr, "\t-F, --ignore-fcs Ignore frame checksum errors\n"); | |
180 | 179 | fprintf(stderr, "\t-w, --win7 Mimic a Windows 7 registrar [False]\n"); |
181 | 180 | fprintf(stderr, "\t-K, --pixie-dust Run pixiedust attack\n"); |
182 | 181 | fprintf(stderr, "\t-Z Run pixiedust attack\n"); |
35 | 35 | #include "utils/vendor.h" |
36 | 36 | #include "send.h" |
37 | 37 | |
38 | #define MAX_APS 512 | |
39 | ||
38 | 40 | extern const char* get_version(void); |
39 | 41 | static void wash_usage(char *prog); |
40 | 42 | |
41 | 43 | int show_all_aps = 0; |
42 | 44 | int json_mode = 0; |
45 | int show_utf8_ssid = 0; | |
43 | 46 | |
44 | 47 | static struct mac { |
45 | 48 | unsigned char mac[6]; |
46 | 49 | unsigned char vendor_oui[1+3]; |
47 | 50 | unsigned char probes; |
48 | 51 | unsigned char flags; |
49 | } seen_list[256]; | |
52 | } seen_list[MAX_APS]; | |
50 | 53 | enum seen_flags { |
51 | 54 | SEEN_FLAG_PRINTED = 1, |
52 | 55 | SEEN_FLAG_COMPLETE = 2, |
56 | 59 | unsigned i; |
57 | 60 | unsigned char mac[6]; |
58 | 61 | str2mac(bssid, mac); |
59 | if(seen_count >= 256) return -1; | |
60 | 62 | for(i=0; i<seen_count; i++) |
61 | 63 | if(!memcmp(seen_list[i].mac, mac, 6)) return i; |
64 | if(seen_count >= MAX_APS) return -1; | |
62 | 65 | memcpy(seen_list[seen_count].mac, mac, 6); |
63 | 66 | return seen_count++; |
64 | 67 | } |
65 | 68 | static int was_printed(char* bssid) { |
66 | 69 | int x = list_insert(bssid); |
67 | if(x >= 0 && x < 256) { | |
70 | if(x >= 0 && x < MAX_APS) { | |
68 | 71 | unsigned f = seen_list[x].flags; |
69 | 72 | seen_list[x].flags |= SEEN_FLAG_PRINTED; |
70 | 73 | return f & SEEN_FLAG_PRINTED; |
73 | 76 | } |
74 | 77 | static void mark_ap_complete(char *bssid) { |
75 | 78 | int x = list_insert(bssid); |
76 | if(x >= 0 && x < 256) seen_list[x].flags |= SEEN_FLAG_COMPLETE; | |
79 | if(x >= 0 && x < MAX_APS) seen_list[x].flags |= SEEN_FLAG_COMPLETE; | |
77 | 80 | } |
78 | 81 | static int is_done(char *bssid) { |
79 | 82 | int x = list_insert(bssid); |
80 | if(x >= 0 && x < 256) return seen_list[x].flags & SEEN_FLAG_COMPLETE; | |
83 | if(x >= 0 && x < MAX_APS) return seen_list[x].flags & SEEN_FLAG_COMPLETE; | |
81 | 84 | return 1; |
82 | 85 | } |
83 | 86 | static int should_probe(char *bssid) { |
84 | 87 | int x = list_insert(bssid); |
85 | if(x >= 0 && x < 256) return seen_list[x].probes < get_max_num_probes(); | |
88 | if(x >= 0 && x < MAX_APS) return seen_list[x].probes < get_max_num_probes(); | |
86 | 89 | return 0; |
87 | 90 | } |
88 | 91 | static void update_probe_count(char *bssid) { |
89 | 92 | int x = list_insert(bssid); |
90 | if(x >= 0 && x < 256) seen_list[x].probes++; | |
93 | if(x >= 0 && x < MAX_APS) seen_list[x].probes++; | |
91 | 94 | } |
92 | 95 | static void set_ap_vendor(char *bssid) { |
93 | 96 | int x = list_insert(bssid); |
94 | if(x >= 0 && x < 256) memcpy(seen_list[x].vendor_oui, globule->vendor_oui, sizeof(seen_list[x].vendor_oui)); | |
97 | if(x >= 0 && x < MAX_APS) memcpy(seen_list[x].vendor_oui, globule->vendor_oui, sizeof(seen_list[x].vendor_oui)); | |
95 | 98 | } |
96 | 99 | static unsigned char *get_ap_vendor(char* bssid) { |
97 | 100 | int x = list_insert(bssid); |
98 | if(x >= 0 && x < 256 && seen_list[x].vendor_oui[0]) | |
101 | if(x >= 0 && x < MAX_APS && seen_list[x].vendor_oui[0]) | |
99 | 102 | return seen_list[x].vendor_oui+1; |
100 | 103 | return 0; |
101 | 104 | } |
105 | ||
102 | 106 | int wash_main(int argc, char *argv[]) |
103 | 107 | { |
104 | 108 | int c = 0; |
106 | 110 | int long_opt_index = 0, i = 0, channel = 0, passive = 0, mode = 0; |
107 | 111 | int source = INTERFACE, ret_val = EXIT_FAILURE; |
108 | 112 | struct bpf_program bpf = { 0 }; |
109 | char *out_file = NULL, *last_optarg = NULL, *target = NULL, *bssid = NULL; | |
110 | char *short_options = "i:c:n:o:b:5sfuDhaj"; | |
113 | char *last_optarg = NULL, *target = NULL, *bssid = NULL; | |
114 | char *short_options = "i:c:n:b:25sfuFDhajU"; | |
111 | 115 | struct option long_options[] = { |
112 | 116 | { "bssid", required_argument, NULL, 'b' }, |
113 | 117 | { "interface", required_argument, NULL, 'i' }, |
114 | 118 | { "channel", required_argument, NULL, 'c' }, |
115 | { "out-file", required_argument, NULL, 'o' }, | |
116 | 119 | { "probes", required_argument, NULL, 'n' }, |
117 | { "daemonize", no_argument, NULL, 'D' }, | |
118 | 120 | { "file", no_argument, NULL, 'f' }, |
121 | { "ignore-fcs", no_argument, NULL, 'F' }, | |
122 | { "2ghz", no_argument, NULL, '2' }, | |
119 | 123 | { "5ghz", no_argument, NULL, '5' }, |
120 | 124 | { "scan", no_argument, NULL, 's' }, |
121 | 125 | { "survey", no_argument, NULL, 'u' }, |
122 | 126 | { "all", no_argument, NULL, 'a' }, |
123 | 127 | { "json", no_argument, NULL, 'j' }, |
128 | { "utf8", no_argument, NULL, 'U' }, | |
124 | 129 | { "help", no_argument, NULL, 'h' }, |
125 | 130 | { 0, 0, 0, 0 } |
126 | 131 | }; |
127 | 132 | |
128 | fprintf(stderr, "\nWash v%s WiFi Protected Setup Scan Tool\n", get_version()); | |
129 | fprintf(stderr, "Copyright (c) 2011, Tactical Network Solutions, Craig Heffner\n\n"); | |
130 | ||
131 | 133 | globule_init(); |
132 | 134 | set_auto_channel_select(0); |
133 | set_wifi_band(BG_BAND); | |
135 | set_wifi_band(0); | |
134 | 136 | set_debug(INFO); |
135 | 137 | set_validate_fcs(1); |
136 | set_log_file(stdout); | |
138 | /* send all warnings, etc to stderr */ | |
139 | set_log_file(stderr); | |
137 | 140 | set_max_num_probes(DEFAULT_MAX_NUM_PROBES); |
141 | ||
142 | setvbuf(stdout, 0, _IONBF, 0); | |
143 | setvbuf(stderr, 0, _IONBF, 0); | |
138 | 144 | |
139 | 145 | while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1) |
140 | 146 | { |
154 | 160 | set_fixed_channel(1); |
155 | 161 | break; |
156 | 162 | case '5': |
157 | set_wifi_band(AN_BAND); | |
163 | set_wifi_band(get_wifi_band() | AN_BAND); | |
164 | break; | |
165 | case '2': | |
166 | set_wifi_band(get_wifi_band() | BG_BAND); | |
158 | 167 | break; |
159 | 168 | case 'n': |
160 | 169 | set_max_num_probes(atoi(optarg)); |
161 | 170 | break; |
162 | case 'o': | |
163 | out_file = strdup(optarg); | |
164 | break; | |
165 | 171 | case 'j': |
166 | 172 | json_mode = 1; |
167 | 173 | break; |
171 | 177 | case 'u': |
172 | 178 | mode = SURVEY; |
173 | 179 | break; |
174 | case 'D': | |
175 | daemonize(); | |
180 | case 'F': | |
181 | set_validate_fcs(0); | |
176 | 182 | break; |
177 | 183 | case 'a': |
178 | 184 | show_all_aps = 1; |
185 | break; | |
186 | case 'U': | |
187 | show_utf8_ssid = 1; | |
179 | 188 | break; |
180 | 189 | default: |
181 | 190 | wash_usage(argv[0]); |
194 | 203 | } |
195 | 204 | } |
196 | 205 | |
206 | if(get_wifi_band() == 0) set_wifi_band(BG_BAND); | |
207 | ||
197 | 208 | /* The interface value won't be set if capture files were specified; else, there should have been an interface specified */ |
198 | 209 | if(!get_iface() && source != PCAP_FILE) |
199 | 210 | { |
217 | 228 | if(source == PCAP_FILE) |
218 | 229 | { |
219 | 230 | passive = 1; |
220 | } | |
221 | ||
222 | /* Open the output file, if any. If none, write to stdout. */ | |
223 | if(out_file) | |
224 | { | |
225 | fp = fopen(out_file, "wb"); | |
226 | if(!fp) | |
227 | { | |
228 | cprintf(CRITICAL, "[X] ERROR: Failed to open '%s' for writing\n", out_file); | |
229 | goto end; | |
230 | } | |
231 | ||
232 | set_log_file(fp); | |
233 | 231 | } |
234 | 232 | |
235 | 233 | /* |
290 | 288 | end: |
291 | 289 | globule_deinit(); |
292 | 290 | if(bssid) free(bssid); |
293 | if(out_file) free(out_file); | |
294 | 291 | if(wpsmon.fp) fclose(wpsmon.fp); |
295 | 292 | return ret_val; |
296 | 293 | } |
334 | 331 | if(!header_printed) |
335 | 332 | { |
336 | 333 | if(!json_mode) { |
337 | cprintf (INFO, "BSSID Ch dBm WPS Lck Vendor ESSID\n"); | |
338 | //cprintf(INFO, "00:11:22:33:44:55 104 -77 1.0 Yes Bloatcom 0123456789abcdef0123456789abcdef\n"); | |
339 | cprintf (INFO, "--------------------------------------------------------------------------------\n"); | |
334 | fprintf (stdout, "BSSID Ch dBm WPS Lck Vendor ESSID\n"); | |
335 | //fprintf(stdout, "00:11:22:33:44:55 104 -77 1.0 Yes Bloatcom 0123456789abcdef0123456789abcdef\n"); | |
336 | fprintf (stdout, "--------------------------------------------------------------------------------\n"); | |
340 | 337 | } |
341 | 338 | header_printed = 1; |
342 | 339 | } |
438 | 435 | |
439 | 436 | char* vendor = get_vendor_string(get_ap_vendor(bssid)); |
440 | 437 | char* sane_ssid = sanitize_string(ssid); |
438 | ||
439 | if(show_utf8_ssid && verifyssid(ssid)) | |
440 | strcpy(sane_ssid,ssid); | |
441 | ||
441 | 442 | if(wps->version > 0) |
442 | cprintf(INFO, "%17s %3d %.2d %d.%d %3s %8s %s\n", bssid, channel, rssi, (wps->version >> 4), (wps->version & 0x0F), lock_display, vendor ? vendor : " ", sane_ssid); | |
443 | fprintf(stdout, "%17s %3d %.2d %d.%d %3s %8s %s\n", bssid, channel, rssi, (wps->version >> 4), (wps->version & 0x0F), lock_display, vendor ? vendor : " ", sane_ssid); | |
443 | 444 | else |
444 | cprintf(INFO, "%17s %3d %.2d %8s %s\n", bssid, channel, rssi, vendor ? vendor : " ", sane_ssid); | |
445 | fprintf(stdout, "%17s %3d %.2d %8s %s\n", bssid, channel, rssi, vendor ? vendor : " ", sane_ssid); | |
445 | 446 | free(sane_ssid); |
446 | 447 | } |
447 | 448 | |
459 | 460 | mark_ap_complete(bssid); |
460 | 461 | if(json_mode && (show_all_aps || wps->version > 0)) { |
461 | 462 | char *json_string = wps_data_to_json(bssid, ssid, channel, rssi, get_ap_vendor(bssid), wps); |
462 | fprintf(get_log_file(), "%s\n", json_string); | |
463 | fflush(get_log_file()); | |
463 | fprintf(stdout, "%s\n", json_string); | |
464 | fflush(stdout); | |
464 | 465 | free(json_string); |
465 | 466 | } |
466 | 467 | } |
501 | 502 | next_channel(); |
502 | 503 | } |
503 | 504 | |
505 | static void print_header(void) { | |
506 | fprintf(stderr, "\nWash v%s WiFi Protected Setup Scan Tool\n", get_version()); | |
507 | fprintf(stderr, "Copyright (c) 2011, Tactical Network Solutions, Craig Heffner\n\n"); | |
508 | } | |
509 | ||
504 | 510 | static void wash_usage(char *prog) |
505 | 511 | { |
512 | print_header(); | |
513 | ||
506 | 514 | fprintf(stderr, "Required Arguments:\n"); |
507 | 515 | fprintf(stderr, "\t-i, --interface=<iface> Interface to capture packets on\n"); |
508 | 516 | fprintf(stderr, "\t-f, --file [FILE1 FILE2 FILE3 ...] Read packets from capture files\n"); |
509 | 517 | |
510 | 518 | fprintf(stderr, "\nOptional Arguments:\n"); |
511 | 519 | fprintf(stderr, "\t-c, --channel=<num> Channel to listen on [auto]\n"); |
512 | fprintf(stderr, "\t-o, --out-file=<file> Write data to file\n"); | |
513 | 520 | fprintf(stderr, "\t-n, --probes=<num> Maximum number of probes to send to each AP in scan mode [%d]\n", DEFAULT_MAX_NUM_PROBES); |
514 | fprintf(stderr, "\t-D, --daemonize Daemonize wash\n"); | |
521 | fprintf(stderr, "\t-F, --ignore-fcs Ignore frame checksum errors\n"); | |
522 | fprintf(stderr, "\t-2, --2ghz Use 2.4GHz 802.11 channels\n"); | |
515 | 523 | fprintf(stderr, "\t-5, --5ghz Use 5GHz 802.11 channels\n"); |
516 | 524 | fprintf(stderr, "\t-s, --scan Use scan mode\n"); |
517 | 525 | fprintf(stderr, "\t-u, --survey Use survey mode [default]\n"); |
518 | 526 | fprintf(stderr, "\t-a, --all Show all APs, even those without WPS\n"); |
519 | 527 | fprintf(stderr, "\t-j, --json print extended WPS info as json\n"); |
528 | fprintf(stderr, "\t-U, --utf8 Show UTF8 ESSID (does not sanitize ESSID, dangerous)\n"); | |
520 | 529 | fprintf(stderr, "\t-h, --help Show help\n"); |
521 | 530 | |
522 | 531 | fprintf(stderr, "\nExample:\n"); |