-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcrack.c
378 lines (314 loc) · 9.56 KB
/
crack.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/*
* Crack by Chris Fortier
*
* This program will accept a DES hash (presumably form a *NIX /etc/passwd file) and will attempt to crack it.
*
* The first attempt is through a list of 10,000 most commonly used passwords obtained from:
* http://xato.net/passwords/more-top-worst-passwords/
* The next attempt uses the /usr/share/dict/words file
*
* Finally we recursively go through every possible combination of valid ASCII characters hoping to find the password.
*
*/
#define _XOPEN_SOURCE
#define CHAR_SET_SIZE 94
#include <stdio.h>
#include <cs50.h>
#include <unistd.h>
#include <crypt.h>
#include <string.h>
#include <time.h>
// GLOBALS
// these are used by multiple functions within the program and declared here to provide easy access.
string password_hash;
char salt[2];
int long long counter = 0;
char *PASSWORD = NULL;
bool found = false;
bool verbose = true;
//PROTOTYPES
int crack_it(char *word);
int common_passwords(void);
int linux_words(void);
int brute_force(void);
int iterator(char *guess, int *char_set, int this_size, int position);
//main (duh)
int main (int argc, string argv[])
{
//user enters a hashed value to try and crack
if (argc == 2)
{
//assign password_hash
password_hash = argv[1];
//get salt from hash
salt[0] = (char)password_hash[0];
salt[1] = (char)password_hash[1];
//printf("[0]: %d\n", password_hash[0]);
//printf("[1]: %d\n", password_hash[1]);
printf("\n");
//formatting:
if (verbose)
{
printf("\n");
for (int i = 0; i < 51; i++)
{
printf("*");
}
printf("\n");
//printf(" ");
}
//PASSWORD = "TEMP";
//printf("PASSWORD: %s\n", PASSWORD);
}
else
{
printf("\nYou did not enter a hash. Program is exiting now.\n");
return 1;
}
//start timer
time_t start, end;
double dif;
time (&start);
//call common_passwords
if (!found)
{
if(verbose)
{
printf("Checking a list of common passwords...\n");
}
int common_passwords_return = common_passwords();
//printf("common_passwords_return: %d\n", common_passwords_return);
//printf("password: %s\n", PASSWORD);
if (common_passwords_return == 0)
found = true;
}
//call linux_words
if (!found)
{
if(verbose)
{
printf("Checking a list of dictionary words...\n");
}
int linux_words_return = linux_words();
//printf("linux_words_return: %d\n", linux_words_return);
if (linux_words_return == 0)
found = true;
}
//call brute_force
if (!found)
{
if(verbose)
{
printf("Starting a brute force attack...\n");
}
int brute_force_return = brute_force();
//printf("brute_force_return: %d\n", brute_force_return);
if (brute_force_return == 0)
found = true;
}
//all loops processed
if (found)
{
if (verbose)
{
printf("Found it The password is: %s\n", PASSWORD);
}
else
{
printf("%s\n", PASSWORD);
}
}
else
{
if (verbose)
{
printf("A match could not be found :(\n");
}
}
//end timer
time (&end);
dif = difftime(end, start);
//output stats
if (verbose)
{
printf("There were %llu combinations checked.\n", counter);
printf("The program ran for: %.0lf seconds.\n", dif);
printf("Processed: %.0f combinations per second.\n", (counter/dif));
//formatting:
printf("\n");
for (int i = 0; i < 51; i++)
printf("*");
printf("\n");
}
return 0;
}
/*
* crack_it - this accepts a word provided by one of the functions within the program.
* It removes any newline or carriage returns (windows) and creates a hash.
* Then compares that hash to the password_hash provided
*
*/
int crack_it(char *word)
{
//trim \n & \r
if( word[strlen(word)-1] == '\n' )
word[strlen(word)-1] = '\0';
//printf("strlen(line): %d\n", strlen(line));
if( word[strlen(word)-1] == '\r' )
word[strlen(word)-1] = '\0';
char *word_hash = crypt(word, salt);
//debug stuff
//printf("%s\n", word_hash);
//printf("\nsalt: %d, %d, %s, %s, : %s, %d\n", salt[0], salt[1], password_hash, word, word_hash, strcmp(password_hash, word_hash))
//printf("%d\n", strcmp(password_hash, word_hash) );
//check for match
if (strcmp(password_hash, word_hash) == 0)
{
PASSWORD = word;
//printf("password_hash: %s\n", password_hash);
//printf("crack_it:PASSWORD: %s\n", PASSWORD);
//printf("crack_it:word: %s\n", word);
return 0; //for success
}
else
{
return 1; //for no match
}
}
//checks through the 10,000 most common passwords
int common_passwords(void)
{
//open file for dictionary attack and read into array
FILE *common_passwords = fopen("most_common_passwords.txt", "r");
//read each line of most_common_passwords and pass to crack it
char word[80];
while (fgets ( word, sizeof(word), common_passwords) != NULL)
{
//call crack_it
int crack_it_return = crack_it(word);
//printf("crack_it_return: %d \n",crack_it_return);
counter++;
if (crack_it_return == 0)
{
//password = word;
//printf("%s\n", password);
//printf("%s\n", word);
//notFound = false;
fclose(common_passwords);
return 0;
}
}
//close file
fclose(common_passwords);
return 1;
}
//checks through all the words in /usr/share/dict/words
int linux_words(void)
{
//open file for dictionary attack and read into array
FILE *linux_words = fopen("/usr/share/dict/words", "r");
//read each line of most_common_passwords and pass to crack it
char word[80];
while (fgets ( word, sizeof(word), linux_words) != NULL)
{
//call crack_it
int crack_it_return = crack_it(word);
//printf("crack_it_return: %d \n",crack_it_return);
counter++;
if (crack_it_return == 0)
{
//password = word;
//printf("%s\n", password);
//printf("%s\n", word);
//notFound = false;
fclose(linux_words);
return 0;
}
}
//close file
fclose(linux_words);
return 1;
}
int brute_force (void)
{
//maximum size of word to guess
int max_size = 8;
// Create an array of all possible ASCII characters
int char_set[CHAR_SET_SIZE];
for (int i = 0; i < CHAR_SET_SIZE; i++)
{
char_set[i] = (i + 33);
}
// print array to make sure the characters are correct
/*
for (int i = 0; i < CHAR_SET_SIZE; i++)
{
printf("i: %d = %c\n", i, (char)char_set[i]);
}
printf("sizeof(char_set): %d\n", sizeof(char_set));
*/
// call iterator starting with a 4 letter word and working up to max_size
for (int this_size = 4; this_size <= max_size; this_size++)
{
if (!found)
{
//define word
char b_word[this_size + 1];
// declare starting characters for word
for (int i = 0; i < this_size; i++)
{
b_word[i] = (char)char_set[0];
//terminate string
if (i == (this_size - 1))
b_word[i + 1] = '\0';
}
//printf("starting word: %s\n", b_word);
int iterator_out = iterator(b_word, char_set, this_size, 0);
if (iterator_out == 0)
found = true;
//printf("%s\n", word);
}
}
return 0;
}
// Recursively iterate through each possible character in char_set
int iterator(char *guess, int *char_set, int this_size, int position)
{
//base case
if (position == (this_size - 1)) // this is the right most digit
{
//check every character in char_set
for(int i = 0; i < (CHAR_SET_SIZE - 1); i++)
{
//incremet position
guess[position] = char_set[i];
//printf("%s, %d\n", guess, strlen(guess));
//call crack_it
int crack_it_return = crack_it(guess);
//printf("crack_it_return: %d \n",crack_it_return);
counter++;
if (crack_it_return == 0)
{
//password = word;
//printf("%s\n", password);
//printf("%s\n", word);
//notFound = false;
return 0; // for success
}
}
return 1; // not found
}
//recursive case
else
{
int result;
for(int i = 0; i < (CHAR_SET_SIZE - 1); i++)
{
guess[position] = (char)char_set[i];
result = iterator(guess, char_set, this_size, (position + 1));
if (result == 0)
return 0; //success
}
return 1; //not found
}
}