2 * rcracki_mt is a multithreaded implementation and fork of the original
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
11 * This file is part of rcracki_mt.
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.
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.
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/>.
27 #if defined(_WIN32) && !defined(__GNUC__)
28 #pragma warning(disable : 4786 4267 4018)
31 #include "CrackEngine.h"
32 #include "RTI2Reader.h"
35 #include <sys/resource.h>
38 CCrackEngine::CCrackEngine()
42 resumeSession = false;
44 keepPrecalcFiles = false;
46 sSessionPathName = "";
47 sProgressPathName = "";
50 CCrackEngine::~CCrackEngine()
54 //////////////////////////////////////////////////////////////////////
56 void CCrackEngine::ResetStatistics()
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;
67 int CCrackEngine::BinarySearchOld(RainbowChainO* pChain, int nRainbowChainCount, uint64 nIndex)
70 int nHigh = nRainbowChainCount - 1;
73 int nMid = (nLow + nHigh) / 2;
74 if (nIndex == pChain[nMid].nIndexE)
76 else if (nIndex < pChain[nMid].nIndexE)
85 RainbowChain *CCrackEngine::BinarySearch(RainbowChain *pChain, int nChainCountRead, uint64 nIndex, IndexChain *pIndex, int nIndexSize, int nIndexStart)
87 uint64 nPrefix = nIndex >> 16;
92 if(nPrefix > (pIndex[nIndexSize-1].nPrefix & 0x000000FFFFFFFFFFULL)) // check if its in the index file
98 int nBHigh = nIndexSize - 1;
99 while (nBLow <= nBHigh)
101 int nBMid = (nBLow + nBHigh) / 2;
102 if (nPrefix == (pIndex[nBMid].nPrefix & 0x000000FFFFFFFFFFULL))
107 nLow = pIndex[nBMid].nFirstChain;
108 nHigh = nLow + pIndex[nBMid].nChainCount;
109 if(nLow >= nIndexStart && nLow <= nIndexStart + nChainCountRead)
111 if(nHigh > nIndexStart + nChainCountRead)
112 nHigh = nIndexStart + nChainCountRead;
114 else if(nLow < nIndexStart && nHigh >= nIndexStart)
122 else if (nPrefix < (pIndex[nBMid].nPrefix & 0x000000FFFFFFFFFFULL))
129 for(int i = nLow - nIndexStart; i < nHigh - nIndexStart; i++)
131 int nSIndex = ((int)nIndex) & 0x0000FFFF;
133 if (nSIndex == pChain[i].nIndexE)
137 else if(pChain[i].nIndexE > nSIndex)
144 // not used currently, leaving code for future checkpoints
145 //bool CCrackEngine::CheckAlarm(RainbowChain* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs)
147 // CChainWalkContext cwc;
148 // //uint64 nIndexS = pChain->nIndexS >> 16;
149 // uint64 nIndexS = pChain->nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes
150 // cwc.SetIndex(nIndexS);
152 // for (nPos = 0; nPos < nGuessedPos; nPos++)
154 // cwc.IndexToPlain();
155 // cwc.PlainToHash();
156 // cwc.HashToIndex(nPos);
157 // // Not using checkpoints atm
162 // if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000080) >> 7)
164 // m_nTotalFalseAlarmSkipped += 10000 - 5000;
165 //// printf("CheckPoint caught false alarm at position 7600\n");
170 // if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000040) >> 6)
172 //// printf("CheckPoint caught false alarm at position 8200\n");
173 // m_nTotalFalseAlarmSkipped += 10000 - 6000;
179 // if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000020) >> 5)
181 //// printf("CheckPoint caught false alarm at position 8700\n");
182 // m_nTotalFalseAlarmSkipped += 10000 - 7600;
188 // if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000010) >> 4)
190 //// printf("CheckPoint caught false alarm at position 9000\n");
191 // m_nTotalFalseAlarmSkipped += 10000 - 8200;
197 // if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000008) >> 3)
199 //// printf("CheckPoint caught false alarm at position 9300\n");
200 // m_nTotalFalseAlarmSkipped += 10000 - 8700;
206 // if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000004) >> 2)
208 //// printf("CheckPoint caught false alarm at position 9600\n");
209 // m_nTotalFalseAlarmSkipped += 10000 - 9000;
215 // if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000002) >> 1)
217 //// printf("CheckPoint caught false alarm at position 9600\n");
218 // m_nTotalFalseAlarmSkipped += 10000 - 9300;
223 // if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000001))
225 //// printf("CheckPoint caught false alarm at position 9600\n");
226 // m_nTotalFalseAlarmSkipped += 10000 - 9600;
233 // cwc.IndexToPlain();
234 // cwc.PlainToHash();
235 // if (cwc.CheckHash(pHash))
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());
245 //bool CCrackEngine::CheckAlarmOld(RainbowChainO* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs)
247 // CChainWalkContext cwc;
248 // cwc.SetIndex(pChain->nIndexS);
250 // for (nPos = 0; nPos < nGuessedPos; nPos++)
252 // cwc.IndexToPlain();
253 // cwc.PlainToHash();
254 // cwc.HashToIndex(nPos);
256 // cwc.IndexToPlain();
257 // cwc.PlainToHash();
258 // if (cwc.CheckHash(pHash))
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());
268 void CCrackEngine::GetChainIndexRangeWithSameEndpoint(RainbowChainO* pChain,
269 int nRainbowChainCount,
271 int& nMatchingIndexEFrom,
272 int& nMatchingIndexETo)
274 nMatchingIndexEFrom = nMatchingIndexE;
275 nMatchingIndexETo = nMatchingIndexE;
276 while (nMatchingIndexEFrom > 0)
278 if (pChain[nMatchingIndexEFrom - 1].nIndexE == pChain[nMatchingIndexE].nIndexE)
279 nMatchingIndexEFrom--;
283 while (nMatchingIndexETo < nRainbowChainCount - 1)
285 if (pChain[nMatchingIndexETo + 1].nIndexE == pChain[nMatchingIndexE].nIndexE)
292 void CCrackEngine::SearchTableChunkOld(RainbowChainO* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs)
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" : "");
299 int nChainWalkStep = 0;
301 int nChainWalkStepDueToFalseAlarm = 0;
303 vector<rcrackiThread*> threadPool;
304 vector<pthread_t> pThreads;
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
313 setpriority( PRIO_PROCESS, 0, 2 );
317 pthread_attr_init(&attr);
318 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
322 * windows scheduling is 0 to 32 (low to high) with 8 as normal and 7 as
325 param.sched_priority = THREAD_PRIORITY_BELOW_NORMAL;
326 pthread_attr_setschedparam (&attr, ¶m);
329 bool pausing = false;
332 for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)
342 printf( "\nPausing, press P again to continue... ");
347 gettimeofday( &tv, NULL );
357 printf( " [Continuing]\n");
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;
370 printf( "\nPress 'P' to pause...\n");
374 int c = tty_getchar();
379 printf( "\nPausing, press 'p' again to continue... ");
384 gettimeofday( &tv, NULL );
388 if ((c = tty_getchar()) >= 0)
393 printf( " [Continuing]\n");
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;
405 printf( "\nPress 'p' to pause...\n");
409 unsigned char TargetHash[MAX_HASH_LEN];
411 ParseHash(vHash[nHashIndex], TargetHash, nHashLen);
412 if (nHashLen != CChainWalkContext::GetHashLen())
413 printf("debug: nHashLen mismatch\n");
416 bool fNewlyGenerated;
417 uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,
419 CChainWalkContext::GetHashRoutineName(),
420 CChainWalkContext::GetPlainCharsetName(),
421 CChainWalkContext::GetPlainLenMin(),
422 CChainWalkContext::GetPlainLenMax(),
423 CChainWalkContext::GetRainbowTableIndex(),
428 //printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",
429 // vHash[nHashIndex].c_str());
438 gettimeofday( &tv, NULL );
440 printf("Pre-calculating hash %lu of %lu.%-20s\r",
441 (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");
446 for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
448 rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);
452 int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
454 if( returnValue != 0 )
456 printf("pThread creation failed, returnValue: %d\n", returnValue);
460 pThreads.push_back(pThread);
463 threadPool.push_back(r_Thread);
467 printf("r_Thread creation failed!\n");
471 //printf("%d r_Threads created\t\t\n", threadPool.size());
473 for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
475 pthread_t pThread = pThreads[thread_ID];
476 int returnValue = pthread_join(pThread, NULL);
477 if( returnValue != 0 )
479 printf("pThread join failed, returnValue: %d\n", returnValue);
482 rcrackiThread* rThread = threadPool[thread_ID];
483 nChainWalkStep += rThread->GetChainWalkStep();
486 gettimeofday( &tv2, NULL );
487 final = sub_timeofday( tv2, tv );
489 float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
491 m_fTotalPrecalculationTime += fTime;
492 m_fTotalCryptanalysisTime -= fTime;
494 printf("%-50s\r", "");
497 printf("pre-calculation time: %.2f s\n", fTime);
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(), "");
508 for (i = 0; i < maxThreads; i++)
510 rcrackiThread* r_Thread = new rcrackiThread(TargetHash, true);
511 threadPool.push_back(r_Thread);
516 for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)
518 uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];
520 // Search matching nIndexE
521 int nMatchingIndexE = BinarySearchOld(pChain, nRainbowChainCount, nIndexEOfCurPos);
522 if (nMatchingIndexE != -1)
524 int nMatchingIndexEFrom, nMatchingIndexETo;
525 GetChainIndexRangeWithSameEndpoint(pChain, nRainbowChainCount,
527 nMatchingIndexEFrom, nMatchingIndexETo);
529 for (i = nMatchingIndexEFrom; i <= nMatchingIndexETo; i++)
531 rcrackiThread* rThread = threadPool[thread_ID];
532 rThread->AddAlarmCheckO(pChain + i, nPos);
533 if (thread_ID < (unsigned long)maxThreads - 1 ) {
542 for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
544 rcrackiThread* r_Thread = threadPool[thread_ID];
547 int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
549 if( returnValue != 0 )
551 printf("pThread creation failed, returnValue: %d\n", returnValue);
555 pThreads.push_back(pThread);
559 //printf("%d r_Threads created\t\t\n", threadPool.size());
561 bool foundHashInThread = false;
562 for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
564 rcrackiThread* rThread = threadPool[thread_ID];
565 pthread_t pThread = pThreads[thread_ID];
567 int returnValue = pthread_join(pThread, NULL);
568 if( returnValue != 0 )
570 printf("pThread join failed, returnValue: %d\n", returnValue);
573 nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();
574 nFalseAlarm += rThread->GetnFalseAlarm();
576 if (rThread->FoundHash() && !foundHashInThread) {
577 //printf("\t\t\t\t\t\t\r");
578 printf("%-50s\r", "");
580 printf("plaintext of %s is %s\n", rThread->GetHash().c_str(), rThread->GetPlain().c_str());
583 if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))
584 printf("Couldn't write this result to file!\n");
586 hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());
588 FILE* file = fopen(sSessionPathName.c_str(), "a");
591 string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";
592 fputs (buffer.c_str(), file);
596 m_cws.DiscardWalk(pStartPosIndexE);
597 foundHashInThread = true;
605 //printf("\t\t\t\t\t\t\t\r");
606 printf("%-50s\r", "");
609 pthread_attr_destroy(&attr);
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);
615 m_nTotalChainWalkStep += nChainWalkStep;
616 m_nTotalFalseAlarm += nFalseAlarm;
617 m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;
620 void CCrackEngine::SearchTableChunk(RainbowChain* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs, IndexChain *pIndex, int nIndexSize, int nChainStart)
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" : "");
629 int nChainWalkStep = 0;
631 int nChainWalkStepDueToFalseAlarm = 0;
633 vector<rcrackiThread*> threadPool;
634 vector<pthread_t> pThreads;
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
643 setpriority( PRIO_PROCESS, 0, 2 );
647 pthread_attr_init(&attr);
648 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
651 param.sched_priority = THREAD_PRIORITY_BELOW_NORMAL;
652 pthread_attr_setschedparam (&attr, ¶m);
654 // else set it to 5 or something (for linux)?
656 bool pausing = false;
659 for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)
669 printf( "\nPausing, press P again to continue... ");
674 gettimeofday( &tv, NULL );
684 printf( " [Continuing]\n");
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;
697 printf( "\nPress 'P' to pause...\n");
701 int c = tty_getchar();
706 printf( "\nPausing, press 'p' again to continue... ");
711 gettimeofday( &tv, NULL );
715 if ((c = tty_getchar()) >= 0)
720 printf( " [Continuing]\n");
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;
732 printf( "\nPress 'p' to pause...\n");
736 unsigned char TargetHash[MAX_HASH_LEN];
738 ParseHash(vHash[nHashIndex], TargetHash, nHashLen);
739 if (nHashLen != CChainWalkContext::GetHashLen())
740 printf("debug: nHashLen mismatch\n");
743 bool fNewlyGenerated;
744 // printf("Requesting walk...");
747 uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,
749 CChainWalkContext::GetHashRoutineName(),
750 CChainWalkContext::GetPlainCharsetName(),
751 CChainWalkContext::GetPlainLenMin(),
752 CChainWalkContext::GetPlainLenMax(),
753 CChainWalkContext::GetRainbowTableIndex(),
758 // printf("done!\n");
759 // printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",
760 // vHash[nHashIndex].c_str());
768 gettimeofday( &tv, NULL );
770 printf("Pre-calculating hash %lu of %lu.%-20s\r",
771 (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");
776 for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
778 rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);
782 int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
784 if( returnValue != 0 )
786 printf("pThread creation failed, returnValue: %d\n", returnValue);
790 pThreads.push_back(pThread);
793 threadPool.push_back(r_Thread);
797 printf("r_Thread creation failed!\n");
801 //printf("%d r_Threads created\t\t\n", threadPool.size());
803 for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
805 pthread_t pThread = pThreads[thread_ID];
806 int returnValue = pthread_join(pThread, NULL);
807 if( returnValue != 0 )
809 printf("pThread join failed, returnValue: %d\n", returnValue);
812 rcrackiThread* rThread = threadPool[thread_ID];
813 nChainWalkStep += rThread->GetChainWalkStep();
817 m_cws.StoreToFile(pStartPosIndexE, TargetHash, nHashLen);
818 gettimeofday( &tv2, NULL );
819 final = sub_timeofday( tv2, tv );
821 float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
823 m_fTotalPrecalculationTime += fTime;
824 m_fTotalCryptanalysisTime -= fTime;
826 //printf("\npStartPosIndexE[0]: %s\n", uint64tostr(pStartPosIndexE[0]).c_str());
827 //printf("\npStartPosIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pStartPosIndexE[nRainbowChainLen-2]).c_str());
829 printf("%-50s\r", "");
832 printf("pre-calculation time: %.2f s\n", fTime);
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(), "");
843 for (i = 0; i < maxThreads; i++)
845 rcrackiThread* r_Thread = new rcrackiThread(TargetHash);
846 threadPool.push_back(r_Thread);
851 for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)
853 uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];
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!)
859 rcrackiThread* rThread = threadPool[thread_ID];
860 rThread->AddAlarmCheck(pChainFound, nPos);
861 if (thread_ID < (unsigned long)maxThreads - 1 ) {
869 for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
871 rcrackiThread* r_Thread = threadPool[thread_ID];
874 int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
876 if( returnValue != 0 )
878 printf("pThread creation failed, returnValue: %d\n", returnValue);
882 pThreads.push_back(pThread);
886 //printf("%d r_Threads created\t\t\n", threadPool.size());
888 bool foundHashInThread = false;
889 for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
891 rcrackiThread* rThread = threadPool[thread_ID];
892 pthread_t pThread = pThreads[thread_ID];
894 int returnValue = pthread_join(pThread, NULL);
895 if( returnValue != 0 )
897 printf("pThread join failed, returnValue: %d\n", returnValue);
900 nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();
901 nFalseAlarm += rThread->GetnFalseAlarm();
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());
909 if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))
910 printf("Couldn't write this result to file!\n");
912 hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());
914 FILE* file = fopen(sSessionPathName.c_str(), "a");
917 string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";
918 fputs (buffer.c_str(), file);
922 m_cws.DiscardWalk(pStartPosIndexE);
923 foundHashInThread = true;
932 //printf("\t\t\t\t\r");
933 //printf("pChainFounds: %d\n", pChainsFound.size());
936 //printf("\t\t\t\t\t\t\t\r");
937 printf("%-50s\r", "");
940 pthread_attr_destroy(&attr);
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);
946 m_nTotalChainWalkStep += nChainWalkStep;
947 m_nTotalFalseAlarm += nFalseAlarm;
948 m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;
951 void CCrackEngine::SearchRainbowTable(string sPathName, CHashSet& hs)
953 // Did we already go through this file in this session?
956 vector<string> sessionFinishedPathNames;
957 if (ReadLinesFromFile(sProgressPathName.c_str(), sessionFinishedPathNames))
960 for (i = 0; i < sessionFinishedPathNames.size(); i++)
962 if (sessionFinishedPathNames[i] == sPathName)
964 printf("Skipping %s\n", sPathName.c_str());
973 string::size_type nIndex = sPathName.find_last_of('\\');
975 string::size_type nIndex = sPathName.find_last_of('/');
978 if (nIndex != string::npos)
979 sFileName = sPathName.substr(nIndex + 1);
981 sFileName = sPathName;
984 printf("%s:\n", sFileName.c_str());
987 int nRainbowChainLen, nRainbowChainCount;
988 if (!CChainWalkContext::SetupWithPathName(sPathName, nRainbowChainLen, nRainbowChainCount))
990 //printf("keyspace: %llu\n", CChainWalkContext::GetPlainSpaceTotal());
992 if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
994 printf("this table contains hashes with length %d only\n", CChainWalkContext::GetHashLen());
999 FILE* file = fopen(sPathName.c_str(), "rb");
1002 // File length check
1003 bool doOldFormat = CChainWalkContext::isOldFormat();
1004 bool doRti2Format = CChainWalkContext::isRti2Format();
1006 bool fVerified = false;
1007 UINT4 nFileLen = GetFileLen(file);
1014 //if (nFileLen % 8 != 0 || nRainbowChainCount * 8 != nFileLen)
1015 if ( (nFileLen % sizeOfChain != 0 || nRainbowChainCount * sizeOfChain != nFileLen) && doRti2Format == false )
1016 printf("file length mismatch\n");
1019 fseek(file, 0, SEEK_SET);
1024 unsigned int bytesForChainWalkSet = hs.GetStatHashTotal() * (nRainbowChainLen-1) * 8;
1025 if (debug) printf("Debug: Saving %u bytes of memory for chainwalkset.\n", bytesForChainWalkSet);
1027 uint64 nAllocatedSize;
1029 if (doRti2Format || doOldFormat)
1031 RTI2Reader *pReader = NULL;
1034 pReader = new RTI2Reader(sPathName);
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");
1046 static CMemoryPool mp(bytesForChainWalkSet, debug, maxMem);
1047 RainbowChainO* pChain = (RainbowChainO*)mp.Allocate(nFileLen, nAllocatedSize);
1049 if (debug) printf("Allocated %I64u bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);
1051 if (debug) printf("Allocated %llu bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);
1056 nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain; // Round to sizeOfChain boundary
1058 //fseek(file, 0, SEEK_SET);
1059 //bool fVerified = false;
1060 while (true) // Chunk read loop
1062 if ((unsigned long)ftell(file) == nFileLen)
1066 if (debug) printf("reading...\n");
1067 unsigned int nDataRead = 0, nDataToRead = 0;
1068 gettimeofday( &tv, NULL );
1071 nDataToRead = nAllocatedSize / 16;
1072 nDataRead = nDataToRead;
1073 pReader->ReadChains(nDataRead, pChain);
1074 nDataRead *= 8; // Convert from chains read to bytes
1078 nDataRead = fread(pChain, 1, nAllocatedSize, file);
1080 gettimeofday( &tv2, NULL );
1081 final = sub_timeofday( tv2, tv );
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;
1087 int nRainbowChainCountRead = nDataRead / 16;
1089 // Verify table chunk
1092 printf("verifying the file...\n");
1094 // Chain length test
1095 int nIndexToVerify = nRainbowChainCountRead / 2;
1096 CChainWalkContext cwc;
1097 cwc.SetIndex(pChain[nIndexToVerify].nIndexS);
1099 for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
1103 cwc.HashToIndex(nPos);
1105 if (cwc.GetIndex() != pChain[nIndexToVerify].nIndexE)
1107 printf("rainbow chain length verify fail\n");
1113 for (i = 0; i < nRainbowChainCountRead - 1; i++)
1115 if (pChain[i].nIndexE > pChain[i + 1].nIndexE)
1118 if (i != nRainbowChainCountRead - 1)
1120 printf("this file is not sorted\n");
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;
1136 // Already finished?
1137 if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
1140 // finished the current table
1141 if( doRti2Format && nDataToRead > (nDataRead / 8) )
1149 printf("memory allocation fail\n");
1155 static CMemoryPool mpIndex(bytesForChainWalkSet, debug, maxMem);
1156 uint64 nAllocatedSizeIndex;
1158 //int nIndexSize = 0;
1159 //IndexChain *pIndex = NULL;
1161 FILE* fIndex = fopen(((string)(sPathName + string(".index"))).c_str(), "rb");
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);
1173 //printf("index nSize: %d\n", nSize);
1174 //pIndex = (IndexChain*)new unsigned char[nSize];
1175 IndexChain *pIndex = (IndexChain*)mpIndex.Allocate(nFileLenIndex, nAllocatedSizeIndex);
1177 if (debug) printf("Debug: Allocated %I64u bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
1179 if (debug) printf("Debug: Allocated %llu bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
1182 static CMemoryPool mp(bytesForChainWalkSet + nAllocatedSizeIndex, debug, maxMem);
1184 if (pIndex != NULL && nAllocatedSizeIndex > 0)
1186 nAllocatedSizeIndex = nAllocatedSizeIndex / sizeof(IndexChain) * sizeof(IndexChain); // Round to sizeOfIndexChain boundary
1188 fseek(fIndex, 0, SEEK_SET);
1190 while ( (unsigned long)ftell(fIndex) != nFileLenIndex ) // Index chunk read loop
1194 if (debug) printf("Debug: Setting index to 0x00 in memory, %I64u bytes\n", nAllocatedSizeIndex);
1196 if (debug) printf("Debug: Setting index to 0x00 in memory, %llu bytes\n", nAllocatedSizeIndex);
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 );
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;
1209 //nIndexSize = nFileLenIndex / 11;
1210 int nIndexChainCountRead = nDataRead / sizeof(IndexChain);
1212 unsigned int nCoveredRainbowTableChains = 0;
1213 for(int i = 0; i < nIndexChainCountRead; i++)
1215 nCoveredRainbowTableChains += pIndex[i].nChainCount;
1218 //RainbowChain* pChain = (RainbowChain*)mp.Allocate(nFileLen, nAllocatedSize);
1219 RainbowChain* pChain = (RainbowChain*)mp.Allocate(nCoveredRainbowTableChains * sizeOfChain, nAllocatedSize);
1221 if (debug) printf("Debug: Allocated %I64u bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);
1223 if (debug) printf("Debug: Allocated %llu bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);
1226 if (pChain != NULL && nAllocatedSize > 0)
1228 nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain; // Round to sizeOfChain boundary
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
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 );
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)
1253 printf("verifying the file... ");
1255 // Chain length test
1256 int nIndexToVerify = nRainbowChainCountRead / 2;
1257 CChainWalkContext cwc;
1259 nIndexS = pChain[nIndexToVerify].nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes
1261 //printf("nIndexS: %s\n", uint64tostr(nIndexS).c_str());
1262 cwc.SetIndex(nIndexS);
1265 for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
1269 cwc.HashToIndex(nPos);
1272 uint64 nEndPoint = 0;
1274 //for(int i = 0; i < nIndexSize; i++)
1275 for(int i = 0; i < nIndexChainCountRead; i++)
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;
1288 if (cwc.GetIndex() != nEndPoint)
1290 printf("rainbow chain length verify fail\n");
1298 // Search table chunk
1299 gettimeofday( &tv, NULL );
1300 float preTime = m_fTotalCryptanalysisTime;
1302 SearchTableChunk(pChain, nRainbowChainLen, nRainbowChainCountRead, hs, pIndex, nIndexChainCountRead, nProcessedChains);
1303 float postTime = m_fTotalCryptanalysisTime;
1304 gettimeofday( &tv2, NULL );
1305 final = sub_timeofday( tv2, tv );
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()))
1316 else printf("memory allocation failed for rainbow table\n");
1321 else printf("memory allocation failed for index\n");
1326 printf("Can't load index\n");
1336 if (debug) printf("Debug: writing progress to %s\n", sProgressPathName.c_str());
1337 FILE* file = fopen(sProgressPathName.c_str(), "a");
1340 string buffer = sPathName + "\n";
1341 fputs (buffer.c_str(), file);
1346 printf("can't open file\n");
1349 void CCrackEngine::Run(vector<string> vPathName, CHashSet& hs, int i_maxThreads, uint64 i_maxMem, bool resume, bool bDebug)
1354 resumeSession = resume;
1357 maxThreads = i_maxThreads;
1362 // Sort vPathName (CChainWalkSet need it)
1364 for (i = 0; i < vPathName.size() - 1; i++)
1365 for (j = 0; j < vPathName.size() - i - 1; j++)
1367 if (vPathName[j] > vPathName[j + 1])
1370 sTemp = vPathName[j];
1371 vPathName[j] = vPathName[j + 1];
1372 vPathName[j + 1] = sTemp;
1377 for (i = 0; i < vPathName.size() && hs.AnyhashLeft(); i++)
1379 SearchRainbowTable(vPathName[i], hs);
1383 // delete precalc files
1384 if (!keepPrecalcFiles)
1385 m_cws.removePrecalcFiles();
1392 void CCrackEngine::setOutputFile(string sPathName)
1395 outputFile = sPathName;
1398 void CCrackEngine::setSession(string sSession, string sProgress, string sPrecalc, bool keepPrecalc)
1400 sSessionPathName = sSession;
1401 sProgressPathName = sProgress;
1402 sPrecalcPathName = sPrecalc;
1403 keepPrecalcFiles = keepPrecalc;
1406 float CCrackEngine::GetStatTotalDiskAccessTime()
1408 return m_fTotalDiskAccessTime;
1410 /*float CCrackEngine::GetWastedTime()
1412 return m_fIndexTime;
1414 float CCrackEngine::GetStatTotalCryptanalysisTime()
1416 return m_fTotalCryptanalysisTime;
1419 float CCrackEngine::GetStatTotalPrecalculationTime()
1421 return m_fTotalPrecalculationTime;
1424 int CCrackEngine::GetStatTotalChainWalkStep()
1426 return m_nTotalChainWalkStep;
1429 int CCrackEngine::GetStatTotalFalseAlarm()
1431 return m_nTotalFalseAlarm;
1434 int CCrackEngine::GetStatTotalChainWalkStepDueToFalseAlarm()
1436 return m_nTotalChainWalkStepDueToFalseAlarm;