2 * rcracki_mt is a multithreaded implementation and fork of the original
\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, 2011 James Nobis <frt@quelrod.net>
\r
10 * Copyright 2010 uroskn
\r
12 * Modified by Martin Westergaard Jørgensen <martinwj2005@gmail.com> to support * indexed and hybrid tables
\r
14 * Modified by neinbrucke to support multi threading and a bunch of other stuff :)
\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
19 * This file is part of rcracki_mt.
\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
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
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
35 #if defined(_WIN32) && !defined(__GNUC__)
\r
36 #pragma warning(disable : 4786 4267 4018)
\r
39 #include "CrackEngine.h"
\r
40 #include "lm2ntlm.h"
\r
41 #include <algorithm>
\r
46 #include <sys/types.h>
\r
47 #include <sys/stat.h>
\r
52 #if defined(_WIN32) && !defined(__GNUC__)
\r
53 #pragma comment(lib, "libeay32.lib")
\r
56 //////////////////////////////////////////////////////////////////////
\r
59 void GetTableList(string sWildCharPathName, vector<string>& vPathName)
\r
61 //vPathName.clear();
\r
64 string::size_type n = sWildCharPathName.find_last_of('\\');
\r
66 if ( n == (sWildCharPathName.size() - 1) )
\r
68 sWildCharPathName = sWildCharPathName.substr(0, n);
\r
69 n = sWildCharPathName.find_last_of('\\');
\r
72 if (n != string::npos)
\r
73 sPath = sWildCharPathName.substr(0, n + 1);
\r
77 long handle = _findfirst(sWildCharPathName.c_str(), &fd);
\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
86 string sPathName = sPath + sName;
\r
87 vPathName.push_back(sPathName);
\r
90 if (sName.size()>4) {
\r
91 if (sName.substr(sName.size()-4, 4) == ".rti" && !(fd.attrib & _A_SUBDIR))
\r
93 string sPathName = sPath + sName;
\r
94 vPathName.push_back(sPathName);
\r
97 if (sName.size()>5) {
\r
98 if (sName.substr(sName.size()-5, 5) == ".rti2" && !(fd.attrib & _A_SUBDIR))
\r
100 string sPathName = sPath + sName;
\r
101 vPathName.push_back(sPathName);
\r
105 if (sName != "." && sName != ".." && (fd.attrib & _A_SUBDIR))
\r
107 string sPath_sub = sPath + sName + '\\';
\r
108 string sWildCharPathName_sub = sPath_sub + '*';
\r
109 GetTableList(sWildCharPathName_sub, vPathName);
\r
112 } while (_findnext(handle, &fd) == 0);
\r
114 _findclose(handle);
\r
116 //printf("Found %d rainbowtables (files) in %d sub directories...\n", vPathName.size(), subDir_count);
\r
119 //void GetTableList(int argc, char* argv[], vector<string>& vPathName)
\r
120 void GetTableList(string sWildCharPathName, vector<string>& vPathName)
\r
122 //vPathName.clear();
\r
125 if (lstat(sWildCharPathName.c_str(), &buf) == 0)
\r
127 if (S_ISDIR(buf.st_mode))
\r
129 DIR *dir = opendir(sWildCharPathName.c_str());
\r
132 struct dirent *pDir=NULL;
\r
133 while((pDir = readdir(dir)) != NULL)
\r
135 string filename = "";
\r
136 filename += (*pDir).d_name;
\r
137 if (filename != "." && filename != "..")
\r
139 string new_filename = sWildCharPathName + '/' + filename;
\r
140 GetTableList(new_filename, vPathName);
\r
146 else if (S_ISREG(buf.st_mode))
\r
148 if (sWildCharPathName.size()>3)
\r
150 if (sWildCharPathName.substr(sWildCharPathName.size()-3, 3) == ".rt")
\r
152 vPathName.push_back(sWildCharPathName);
\r
155 if (sWildCharPathName.size()>4)
\r
157 if (sWildCharPathName.substr(sWildCharPathName.size()-4, 4) == ".rti")
\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
164 if ( sWildCharPathName.size() > 5 )
\r
166 if ( sWildCharPathName.substr( sWildCharPathName.size() - 5, 5 ) == ".rti2" )
\r
168 vPathName.push_back( sWildCharPathName );
\r
176 bool NormalizeHash(string& sHash)
\r
178 string sNormalizedHash = sHash;
\r
180 if ( sNormalizedHash.size() % 2 != 0
\r
181 || sNormalizedHash.size() < MIN_HASH_LEN * 2
\r
182 || sNormalizedHash.size() > MAX_HASH_LEN * 2)
\r
187 for (i = 0; i < sNormalizedHash.size(); i++)
\r
189 if (sNormalizedHash[i] >= 'A' && sNormalizedHash[i] <= 'F')
\r
190 sNormalizedHash[i] = (char) sNormalizedHash[i] - 'A' + 'a';
\r
194 for (i = 0; i < sNormalizedHash.size(); i++)
\r
196 if ( (sNormalizedHash[i] < 'a' || sNormalizedHash[i] > 'f')
\r
197 && (sNormalizedHash[i] < '0' || sNormalizedHash[i] > '9'))
\r
201 sHash = sNormalizedHash;
\r
205 void LoadLMHashFromPwdumpFile(string sPathName, vector<string>& vUserName, vector<string>& vLMHash, vector<string>& vNTLMHash)
\r
207 vector<string> vLine;
\r
208 if (ReadLinesFromFile(sPathName, vLine))
\r
211 for (i = 0; i < vLine.size(); i++)
\r
213 vector<string> vPart;
\r
214 if (SeperateString(vLine[i], "::::", vPart))
\r
216 string sUserName = vPart[0];
\r
217 string sLMHash = vPart[2];
\r
218 string sNTLMHash = vPart[3];
\r
220 if (sLMHash.size() == 32 && sNTLMHash.size() == 32)
\r
222 if (NormalizeHash(sLMHash) && NormalizeHash(sNTLMHash))
\r
224 vUserName.push_back(sUserName);
\r
225 vLMHash.push_back(sLMHash);
\r
226 vNTLMHash.push_back(sNTLMHash);
\r
229 printf("invalid lm/ntlm hash %s:%s\n", sLMHash.c_str(), sNTLMHash.c_str());
\r
235 printf("can't open %s\n", sPathName.c_str());
\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
241 vector<string> vLine;
\r
242 if (ReadLinesFromFile(sPathName, vLine))
\r
245 for (i = 0; i < vLine.size(); i++)
\r
247 vector<string> vPart;
\r
248 if (SeperateString(vLine[i], "\t\t\t\t\t\t", vPart))
\r
250 string sUserName = vPart[0];
\r
251 string sLMHash = vPart[4];
\r
252 string sNTLMHash = vPart[5];
\r
254 if (sLMHash.size() == 32 && sNTLMHash.size() == 32)
\r
256 if (NormalizeHash(sLMHash) && NormalizeHash(sNTLMHash))
\r
258 vUserName.push_back(sUserName);
\r
259 vLMHash.push_back(sLMHash);
\r
260 vNTLMHash.push_back(sNTLMHash);
\r
263 printf("invalid lm/ntlm hash %s:%s\n", sLMHash.c_str(), sNTLMHash.c_str());
\r
269 printf("can't open %s\n", sPathName.c_str());
\r
272 bool NTLMPasswordSeek(unsigned char* pLMPassword, int nLMPasswordLen, int nLMPasswordNext,
\r
273 unsigned char* pNTLMHash, string& sNTLMPassword)
\r
275 if (nLMPasswordNext == nLMPasswordLen)
\r
277 unsigned char md[MD4_DIGEST_LENGTH];
\r
278 MD4_NEW(pLMPassword, nLMPasswordLen * 2, md);
\r
280 if (memcmp(md, pNTLMHash, MD4_DIGEST_LENGTH) == 0)
\r
282 sNTLMPassword = "";
\r
284 for (i = 0; i < nLMPasswordLen; i++)
\r
285 sNTLMPassword += char(pLMPassword[i * 2]);
\r
292 if (NTLMPasswordSeek(pLMPassword, nLMPasswordLen, nLMPasswordNext + 1, pNTLMHash, sNTLMPassword))
\r
295 if ( pLMPassword[nLMPasswordNext * 2] >= 'A'
\r
296 && pLMPassword[nLMPasswordNext * 2] <= 'Z')
\r
298 pLMPassword[nLMPasswordNext * 2] = (unsigned char) pLMPassword[nLMPasswordNext * 2] - 'A' + 'a';
\r
299 if (NTLMPasswordSeek(pLMPassword, nLMPasswordLen, nLMPasswordNext + 1, pNTLMHash, sNTLMPassword))
\r
301 pLMPassword[nLMPasswordNext * 2] = (unsigned char) pLMPassword[nLMPasswordNext * 2] - 'a' + 'A';
\r
307 bool LMPasswordCorrectCase(string sLMPassword, unsigned char* pNTLMHash, string& sNTLMPassword)
\r
309 if (sLMPassword.size() == 0)
\r
311 sNTLMPassword = "";
\r
315 unsigned char* pLMPassword = new unsigned char[sLMPassword.size() * 2];
\r
317 for (i = 0; i < sLMPassword.size(); i++)
\r
319 pLMPassword[i * 2 ] = sLMPassword[i];
\r
320 pLMPassword[i * 2 + 1] = 0x00;
\r
322 bool fRet = NTLMPasswordSeek(pLMPassword, sLMPassword.size(), 0, pNTLMHash, sNTLMPassword);
\r
324 delete pLMPassword;
\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
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
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
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
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
359 printf(" rcracki_mt -f hash.txt -t 4 -o results.txt *.rti\n");
\r
362 int main(int argc, char* argv[])
\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
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
397 else if (ReadLinesFromFile(GetApplicationPath() + sIniPathName, vLine)) {
\r
398 readFromIni = true;
\r
403 for (i = 0; i < vLine.size(); i++)
\r
405 if (vLine[i].substr(0,1) != "#")
\r
407 vector<string> vPart;
\r
408 if (SeperateString(vLine[i], "=", vPart))
\r
410 string sOption = vPart[0];
\r
411 string sValue = vPart[1];
\r
413 if (sOption == "Threads") {
\r
414 maxThreads = atoi(sValue.c_str());
\r
416 else if (sOption == "MaxMemoryUsage" ) {
\r
417 maxMem = atoi(sValue.c_str()) * 1024 *1024;
\r
419 else if (sOption == "DefaultResultsFile") {
\r
420 outputFile = sValue;
\r
422 else if (sOption == "AlwaysStoreResultsToFile") {
\r
424 writeOutput = true;
\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
430 else if (sOption == "DefaultAlgorithm") {
\r
431 useDefaultRainbowTablePath = true;
\r
432 sAlgorithm = sValue;
\r
434 else if (sOption == "AlwaysDebug") {
\r
438 else if (sOption == "AlwaysKeepPrecalcFiles") {
\r
440 keepPrecalcFiles = true;
\r
443 printf("illegal option %s in ini file %s\n", sOption.c_str(), sIniPathName.c_str());
\r
449 if (writeOutput && outputFile == "")
\r
451 printf("You need to specify a 'DefaultResultsFile' with 'AlwaysStoreResultsToFile=1'\n");
\r
452 writeOutput = false;
\r
456 // Parse command line arguments
\r
458 for (i = 1; i < argc; i++)
\r
460 string cla = argv[i];
\r
467 else if (cla == "-l") {
\r
473 else if (cla == "-f") {
\r
479 else if (cla == "-c") {
\r
485 else if (cla == "-t") {
\r
488 maxThreads = atoi(argv[i]);
\r
490 else if ( cla == "-m" ) {
\r
493 maxMem = atoi(argv[i]) * 1024 * 1024;
\r
495 else if (cla == "-o") {
\r
496 writeOutput = true;
\r
499 outputFile = argv[i];
\r
501 else if (cla == "-r") {
\r
502 resumeSession = true;
\r
504 else if (cla == "-s") {
\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
516 else if (cla == "-v") {
\r
519 else if (cla == "-k") {
\r
520 keepPrecalcFiles = true;
\r
522 else if (cla == "-a") {
\r
523 useDefaultRainbowTablePath = true;
\r
526 sAlgorithm = argv[i];
\r
529 GetTableList(cla, vPathName);
\r
533 if (debug && !readFromIni)
\r
534 printf("Debug: Couldn't read rcracki_mt.ini, continuing anyway.\n");
\r
536 // Load session data if we are resuming
\r
540 vector<string> sSessionData;
\r
541 if (ReadLinesFromFile(sSessionPathName.c_str(), sSessionData))
\r
544 for (i = 0; i < sSessionData.size(); i++)
\r
546 vector<string> vPart;
\r
547 if (SeperateString(sSessionData[i], "=", vPart))
\r
549 string sOption = vPart[0];
\r
550 string sValue = vPart[1];
\r
552 if (sOption == "sPathName") {
\r
553 vPathName.push_back(sValue);
\r
555 else if (sOption == "sInputType") {
\r
556 sInputType = sValue;
\r
558 else if (sOption == "sInput") {
\r
561 else if (sOption == "outputFile") {
\r
562 writeOutput = true;
\r
563 outputFile = sValue;
\r
565 else if (sOption == "keepPrecalcFiles") {
\r
567 keepPrecalcFiles = true;
\r
573 printf("Couldn't open session file %s\n", sSessionPathName.c_str());
\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
585 for (i = 0; i < vDefaultRainbowTablePath.size(); i++)
\r
587 vector<string> vPart;
\r
588 if (SeperateString(vDefaultRainbowTablePath[i], ".=", vPart))
\r
590 string lineAlgorithm = vPart[1];
\r
591 string linePath = vPart[2];
\r
593 if (lineAlgorithm == sAlgorithm)
\r
594 GetTableList(linePath, vPathName);
\r
599 printf("Using %d threads for pre-calculation and false alarm checking...\n", maxThreads);
\r
601 setvbuf(stdout, NULL, _IONBF,0);
\r
602 if (vPathName.size() == 0)
\r
604 printf("no rainbow table found\n");
\r
607 printf("Found %lu rainbowtable files...\n\n",
\r
608 (unsigned long)vPathName.size());
\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
617 fCrackerType = true;
\r
619 string sHash = sInput;
\r
620 if (NormalizeHash(sHash))
\r
621 vHash.push_back(sHash);
\r
623 printf("invalid hash: %s\n", sHash.c_str());
\r
625 else if (sInputType == "-l")
\r
627 fCrackerType = true;
\r
629 string sPathName = sInput;
\r
630 vector<string> vLine;
\r
631 if (ReadLinesFromFile(sPathName, vLine))
\r
634 for (i = 0; i < vLine.size(); i++)
\r
636 string sHash = vLine[i];
\r
637 if (NormalizeHash(sHash))
\r
638 vHash.push_back(sHash);
\r
640 printf("invalid hash: %s\n", sHash.c_str());
\r
644 printf("can't open %s\n", sPathName.c_str());
\r
646 else if (sInputType == "-f")
\r
648 fCrackerType = false;
\r
650 string sPathName = sInput;
\r
651 LoadLMHashFromPwdumpFile(sPathName, vUserName, vLMHash, vNTLMHash);
\r
653 else if (sInputType == "-c")
\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
666 if (fCrackerType && vHash.size() == 0)
\r
668 printf("no hashes found");
\r
671 if (!fCrackerType && vLMHash.size() == 0)
\r
674 printf("no hashes found");
\r
680 for (i = 0; i < vHash.size(); i++)
\r
681 hs.AddHash(vHash[i]);
\r
686 for (i = 0; i < vLMHash.size(); i++)
\r
688 hs.AddHash(vLMHash[i].substr(0, 16));
\r
689 hs.AddHash(vLMHash[i].substr(16, 16));
\r
693 // Load found hashes from session file
\r
696 vector<string> sSessionData;
\r
697 if (ReadLinesFromFile(sSessionPathName.c_str(), sSessionData))
\r
700 for (i = 0; i < sSessionData.size(); i++)
\r
702 vector<string> vPart;
\r
703 if (SeperateString(sSessionData[i], "=", vPart))
\r
705 string sOption = vPart[0];
\r
706 string sValue = vPart[1];
\r
708 if (sOption == "sHash") {
\r
709 vector<string> vPartHash;
\r
710 if (SeperateString(sValue, "::", vPartHash))
\r
712 string sHash = vPartHash[0];
\r
713 string sBinary = vPartHash[1];
\r
714 string sPlain = vPartHash[2];
\r
716 hs.SetPlain(sHash, sPlain, sBinary);
\r
725 // (Over)write session data if we are not resuming
\r
726 FILE* file = fopen(sSessionPathName.c_str(), "w");
\r
727 string buffer = "";
\r
731 buffer += "sInputType=" + sInputType + "\n";
\r
732 buffer += "sInput=" + sInput + "\n";
\r
735 for (i = 0; i < vPathName.size(); i++)
\r
737 buffer += "sPathName=" + vPathName[i] + "\n";
\r
741 buffer += "outputFile=" + outputFile + "\n";
\r
743 if (keepPrecalcFiles)
\r
744 buffer += "keepPrecalcFiles=1\n";
\r
746 fputs (buffer.c_str(), file);
\r
749 file = fopen(sProgressPathName.c_str(), "w");
\r
756 ce.setOutputFile(outputFile);
\r
757 ce.setSession(sSessionPathName, sProgressPathName, sPrecalcPathName, keepPrecalcFiles);
\r
758 ce.Run(vPathName, hs, maxThreads, maxMem, resumeSession, debug);
\r
760 // Remove session files
\r
761 if (debug) printf("Debug: Removing session files.\n");
\r
763 if (remove(sSessionPathName.c_str()) == 0)
\r
764 remove(sProgressPathName.c_str());
\r
766 if (debug) printf("Debug: Failed removing session files.\n");
\r
769 printf("statistics\n");
\r
770 printf("-------------------------------------------------------\n");
\r
771 printf("plaintext found: %d of %d (%.2f%%)\n", hs.GetStatHashFound(),
\r
772 hs.GetStatHashTotal(),
\r
773 100.0f * hs.GetStatHashFound() / hs.GetStatHashTotal());
\r
774 printf("total disk access time: %.2f s\n", ce.GetStatTotalDiskAccessTime());
\r
775 printf("total cryptanalysis time: %.2f s\n", ce.GetStatTotalCryptanalysisTime());
\r
776 printf("total pre-calculation time: %.2f s\n", ce.GetStatTotalPrecalculationTime());
\r
777 // printf("total chain walk step: %d\n", ce.GetStatTotalChainWalkStep());
\r
778 printf("total chain walk step: %llu\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 due to false alarm: %llu\n", ce.GetStatTotalChainWalkStepDueToFalseAlarm());
\r
782 // printf("total chain walk step skipped due to checkpoints: %d\n", ce.GetStatTotalFalseAlarmSkipped()); // Checkpoints not used - yet
\r
786 printf("result\n");
\r
787 printf("-------------------------------------------------------\n");
\r
791 for (i = 0; i < vHash.size(); i++)
\r
793 string sPlain, sBinary;
\r
794 if (!hs.GetPlain(vHash[i], sPlain, sBinary))
\r
796 sPlain = "<notfound>";
\r
797 sBinary = "<notfound>";
\r
800 printf("%s\t%s\thex:%s\n", vHash[i].c_str(), sPlain.c_str(), sBinary.c_str());
\r
806 for (i = 0; i < vLMHash.size(); i++)
\r
808 string sPlain1, sBinary1;
\r
809 bool fPart1Found = hs.GetPlain(vLMHash[i].substr(0, 16), sPlain1, sBinary1);
\r
812 sPlain1 = "<notfound>";
\r
813 sBinary1 = "<notfound>";
\r
816 string sPlain2, sBinary2;
\r
817 bool fPart2Found = hs.GetPlain(vLMHash[i].substr(16, 16), sPlain2, sBinary2);
\r
820 sPlain2 = "<notfound>";
\r
821 sBinary2 = "<notfound>";
\r
824 string sPlain = sPlain1 + sPlain2;
\r
825 string sBinary = sBinary1 + sBinary2;
\r
828 if (fPart1Found && fPart2Found)
\r
830 unsigned char NTLMHash[16];
\r
832 ParseHash(vNTLMHash[i], NTLMHash, nHashLen);
\r
833 if (nHashLen != 16)
\r
834 printf("debug: nHashLen mismatch\n");
\r
835 string sNTLMPassword;
\r
836 if (LMPasswordCorrectCase(sPlain, NTLMHash, sNTLMPassword))
\r
838 sPlain = sNTLMPassword;
\r
839 sBinary = HexToStr((const unsigned char*)sNTLMPassword.c_str(), sNTLMPassword.size());
\r
843 printf("%-14s\t%s\thex:%s\n", vUserName[i].c_str(), sPlain.c_str(), sBinary.c_str());
\r
844 LM2NTLMcorrector corrector;
\r
845 if (corrector.LMPasswordCorrectUnicode(sBinary, NTLMHash, sNTLMPassword))
\r
847 sPlain = sNTLMPassword;
\r
848 sBinary = corrector.getBinary();
\r
851 if (!writeResultLineToFile(outputFile, vNTLMHash[i].c_str(), sPlain.c_str(), sBinary.c_str()))
\r
852 printf("Couldn't write final result to file!\n");
\r
856 printf("case correction for password %s failed!\n", sPlain.c_str());
\r
862 printf("%-14s\t%s\thex:%s\n", vUserName[i].c_str(),
\r