]> git.sesse.net Git - freerainbowtables/blob - Client Applications/rcracki_mt/CrackEngine.cpp
test
[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 = (RainbowChainO*)mp.Allocate(nFileLen, nAllocatedSize);
1048                                 #ifdef _WIN32
1049                                         if (debug) printf("Allocated %I64u bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);
1050                                 #else
1051                                         if (debug) printf("Allocated %llu bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);
1052                                 #endif
1053
1054                                 if (pChain != NULL)
1055                                 {
1056                                         nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain;            // Round to sizeOfChain boundary
1057
1058                                         //fseek(file, 0, SEEK_SET);
1059                                         //bool fVerified = false;
1060                                         while (true)    // Chunk read loop
1061                                         {
1062                                                 if ((unsigned long)ftell(file) == nFileLen)
1063                                                         break;
1064
1065                                                 // Load table chunk
1066                                                 if (debug) printf("reading...\n");
1067                                                 unsigned int nDataRead = 0, nDataToRead = 0;
1068                                                 gettimeofday( &tv, NULL );
1069                                                 if ( doRti2Format )
1070                                                 {
1071                                                         nDataToRead = nAllocatedSize / 16;
1072                                                         nDataRead = nDataToRead;
1073                                                         pReader->ReadChains(nDataRead, pChain);
1074                                                         nDataRead *= 8; // Convert from chains read to bytes
1075                                                 }
1076                                                 else
1077                                                 {
1078                                                         nDataRead = fread(pChain, 1, nAllocatedSize, file);
1079                                                 }
1080                                                 gettimeofday( &tv2, NULL );
1081                                                 final = sub_timeofday( tv2, tv );
1082
1083                                                 float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
1084                                                 printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
1085                                                 m_fTotalDiskAccessTime += fTime;
1086
1087                                                 int nRainbowChainCountRead = nDataRead / 16;
1088
1089                                                 // Verify table chunk
1090                                                 if (!fVerified)
1091                                                 {
1092                                                         printf("verifying the file...\n");
1093
1094                                                         // Chain length test
1095                                                         int nIndexToVerify = nRainbowChainCountRead / 2;
1096                                                         CChainWalkContext cwc;
1097                                                         cwc.SetIndex(pChain[nIndexToVerify].nIndexS);
1098                                                         int nPos;
1099                                                         for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
1100                                                         {
1101                                                                 cwc.IndexToPlain();
1102                                                                 cwc.PlainToHash();
1103                                                                 cwc.HashToIndex(nPos);
1104                                                         }
1105                                                         if (cwc.GetIndex() != pChain[nIndexToVerify].nIndexE)
1106                                                         {
1107                                                                 printf("rainbow chain length verify fail\n");
1108                                                                 break;
1109                                                         }
1110
1111                                                         // Chain sort test
1112                                                         int i;
1113                                                         for (i = 0; i < nRainbowChainCountRead - 1; i++)
1114                                                         {
1115                                                                 if (pChain[i].nIndexE > pChain[i + 1].nIndexE)
1116                                                                         break;
1117                                                         }
1118                                                         if (i != nRainbowChainCountRead - 1)
1119                                                         {
1120                                                                 printf("this file is not sorted\n");
1121                                                                 break;
1122                                                         }
1123
1124                                                         fVerified = true;
1125                                                 }
1126
1127                                                 // Search table chunk
1128                                                 gettimeofday( &tv, NULL );
1129                                                 SearchTableChunkOld(pChain, nRainbowChainLen, nRainbowChainCountRead, hs);
1130                                                 gettimeofday( &tv2, NULL );
1131                                                 final = sub_timeofday( tv2, tv );
1132                                                 fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
1133                                                 printf("cryptanalysis time: %.2f s\n", fTime);
1134                                                 m_fTotalCryptanalysisTime += fTime;
1135
1136                                                 // Already finished?
1137                                                 if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
1138                                                         break;
1139
1140                                                 // finished the current table
1141                                                 if( doRti2Format && nDataToRead > (nDataRead / 8) )
1142                                                 {
1143                                                         delete pReader;
1144                                                         break;
1145                                                 }
1146                                         }
1147                                 }
1148                                 else
1149                                         printf("memory allocation fail\n");
1150                                 
1151                                 //delete pChain;
1152                         }
1153                         else
1154                         {
1155                                 static CMemoryPool mpIndex(bytesForChainWalkSet, debug, maxMem);
1156                                 uint64 nAllocatedSizeIndex;
1157
1158                                 //int nIndexSize = 0;
1159                                 //IndexChain *pIndex = NULL;
1160
1161                                 FILE* fIndex = fopen(((string)(sPathName + string(".index"))).c_str(), "rb");
1162                                 if(fIndex != NULL)
1163                                 {
1164                                         // File length check
1165                                         unsigned int nFileLenIndex = GetFileLen(fIndex);
1166                                         //unsigned int nRows = nFileLenIndex / 11;
1167                                         //unsigned int nSize = nRows * sizeof(IndexChain);
1168                                         //printf("Debug: 8\n");
1169                                         if (nFileLenIndex % 11 != 0)
1170                                                 printf("index file length mismatch (%u bytes)\n", nFileLenIndex);
1171                                         else
1172                                         {
1173                                                 //printf("index nSize: %d\n", nSize);
1174                                                 //pIndex = (IndexChain*)new unsigned char[nSize];
1175                                                 IndexChain *pIndex = (IndexChain*)mpIndex.Allocate(nFileLenIndex, nAllocatedSizeIndex);
1176                                                 #ifdef _WIN32
1177                                                         if (debug) printf("Debug: Allocated %I64u bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
1178                                                 #else
1179                                                         if (debug) printf("Debug: Allocated %llu bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
1180                                                 #endif
1181                                 
1182                                                 static CMemoryPool mp(bytesForChainWalkSet + nAllocatedSizeIndex, debug, maxMem);
1183                                                 
1184                                                 if (pIndex != NULL && nAllocatedSizeIndex > 0)
1185                                                 {
1186                                                         nAllocatedSizeIndex = nAllocatedSizeIndex / sizeof(IndexChain) * sizeof(IndexChain);            // Round to sizeOfIndexChain boundary
1187                                                 
1188                                                         fseek(fIndex, 0, SEEK_SET);
1189
1190                                                         while ( (unsigned long)ftell(fIndex) != nFileLenIndex ) // Index chunk read loop
1191                                                         {
1192                                                                 // Load index chunk
1193 #ifdef _WIN32
1194                                                                 if (debug) printf("Debug: Setting index to 0x00 in memory, %I64u bytes\n", nAllocatedSizeIndex);
1195 #else
1196                                                                 if (debug) printf("Debug: Setting index to 0x00 in memory, %llu bytes\n", nAllocatedSizeIndex);
1197 #endif
1198                                                                 memset(pIndex, 0x00, nAllocatedSizeIndex);
1199                                                                 printf("reading index... ");
1200                                                                 gettimeofday( &tv, NULL );
1201                                                                 unsigned int nDataRead = fread(pIndex, 1, nAllocatedSizeIndex, fIndex);
1202                                                                 gettimeofday( &tv2, NULL );
1203                                                                 final = sub_timeofday( tv2, tv );
1204
1205                                                                 float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
1206                                                                 printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
1207                                                                 m_fTotalDiskAccessTime += fTime;
1208                                                         
1209                                                                 //nIndexSize = nFileLenIndex / 11;
1210                                                                 int nIndexChainCountRead = nDataRead / sizeof(IndexChain);
1211                                                                 //fclose(fIndex);
1212                                                                 unsigned int nCoveredRainbowTableChains = 0;
1213                                                                 for(int i = 0; i < nIndexChainCountRead; i++)
1214                                                                 {
1215                                                                         nCoveredRainbowTableChains += pIndex[i].nChainCount;
1216                                                                 }
1217
1218                                                                 //RainbowChain* pChain = (RainbowChain*)mp.Allocate(nFileLen, nAllocatedSize);
1219                                                                 RainbowChain* pChain = (RainbowChain*)mp.Allocate(nCoveredRainbowTableChains * sizeOfChain, nAllocatedSize);
1220                                                                 #ifdef _WIN32
1221                                                                         if (debug) printf("Debug: Allocated %I64u bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);
1222                                                                 #else
1223                                                                         if (debug) printf("Debug: Allocated %llu bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);
1224                                                                 #endif
1225
1226                                                                 if (pChain != NULL && nAllocatedSize > 0)
1227                                                                 {
1228                                                                         nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain;            // Round to sizeOfChain boundary
1229
1230                                                                         //fseek(file, 0, SEEK_SET);
1231                                                                         //bool fVerified = false;
1232                                                                         UINT4 nProcessedChains = 0;
1233                                                                         while ( (unsigned long)ftell(file) != nFileLen 
1234                                                                                 && nProcessedChains < nCoveredRainbowTableChains )      // Chunk read loop
1235                                                                         {
1236                                                                                 // Load table chunk
1237                                                                                 if (debug) printf("Debug: Setting pChain to 0x00 in memory\n");
1238                                                                                 memset(pChain, 0x00, nAllocatedSize);
1239                                                                                 printf("reading table... ");
1240                                                                                 gettimeofday( &tv, NULL );
1241                                                                                 unsigned int nDataRead = fread(pChain, 1, nAllocatedSize, file);
1242                                                                                 gettimeofday( &tv2, NULL );
1243                                                                                 final = sub_timeofday( tv2, tv );
1244
1245                                                                                 float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
1246                                                                                 printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
1247                                                                                 m_fTotalDiskAccessTime += fTime;
1248                                                                                 int nRainbowChainCountRead = nDataRead / sizeOfChain;
1249                                                                                 // Verify table chunk (Too lazy to implement this)
1250                                                                                 
1251                                                                                 if (!fVerified)
1252                                                                                 {
1253                                                                                         printf("verifying the file... ");
1254
1255                                                                                         // Chain length test
1256                                                                                         int nIndexToVerify = nRainbowChainCountRead / 2;
1257                                                                                         CChainWalkContext cwc;
1258                                                                                         uint64 nIndexS;
1259                                                                                         nIndexS = pChain[nIndexToVerify].nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes
1260
1261                                                                                         //printf("nIndexS: %s\n", uint64tostr(nIndexS).c_str());
1262                                                                                         cwc.SetIndex(nIndexS);
1263                                                                                         
1264                                                                                         int nPos;
1265                                                                                         for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
1266                                                                                         {
1267                                                                                                 cwc.IndexToPlain();
1268                                                                                                 cwc.PlainToHash();
1269                                                                                                 cwc.HashToIndex(nPos);
1270                                                                                         }
1271
1272                                                                                         uint64 nEndPoint = 0;
1273
1274                                                                                         //for(int i = 0; i < nIndexSize; i++)
1275                                                                                         for(int i = 0; i < nIndexChainCountRead; i++)
1276                                                                                         {
1277                                                                                                 if(nIndexToVerify >= pIndex[i].nFirstChain && nIndexToVerify < pIndex[i].nFirstChain + pIndex[i].nChainCount) // We found the matching index
1278                                                                                                 { // Now we need to seek nIndexToVerify into the chains
1279                                                                                                         nEndPoint += (pIndex[i].nPrefix & 0x000000FFFFFFFFFFULL) << 16; // & 0x000000FFFFFFFFFFULL for first 5 bytes
1280                                                                                                         //printf("nPrefix: %s\n", uint64tostr(pIndex[i].nPrefix & 0x000000FFFFFFFFFF).c_str());
1281                                                                                                         //printf("nFirstChain: %d\n", pIndex[i].nFirstChain);
1282                                                                                                         //printf("nChainCount: %d\n", pIndex[i].nChainCount);
1283                                                                                                         nEndPoint += pChain[nIndexToVerify].nIndexE;
1284                                                                                                         break;
1285                                                                                                 }
1286                                                                                         }
1287
1288                                                                                         if (cwc.GetIndex() != nEndPoint)
1289                                                                                         {
1290                                                                                                 printf("rainbow chain length verify fail\n");
1291                                                                                                 break;
1292                                                                                         }
1293
1294                                                                                         fVerified = true;
1295                                                                                         printf("ok\n");
1296                                                                                 }
1297
1298                                                                                 // Search table chunk
1299                                                                                 gettimeofday( &tv, NULL );
1300                                                                                 float preTime = m_fTotalCryptanalysisTime;
1301
1302                                                                                 SearchTableChunk(pChain, nRainbowChainLen, nRainbowChainCountRead, hs, pIndex, nIndexChainCountRead, nProcessedChains);
1303                                                                                 float postTime = m_fTotalCryptanalysisTime;
1304                                                                                 gettimeofday( &tv2, NULL );
1305                                                                                 final = sub_timeofday( tv2, tv );
1306
1307                                                                                 fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
1308                                                                                 printf("cryptanalysis time: %.2f s\n", fTime + postTime - preTime);
1309                                                                                 m_fTotalCryptanalysisTime += fTime;
1310                                                                                 nProcessedChains += nRainbowChainCountRead;
1311                                                                                 // Already finished?
1312                                                                                 if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
1313                                                                                         break;
1314                                                                         }
1315                                                                 }
1316                                                                 else printf("memory allocation failed for rainbow table\n");
1317
1318                                                                 //delete pChain;
1319                                                         }
1320                                                 }
1321                                                 else printf("memory allocation failed for index\n");
1322                                         }               
1323                                 }
1324                                 else 
1325                                 {
1326                                         printf("Can't load index\n");
1327                                         return;
1328                                 }
1329                                 fclose(fIndex);
1330                                 
1331                                 //delete pIndex;
1332                         }
1333                 }
1334                 fclose(file);
1335
1336                 if (debug) printf("Debug: writing progress to %s\n", sProgressPathName.c_str());
1337                 FILE* file = fopen(sProgressPathName.c_str(), "a");
1338                 if (file!=NULL)
1339                 {
1340                         string buffer = sPathName + "\n";
1341                         fputs (buffer.c_str(), file);
1342                         fclose (file);
1343                 }
1344         }
1345         else
1346                 printf("can't open file\n");
1347 }
1348
1349 void CCrackEngine::Run(vector<string> vPathName, CHashSet& hs, int i_maxThreads, uint64 i_maxMem, bool resume, bool bDebug)
1350 {
1351 #ifndef _WIN32
1352         tty_init();
1353 #endif
1354         resumeSession = resume;
1355         debug = bDebug;
1356
1357         maxThreads = i_maxThreads;
1358         maxMem = i_maxMem;
1359         // Reset statistics
1360         ResetStatistics();
1361
1362         // Sort vPathName (CChainWalkSet need it)
1363         UINT4 i, j;
1364         for (i = 0; i < vPathName.size() - 1; i++)
1365                 for (j = 0; j < vPathName.size() - i - 1; j++)
1366                 {
1367                         if (vPathName[j] > vPathName[j + 1])
1368                         {
1369                                 string sTemp;
1370                                 sTemp = vPathName[j];
1371                                 vPathName[j] = vPathName[j + 1];
1372                                 vPathName[j + 1] = sTemp;
1373                         }
1374                 }
1375
1376         // Run
1377         for (i = 0; i < vPathName.size() && hs.AnyhashLeft(); i++)
1378         {
1379                 SearchRainbowTable(vPathName[i], hs);
1380                 printf("\n");
1381         }
1382
1383         // delete precalc files
1384         if (!keepPrecalcFiles)
1385                 m_cws.removePrecalcFiles();
1386
1387 #ifndef _WIN32
1388         tty_done();
1389 #endif
1390 }
1391
1392 void CCrackEngine::setOutputFile(string sPathName)
1393 {
1394         writeOutput = true;
1395         outputFile = sPathName;
1396 }
1397
1398 void CCrackEngine::setSession(string sSession, string sProgress, string sPrecalc, bool keepPrecalc)
1399 {
1400         sSessionPathName = sSession;
1401         sProgressPathName = sProgress;
1402         sPrecalcPathName = sPrecalc;
1403         keepPrecalcFiles = keepPrecalc;
1404 }
1405
1406 float CCrackEngine::GetStatTotalDiskAccessTime()
1407 {
1408         return m_fTotalDiskAccessTime;
1409 }
1410 /*float CCrackEngine::GetWastedTime()
1411 {
1412         return m_fIndexTime;
1413 }*/
1414 float CCrackEngine::GetStatTotalCryptanalysisTime()
1415 {
1416         return m_fTotalCryptanalysisTime;
1417 }
1418
1419 float CCrackEngine::GetStatTotalPrecalculationTime()
1420 {
1421         return m_fTotalPrecalculationTime;
1422 }
1423
1424 int CCrackEngine::GetStatTotalChainWalkStep()
1425 {
1426         return m_nTotalChainWalkStep;
1427 }
1428
1429 int CCrackEngine::GetStatTotalFalseAlarm()
1430 {
1431         return m_nTotalFalseAlarm;
1432 }
1433
1434 int CCrackEngine::GetStatTotalChainWalkStepDueToFalseAlarm()
1435 {
1436         return m_nTotalChainWalkStepDueToFalseAlarm;
1437 }