nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /*
2 * genpmk - Generate a file with precomputed PMK's and words
3 *
4 * Copyright (c) 2005, Joshua Wright <jwright@hasborg.com>
5 *
6 * $Id: genpmk.c,v 4.1 2008-03-20 16:49:38 jwright Exp $
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation. See COPYING for more
11 * details.
12 *
13 * coWPAtty is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18  
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 #include <pcap.h>
25 #include <signal.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include <errno.h>
29  
30 #include "cowpatty.h"
31 #include "common.h"
32 #include "utils.h"
33 #include "sha1.h"
34  
35 #define PROGNAME "genpmk"
36 #define VER "1.1"
37  
38 /* Globals */
39 int sig = 0; /* Used for handling signals */
40 char *words;
41  
42 /* Prototypes */
43 void usage(char *message);
44 int nextword(char *word, FILE * fp);
45  
46 void usage(char *message)
47 {
48  
49 if (strlen(message) > 0) {
50 printf("%s: %s\n", PROGNAME, message);
51 }
52  
53 printf("Usage: %s [options]\n", PROGNAME);
54 printf("\n"
55 "\t-f \tDictionary file\n"
56 "\t-d \tOutput hash file\n"
57 "\t-s \tNetwork SSID\n"
58 "\t-h \tPrint this help information and exit\n"
59 "\t-v \tPrint verbose information (more -v for more verbosity)\n"
60 "\t-V \tPrint program version and exit\n" "\n");
61 printf("After precomputing the hash file, run cowpatty with the -d "
62 "argument.\n");
63 }
64  
65 void cleanup()
66 {
67 /* lame-o-meter++ */
68 sig = 1;
69 }
70  
71  
72 int nextword(char *word, FILE * fp)
73 {
74  
75 if (fgets(word, MAXPASSLEN + 1, fp) == NULL) {
76 return (-1);
77 }
78  
79 /* Remove newline */
80 word[strlen(word) - 1] = '\0';
81  
82 if (feof(fp)) {
83 return (-1);
84 }
85  
86 return (strlen(word));
87 }
88  
89 int main(int argc, char **argv)
90 {
91 int fret = 0, c, ret;
92 unsigned long int wordstested=0;
93 float elapsed = 0;
94 char passphrase[MAXPASSLEN + 1];
95 struct user_opt opt;
96 struct hashdb_head hf_header;
97 struct hashdb_rec rec;
98 struct stat teststat;
99 FILE *fpin = NULL, *fpout = NULL;
100 struct timeval start, end;
101 u8 pmk[32];
102  
103 printf("%s %s - WPA-PSK precomputation attack. <jwright@hasborg.com>\n",
104 PROGNAME, VER);
105  
106 memset(&opt, 0, sizeof(opt));
107 memset(&hf_header, 0, sizeof(hf_header));
108  
109 signal(SIGINT, cleanup);
110 signal(SIGTERM, cleanup);
111 signal(SIGQUIT, cleanup);
112  
113 /* Collect and test command-line arguments */
114 while ((c = getopt(argc, argv, "f:d:s:hvV")) != EOF) {
115 switch(c) {
116 case 'f':
117 strncpy(opt.dictfile, optarg, sizeof(opt.dictfile));
118 break;
119 case 'd':
120 strncpy(opt.hashfile, optarg, sizeof(opt.hashfile));
121 break;
122 case 's':
123 strncpy(opt.ssid, optarg, sizeof(opt.ssid));
124 break;
125 case 'h':
126 usage("");
127 exit(0);
128 case 'v':
129 opt.verbose++;
130 break;
131 case 'V':
132 printf("$Id: genpmk.c,v 4.1 2008-03-20 16:49:38 jwright Exp $\n");
133 exit(0);
134 }
135 }
136  
137 if (IsBlank(opt.dictfile)) {
138 usage("Must specify a dictionary file with -f");
139 exit(1);
140 }
141  
142 if (IsBlank(opt.hashfile)) {
143 usage("Must specify an output hasfile with -d");
144 exit(1);
145 }
146  
147 if (IsBlank(opt.ssid)) {
148 usage("Must specify a SSID with -s");
149 exit(1);
150 }
151  
152 /* Open the dictionary file */
153 if (*opt.dictfile == '-') {
154 printf("Using STDIN for words.\n");
155 fpin = stdin;
156 } else {
157 fpin = fopen(opt.dictfile, "r");
158 if (fpin == NULL) {
159 perror("fopen");
160 exit(-1);
161 }
162 }
163  
164  
165 /* stat the hashfile, if it exists, print a message and check to
166 ensure specified SSID matches header information. If so, append
167 new words to the end of the hashdb file.
168 If the file does not exist, populate the hashdb_head record and
169 create the file. */
170 ret = stat(opt.hashfile, &teststat);
171 if (errno == ENOENT || teststat.st_size == 0) {
172 /* File does not exist or is empty, populate header and
173 create */
174 printf("File %s does not exist, creating.\n", opt.hashfile);
175 memcpy(hf_header.ssid, opt.ssid, strlen(opt.ssid));
176 hf_header.ssidlen = strlen(opt.ssid);
177 hf_header.magic = GENPMKMAGIC;
178  
179 fpout = fopen(opt.hashfile, "wb");
180 if (fpout == NULL) {
181 perror("fopen");
182 exit(-1);
183 }
184  
185 if (fwrite(&hf_header, sizeof(hf_header), 1, fpout) != 1) {
186 perror("fwrite");
187 exit(-1);
188 }
189  
190 } else {
191  
192 /* File does exist, append to EOF after matching SSID */
193 fpout = fopen(opt.hashfile, "r+b");
194 if (fpout == NULL) {
195 perror("fopen");
196 exit(-1);
197 }
198  
199 if (fread(&hf_header, sizeof(hf_header), 1, fpout) != 1) {
200 perror("fread");
201 exit(-1);
202 }
203  
204 if (fclose(fpout) != 0) {
205 perror("fclose");
206 exit(-1);
207 }
208  
209 if (memcmp(opt.ssid, hf_header.ssid, hf_header.ssidlen) != 0) {
210 fprintf(stderr, "Specified SSID \"%s\" and the SSID in "
211 "the output file (\"%s\") do not match.\nCreate"
212 " a new file, or change SSID to match.\n",
213 opt.ssid, hf_header.ssid);
214 exit(-1);
215 }
216  
217 printf("File %s exists, appending new data.\n", opt.hashfile);
218 if (fopen(opt.hashfile, "ab") == NULL) {
219 perror("fopen");
220 exit(-1);
221 }
222 }
223  
224  
225  
226 /* Populate capdata struct */
227  
228 gettimeofday(&start, 0);
229  
230 while (feof(fpin) == 0 && sig == 0) {
231  
232 /* Populate "passphrase" with the next word */
233 fret = nextword(passphrase, fpin);
234 if (fret < 0) {
235 break;
236 }
237  
238 if (opt.verbose > 1) {
239 printf("Testing passphrase: %s\n", passphrase);
240 }
241  
242 /*
243 * Test length of word. IEEE 802.11i indicates the passphrase must be
244 * at least 8 characters in length, and no more than 63 characters in
245 * length.
246 */
247 if (fret < 8 || fret > 63) {
248 if (opt.verbose) {
249 printf("Invalid passphrase length: %s (%u).\n",
250 passphrase, strlen(passphrase));
251 }
252 continue;
253 } else {
254 /* This word is good, increment the words tested counter */
255 wordstested++;
256 }
257  
258 /* Status display */
259 if ((wordstested % 1000) == 0) {
260 printf("key no. %ld: %s\n", wordstested, passphrase);
261 fflush(stdout);
262 }
263  
264 if (opt.verbose > 1) {
265 printf("Calculating PMK for \"%s\".\n", passphrase);
266 }
267 pbkdf2_sha1(passphrase, opt.ssid, strlen(opt.ssid), 4096,
268 pmk, sizeof(pmk), USECACHED);
269 if (opt.verbose > 2) {
270 printf("PMK is");
271 lamont_hdump(pmk, sizeof(pmk));
272 }
273  
274 /* Populate record with PMK and record length */
275 memcpy(rec.pmk, pmk, sizeof(pmk));
276 rec.rec_size = (strlen(passphrase) + sizeof(rec.rec_size) +
277 sizeof(rec.pmk));
278  
279 /* Write the record contents to the file */
280 if (fwrite(&rec.rec_size, sizeof(rec.rec_size), 1, fpout) != 1) {
281 perror("fwrite");
282 break;
283 }
284 if (fwrite(passphrase, strlen(passphrase), 1, fpout) != 1) {
285 perror("fwrite");
286 break;
287 }
288 if (fwrite(rec.pmk, sizeof(rec.pmk), 1, fpout) != 1) {
289 perror("fwrite");
290 break;
291 }
292  
293 }
294  
295 if (fclose(fpin) != 0) {
296 perror("fclose");
297 exit(-1);
298 }
299 if (fclose(fpout) != 0) {
300 perror("fclose");
301 exit(-1);
302 }
303  
304 gettimeofday(&end, 0);
305  
306 /* print time elapsed */
307 if (end.tv_usec < start.tv_usec) {
308 end.tv_sec -= 1;
309 end.tv_usec += 1000000;
310 }
311 end.tv_sec -= start.tv_sec;
312 end.tv_usec -= start.tv_usec;
313 elapsed = end.tv_sec + end.tv_usec / 1000000.0;
314  
315 printf("\n%lu passphrases tested in %.2f seconds: %.2f passphrases/"
316 "second\n", wordstested, elapsed, wordstested / elapsed);
317  
318 return (0);
319 }