]> git.sesse.net Git - freerainbowtables/blob - Client Applications/rcracki_mt/RainbowCrack.cpp
UINT4 -> uint32
[freerainbowtables] / Client Applications / rcracki_mt / RainbowCrack.cpp
1 /*\r
2  * rcracki_mt is a multithreaded implementation and fork of the original \r
3  * RainbowCrack\r
4  *\r
5  * Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>\r
6  * Copyright Martin Westergaard Jørgensen <martinwj2005@gmail.com>\r
7  * Copyright 2009, 2010  Daniël Niggebrugge <niggebrugge@fox-it.com>\r
8  * Copyright 2009 James Dickson\r
9  * Copyright 2009, 2010 James Nobis <frt@quelrod.net>\r
10  * Copyright 2010 uroskn\r
11  *\r
12  * Modified by Martin Westergaard Jørgensen <martinwj2005@gmail.com> to support  * indexed and hybrid tables\r
13  *\r
14  * Modified by neinbrucke to support multi threading and a bunch of other stuff :)\r
15  *\r
16  * 2009-01-04 - <james.dickson@comhem.se> - Slightly modified (or "fulhack" as \r
17  * we say in sweden)  to support cain .lst files.\r
18  *\r
19  * This file is part of rcracki_mt.\r
20  *\r
21  * rcracki_mt is free software: you can redistribute it and/or modify\r
22  * it under the terms of the GNU General Public License as published by\r
23  * the Free Software Foundation, either version 2 of the License, or\r
24  * (at your option) any later version.\r
25  *\r
26  * rcracki_mt is distributed in the hope that it will be useful,\r
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
29  * GNU General Public License for more details.\r
30  *\r
31  * You should have received a copy of the GNU General Public License\r
32  * along with rcracki_mt.  If not, see <http://www.gnu.org/licenses/>.\r
33  */\r
34 \r
35 #if defined(_WIN32) && !defined(__GNUC__)\r
36         #pragma warning(disable : 4786 4267 4018)\r
37 #endif\r
38 \r
39 #include "CrackEngine.h"\r
40 #include "lm2ntlm.h"\r
41 #include <algorithm>\r
42 \r
43 #ifdef _WIN32\r
44         #include <io.h>\r
45 #else\r
46         #include <sys/types.h>\r
47         #include <sys/stat.h>\r
48         #include <unistd.h>\r
49         #include <dirent.h>\r
50 #endif\r
51 \r
52 #if defined(_WIN32) && !defined(__GNUC__)\r
53         #pragma comment(lib, "libeay32.lib")\r
54 #endif\r
55 \r
56 //////////////////////////////////////////////////////////////////////\r
57 \r
58 #ifdef _WIN32\r
59 void GetTableList(string sWildCharPathName, vector<string>& vPathName)\r
60 {\r
61         //vPathName.clear();\r
62 \r
63         string sPath;\r
64         string::size_type n = sWildCharPathName.find_last_of('\\');\r
65 \r
66         if ( n == (sWildCharPathName.size() - 1) )\r
67         {\r
68                 sWildCharPathName = sWildCharPathName.substr(0, n);\r
69                 n = sWildCharPathName.find_last_of('\\');\r
70         }\r
71 \r
72         if (n != string::npos)\r
73                 sPath = sWildCharPathName.substr(0, n + 1);\r
74 \r
75         _finddata_t fd;\r
76 \r
77         long handle = _findfirst(sWildCharPathName.c_str(), &fd);\r
78         if (handle != -1)\r
79         {\r
80                 do\r
81                 {\r
82                         string sName = fd.name;\r
83                         if (sName.size()>3) {\r
84                                 if (sName.substr(sName.size()-3, 3) == ".rt" && !(fd.attrib & _A_SUBDIR))\r
85                                 {\r
86                                         string sPathName = sPath + sName;\r
87                                         vPathName.push_back(sPathName);\r
88                                 }\r
89                         }\r
90                         if (sName.size()>4) {\r
91                                 if (sName.substr(sName.size()-4, 4) == ".rti" && !(fd.attrib & _A_SUBDIR))\r
92                                 {\r
93                                         string sPathName = sPath + sName;\r
94                                         vPathName.push_back(sPathName);\r
95                                 }\r
96                         }\r
97                         if (sName.size()>5) {\r
98                                 if (sName.substr(sName.size()-5, 5) == ".rti2" && !(fd.attrib & _A_SUBDIR))\r
99                                 {\r
100                                         string sPathName = sPath + sName;\r
101                                         vPathName.push_back(sPathName);\r
102                                 }\r
103                         }\r
104 \r
105                         if (sName != "." && sName != ".." && (fd.attrib & _A_SUBDIR))\r
106                         {\r
107                                 string sPath_sub = sPath + sName + '\\';\r
108                                 string sWildCharPathName_sub = sPath_sub + '*';\r
109                                 GetTableList(sWildCharPathName_sub, vPathName);\r
110                         }\r
111 \r
112                 } while (_findnext(handle, &fd) == 0);\r
113 \r
114                 _findclose(handle);\r
115         }\r
116         //printf("Found %d rainbowtables (files) in %d sub directories...\n", vPathName.size(), subDir_count);\r
117 }\r
118 #else\r
119 //void GetTableList(int argc, char* argv[], vector<string>& vPathName)\r
120 void GetTableList(string sWildCharPathName, vector<string>& vPathName)\r
121 {\r
122         //vPathName.clear();\r
123 \r
124         struct stat buf;\r
125         if (lstat(sWildCharPathName.c_str(), &buf) == 0)\r
126         {\r
127                 if (S_ISDIR(buf.st_mode))\r
128                 {\r
129                         DIR *dir = opendir(sWildCharPathName.c_str());\r
130                         if(dir)\r
131                         {\r
132                                 struct dirent *pDir=NULL;\r
133                                 while((pDir = readdir(dir)) != NULL)\r
134                                 {\r
135                                         string filename = "";\r
136                                         filename += (*pDir).d_name;\r
137                                         if (filename != "." && filename != "..")\r
138                                         {\r
139                                                 string new_filename = sWildCharPathName + '/' + filename;\r
140                                                 GetTableList(new_filename, vPathName);\r
141                                         }\r
142                                 }\r
143                                 closedir(dir);\r
144                         }\r
145                 }\r
146                 else if (S_ISREG(buf.st_mode))\r
147                 {\r
148                         if (sWildCharPathName.size()>3)\r
149                         {\r
150                                 if (sWildCharPathName.substr(sWildCharPathName.size()-3, 3) == ".rt")\r
151                                 {\r
152                                         vPathName.push_back(sWildCharPathName);\r
153                                 }\r
154                         }\r
155                         if (sWildCharPathName.size()>4)\r
156                         {\r
157                                 if (sWildCharPathName.substr(sWildCharPathName.size()-4, 4) == ".rti")\r
158                                 {\r
159                                         //string sPathName_sub = sPath_sub + sName_sub;\r
160                                         vPathName.push_back(sWildCharPathName);\r
161                                         //printf("sPathName_sub: %s\n", sPathName_sub.c_str());\r
162                                 }\r
163                         }\r
164                         if ( sWildCharPathName.size() > 5 )\r
165                         {\r
166                                 if ( sWildCharPathName.substr( sWildCharPathName.size() - 5, 5 ) == ".rti2" )\r
167                                 {\r
168                                         vPathName.push_back( sWildCharPathName );\r
169                                 }\r
170                         }\r
171                 }\r
172         }\r
173 }\r
174 #endif\r
175 \r
176 bool NormalizeHash(string& sHash)\r
177 {\r
178         string sNormalizedHash = sHash;\r
179 \r
180         if (   sNormalizedHash.size() % 2 != 0\r
181                 || sNormalizedHash.size() < MIN_HASH_LEN * 2\r
182                 || sNormalizedHash.size() > MAX_HASH_LEN * 2)\r
183                 return false;\r
184 \r
185         // Make lower\r
186         uint32 i;\r
187         for (i = 0; i < sNormalizedHash.size(); i++)\r
188         {\r
189                 if (sNormalizedHash[i] >= 'A' && sNormalizedHash[i] <= 'F')\r
190                         sNormalizedHash[i] = (char) sNormalizedHash[i] - 'A' + 'a';\r
191         }\r
192 \r
193         // Character check\r
194         for (i = 0; i < sNormalizedHash.size(); i++)\r
195         {\r
196                 if (   (sNormalizedHash[i] < 'a' || sNormalizedHash[i] > 'f')\r
197                         && (sNormalizedHash[i] < '0' || sNormalizedHash[i] > '9'))\r
198                         return false;\r
199         }\r
200 \r
201         sHash = sNormalizedHash;\r
202         return true;\r
203 }\r
204 \r
205 void LoadLMHashFromPwdumpFile(string sPathName, vector<string>& vUserName, vector<string>& vLMHash, vector<string>& vNTLMHash)\r
206 {\r
207         vector<string> vLine;\r
208         if (ReadLinesFromFile(sPathName, vLine))\r
209         {\r
210                 uint32 i;\r
211                 for (i = 0; i < vLine.size(); i++)\r
212                 {\r
213                         vector<string> vPart;\r
214                         if (SeperateString(vLine[i], "::::", vPart))\r
215                         {\r
216                                 string sUserName = vPart[0];\r
217                                 string sLMHash   = vPart[2];\r
218                                 string sNTLMHash = vPart[3];\r
219 \r
220                                 if (sLMHash.size() == 32 && sNTLMHash.size() == 32)\r
221                                 {\r
222                                         if (NormalizeHash(sLMHash) && NormalizeHash(sNTLMHash))\r
223                                         {\r
224                                                 vUserName.push_back(sUserName);\r
225                                                 vLMHash.push_back(sLMHash);\r
226                                                 vNTLMHash.push_back(sNTLMHash);\r
227                                         }\r
228                                         else\r
229                                                 printf("invalid lm/ntlm hash %s:%s\n", sLMHash.c_str(), sNTLMHash.c_str());\r
230                                 }\r
231                         }\r
232                 }\r
233         }\r
234         else\r
235                 printf("can't open %s\n", sPathName.c_str());\r
236 }\r
237 \r
238 // 2009-01-04 - james.dickson - Added this so we can load hashes from cain .LST files.\r
239 void LoadLMHashFromCainLSTFile(string sPathName, vector<string>& vUserName, vector<string>& vLMHash, vector<string>& vNTLMHash)\r
240 {\r
241         vector<string> vLine;\r
242         if (ReadLinesFromFile(sPathName, vLine))\r
243         {\r
244                 uint32 i;\r
245                 for (i = 0; i < vLine.size(); i++)\r
246                 {\r
247                         vector<string> vPart;\r
248                         if (SeperateString(vLine[i], "\t\t\t\t\t\t", vPart))\r
249                         {\r
250                                 string sUserName = vPart[0];\r
251                                 string sLMHash   = vPart[4];\r
252                                 string sNTLMHash = vPart[5];\r
253 \r
254                                 if (sLMHash.size() == 32 && sNTLMHash.size() == 32)\r
255                                 {\r
256                                         if (NormalizeHash(sLMHash) && NormalizeHash(sNTLMHash))\r
257                                         {\r
258                                                 vUserName.push_back(sUserName);\r
259                                                 vLMHash.push_back(sLMHash);\r
260                                                 vNTLMHash.push_back(sNTLMHash);\r
261                                         }\r
262                                         else\r
263                                                 printf("invalid lm/ntlm hash %s:%s\n", sLMHash.c_str(), sNTLMHash.c_str());\r
264                                 }\r
265                         }\r
266                 }\r
267         }\r
268         else\r
269                 printf("can't open %s\n", sPathName.c_str());\r
270 }\r
271 \r
272 bool NTLMPasswordSeek(unsigned char* pLMPassword, int nLMPasswordLen, int nLMPasswordNext,\r
273                                           unsigned char* pNTLMHash, string& sNTLMPassword)\r
274 {\r
275         if (nLMPasswordNext == nLMPasswordLen)\r
276         {\r
277                 unsigned char md[MD4_DIGEST_LENGTH];\r
278                 MD4_NEW(pLMPassword, nLMPasswordLen * 2, md);\r
279 \r
280                 if (memcmp(md, pNTLMHash, MD4_DIGEST_LENGTH) == 0)\r
281                 {\r
282                         sNTLMPassword = "";\r
283                         int i;\r
284                         for (i = 0; i < nLMPasswordLen; i++)\r
285                                 sNTLMPassword += char(pLMPassword[i * 2]);\r
286                         return true;\r
287                 }\r
288                 else\r
289                         return false;\r
290         }\r
291 \r
292         if (NTLMPasswordSeek(pLMPassword, nLMPasswordLen, nLMPasswordNext + 1, pNTLMHash, sNTLMPassword))\r
293                 return true;\r
294 \r
295         if (   pLMPassword[nLMPasswordNext * 2] >= 'A'\r
296                 && pLMPassword[nLMPasswordNext * 2] <= 'Z')\r
297         {\r
298                 pLMPassword[nLMPasswordNext * 2] = (unsigned char) pLMPassword[nLMPasswordNext * 2] - 'A' + 'a';\r
299                 if (NTLMPasswordSeek(pLMPassword, nLMPasswordLen, nLMPasswordNext + 1, pNTLMHash, sNTLMPassword))\r
300                         return true;\r
301                 pLMPassword[nLMPasswordNext * 2] = (unsigned char) pLMPassword[nLMPasswordNext * 2] - 'a' + 'A';\r
302         }\r
303 \r
304         return false;\r
305 }\r
306 \r
307 bool LMPasswordCorrectCase(string sLMPassword, unsigned char* pNTLMHash, string& sNTLMPassword)\r
308 {\r
309         if (sLMPassword.size() == 0)\r
310         {\r
311                 sNTLMPassword = "";\r
312                 return true;\r
313         }\r
314 \r
315         unsigned char* pLMPassword = new unsigned char[sLMPassword.size() * 2];\r
316         uint32 i;\r
317         for (i = 0; i < sLMPassword.size(); i++)\r
318         {\r
319                 pLMPassword[i * 2    ] = sLMPassword[i];\r
320                 pLMPassword[i * 2 + 1] = 0x00;\r
321         }\r
322         bool fRet = NTLMPasswordSeek(pLMPassword, sLMPassword.size(), 0, pNTLMHash, sNTLMPassword);\r
323 \r
324         delete pLMPassword;\r
325 \r
326         return fRet;\r
327 }\r
328 \r
329 void Usage()\r
330 {\r
331         Logo();\r
332 \r
333         printf("usage: rcracki_mt -h hash rainbow_table_pathname\n");\r
334         printf("       rcracki_mt -l hash_list_file rainbow_table_pathname\n");\r
335         printf("       rcracki_mt -f pwdump_file rainbow_table_pathname\n");\r
336         printf("       rcracki_mt -c lst_file rainbow_table_pathname\n");\r
337         printf("\n");\r
338         printf("-h hash:                use raw hash as input\n");\r
339         printf("-l hash_list_file:      use hash list file as input, each hash in a line\n");\r
340         printf("-f pwdump_file:         use pwdump file as input, handles lanmanager hash only\n");\r
341         printf("-c lst_file:            use .lst (cain format) file as input\n");\r
342         printf("-r [-s session_name]:   resume from previous session, optional session name\n");\r
343         printf("rainbow_table_pathname: pathname(s) of the rainbow table(s)\n");\r
344         printf("\n");\r
345         printf("Extra options:    -t [nr] use this amount of threads/cores, default is 1\n");\r
346         printf("                  -o [output_file] write (temporary) results to this file\n");\r
347         printf("                  -s [session_name] write session data with this name\n");\r
348         printf("                  -k keep precalculation on disk\n");\r
349         printf("                  -m [megabytes] limit memory usage\n");\r
350         printf("                  -v show debug information\n");\r
351         printf("\n");\r
352 #ifdef _WIN32\r
353         printf("example: rcracki_mt -h 5d41402abc4b2a76b9719d911017c592 -t 2 [path]\\MD5\n");\r
354         printf("         rcracki_mt -l hash.txt [path_to_specific_table]\\*\n");\r
355 #else\r
356         printf("example: rcracki_mt -h 5d41402abc4b2a76b9719d911017c592 -t 2 [path]/MD5\n");\r
357         printf("         rcracki_mt -l hash.txt [path_to_specific_table]/*\n");\r
358 #endif\r
359         printf("         rcracki_mt -f hash.txt -t 4 -o results.txt *.rti\n");\r
360 }\r
361 \r
362 int main(int argc, char* argv[])\r
363 {\r
364         if (argc < 2)\r
365         {\r
366                 Usage();\r
367                 return 0;\r
368         }\r
369 \r
370         vector<string> vPathName;\r
371         vector<string> vDefaultRainbowTablePath;\r
372         string sWildCharPathName                        = "";\r
373         string sInputType                                               = "";\r
374         string sInput                                                   = "";\r
375         string outputFile                                               = "";\r
376         string sApplicationPath                         = "";\r
377         string sIniPathName                                     = "rcracki_mt.ini";\r
378         bool writeOutput                                                = false;\r
379         string sSessionPathName                         = "rcracki.session";\r
380         string sProgressPathName                        = "rcracki.progress";\r
381         string sPrecalcPathName                         = "rcracki.precalc";\r
382         bool resumeSession                                      = false;\r
383         bool useDefaultRainbowTablePath = false;\r
384         bool debug                                                              = false;\r
385         bool keepPrecalcFiles                           = false;\r
386         string sAlgorithm                                               = "";\r
387         int maxThreads                                                  = 1;\r
388         uint64 maxMem                                                   = 0;\r
389         CHashSet hs;\r
390 \r
391         // Read defaults from ini file;\r
392         bool readFromIni = false;\r
393         vector<string> vLine;\r
394         if (ReadLinesFromFile(sIniPathName, vLine)) {\r
395                 readFromIni = true;\r
396         }\r
397         else if (ReadLinesFromFile(GetApplicationPath() + sIniPathName, vLine)) {\r
398                 readFromIni = true;\r
399         }\r
400         if (readFromIni)\r
401         {\r
402                 uint32 i;\r
403                 for (i = 0; i < vLine.size(); i++)\r
404                 {\r
405                         if (vLine[i].substr(0,1) != "#")\r
406                         {\r
407                                 vector<string> vPart;\r
408                                 if (SeperateString(vLine[i], "=", vPart))\r
409                                 {\r
410                                         string sOption = vPart[0];\r
411                                         string sValue  = vPart[1];\r
412                                         \r
413                                         if (sOption == "Threads") {\r
414                                                 maxThreads = atoi(sValue.c_str());\r
415                                         }\r
416                                         else if (sOption == "MaxMemoryUsage" ) {\r
417                                                 maxMem = atoi(sValue.c_str()) * 1024 *1024;\r
418                                         }\r
419                                         else if (sOption == "DefaultResultsFile") {\r
420                                                 outputFile = sValue;\r
421                                         }\r
422                                         else if (sOption == "AlwaysStoreResultsToFile") {\r
423                                                 if (sValue == "1")\r
424                                                         writeOutput = true;\r
425                                         }\r
426                                         else if (sOption.substr(0,24) == "DefaultRainbowTablePath.") {\r
427                                                 //printf("Default RT path: %s\n", sValue.c_str());\r
428                                                 vDefaultRainbowTablePath.push_back(vLine[i]);\r
429                                         }\r
430                                         else if (sOption == "DefaultAlgorithm") {\r
431                                                 useDefaultRainbowTablePath = true;\r
432                                                 sAlgorithm = sValue;\r
433                                         }\r
434                                         else if (sOption == "AlwaysDebug") {\r
435                                                 if (sValue == "1")\r
436                                                         debug = true;\r
437                                         }\r
438                                         else if (sOption == "AlwaysKeepPrecalcFiles") {\r
439                                                 if (sValue == "1")\r
440                                                         keepPrecalcFiles = true;\r
441                                         }\r
442                                         else {\r
443                                                 printf("illegal option %s in ini file %s\n", sOption.c_str(), sIniPathName.c_str());\r
444                                                 return 0;\r
445                                         }\r
446                                 }\r
447                         }\r
448                 }\r
449                 if (writeOutput && outputFile == "")\r
450                 {\r
451                         printf("You need to specify a 'DefaultResultsFile' with 'AlwaysStoreResultsToFile=1'\n");\r
452                         writeOutput = false;\r
453                 }\r
454         }\r
455 \r
456         // Parse command line arguments\r
457         int i;\r
458         for (i = 1; i < argc; i++)\r
459         {\r
460                 string cla = argv[i];\r
461                 if (cla == "-h") {\r
462                         sInputType = cla;\r
463                         i++;\r
464                         if (i < argc)\r
465                                 sInput = argv[i];\r
466                 }\r
467                 else if (cla == "-l") {\r
468                         sInputType = cla;\r
469                         i++;\r
470                         if (i < argc)\r
471                                 sInput = argv[i];\r
472                 }\r
473                 else if (cla == "-f") {\r
474                         sInputType = cla;\r
475                         i++;\r
476                         if (i < argc)\r
477                                 sInput = argv[i];\r
478                 }\r
479                 else if (cla == "-c") {\r
480                         sInputType = cla;\r
481                         i++;\r
482                         if (i < argc)\r
483                                 sInput = argv[i];\r
484                 }\r
485                 else if (cla == "-t") {\r
486                         i++;\r
487                         if (i < argc)\r
488                                 maxThreads = atoi(argv[i]);\r
489                 }\r
490                 else if ( cla == "-m" ) {\r
491                         i++;\r
492                         if ( i < argc )\r
493                                 maxMem = atoi(argv[i]) * 1024 * 1024;\r
494                 }\r
495                 else if (cla == "-o") {\r
496                         writeOutput = true;\r
497                         i++;\r
498                         if (i < argc)\r
499                                 outputFile = argv[i];\r
500                 }\r
501                 else if (cla == "-r") {\r
502                         resumeSession = true;\r
503                 }\r
504                 else if (cla == "-s") {\r
505                         i++;\r
506                         if (i < argc)\r
507                         {\r
508                                 sSessionPathName                =  argv[i];\r
509                                 sSessionPathName                += ".session";\r
510                                 sProgressPathName               =  argv[i];\r
511                                 sProgressPathName               += ".progress";\r
512                                 sPrecalcPathName                =  argv[i];\r
513                                 sPrecalcPathName                += ".precalc";\r
514                         }\r
515                 }\r
516                 else if (cla == "-v") {\r
517                         debug = true;\r
518                 }\r
519                 else if (cla == "-k") {\r
520                         keepPrecalcFiles = true;\r
521                 }\r
522                 else if (cla == "-a") {\r
523                         useDefaultRainbowTablePath = true;\r
524                         i++;\r
525                         if (i < argc)\r
526                                 sAlgorithm = argv[i];\r
527                 }\r
528                 else {\r
529                         GetTableList(cla, vPathName);\r
530                 }\r
531         }\r
532 \r
533         if (debug && !readFromIni)\r
534                 printf("Debug: Couldn't read rcracki_mt.ini, continuing anyway.\n");\r
535 \r
536         // Load session data if we are resuming\r
537         if (resumeSession)\r
538         {\r
539                 vPathName.clear();\r
540                 vector<string> sSessionData;\r
541                 if (ReadLinesFromFile(sSessionPathName.c_str(), sSessionData))\r
542                 {\r
543                         uint32 i;\r
544                         for (i = 0; i < sSessionData.size(); i++)\r
545                         {\r
546                                 vector<string> vPart;\r
547                                 if (SeperateString(sSessionData[i], "=", vPart))\r
548                                 {\r
549                                         string sOption = vPart[0];\r
550                                         string sValue  = vPart[1];\r
551                                         \r
552                                         if (sOption == "sPathName") {\r
553                                                 vPathName.push_back(sValue);\r
554                                         }\r
555                                         else if (sOption == "sInputType") {\r
556                                                 sInputType = sValue;\r
557                                         }\r
558                                         else if (sOption == "sInput") {\r
559                                                 sInput = sValue;\r
560                                         }\r
561                                         else if (sOption == "outputFile") {\r
562                                                 writeOutput = true;\r
563                                                 outputFile = sValue;\r
564                                         }\r
565                                         else if (sOption == "keepPrecalcFiles") {\r
566                                                 if (sValue == "1")\r
567                                                         keepPrecalcFiles = true;\r
568                                         }\r
569                                 }\r
570                         }\r
571                 }\r
572                 else {\r
573                         printf("Couldn't open session file %s\n", sSessionPathName.c_str());\r
574                         return 0;\r
575                 }\r
576         }\r
577 \r
578         if (maxThreads<1)\r
579                 maxThreads = 1;\r
580 \r
581         // don't load these if we are resuming a session that already has a list of tables\r
582         if (useDefaultRainbowTablePath && !resumeSession)\r
583         {\r
584                 uint32 i;\r
585                 for (i = 0; i < vDefaultRainbowTablePath.size(); i++)\r
586                 {\r
587                         vector<string> vPart;\r
588                         if (SeperateString(vDefaultRainbowTablePath[i], ".=", vPart))\r
589                         {\r
590                                 string lineAlgorithm = vPart[1];\r
591                                 string linePath = vPart[2];\r
592 \r
593                                 if (lineAlgorithm == sAlgorithm)\r
594                                         GetTableList(linePath, vPathName);\r
595                         }\r
596                 }\r
597         }\r
598 \r
599         printf("Using %d threads for pre-calculation and false alarm checking...\n", maxThreads);\r
600 \r
601         setvbuf(stdout, NULL, _IONBF,0);\r
602         if (vPathName.size() == 0)\r
603         {\r
604                 printf("no rainbow table found\n");\r
605                 return 0;\r
606         }\r
607         printf("Found %lu rainbowtable files...\n\n",\r
608                 (unsigned long)vPathName.size());\r
609 \r
610         bool fCrackerType;                      // true: hash cracker, false: lm cracker\r
611         vector<string> vHash;           // hash cracker\r
612         vector<string> vUserName;       // lm cracker\r
613         vector<string> vLMHash;         // lm cracker\r
614         vector<string> vNTLMHash;       // lm cracker\r
615         if (sInputType == "-h")\r
616         {\r
617                 fCrackerType = true;\r
618 \r
619                 string sHash = sInput;\r
620                 if (NormalizeHash(sHash))\r
621                         vHash.push_back(sHash);\r
622                 else\r
623                         printf("invalid hash: %s\n", sHash.c_str());\r
624         }\r
625         else if (sInputType == "-l")\r
626         {\r
627                 fCrackerType = true;\r
628 \r
629                 string sPathName = sInput;\r
630                 vector<string> vLine;\r
631                 if (ReadLinesFromFile(sPathName, vLine))\r
632                 {\r
633                         uint32 i;\r
634                         for (i = 0; i < vLine.size(); i++)\r
635                         {\r
636                                 string sHash = vLine[i];\r
637                                 if (NormalizeHash(sHash))\r
638                                         vHash.push_back(sHash);\r
639                                 else\r
640                                         printf("invalid hash: %s\n", sHash.c_str());\r
641                         }\r
642                 }\r
643                 else\r
644                         printf("can't open %s\n", sPathName.c_str());\r
645         }\r
646         else if (sInputType == "-f")\r
647         {\r
648                 fCrackerType = false;\r
649 \r
650                 string sPathName = sInput;\r
651                 LoadLMHashFromPwdumpFile(sPathName, vUserName, vLMHash, vNTLMHash);\r
652         }\r
653         else if (sInputType == "-c")\r
654         {\r
655                 // 2009-01-04 - james.dickson - Added this for cain-files.\r
656                 fCrackerType = false;\r
657                 string sPathName = sInput;\r
658                 LoadLMHashFromCainLSTFile(sPathName, vUserName, vLMHash, vNTLMHash);\r
659         }\r
660         else\r
661         {\r
662                 Usage();\r
663                 return 0;\r
664         }\r
665 \r
666         if (fCrackerType && vHash.size() == 0)\r
667         {\r
668                 printf("no hashes found");\r
669                 return 0;\r
670         }\r
671         if (!fCrackerType && vLMHash.size() == 0)\r
672         {\r
673                 return 0;\r
674                 printf("no hashes found");\r
675         }\r
676 \r
677         if (fCrackerType)\r
678         {\r
679                 uint32 i;\r
680                 for (i = 0; i < vHash.size(); i++)\r
681                         hs.AddHash(vHash[i]);\r
682         }\r
683         else\r
684         {\r
685                 uint32 i;\r
686                 for (i = 0; i < vLMHash.size(); i++)\r
687                 {\r
688                         hs.AddHash(vLMHash[i].substr(0, 16));\r
689                         hs.AddHash(vLMHash[i].substr(16, 16));\r
690                 }\r
691         }\r
692 \r
693         // Load found hashes from session file\r
694         if (resumeSession)\r
695         {\r
696                 vector<string> sSessionData;\r
697                 if (ReadLinesFromFile(sSessionPathName.c_str(), sSessionData))\r
698                 {\r
699                         uint32 i;\r
700                         for (i = 0; i < sSessionData.size(); i++)\r
701                         {\r
702                                 vector<string> vPart;\r
703                                 if (SeperateString(sSessionData[i], "=", vPart))\r
704                                 {\r
705                                         string sOption = vPart[0];\r
706                                         string sValue  = vPart[1];\r
707                                         \r
708                                         if (sOption == "sHash") {\r
709                                                 vector<string> vPartHash;\r
710                                                 if (SeperateString(sValue, "::", vPartHash))\r
711                                                 {\r
712                                                         string sHash = vPartHash[0];\r
713                                                         string sBinary = vPartHash[1];\r
714                                                         string sPlain = vPartHash[2];\r
715                                                         \r
716                                                         hs.SetPlain(sHash, sPlain, sBinary);\r
717                                                 }\r
718                                         }\r
719                                 }\r
720                         }\r
721                 }\r
722         }\r
723 \r
724         // (Over)write session data if we are not resuming\r
725         if (!resumeSession)\r
726         {\r
727                 FILE* file = fopen(sSessionPathName.c_str(), "w");\r
728                 string buffer = "";\r
729 \r
730                 if (file!=NULL)\r
731                 {\r
732                         buffer += "sInputType=" + sInputType + "\n";\r
733                         buffer += "sInput=" + sInput + "\n";\r
734 \r
735                         uint32 i;\r
736                         for (i = 0; i < vPathName.size(); i++)\r
737                         {\r
738                                 buffer += "sPathName=" + vPathName[i] + "\n";\r
739                         }\r
740 \r
741                         if (writeOutput)\r
742                                 buffer += "outputFile=" + outputFile + "\n";\r
743 \r
744                         if (keepPrecalcFiles)\r
745                                 buffer += "keepPrecalcFiles=1\n";\r
746 \r
747                         fputs (buffer.c_str(), file);\r
748                         fclose (file);\r
749                 }\r
750                 file = fopen(sProgressPathName.c_str(), "w");\r
751                 fclose (file);\r
752         }\r
753 \r
754         // Run\r
755         CCrackEngine ce;\r
756         if (writeOutput)\r
757                 ce.setOutputFile(outputFile);\r
758         ce.setSession(sSessionPathName, sProgressPathName, sPrecalcPathName, keepPrecalcFiles);\r
759         ce.Run(vPathName, hs, maxThreads, maxMem, resumeSession, debug);\r
760 \r
761         // Remove session files\r
762         if (debug) printf("Debug: Removing session files.\n");\r
763 \r
764         if (remove(sSessionPathName.c_str()) == 0)\r
765                 remove(sProgressPathName.c_str());\r
766         else\r
767                 if (debug) printf("Debug: Failed removing session files.\n");\r
768 \r
769         // Statistics\r
770         printf("statistics\n");\r
771         printf("-------------------------------------------------------\n");\r
772         printf("plaintext found:            %d of %d (%.2f%%)\n", hs.GetStatHashFound(),\r
773                                                                                                                         hs.GetStatHashTotal(),\r
774                                                                                                                         100.0f * hs.GetStatHashFound() / hs.GetStatHashTotal());\r
775         printf("total disk access time:     %.2f s\n", ce.GetStatTotalDiskAccessTime());\r
776         printf("total cryptanalysis time:   %.2f s\n", ce.GetStatTotalCryptanalysisTime());\r
777         printf("total pre-calculation time: %.2f s\n", ce.GetStatTotalPrecalculationTime());\r
778         printf("total chain walk step:      %d\n",     ce.GetStatTotalChainWalkStep());\r
779         printf("total false alarm:          %d\n",     ce.GetStatTotalFalseAlarm());\r
780         printf("total chain walk step due to false alarm: %d\n", ce.GetStatTotalChainWalkStepDueToFalseAlarm());\r
781 //      printf("total chain walk step skipped due to checkpoints: %d\n", ce.GetStatTotalFalseAlarmSkipped()); // Checkpoints not used - yet\r
782         printf("\n");\r
783 \r
784         // Result\r
785         printf("result\n");\r
786         printf("-------------------------------------------------------\n");\r
787         if (fCrackerType)\r
788         {\r
789                 uint32 i;\r
790                 for (i = 0; i < vHash.size(); i++)\r
791                 {\r
792                         string sPlain, sBinary;\r
793                         if (!hs.GetPlain(vHash[i], sPlain, sBinary))\r
794                         {\r
795                                 sPlain  = "<notfound>";\r
796                                 sBinary = "<notfound>";\r
797                         }\r
798 \r
799                         printf("%s\t%s\thex:%s\n", vHash[i].c_str(), sPlain.c_str(), sBinary.c_str());\r
800                 }\r
801         }\r
802         else\r
803         {\r
804                 uint32 i;\r
805                 for (i = 0; i < vLMHash.size(); i++)\r
806                 {\r
807                         string sPlain1, sBinary1;\r
808                         bool fPart1Found = hs.GetPlain(vLMHash[i].substr(0, 16), sPlain1, sBinary1);\r
809                         if (!fPart1Found)\r
810                         {\r
811                                 sPlain1  = "<notfound>";\r
812                                 sBinary1 = "<notfound>";\r
813                         }\r
814 \r
815                         string sPlain2, sBinary2;\r
816                         bool fPart2Found = hs.GetPlain(vLMHash[i].substr(16, 16), sPlain2, sBinary2);\r
817                         if (!fPart2Found)\r
818                         {\r
819                                 sPlain2  = "<notfound>";\r
820                                 sBinary2 = "<notfound>";\r
821                         }\r
822 \r
823                         string sPlain = sPlain1 + sPlain2;\r
824                         string sBinary = sBinary1 + sBinary2;\r
825 \r
826                         // Correct case\r
827                         if (fPart1Found && fPart2Found)\r
828                         {\r
829                                 unsigned char NTLMHash[16];\r
830                                 int nHashLen;\r
831                                 ParseHash(vNTLMHash[i], NTLMHash, nHashLen);\r
832                                 if (nHashLen != 16)\r
833                                         printf("debug: nHashLen mismatch\n");\r
834                                 string sNTLMPassword;\r
835                                 if (LMPasswordCorrectCase(sPlain, NTLMHash, sNTLMPassword))\r
836                                 {\r
837                                         sPlain = sNTLMPassword;\r
838                                         sBinary = HexToStr((const unsigned char*)sNTLMPassword.c_str(), sNTLMPassword.size());\r
839                                 }\r
840                                 else\r
841                                 {\r
842                                         printf("%-14s\t%s\thex:%s\n", vUserName[i].c_str(), sPlain.c_str(), sBinary.c_str());\r
843                                         LM2NTLMcorrector corrector;\r
844                                         if (corrector.LMPasswordCorrectUnicode(sBinary, NTLMHash, sNTLMPassword))\r
845                                         {\r
846                                                 sPlain = sNTLMPassword;\r
847                                                 sBinary = corrector.getBinary();\r
848                                                 if (writeOutput)\r
849                                                 {\r
850                                                         if (!writeResultLineToFile(outputFile, vNTLMHash[i].c_str(), sPlain.c_str(), sBinary.c_str()))\r
851                                                                 printf("Couldn't write final result to file!\n");\r
852                                                 }\r
853                                         }\r
854                                         else {\r
855                                                 printf("case correction for password %s failed!\n", sPlain.c_str());\r
856                                         }\r
857                                 }\r
858                         }\r
859 \r
860                         // Display\r
861                         printf("%-14s\t%s\thex:%s\n", vUserName[i].c_str(),\r
862                                                                                   sPlain.c_str(),\r
863                                                                                   sBinary.c_str());\r
864                         \r
865                 }\r
866         }\r
867 \r
868         return 0;\r
869 }\r