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