]> git.sesse.net Git - freerainbowtables/blob - Client Applications/rcracki_mt/CrackEngine.cpp
3ed82de4ef6aaf346db69a554071db8dbe16b0c6
[freerainbowtables] / Client Applications / rcracki_mt / CrackEngine.cpp
1 /*
2    RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique.
3
4    Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>
5 */
6
7 #ifdef _WIN32
8         #pragma warning(disable : 4786 4267 4018)
9 #endif
10
11 #include "CrackEngine.h"
12
13 #include <time.h>
14 #include "RTI2Reader.h"
15
16 CCrackEngine::CCrackEngine()
17 {
18         ResetStatistics();
19         writeOutput = false;
20         resumeSession = false;
21         debug = false;
22         keepPrecalcFiles = false;
23
24         sSessionPathName = "";
25         sProgressPathName = "";
26 }
27
28 CCrackEngine::~CCrackEngine()
29 {
30 }
31
32 //////////////////////////////////////////////////////////////////////
33
34 void CCrackEngine::ResetStatistics()
35 {
36         m_fTotalDiskAccessTime               = 0.0f;
37         m_fTotalCryptanalysisTime            = 0.0f;
38         m_nTotalChainWalkStep                = 0;
39         m_nTotalFalseAlarm                   = 0;
40         m_nTotalChainWalkStepDueToFalseAlarm = 0;
41 //      m_nTotalFalseAlarmSkipped                        = 0;
42 }
43
44 int CCrackEngine::BinarySearchOld(RainbowChainO* pChain, int nRainbowChainCount, uint64 nIndex)
45 {
46         int nLow = 0;
47         int nHigh = nRainbowChainCount - 1;
48         while (nLow <= nHigh)
49         {
50                 int nMid = (nLow + nHigh) / 2;
51                 if (nIndex == pChain[nMid].nIndexE)
52                         return nMid;
53                 else if (nIndex < pChain[nMid].nIndexE)
54                         nHigh = nMid - 1;
55                 else
56                         nLow = nMid + 1;
57         }
58
59         return -1;
60 }
61
62 RainbowChain *CCrackEngine::BinarySearch(RainbowChain *pChain, int nChainCountRead, uint64 nIndex, IndexChain *pIndex, int nIndexSize, int nIndexStart)
63 {
64         uint64 nPrefix = nIndex >> 16;
65         int nLow, nHigh;        
66         bool found = false;
67         int nChains = 0;
68         
69         if(nPrefix > (pIndex[nIndexSize-1].nPrefix & 0x000000FFFFFFFFFFULL)) // check if its in the index file
70         {
71                 return NULL;
72         }
73
74         int nBLow = 0;
75         int nBHigh = nIndexSize - 1;
76         while (nBLow <= nBHigh)
77         {
78                 int nBMid = (nBLow + nBHigh) / 2;
79                 if (nPrefix == (pIndex[nBMid].nPrefix & 0x000000FFFFFFFFFFULL))
80                 {
81                         //nLow = nChains;
82                         int nChains = 0;
83
84                         nLow = pIndex[nBMid].nFirstChain;
85                         nHigh = nLow + pIndex[nBMid].nChainCount;
86                         if(nLow >= nIndexStart && nLow <= nIndexStart + nChainCountRead) 
87                         {                                       
88                                 if(nHigh > nIndexStart + nChainCountRead)
89                                         nHigh = nIndexStart + nChainCountRead;
90                         }
91                         else if(nLow < nIndexStart && nHigh >= nIndexStart)
92                         {
93                                 nLow = nIndexStart;
94                         }
95                         else break;                                     
96                         found = true;
97                         break;
98                 }
99                 else if (nPrefix < (pIndex[nBMid].nPrefix & 0x000000FFFFFFFFFFULL))
100                         nBHigh = nBMid - 1;
101                 else
102                         nBLow = nBMid + 1;
103         }
104         if(found == true)
105         {
106                 for(int i = nLow - nIndexStart; i < nHigh - nIndexStart; i++)
107                 {
108                         int nSIndex = ((int)nIndex) & 0x0000FFFF;
109
110                         if (nSIndex == pChain[i].nIndexE)
111                         {
112                                 return &pChain[i];
113                         }                               
114                         else if(pChain[i].nIndexE > nSIndex)
115                                 break;
116                 }
117         }       
118         return NULL;
119 }
120
121 // not used currently, leaving code for future checkpoints
122 //bool CCrackEngine::CheckAlarm(RainbowChain* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs)
123 //{
124 //      CChainWalkContext cwc;
125 //      //uint64 nIndexS = pChain->nIndexS >> 16;
126 //      uint64 nIndexS = pChain->nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes
127 //      cwc.SetIndex(nIndexS);
128 //      int nPos;
129 //      for (nPos = 0; nPos < nGuessedPos; nPos++)
130 //      {
131 //              cwc.IndexToPlain();
132 //              cwc.PlainToHash();
133 //              cwc.HashToIndex(nPos);
134 //              // Not using checkpoints atm
135 //              /*
136 //              switch(nPos)
137 //              {
138 //              case 5000:
139 //                              if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000080) >> 7)
140 //                              {
141 //                                      m_nTotalFalseAlarmSkipped += 10000 - 5000;
142 ////                                    printf("CheckPoint caught false alarm at position 7600\n");
143 //                                      return false;
144 //                              }
145 //                              break;
146 //              case 6000:
147 //                              if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000040) >> 6)
148 //                              {
149 ////                                    printf("CheckPoint caught false alarm at position 8200\n");
150 //                                      m_nTotalFalseAlarmSkipped += 10000 - 6000;
151 //                                      return false;
152 //                              }
153 //                              break;
154 //
155 //              case 7600:
156 //                              if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000020) >> 5)
157 //                              {
158 ////                                    printf("CheckPoint caught false alarm at position 8700\n");
159 //                                      m_nTotalFalseAlarmSkipped += 10000 - 7600;
160 //                                      return false;
161 //                              }
162 //                              break;
163 //
164 //              case 8200:
165 //                              if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000010) >> 4)
166 //                              {
167 ////                                    printf("CheckPoint caught false alarm at position 9000\n");
168 //                                      m_nTotalFalseAlarmSkipped += 10000 - 8200;
169 //                                      return false;
170 //                              }
171 //                              break;
172 //
173 //                      case 8700:
174 //                              if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000008) >> 3)
175 //                              {
176 ////                                    printf("CheckPoint caught false alarm at position 9300\n");
177 //                                      m_nTotalFalseAlarmSkipped += 10000 - 8700;
178 //                                      return false;
179 //                              }
180 //
181 //                              break;
182 //                      case 9000:
183 //                              if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000004) >> 2)
184 //                              {
185 ////                                    printf("CheckPoint caught false alarm at position 9600\n");
186 //                                      m_nTotalFalseAlarmSkipped += 10000 - 9000;
187 //                                      return false;
188 //                              }
189 //
190 //                              break;
191 //                      case 9300:
192 //                              if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000002) >> 1)
193 //                              {
194 ////                                    printf("CheckPoint caught false alarm at position 9600\n");
195 //                                      m_nTotalFalseAlarmSkipped += 10000 - 9300;
196 //                                      return false;
197 //                              }
198 //                              break;
199 //                      case 9600:
200 //                              if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000001))
201 //                              {
202 ////                                    printf("CheckPoint caught false alarm at position 9600\n");
203 //                                      m_nTotalFalseAlarmSkipped += 10000 - 9600;
204 //                                      return false;
205 //                              }
206 //                              break;
207 //
208 //              }*/
209 //      }
210 //      cwc.IndexToPlain();
211 //      cwc.PlainToHash();
212 //      if (cwc.CheckHash(pHash))
213 //      {
214 //              printf("plaintext of %s is %s\n", cwc.GetHash().c_str(), cwc.GetPlain().c_str());
215 //              hs.SetPlain(cwc.GetHash(), cwc.GetPlain(), cwc.GetBinary());
216 //              return true;
217 //      }
218 //
219 //      return false;
220 //}
221
222 //bool CCrackEngine::CheckAlarmOld(RainbowChainO* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs)
223 //{
224 //      CChainWalkContext cwc;
225 //      cwc.SetIndex(pChain->nIndexS);
226 //      int nPos;
227 //      for (nPos = 0; nPos < nGuessedPos; nPos++)
228 //      {
229 //              cwc.IndexToPlain();
230 //              cwc.PlainToHash();
231 //              cwc.HashToIndex(nPos);
232 //      }
233 //      cwc.IndexToPlain();
234 //      cwc.PlainToHash();
235 //      if (cwc.CheckHash(pHash))
236 //      {
237 //              printf("plaintext of %s is %s\n", cwc.GetHash().c_str(), cwc.GetPlain().c_str());
238 //              hs.SetPlain(cwc.GetHash(), cwc.GetPlain(), cwc.GetBinary());
239 //              return true;
240 //      }
241 //
242 //      return false;
243 //}
244
245 void CCrackEngine::GetChainIndexRangeWithSameEndpoint(RainbowChainO* pChain,
246                                                                                                           int nRainbowChainCount,
247                                                                                                           int nMatchingIndexE,
248                                                                                                           int& nMatchingIndexEFrom,
249                                                                                                           int& nMatchingIndexETo)
250 {
251         nMatchingIndexEFrom = nMatchingIndexE;
252         nMatchingIndexETo   = nMatchingIndexE;
253         while (nMatchingIndexEFrom > 0)
254         {
255                 if (pChain[nMatchingIndexEFrom - 1].nIndexE == pChain[nMatchingIndexE].nIndexE)
256                         nMatchingIndexEFrom--;
257                 else
258                         break;
259         }
260         while (nMatchingIndexETo < nRainbowChainCount - 1)
261         {
262                 if (pChain[nMatchingIndexETo + 1].nIndexE == pChain[nMatchingIndexE].nIndexE)
263                         nMatchingIndexETo++;
264                 else
265                         break;
266         }
267 }
268
269 void CCrackEngine::SearchTableChunkOld(RainbowChainO* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs)
270 {
271         vector<string> vHash;
272         hs.GetLeftHashWithLen(vHash, CChainWalkContext::GetHashLen());
273         printf("searching for %d hash%s...\n", vHash.size(),
274                                                                                    vHash.size() > 1 ? "es" : "");
275
276         int nChainWalkStep = 0;
277         int nFalseAlarm = 0;
278         int nChainWalkStepDueToFalseAlarm = 0;
279
280         vector<rcrackiThread*> threadPool;
281         vector<pthread_t> pThreads;
282
283         pthread_attr_t attr;
284         pthread_attr_init(&attr);
285         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
286         #ifdef _WIN32
287         sched_param param;
288         param.sched_priority = THREAD_PRIORITY_BELOW_NORMAL;
289         pthread_attr_setschedparam (&attr, &param);
290         #endif
291         // else set it to 5 or something (for linux)?
292
293         bool pausing = false;
294
295         int nHashIndex;
296         for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)
297         {
298                 #ifdef _WIN32
299                 if (_kbhit())
300                 {
301                         int ch = _getch();
302                         ch = toupper(ch);
303                         if (ch == 'P')
304                         {
305                                 pausing = true;
306                                 printf( "\nPausing, press P again to continue... ");
307                                 clock_t t1 = clock();
308                                 while (pausing)
309                                 {
310                                         if (_kbhit())
311                                         {
312                                                 ch = _getch();
313                                                 ch = toupper(ch);
314                                                 if (ch == 'P')
315                                                 {
316                                                         printf( " [Continuing]\n");
317                                                         pausing = false;
318                                                         clock_t t2 = clock();
319                                                         float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
320                                                         m_fTotalCryptanalysisTime -= fTime;
321                                                 }
322                                         }
323                                         Sleep(500);
324                                 }
325                         }
326                         else
327                         {
328                                 printf( "\nPress 'P' to pause...\n");
329                         }
330                 }
331                 #else
332                 int c = tty_getchar();
333                 if (c >= 0) {
334                         tty_flush();
335                         if (c==112) { // = p
336                                 pausing = true;
337                                 printf( "\nPausing, press 'p' again to continue... ");
338                                 clock_t t1 = clock();
339                                 while (pausing)
340                                 {
341                                         if ((c = tty_getchar()) >= 0)
342                                         {
343                                                 tty_flush();
344                                                 if (c == 112)
345                                                 {
346                                                         printf( " [Continuing]\n");
347                                                         pausing = false;
348                                                         clock_t t2 = clock();
349                                                         float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
350                                                         m_fTotalCryptanalysisTime -= fTime;
351                                                 }
352                                         }
353                                         usleep(500*1000);
354                                 }
355                         }
356                         else {
357                                 printf( "\nPress 'p' to pause...\n");
358                         }
359                 }
360                 #endif
361                 unsigned char TargetHash[MAX_HASH_LEN];
362                 int nHashLen;
363                 ParseHash(vHash[nHashIndex], TargetHash, nHashLen);
364                 if (nHashLen != CChainWalkContext::GetHashLen())
365                         printf("debug: nHashLen mismatch\n");
366
367                 // Rqeuest ChainWalk
368                 bool fNewlyGenerated;
369                 uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,
370                                                                                                         nHashLen,
371                                                                                                         CChainWalkContext::GetHashRoutineName(),
372                                                                                                         CChainWalkContext::GetPlainCharsetName(),
373                                                                                                         CChainWalkContext::GetPlainLenMin(),
374                                                                                                         CChainWalkContext::GetPlainLenMax(),
375                                                                                                         CChainWalkContext::GetRainbowTableIndex(),
376                                                                                                         nRainbowChainLen,
377                                                                                                         fNewlyGenerated,
378                                                                                                         debug,
379                                                                                                         sPrecalcPathName);
380                 //printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",
381                 //                                                                              vHash[nHashIndex].c_str());
382
383                 // Walk
384                 if (fNewlyGenerated)
385                 {
386                         //printf("Pre-calculating hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());
387                         printf("Pre-calculating hash %d of %d.%-20s\r", nHashIndex+1, vHash.size(), "");
388                         threadPool.clear();
389                         pThreads.clear();
390                         
391                         int thread_ID;
392                         for (thread_ID = 0; thread_ID < maxThreads; thread_ID++)
393                         {
394                                 rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);
395                                 if (r_Thread)
396                                 {
397                                         pthread_t pThread;
398                                         int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
399
400                                         if( returnValue != 0 )
401                                         {
402                                                 printf("pThread creation failed, returnValue: %d\n", returnValue);
403                                         }
404                                         else
405                                         {
406                                                 pThreads.push_back(pThread);
407                                         }
408
409                                         threadPool.push_back(r_Thread);
410                                 }
411                                 else 
412                                 {
413                                         printf("r_Thread creation failed!\n");
414                                 }
415                         }
416                         
417                         //printf("%d r_Threads created\t\t\n", threadPool.size());
418                         
419                         for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
420                         {
421                                 pthread_t pThread = pThreads[thread_ID];
422                                 int returnValue = pthread_join(pThread, NULL);
423                                 if( returnValue != 0 )
424                                 {
425                                         printf("pThread join failed, returnValue: %d\n", returnValue);
426                                 }
427                                         
428                                 rcrackiThread* rThread = threadPool[thread_ID];
429                                 nChainWalkStep += rThread->GetChainWalkStep();
430                         }
431
432                         //printf("\t\t\t\t\r");
433                         printf("%-50s\r", "");
434
435
436                 }
437
438                 //printf("Checking false alarms for hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());
439                 printf("Checking false alarms for hash %d of %d.%-20s\r", nHashIndex+1, vHash.size(), "");
440
441                 threadPool.clear();
442                 pThreads.clear();
443
444                 int i;
445                 for (i = 0; i < maxThreads; i++)
446                 {
447                         rcrackiThread* r_Thread = new rcrackiThread(TargetHash, true);
448                         threadPool.push_back(r_Thread);
449                 }
450
451                 int thread_ID = 0;
452                 int nPos;
453                 for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)
454                 {
455                         uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];
456                 
457                         // Search matching nIndexE
458                         int nMatchingIndexE = BinarySearchOld(pChain, nRainbowChainCount, nIndexEOfCurPos);
459                         if (nMatchingIndexE != -1)
460                         {
461                                 int nMatchingIndexEFrom, nMatchingIndexETo;
462                                 GetChainIndexRangeWithSameEndpoint(pChain, nRainbowChainCount,
463                                                                                                    nMatchingIndexE,
464                                                                                                    nMatchingIndexEFrom, nMatchingIndexETo);
465                                 int i;
466                                 for (i = nMatchingIndexEFrom; i <= nMatchingIndexETo; i++)
467                                 {
468                                         rcrackiThread* rThread = threadPool[thread_ID];
469                                         rThread->AddAlarmCheckO(pChain + i, nPos);
470                                         if (thread_ID < maxThreads - 1 ) {
471                                                 thread_ID++;
472                                         } else {
473                                                 thread_ID = 0;
474                                         }
475                                 }
476                         }
477                 }
478
479                 for (thread_ID = 0; thread_ID < maxThreads; thread_ID++)
480                 {
481                         rcrackiThread* r_Thread = threadPool[thread_ID];
482                         pthread_t pThread;
483
484                         int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
485
486                         if( returnValue != 0 )
487                         {
488                                 printf("pThread creation failed, returnValue: %d\n", returnValue);
489                         }
490                         else
491                         {
492                                 pThreads.push_back(pThread);
493                         }
494                 }
495                 
496                 //printf("%d r_Threads created\t\t\n", threadPool.size());
497
498                 bool foundHashInThread = false;
499                 for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
500                 {
501                         rcrackiThread* rThread = threadPool[thread_ID];
502                         pthread_t pThread = pThreads[thread_ID];
503
504                         int returnValue = pthread_join(pThread, NULL);
505                         if( returnValue != 0 )
506                         {
507                                 printf("pThread join failed, returnValue: %d\n", returnValue);
508                         }
509
510                         nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();
511                         nFalseAlarm += rThread->GetnFalseAlarm();
512
513                         if (rThread->FoundHash() && !foundHashInThread) {
514                                 //printf("\t\t\t\t\t\t\r");
515                                 printf("%-50s\r", "");
516
517                                 printf("plaintext of %s is %s\n", rThread->GetHash().c_str(), rThread->GetPlain().c_str());
518                                 if (writeOutput)
519                                 {
520                                         if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))
521                                                 printf("Couldn't write this result to file!\n");
522                                 }
523                                 hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());
524
525                                 FILE* file = fopen(sSessionPathName.c_str(), "a");
526                                 if (file!=NULL)
527                                 {
528                                         string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";
529                                         fputs (buffer.c_str(), file);
530                                         fclose (file);
531                                 }
532
533                                 m_cws.DiscardWalk(pStartPosIndexE);
534                                 foundHashInThread = true;
535                         }
536                 }
537
538                 pThreads.clear();
539                 threadPool.clear();
540         }
541
542         //printf("\t\t\t\t\t\t\t\r");
543         printf("%-50s\r", "");
544         pThreads.clear();
545         threadPool.clear();
546         pthread_attr_destroy(&attr);
547
548         //printf("debug: chain walk step: %d\n", nChainWalkStep);
549         //printf("debug: false alarm: %d\n", nFalseAlarm);
550         //printf("debug: chain walk step due to false alarm: %d\n", nChainWalkStepDueToFalseAlarm);
551
552         m_nTotalChainWalkStep += nChainWalkStep;
553         m_nTotalFalseAlarm += nFalseAlarm;
554         m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;
555 }
556
557 void CCrackEngine::SearchTableChunk(RainbowChain* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs, IndexChain *pIndex, int nIndexSize, int nChainStart)
558 {
559         vector<string> vHash;
560         //vector<uint64 *> vIndices;
561         //vector<RainbowChain *> vChains;
562         hs.GetLeftHashWithLen(vHash, CChainWalkContext::GetHashLen());
563         printf("searching for %d hash%s...\n", vHash.size(),
564                                                                                    vHash.size() > 1 ? "es" : "");
565
566         int nChainWalkStep = 0;
567         int nFalseAlarm = 0;
568         int nChainWalkStepDueToFalseAlarm = 0;
569
570         vector<rcrackiThread*> threadPool;
571         vector<pthread_t> pThreads;
572
573         pthread_attr_t attr;
574         pthread_attr_init(&attr);
575         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
576         #ifdef _WIN32
577         sched_param param;
578         param.sched_priority = THREAD_PRIORITY_BELOW_NORMAL;
579         pthread_attr_setschedparam (&attr, &param);
580         #endif
581         // else set it to 5 or something (for linux)?
582
583         bool pausing = false;
584
585         int nHashIndex;
586         for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)
587         {
588                 #ifdef _WIN32
589                 if (_kbhit())
590                 {
591                         int ch = _getch();
592                         ch = toupper(ch);
593                         if (ch == 'P')
594                         {
595                                 pausing = true;
596                                 printf( "\nPausing, press P again to continue... ");
597                                 clock_t t1 = clock();
598                                 while (pausing)
599                                 {
600                                         if (_kbhit())
601                                         {
602                                                 ch = _getch();
603                                                 ch = toupper(ch);
604                                                 if (ch == 'P')
605                                                 {
606                                                         printf( " [Continuing]\n");
607                                                         pausing = false;
608                                                         clock_t t2 = clock();
609                                                         float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
610                                                         m_fTotalCryptanalysisTime -= fTime;
611                                                 }
612                                         }
613                                         Sleep(500);
614                                 }
615                         }
616                         else
617                         {
618                                 printf( "\nPress 'P' to pause...\n");
619                         }
620                 }
621                 #else
622                 int c = tty_getchar();
623                 if (c >= 0) {
624                         tty_flush();
625                         if (c==112) { // = p
626                                 pausing = true;
627                                 printf( "\nPausing, press 'p' again to continue... ");
628                                 clock_t t1 = clock();
629                                 while (pausing)
630                                 {
631                                         if ((c = tty_getchar()) >= 0)
632                                         {
633                                                 tty_flush();
634                                                 if (c == 112)
635                                                 {
636                                                         printf( " [Continuing]\n");
637                                                         pausing = false;
638                                                         clock_t t2 = clock();
639                                                         float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
640                                                         m_fTotalCryptanalysisTime -= fTime;
641                                                 }
642                                         }
643                                         usleep(500*1000);
644                                 }
645                         }
646                         else {
647                                 printf( "\nPress 'p' to pause...\n");
648                         }
649                 }
650                 #endif
651                 unsigned char TargetHash[MAX_HASH_LEN];
652                 int nHashLen;
653                 ParseHash(vHash[nHashIndex], TargetHash, nHashLen);
654                 if (nHashLen != CChainWalkContext::GetHashLen())
655                         printf("debug: nHashLen mismatch\n");
656
657                 // Request ChainWalk
658                 bool fNewlyGenerated;
659 //              printf("Requesting walk...");
660                  
661
662                 uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,
663                                                                                                         nHashLen,
664                                                                                                         CChainWalkContext::GetHashRoutineName(),
665                                                                                                         CChainWalkContext::GetPlainCharsetName(),
666                                                                                                         CChainWalkContext::GetPlainLenMin(),
667                                                                                                         CChainWalkContext::GetPlainLenMax(),
668                                                                                                         CChainWalkContext::GetRainbowTableIndex(),
669                                                                                                         nRainbowChainLen,
670                                                                                                         fNewlyGenerated,
671                                                                                                         debug,
672                                                                                                         sPrecalcPathName);
673 //              printf("done!\n");
674 //              printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",
675 //                                                                                              vHash[nHashIndex].c_str());
676
677                 if (fNewlyGenerated)
678                 {
679                         //printf("Pre-calculating hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());
680                         printf("Pre-calculating hash %d of %d.%-20s\r", nHashIndex+1, vHash.size(), "");
681                         threadPool.clear();
682                         pThreads.clear();
683                         
684                         int thread_ID;
685                         for (thread_ID = 0; thread_ID < maxThreads; thread_ID++)
686                         {
687                                 rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);
688                                 if (r_Thread)
689                                 {
690                                         pthread_t pThread;
691                                         int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
692
693                                         if( returnValue != 0 )
694                                         {
695                                                 printf("pThread creation failed, returnValue: %d\n", returnValue);
696                                         }
697                                         else
698                                         {
699                                                 pThreads.push_back(pThread);
700                                         }
701
702                                         threadPool.push_back(r_Thread);
703                                 }
704                                 else 
705                                 {
706                                         printf("r_Thread creation failed!\n");
707                                 }
708                         }
709                         
710                         //printf("%d r_Threads created\t\t\n", threadPool.size());
711                         
712                         for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
713                         {
714                                 pthread_t pThread = pThreads[thread_ID];
715                                 int returnValue = pthread_join(pThread, NULL);
716                                 if( returnValue != 0 )
717                                 {
718                                         printf("pThread join failed, returnValue: %d\n", returnValue);
719                                 }
720                                         
721                                 rcrackiThread* rThread = threadPool[thread_ID];
722                                 nChainWalkStep += rThread->GetChainWalkStep();
723                         }
724
725                         m_cws.StoreToFile(pStartPosIndexE, TargetHash, nHashLen);
726
727                         //printf("\npStartPosIndexE[0]: %s\n", uint64tostr(pStartPosIndexE[0]).c_str());
728                         //printf("\npStartPosIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pStartPosIndexE[nRainbowChainLen-2]).c_str());
729
730                         printf("%-50s\r", "");
731
732
733                 }
734
735                 threadPool.clear();
736                 pThreads.clear();
737
738                 //printf("Checking false alarms for hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());
739                 printf("Checking false alarms for hash %d of %d.%-20s\r", nHashIndex+1, vHash.size(), "");
740
741                 int i;
742                 for (i = 0; i < maxThreads; i++)
743                 {
744                         rcrackiThread* r_Thread = new rcrackiThread(TargetHash);
745                         threadPool.push_back(r_Thread);
746                 }
747
748                 int thread_ID = 0;
749                 int nPos;
750                 for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)
751                 {
752                         uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];
753                 
754                         // Search matching nIndexE
755                         RainbowChain *pChainFound = BinarySearch(pChain, nRainbowChainCount, nIndexEOfCurPos, pIndex, nIndexSize, nChainStart);
756                         if (pChainFound != NULL) // For perfected indexed tables we only recieve 1 result (huge speed increase!)
757                         {
758                                 rcrackiThread* rThread = threadPool[thread_ID];
759                                 rThread->AddAlarmCheck(pChainFound, nPos);
760                                 if (thread_ID < maxThreads - 1 ) {
761                                         thread_ID++;
762                                 } else {
763                                         thread_ID = 0;
764                                 }
765                         }
766                 }
767
768                 for (thread_ID = 0; thread_ID < maxThreads; thread_ID++)
769                 {
770                         rcrackiThread* r_Thread = threadPool[thread_ID];
771                         pthread_t pThread;
772
773                         int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
774
775                         if( returnValue != 0 )
776                         {
777                                 printf("pThread creation failed, returnValue: %d\n", returnValue);
778                         }
779                         else
780                         {
781                                 pThreads.push_back(pThread);
782                         }
783                 }
784                 
785                 //printf("%d r_Threads created\t\t\n", threadPool.size());
786
787                 bool foundHashInThread = false;
788                 for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
789                 {
790                         rcrackiThread* rThread = threadPool[thread_ID];
791                         pthread_t pThread = pThreads[thread_ID];
792
793                         int returnValue = pthread_join(pThread, NULL);
794                         if( returnValue != 0 )
795                         {
796                                 printf("pThread join failed, returnValue: %d\n", returnValue);
797                         }
798
799                         nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();
800                         nFalseAlarm += rThread->GetnFalseAlarm();
801
802                         if (rThread->FoundHash() && !foundHashInThread) {
803                                 //printf("\t\t\t\t\t\t\r");
804                                 printf("%-50s\r", "");
805                                 printf("plaintext of %s is %s\n", rThread->GetHash().c_str(), rThread->GetPlain().c_str());
806                                 if (writeOutput)
807                                 {
808                                         if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))
809                                                 printf("Couldn't write this result to file!\n");
810                                 }
811                                 hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());
812                                 
813                                 FILE* file = fopen(sSessionPathName.c_str(), "a");
814                                 if (file!=NULL)
815                                 {
816                                         string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";
817                                         fputs (buffer.c_str(), file);
818                                         fclose (file);
819                                 }
820
821                                 m_cws.DiscardWalk(pStartPosIndexE);
822                                 foundHashInThread = true;
823                         }
824                         //pthread
825                         delete rThread;
826                 }
827
828                 pThreads.clear();
829                 threadPool.clear();
830
831                 //printf("\t\t\t\t\r");
832                 //printf("pChainFounds: %d\n", pChainsFound.size());
833 //NEXT_HASH:;
834         }
835         //printf("\t\t\t\t\t\t\t\r");
836         printf("%-50s\r", "");
837         pThreads.clear();
838         threadPool.clear();
839         pthread_attr_destroy(&attr);
840
841         //printf("debug: chain walk step: %d\n", nChainWalkStep);
842         //printf("debug: false alarm: %d\n", nFalseAlarm);
843         //printf("debug: chain walk step due to false alarm: %d\n", nChainWalkStepDueToFalseAlarm);
844
845         m_nTotalChainWalkStep += nChainWalkStep;
846         m_nTotalFalseAlarm += nFalseAlarm;
847         m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;
848 }
849
850 void CCrackEngine::SearchRainbowTable(string sPathName, CHashSet& hs)
851 {
852         // Did we already go through this file in this session?
853         if (resumeSession)
854         {
855                 vector<string> sessionFinishedPathNames;
856                 if (ReadLinesFromFile(sProgressPathName.c_str(), sessionFinishedPathNames))
857                 {
858                         int i;
859                         for (i = 0; i < sessionFinishedPathNames.size(); i++)
860                         {
861                                 if (sessionFinishedPathNames[i] == sPathName)
862                                 {
863                                         printf("Skipping %s\n", sPathName.c_str());
864                                         return;
865                                 }
866                         }
867                 }
868         }
869
870         // FileName
871 #ifdef _WIN32
872         int nIndex = sPathName.find_last_of('\\');
873 #else
874         int nIndex = sPathName.find_last_of('/');
875 #endif
876         string sFileName;
877         if (nIndex != -1)
878                 sFileName = sPathName.substr(nIndex + 1);
879         else
880                 sFileName = sPathName;
881
882         // Info
883         printf("%s:\n", sFileName.c_str());
884
885         // Setup
886         int nRainbowChainLen, nRainbowChainCount;
887         if (!CChainWalkContext::SetupWithPathName(sPathName, nRainbowChainLen, nRainbowChainCount))
888                 return;
889         //printf("keyspace: %u\n", CChainWalkContext::GetPlainSpaceTotal());
890         // Already finished?
891         if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
892         {
893                 printf("this table contains hashes with length %d only\n", CChainWalkContext::GetHashLen());
894                 return;
895         }
896
897         // Open
898         FILE* file = fopen(sPathName.c_str(), "rb");
899         if (file != NULL)
900         {
901                 // File length check
902                 bool doOldFormat = CChainWalkContext::isOldFormat();
903                 bool doNewFormat = CChainWalkContext::isNewFormat();
904                 int sizeOfChain;
905                 bool fVerified = false;
906                 unsigned int nFileLen = GetFileLen(file);
907
908                 if (doOldFormat)
909                         sizeOfChain = 16;
910                 else
911                         sizeOfChain = 8;
912
913                 //if (nFileLen % 8 != 0 || nRainbowChainCount * 8 != nFileLen)
914                 if ((nFileLen % sizeOfChain != 0 || nRainbowChainCount * sizeOfChain != nFileLen) && doNewFormat == false)
915                                 printf("file length mismatch\n");
916                 else
917                 {
918                         fseek(file, 0, SEEK_SET);
919
920                         unsigned int bytesForChainWalkSet = hs.GetStatHashTotal() * (nRainbowChainLen-1) * 8;
921                         if (debug) printf("Debug: Saving %u bytes of memory for chainwalkset.\n", bytesForChainWalkSet);
922
923                         static CMemoryPool mp(bytesForChainWalkSet);
924                         unsigned int nAllocatedSize;
925                         if (doNewFormat || doOldFormat)
926                         {
927                                 RTI2Reader *pReader;
928                                 if(doNewFormat) {
929                                         pReader = new RTI2Reader(sPathName);
930
931                                 }
932                                 if (debug) printf("Debug: This is a table in the old .rt format.\n");
933                                 RainbowChainO* pChain = (RainbowChainO*)mp.Allocate(nFileLen, nAllocatedSize);
934                                 if (debug) printf("Allocated %u bytes, filelen %u\n", nAllocatedSize, nFileLen);
935                                 if (pChain != NULL)
936                                 {
937                                         nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain;            // Round to sizeOfChain boundary
938
939                                         //fseek(file, 0, SEEK_SET);
940                                         //bool fVerified = false;
941                                         while (true)    // Chunk read loop
942                                         {
943                                                 if (ftell(file) == nFileLen)
944                                                         break;
945
946                                                 // Load table chunk
947                                                 if (debug) printf("reading...\n");
948                                                 unsigned int nDataRead = 0;
949                                                 clock_t t1 = clock();
950                                                 if (doNewFormat)
951                                                 {
952                                                         nDataRead = nAllocatedSize / 16;
953                                                         pReader->ReadChains(nDataRead, pChain);
954                                                         nDataRead *= 8; // Convert from chains read to bytes
955                                                         if(nDataRead == 0) // No more data
956                                                                 break;
957                                                 }
958                                                 else {
959                                                         nDataRead = fread(pChain, 1, nAllocatedSize, file);
960                                                 }
961                                                 clock_t t2 = clock();
962                                                 float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
963                                                 printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
964                                                 m_fTotalDiskAccessTime += fTime;
965
966                                                 int nRainbowChainCountRead = nDataRead / 16;
967
968                                                 // Verify table chunk
969                                                 if (!fVerified)
970                                                 {
971                                                         printf("verifying the file...\n");
972
973                                                         // Chain length test
974                                                         int nIndexToVerify = nRainbowChainCountRead / 2;
975                                                         CChainWalkContext cwc;
976                                                         cwc.SetIndex(pChain[nIndexToVerify].nIndexS);
977                                                         int nPos;
978                                                         for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
979                                                         {
980                                                                 cwc.IndexToPlain();
981                                                                 cwc.PlainToHash();
982                                                                 cwc.HashToIndex(nPos);
983                                                         }
984                                                         if (cwc.GetIndex() != pChain[nIndexToVerify].nIndexE)
985                                                         {
986                                                                 printf("rainbow chain length verify fail\n");
987                                                                 break;
988                                                         }
989
990                                                         // Chain sort test
991                                                         int i;
992                                                         for (i = 0; i < nRainbowChainCountRead - 1; i++)
993                                                         {
994                                                                 if (pChain[i].nIndexE > pChain[i + 1].nIndexE)
995                                                                         break;
996                                                         }
997                                                         if (i != nRainbowChainCountRead - 1)
998                                                         {
999                                                                 printf("this file is not sorted\n");
1000                                                                 break;
1001                                                         }
1002
1003                                                         fVerified = true;
1004                                                 }
1005
1006                                                 // Search table chunk
1007                                                 t1 = clock();
1008                                                 SearchTableChunkOld(pChain, nRainbowChainLen, nRainbowChainCountRead, hs);
1009                                                 t2 = clock();
1010                                                 fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
1011                                                 printf("cryptanalysis time: %.2f s\n", fTime);
1012                                                 m_fTotalCryptanalysisTime += fTime;
1013
1014                                                 // Already finished?
1015                                                 if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
1016                                                         break;
1017                                         }
1018                                 }
1019                                 else
1020                                         printf("memory allocation fail\n");
1021                                 
1022                                 //delete pChain;
1023                         }
1024                         else
1025                         {
1026                                 static CMemoryPool mpIndex(bytesForChainWalkSet);
1027                                 unsigned int nAllocatedSizeIndex;
1028
1029                                 //int nIndexSize = 0;
1030                                 //IndexChain *pIndex = NULL;
1031
1032                                 FILE* fIndex = fopen(((string)(sPathName + string(".index"))).c_str(), "rb");
1033                                 if(fIndex != NULL)
1034                                 {
1035                                         // File length check
1036                                         unsigned int nFileLenIndex = GetFileLen(fIndex);
1037                                         unsigned int nRows = nFileLenIndex / 11;
1038                                         unsigned int nSize = nRows * sizeof(IndexChain);
1039                                         //printf("Debug: 8\n");
1040                                         if (nFileLenIndex % 11 != 0)
1041                                                 printf("index file length mismatch (%u bytes)\n", nFileLenIndex);
1042                                         else
1043                                         {
1044                                                 //printf("index nSize: %d\n", nSize);
1045                                                 //pIndex = (IndexChain*)new unsigned char[nSize];
1046                                                 IndexChain *pIndex = (IndexChain*)mpIndex.Allocate(nFileLenIndex, nAllocatedSizeIndex);
1047                                                 if (debug) printf("Debug: Allocated %u bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
1048                                                 
1049                                                 if (pIndex != NULL && nAllocatedSizeIndex > 0)
1050                                                 {
1051                                                         nAllocatedSizeIndex = nAllocatedSizeIndex / sizeof(IndexChain) * sizeof(IndexChain);            // Round to sizeOfIndexChain boundary
1052                                                 
1053                                                         fseek(fIndex, 0, SEEK_SET);
1054                                                         int nProcessedIndexChains = 0;
1055
1056                                                         while (true)    // Index chunk read loop
1057                                                         {
1058                                                                 if (ftell(fIndex) == nFileLenIndex)
1059                                                                         break;
1060
1061                                                                 // Load index chunk
1062                                                                 if (debug) printf("Debug: Setting index to 0x00 in memory, %u bytes\n", nAllocatedSizeIndex);
1063                                                                 memset(pIndex, 0x00, nAllocatedSizeIndex);
1064                                                                 printf("reading index... ");
1065                                                                 clock_t t1 = clock();
1066                                                                 unsigned int nDataRead = fread(pIndex, 1, nAllocatedSizeIndex, fIndex);
1067                                                                 clock_t t2 = clock();
1068
1069                                                                 float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
1070                                                                 printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
1071                                                                 m_fTotalDiskAccessTime += fTime;
1072                                                         
1073                                                                 //nIndexSize = nFileLenIndex / 11;
1074                                                                 int nIndexChainCountRead = nDataRead / sizeof(IndexChain);
1075                                                                 //fclose(fIndex);
1076                                                                 unsigned int nCoveredRainbowTableChains = 0;
1077                                                                 for(int i = 0; i < nIndexChainCountRead; i++)
1078                                                                 {
1079                                                                         nCoveredRainbowTableChains += pIndex[i].nChainCount;
1080                                                                 }
1081
1082                                                                 //RainbowChain* pChain = (RainbowChain*)mp.Allocate(nFileLen, nAllocatedSize);
1083                                                                 RainbowChain* pChain = (RainbowChain*)mp.Allocate(nCoveredRainbowTableChains * sizeOfChain, nAllocatedSize);
1084                                                                 if (debug) printf("Debug: Allocated %u bytes for %u chains, filelen %u\n", nAllocatedSize, nCoveredRainbowTableChains, nFileLen);
1085
1086                                                                 if (pChain != NULL && nAllocatedSize > 0)
1087                                                                 {
1088                                                                         nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain;            // Round to sizeOfChain boundary
1089
1090                                                                         //fseek(file, 0, SEEK_SET);
1091                                                                         //bool fVerified = false;
1092                                                                         int nProcessedChains = 0;
1093                                                                         while (true)    // Chunk read loop
1094                                                                         {
1095                                                                                 if (ftell(file) == nFileLen)
1096                                                                                         break;
1097
1098                                                                                 if (nProcessedChains >= nCoveredRainbowTableChains)
1099                                                                                         break;
1100
1101                                                                                 // Load table chunk
1102                                                                                 if (debug) printf("Debug: Setting pChain to 0x00 in memory\n");
1103                                                                                 memset(pChain, 0x00, nAllocatedSize);
1104                                                                                 printf("reading table... ");
1105                                                                                 clock_t t1 = clock();
1106                                                                                 unsigned int nDataRead = fread(pChain, 1, nAllocatedSize, file);
1107                                                                                 clock_t t2 = clock();
1108
1109                                                                                 float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
1110                                                                                 printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
1111                                                                                 m_fTotalDiskAccessTime += fTime;
1112                                                                                 int nRainbowChainCountRead = nDataRead / sizeOfChain;
1113                                                                                 // Verify table chunk (Too lazy to implement this)
1114                                                                                 
1115                                                                                 if (!fVerified)
1116                                                                                 {
1117                                                                                         printf("verifying the file...\n");
1118
1119                                                                                         // Chain length test
1120                                                                                         int nIndexToVerify = nRainbowChainCountRead / 2;
1121                                                                                         CChainWalkContext cwc;
1122                                                                                         uint64 nIndexS;
1123                                                                                         nIndexS = pChain[nIndexToVerify].nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes
1124
1125                                                                                         //printf("nIndexS: %s\n", uint64tostr(nIndexS).c_str());
1126                                                                                         cwc.SetIndex(nIndexS);
1127                                                                                         
1128                                                                                         int nPos;
1129                                                                                         for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
1130                                                                                         {
1131                                                                                                 cwc.IndexToPlain();
1132                                                                                                 cwc.PlainToHash();
1133                                                                                                 cwc.HashToIndex(nPos);
1134                                                                                         }
1135                                                                                         uint64 nEndPoint = 0;
1136
1137                                                                                         //for(int i = 0; i < nIndexSize; i++)
1138                                                                                         for(int i = 0; i < nIndexChainCountRead; i++)
1139                                                                                         {
1140                                                                                                 if(nIndexToVerify >= pIndex[i].nFirstChain && nIndexToVerify < pIndex[i].nFirstChain + pIndex[i].nChainCount) // We found the matching index
1141                                                                                                 { // Now we need to seek nIndexToVerify into the chains
1142                                                                                                         nEndPoint += (pIndex[i].nPrefix & 0x000000FFFFFFFFFFULL) << 16; // & 0x000000FFFFFFFFFFULL for first 5 bytes
1143                                                                                                         //printf("nPrefix: %s\n", uint64tostr(pIndex[i].nPrefix & 0x000000FFFFFFFFFF).c_str());
1144                                                                                                         //printf("nFirstChain: %d\n", pIndex[i].nFirstChain);
1145                                                                                                         //printf("nChainCount: %d\n", pIndex[i].nChainCount);
1146                                                                                                         nEndPoint += pChain[nIndexToVerify].nIndexE;
1147                                                                                                         break;
1148                                                                                                 }
1149                                                                                         }
1150
1151                                                                                         if (cwc.GetIndex() != nEndPoint)
1152                                                                                         {
1153                                                                                                 printf("rainbow chain length verify fail\n");
1154                                                                                                 break;
1155                                                                                         }
1156
1157                                                                                         fVerified = true;
1158                                                                                 }
1159
1160                                                                                 // Search table chunk
1161                                                                                 t1 = clock();
1162                                                                                 float preTime = m_fTotalCryptanalysisTime;
1163
1164                                                                                 SearchTableChunk(pChain, nRainbowChainLen, nRainbowChainCountRead, hs, pIndex, nIndexChainCountRead, nProcessedChains);
1165                                                                                 float postTime = m_fTotalCryptanalysisTime;
1166                                                                                 t2 = clock();
1167                                                                                 fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC;
1168                                                                                 printf("cryptanalysis time: %.2f s\n", fTime + postTime - preTime);
1169                                                                                 m_fTotalCryptanalysisTime += fTime;
1170                                                                                 nProcessedChains += nRainbowChainCountRead;
1171                                                                                 // Already finished?
1172                                                                                 if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
1173                                                                                         break;
1174                                                                         }
1175                                                                 }
1176                                                                 else printf("memory allocation failed for rainbow table\n");
1177
1178                                                                 //delete pChain;
1179                                                         }
1180                                                 }
1181                                                 else printf("memory allocation failed for index\n");
1182                                         }               
1183                                 }
1184                                 else 
1185                                 {
1186                                         printf("Can't load index\n");
1187                                         return;
1188                                 }
1189                                 fclose(fIndex);
1190                                 
1191                                 //delete pIndex;
1192                         }
1193                 }
1194                 fclose(file);
1195
1196                 if (debug) printf("Debug: writing progress to %s\n", sProgressPathName.c_str());
1197                 FILE* file = fopen(sProgressPathName.c_str(), "a");
1198                 if (file!=NULL)
1199                 {
1200                         string buffer = sPathName + "\n";
1201                         fputs (buffer.c_str(), file);
1202                         fclose (file);
1203                 }
1204         }
1205         else
1206                 printf("can't open file\n");
1207 }
1208
1209 void CCrackEngine::Run(vector<string> vPathName, CHashSet& hs, int i_maxThreads, bool resume, bool bDebug)
1210 {
1211 #ifndef _WIN32
1212         tty_init();
1213 #endif
1214         resumeSession = resume;
1215         debug = bDebug;
1216
1217         maxThreads = i_maxThreads;
1218         // Reset statistics
1219         ResetStatistics();
1220
1221         // Sort vPathName (CChainWalkSet need it)
1222         int i, j;
1223         for (i = 0; i < vPathName.size() - 1; i++)
1224                 for (j = 0; j < vPathName.size() - i - 1; j++)
1225                 {
1226                         if (vPathName[j] > vPathName[j + 1])
1227                         {
1228                                 string sTemp;
1229                                 sTemp = vPathName[j];
1230                                 vPathName[j] = vPathName[j + 1];
1231                                 vPathName[j + 1] = sTemp;
1232                         }
1233                 }
1234
1235         // Run
1236         for (i = 0; i < vPathName.size() && hs.AnyhashLeft(); i++)
1237         {
1238                 SearchRainbowTable(vPathName[i], hs);
1239                 printf("\n");
1240         }
1241
1242         // delete precalc files
1243         if (!keepPrecalcFiles)
1244                 m_cws.removePrecalcFiles();
1245
1246 #ifndef _WIN32
1247         tty_done();
1248 #endif
1249 }
1250
1251 void CCrackEngine::setOutputFile(string sPathName)
1252 {
1253         writeOutput = true;
1254         outputFile = sPathName;
1255 }
1256
1257 void CCrackEngine::setSession(string sSession, string sProgress, string sPrecalc, bool keepPrecalc)
1258 {
1259         sSessionPathName = sSession;
1260         sProgressPathName = sProgress;
1261         sPrecalcPathName = sPrecalc;
1262         keepPrecalcFiles = keepPrecalc;
1263 }
1264
1265 float CCrackEngine::GetStatTotalDiskAccessTime()
1266 {
1267         return m_fTotalDiskAccessTime;
1268 }
1269 /*float CCrackEngine::GetWastedTime()
1270 {
1271         return m_fIndexTime;
1272 }*/
1273 float CCrackEngine::GetStatTotalCryptanalysisTime()
1274 {
1275         return m_fTotalCryptanalysisTime;
1276 }
1277
1278 int CCrackEngine::GetStatTotalChainWalkStep()
1279 {
1280         return m_nTotalChainWalkStep;
1281 }
1282
1283 int CCrackEngine::GetStatTotalFalseAlarm()
1284 {
1285         return m_nTotalFalseAlarm;
1286 }
1287
1288 int CCrackEngine::GetStatTotalChainWalkStepDueToFalseAlarm()
1289 {
1290         return m_nTotalChainWalkStepDueToFalseAlarm;
1291 }