]> git.sesse.net Git - freerainbowtables/blobdiff - Client Applications/rcracki_mt/CrackEngine.cpp
Merge branch 'master' of git@gitorious.org:freerainbowtables-applications/freerainbow...
[freerainbowtables] / Client Applications / rcracki_mt / CrackEngine.cpp
index 0a4b1818bb9eb889771e94017cc28fb0ee9302c2..0343588f38015dcead7af0a10818659b97a01cc4 100644 (file)
-/*
- * rcracki_mt is a multithreaded implementation and fork of the original 
- * RainbowCrack
- *
- * Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>
- * Copyright Martin Westergaard Jørgensen <martinwj2005@gmail.com>
- * Copyright 2009, 2010 Daniël Niggebrugge <niggebrugge@fox-it.com>
- * Copyright 2009, 2010 James Nobis <frt@quelrod.net>
- * Copyright 2010 uroskn
- *
- * This file is part of rcracki_mt.
- *
- * rcracki_mt is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * rcracki_mt is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with rcracki_mt.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#if defined(_WIN32) && !defined(__GNUC__)
-       #pragma warning(disable : 4786 4267 4018)
-#endif
-
-#include "CrackEngine.h"
-#include "RTI2Reader.h"
-
-#ifndef _WIN32
-       #include <sys/resource.h>
-#endif
-
-CCrackEngine::CCrackEngine()
-{
-       ResetStatistics();
-       writeOutput = false;
-       resumeSession = false;
-       debug = false;
-       keepPrecalcFiles = false;
-
-       sSessionPathName = "";
-       sProgressPathName = "";
-}
-
-CCrackEngine::~CCrackEngine()
-{
-}
-
-//////////////////////////////////////////////////////////////////////
-
-void CCrackEngine::ResetStatistics()
-{
-       m_fTotalDiskAccessTime               = 0.0f;
-       m_fTotalCryptanalysisTime            = 0.0f;
-       m_fTotalPrecalculationTime           = 0.0f;
-       m_nTotalChainWalkStep                = 0;
-       m_nTotalFalseAlarm                   = 0;
-       m_nTotalChainWalkStepDueToFalseAlarm = 0;
-//     m_nTotalFalseAlarmSkipped                        = 0;
-}
-
-int CCrackEngine::BinarySearchOld(RainbowChainO* pChain, int nRainbowChainCount, uint64 nIndex)
-{
-       int nLow = 0;
-       int nHigh = nRainbowChainCount - 1;
-       while (nLow <= nHigh)
-       {
-               int nMid = (nLow + nHigh) / 2;
-               if (nIndex == pChain[nMid].nIndexE)
-                       return nMid;
-               else if (nIndex < pChain[nMid].nIndexE)
-                       nHigh = nMid - 1;
-               else
-                       nLow = nMid + 1;
-       }
-
-       return -1;
-}
-
-RainbowChain *CCrackEngine::BinarySearch(RainbowChain *pChain, int nChainCountRead, uint64 nIndex, IndexChain *pIndex, int nIndexSize, int nIndexStart)
-{
-       uint64 nPrefix = nIndex >> 16;
-       int nLow, nHigh;        
-       bool found = false;
-       //int nChains = 0;
-       
-       if(nPrefix > (pIndex[nIndexSize-1].nPrefix & 0x000000FFFFFFFFFFULL)) // check if its in the index file
-       {
-               return NULL;
-       }
-
-       int nBLow = 0;
-       int nBHigh = nIndexSize - 1;
-       while (nBLow <= nBHigh)
-       {
-               int nBMid = (nBLow + nBHigh) / 2;
-               if (nPrefix == (pIndex[nBMid].nPrefix & 0x000000FFFFFFFFFFULL))
-               {
-                       //nLow = nChains;
-                       //int nChains = 0;
-
-                       nLow = pIndex[nBMid].nFirstChain;
-                       nHigh = nLow + pIndex[nBMid].nChainCount;
-                       if(nLow >= nIndexStart && nLow <= nIndexStart + nChainCountRead) 
-                       {                                       
-                               if(nHigh > nIndexStart + nChainCountRead)
-                                       nHigh = nIndexStart + nChainCountRead;
-                       }
-                       else if(nLow < nIndexStart && nHigh >= nIndexStart)
-                       {
-                               nLow = nIndexStart;
-                       }
-                       else break;                                     
-                       found = true;
-                       break;
-               }
-               else if (nPrefix < (pIndex[nBMid].nPrefix & 0x000000FFFFFFFFFFULL))
-                       nBHigh = nBMid - 1;
-               else
-                       nBLow = nBMid + 1;
-       }
-       if(found == true)
-       {
-               for(int i = nLow - nIndexStart; i < nHigh - nIndexStart; i++)
-               {
-                       int nSIndex = ((int)nIndex) & 0x0000FFFF;
-
-                       if (nSIndex == pChain[i].nIndexE)
-                       {
-                               return &pChain[i];
-                       }                               
-                       else if(pChain[i].nIndexE > nSIndex)
-                               break;
-               }
-       }       
-       return NULL;
-}
-
-// not used currently, leaving code for future checkpoints
-//bool CCrackEngine::CheckAlarm(RainbowChain* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs)
-//{
-//     CChainWalkContext cwc;
-//     //uint64 nIndexS = pChain->nIndexS >> 16;
-//     uint64 nIndexS = pChain->nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes
-//     cwc.SetIndex(nIndexS);
-//     int nPos;
-//     for (nPos = 0; nPos < nGuessedPos; nPos++)
-//     {
-//             cwc.IndexToPlain();
-//             cwc.PlainToHash();
-//             cwc.HashToIndex(nPos);
-//             // Not using checkpoints atm
-//             /*
-//             switch(nPos)
-//             {
-//             case 5000:
-//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000080) >> 7)
-//                             {
-//                                     m_nTotalFalseAlarmSkipped += 10000 - 5000;
-////                                   printf("CheckPoint caught false alarm at position 7600\n");
-//                                     return false;
-//                             }
-//                             break;
-//             case 6000:
-//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000040) >> 6)
-//                             {
-////                                   printf("CheckPoint caught false alarm at position 8200\n");
-//                                     m_nTotalFalseAlarmSkipped += 10000 - 6000;
-//                                     return false;
-//                             }
-//                             break;
-//
-//             case 7600:
-//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000020) >> 5)
-//                             {
-////                                   printf("CheckPoint caught false alarm at position 8700\n");
-//                                     m_nTotalFalseAlarmSkipped += 10000 - 7600;
-//                                     return false;
-//                             }
-//                             break;
-//
-//             case 8200:
-//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000010) >> 4)
-//                             {
-////                                   printf("CheckPoint caught false alarm at position 9000\n");
-//                                     m_nTotalFalseAlarmSkipped += 10000 - 8200;
-//                                     return false;
-//                             }
-//                             break;
-//
-//                     case 8700:
-//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000008) >> 3)
-//                             {
-////                                   printf("CheckPoint caught false alarm at position 9300\n");
-//                                     m_nTotalFalseAlarmSkipped += 10000 - 8700;
-//                                     return false;
-//                             }
-//
-//                             break;
-//                     case 9000:
-//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000004) >> 2)
-//                             {
-////                                   printf("CheckPoint caught false alarm at position 9600\n");
-//                                     m_nTotalFalseAlarmSkipped += 10000 - 9000;
-//                                     return false;
-//                             }
-//
-//                             break;
-//                     case 9300:
-//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000002) >> 1)
-//                             {
-////                                   printf("CheckPoint caught false alarm at position 9600\n");
-//                                     m_nTotalFalseAlarmSkipped += 10000 - 9300;
-//                                     return false;
-//                             }
-//                             break;
-//                     case 9600:
-//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000001))
-//                             {
-////                                   printf("CheckPoint caught false alarm at position 9600\n");
-//                                     m_nTotalFalseAlarmSkipped += 10000 - 9600;
-//                                     return false;
-//                             }
-//                             break;
-//
-//             }*/
-//     }
-//     cwc.IndexToPlain();
-//     cwc.PlainToHash();
-//     if (cwc.CheckHash(pHash))
-//     {
-//             printf("plaintext of %s is %s\n", cwc.GetHash().c_str(), cwc.GetPlain().c_str());
-//             hs.SetPlain(cwc.GetHash(), cwc.GetPlain(), cwc.GetBinary());
-//             return true;
-//     }
-//
-//     return false;
-//}
-
-//bool CCrackEngine::CheckAlarmOld(RainbowChainO* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs)
-//{
-//     CChainWalkContext cwc;
-//     cwc.SetIndex(pChain->nIndexS);
-//     int nPos;
-//     for (nPos = 0; nPos < nGuessedPos; nPos++)
-//     {
-//             cwc.IndexToPlain();
-//             cwc.PlainToHash();
-//             cwc.HashToIndex(nPos);
-//     }
-//     cwc.IndexToPlain();
-//     cwc.PlainToHash();
-//     if (cwc.CheckHash(pHash))
-//     {
-//             printf("plaintext of %s is %s\n", cwc.GetHash().c_str(), cwc.GetPlain().c_str());
-//             hs.SetPlain(cwc.GetHash(), cwc.GetPlain(), cwc.GetBinary());
-//             return true;
-//     }
-//
-//     return false;
-//}
-
-void CCrackEngine::GetChainIndexRangeWithSameEndpoint(RainbowChainO* pChain,
-                                                                                                         int nRainbowChainCount,
-                                                                                                         int nMatchingIndexE,
-                                                                                                         int& nMatchingIndexEFrom,
-                                                                                                         int& nMatchingIndexETo)
-{
-       nMatchingIndexEFrom = nMatchingIndexE;
-       nMatchingIndexETo   = nMatchingIndexE;
-       while (nMatchingIndexEFrom > 0)
-       {
-               if (pChain[nMatchingIndexEFrom - 1].nIndexE == pChain[nMatchingIndexE].nIndexE)
-                       nMatchingIndexEFrom--;
-               else
-                       break;
-       }
-       while (nMatchingIndexETo < nRainbowChainCount - 1)
-       {
-               if (pChain[nMatchingIndexETo + 1].nIndexE == pChain[nMatchingIndexE].nIndexE)
-                       nMatchingIndexETo++;
-               else
-                       break;
-       }
-}
-
-void CCrackEngine::SearchTableChunkOld(RainbowChainO* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs)
-{
-       vector<string> vHash;
-       hs.GetLeftHashWithLen(vHash, CChainWalkContext::GetHashLen());
-       printf("searching for %lu hash%s...\n", (unsigned long)vHash.size(),
-                                                                                  vHash.size() > 1 ? "es" : "");
-
-       int nChainWalkStep = 0;
-       int nFalseAlarm = 0;
-       int nChainWalkStepDueToFalseAlarm = 0;
-
-       vector<rcrackiThread*> threadPool;
-       vector<pthread_t> pThreads;
-
-       #ifndef _WIN32
-               /*
-                * On linux you cannot set the priority of a thread in the non real time
-                * scheduling groups.  You can set the priority of the process.  In
-                * windows BELOW_NORMAL represents a 1/8th drop in priority and this would
-                * be 20 * 1/8 on linux or about 2.5
-                */
-               setpriority( PRIO_PROCESS, 0, 2 );
-       #endif
-
-       pthread_attr_t attr;
-       pthread_attr_init(&attr);
-       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-       #ifdef _WIN32
-       sched_param param;
-       /*
-        * windows scheduling is 0 to 32 (low to high) with 8 as normal and 7 as
-        * BELOW_NORMAL
-        */
-       param.sched_priority = THREAD_PRIORITY_BELOW_NORMAL;
-       pthread_attr_setschedparam (&attr, &param);
-       #endif
-
-       bool pausing = false;
-
-       UINT4 nHashIndex;
-       for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)
-       {
-               #ifdef _WIN32
-               if (_kbhit())
-               {
-                       int ch = _getch();
-                       ch = toupper(ch);
-                       if (ch == 'P')
-                       {
-                               pausing = true;
-                               printf( "\nPausing, press P again to continue... ");
-
-                               timeval tv;
-                               timeval tv2;
-                               timeval final;
-                               gettimeofday( &tv, NULL );
-
-                               while (pausing)
-                               {
-                                       if (_kbhit())
-                                       {
-                                               ch = _getch();
-                                               ch = toupper(ch);
-                                               if (ch == 'P')
-                                               {
-                                                       printf( " [Continuing]\n");
-                                                       pausing = false;
-                                                       gettimeofday( &tv2, NULL );
-                                                       final = sub_timeofday( tv2, tv );
-                                                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                                       m_fTotalCryptanalysisTime -= fTime;
-                                               }
-                                       }
-                                       Sleep(500);
-                               }
-                       }
-                       else
-                       {
-                               printf( "\nPress 'P' to pause...\n");
-                       }
-               }
-               #else
-               int c = tty_getchar();
-               if (c >= 0) {
-                       tty_flush();
-                       if (c==112) { // = p
-                               pausing = true;
-                               printf( "\nPausing, press 'p' again to continue... ");
-                               
-                               timeval tv;
-                               timeval tv2;
-                               timeval final;
-                               gettimeofday( &tv, NULL );
-                               
-                               while (pausing)
-                               {
-                                       if ((c = tty_getchar()) >= 0)
-                                       {
-                                               tty_flush();
-                                               if (c == 112)
-                                               {
-                                                       printf( " [Continuing]\n");
-                                                       pausing = false;
-                                                       gettimeofday( &tv2, NULL );
-                                                       final = sub_timeofday( tv2, tv );
-                                                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                                       m_fTotalCryptanalysisTime -= fTime;
-                                               }
-                                       }
-                                       usleep(500*1000);
-                               }
-                       }
-                       else {
-                               printf( "\nPress 'p' to pause...\n");
-                       }
-               }
-               #endif
-               unsigned char TargetHash[MAX_HASH_LEN];
-               int nHashLen;
-               ParseHash(vHash[nHashIndex], TargetHash, nHashLen);
-               if (nHashLen != CChainWalkContext::GetHashLen())
-                       printf("debug: nHashLen mismatch\n");
-
-               // Rqeuest ChainWalk
-               bool fNewlyGenerated;
-               uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,
-                                                                                                       nHashLen,
-                                                                                                       CChainWalkContext::GetHashRoutineName(),
-                                                                                                       CChainWalkContext::GetPlainCharsetName(),
-                                                                                                       CChainWalkContext::GetPlainLenMin(),
-                                                                                                       CChainWalkContext::GetPlainLenMax(),
-                                                                                                       CChainWalkContext::GetRainbowTableIndex(),
-                                                                                                       nRainbowChainLen,
-                                                                                                       fNewlyGenerated,
-                                                                                                       debug,
-                                                                                                       sPrecalcPathName);
-               //printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",
-               //                                                                              vHash[nHashIndex].c_str());
-
-               // Walk
-               if (fNewlyGenerated)
-               {
-                       timeval tv;
-                       timeval tv2;
-                       timeval final;
-
-                       gettimeofday( &tv, NULL );
-
-                       printf("Pre-calculating hash %lu of %lu.%-20s\r",
-                               (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");
-                       threadPool.clear();
-                       pThreads.clear();
-                       
-                       UINT4 thread_ID;
-                       for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
-                       {
-                               rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);
-                               if (r_Thread)
-                               {
-                                       pthread_t pThread;
-                                       int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
-
-                                       if( returnValue != 0 )
-                                       {
-                                               printf("pThread creation failed, returnValue: %d\n", returnValue);
-                                       }
-                                       else
-                                       {
-                                               pThreads.push_back(pThread);
-                                       }
-
-                                       threadPool.push_back(r_Thread);
-                               }
-                               else 
-                               {
-                                       printf("r_Thread creation failed!\n");
-                               }
-                       }
-                       
-                       //printf("%d r_Threads created\t\t\n", threadPool.size());
-                       
-                       for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
-                       {
-                               pthread_t pThread = pThreads[thread_ID];
-                               int returnValue = pthread_join(pThread, NULL);
-                               if( returnValue != 0 )
-                               {
-                                       printf("pThread join failed, returnValue: %d\n", returnValue);
-                               }
-                                       
-                               rcrackiThread* rThread = threadPool[thread_ID];
-                               nChainWalkStep += rThread->GetChainWalkStep();
-                       }
-
-                       gettimeofday( &tv2, NULL );
-                       final = sub_timeofday( tv2, tv );
-                       
-                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-
-                       m_fTotalPrecalculationTime += fTime;
-                       m_fTotalCryptanalysisTime -= fTime;
-
-                       printf("%-50s\r", "");
-
-                       if ( debug )
-                               printf("pre-calculation time: %.2f s\n", fTime);
-               }
-
-               //printf("Checking false alarms for hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());
-               printf("Checking false alarms for hash %lu of %lu.%-20s\r", 
-                       (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");
-
-               threadPool.clear();
-               pThreads.clear();
-
-               int i;
-               for (i = 0; i < maxThreads; i++)
-               {
-                       rcrackiThread* r_Thread = new rcrackiThread(TargetHash, true);
-                       threadPool.push_back(r_Thread);
-               }
-
-               UINT4 thread_ID = 0;
-               int nPos;
-               for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)
-               {
-                       uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];
-               
-                       // Search matching nIndexE
-                       int nMatchingIndexE = BinarySearchOld(pChain, nRainbowChainCount, nIndexEOfCurPos);
-                       if (nMatchingIndexE != -1)
-                       {
-                               int nMatchingIndexEFrom, nMatchingIndexETo;
-                               GetChainIndexRangeWithSameEndpoint(pChain, nRainbowChainCount,
-                                                                                                  nMatchingIndexE,
-                                                                                                  nMatchingIndexEFrom, nMatchingIndexETo);
-                               int i;
-                               for (i = nMatchingIndexEFrom; i <= nMatchingIndexETo; i++)
-                               {
-                                       rcrackiThread* rThread = threadPool[thread_ID];
-                                       rThread->AddAlarmCheckO(pChain + i, nPos);
-                                       if (thread_ID < (unsigned long)maxThreads - 1 ) {
-                                               thread_ID++;
-                                       } else {
-                                               thread_ID = 0;
-                                       }
-                               }
-                       }
-               }
-
-               for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
-               {
-                       rcrackiThread* r_Thread = threadPool[thread_ID];
-                       pthread_t pThread;
-
-                       int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
-
-                       if( returnValue != 0 )
-                       {
-                               printf("pThread creation failed, returnValue: %d\n", returnValue);
-                       }
-                       else
-                       {
-                               pThreads.push_back(pThread);
-                       }
-               }
-               
-               //printf("%d r_Threads created\t\t\n", threadPool.size());
-
-               bool foundHashInThread = false;
-               for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
-               {
-                       rcrackiThread* rThread = threadPool[thread_ID];
-                       pthread_t pThread = pThreads[thread_ID];
-
-                       int returnValue = pthread_join(pThread, NULL);
-                       if( returnValue != 0 )
-                       {
-                               printf("pThread join failed, returnValue: %d\n", returnValue);
-                       }
-
-                       nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();
-                       nFalseAlarm += rThread->GetnFalseAlarm();
-
-                       if (rThread->FoundHash() && !foundHashInThread) {
-                               //printf("\t\t\t\t\t\t\r");
-                               printf("%-50s\r", "");
-
-                               printf("plaintext of %s is %s\n", rThread->GetHash().c_str(), rThread->GetPlain().c_str());
-                               if (writeOutput)
-                               {
-                                       if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))
-                                               printf("Couldn't write this result to file!\n");
-                               }
-                               hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());
-
-                               FILE* file = fopen(sSessionPathName.c_str(), "a");
-                               if (file!=NULL)
-                               {
-                                       string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";
-                                       fputs (buffer.c_str(), file);
-                                       fclose (file);
-                               }
-
-                               m_cws.DiscardWalk(pStartPosIndexE);
-                               foundHashInThread = true;
-                       }
-               }
-
-               pThreads.clear();
-               threadPool.clear();
-       }
-
-       //printf("\t\t\t\t\t\t\t\r");
-       printf("%-50s\r", "");
-       pThreads.clear();
-       threadPool.clear();
-       pthread_attr_destroy(&attr);
-
-       //printf("debug: chain walk step: %d\n", nChainWalkStep);
-       //printf("debug: false alarm: %d\n", nFalseAlarm);
-       //printf("debug: chain walk step due to false alarm: %d\n", nChainWalkStepDueToFalseAlarm);
-
-       m_nTotalChainWalkStep += nChainWalkStep;
-       m_nTotalFalseAlarm += nFalseAlarm;
-       m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;
-}
-
-void CCrackEngine::SearchTableChunk(RainbowChain* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs, IndexChain *pIndex, int nIndexSize, int nChainStart)
-{
-       vector<string> vHash;
-       //vector<uint64 *> vIndices;
-       //vector<RainbowChain *> vChains;
-       hs.GetLeftHashWithLen(vHash, CChainWalkContext::GetHashLen());
-       printf("searching for %lu hash%s...\n", (unsigned long)vHash.size(),
-                                                                                  vHash.size() > 1 ? "es" : "");
-
-       int nChainWalkStep = 0;
-       int nFalseAlarm = 0;
-       int nChainWalkStepDueToFalseAlarm = 0;
-
-       vector<rcrackiThread*> threadPool;
-       vector<pthread_t> pThreads;
-       
-       #ifndef _WIN32
-               /*
-                * On linux you cannot set the priority of a thread in the non real time
-                * scheduling groups.  You can set the priority of the process.  In
-                * windows BELOW_NORMAL represents a 1/8th drop in priority and this would
-                * be 20 * 1/8 on linux or about 2.5
-                */
-               setpriority( PRIO_PROCESS, 0, 2 );
-       #endif
-
-       pthread_attr_t attr;
-       pthread_attr_init(&attr);
-       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-       #ifdef _WIN32
-       sched_param param;
-       param.sched_priority = THREAD_PRIORITY_BELOW_NORMAL;
-       pthread_attr_setschedparam (&attr, &param);
-       #endif
-       // else set it to 5 or something (for linux)?
-
-       bool pausing = false;
-
-       UINT4 nHashIndex;
-       for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)
-       {
-               #ifdef _WIN32
-               if (_kbhit())
-               {
-                       int ch = _getch();
-                       ch = toupper(ch);
-                       if (ch == 'P')
-                       {
-                               pausing = true;
-                               printf( "\nPausing, press P again to continue... ");
-                               
-                               timeval tv;
-                               timeval tv2;
-                               timeval final;
-                               gettimeofday( &tv, NULL );
-
-                               while (pausing)
-                               {
-                                       if (_kbhit())
-                                       {
-                                               ch = _getch();
-                                               ch = toupper(ch);
-                                               if (ch == 'P')
-                                               {
-                                                       printf( " [Continuing]\n");
-                                                       pausing = false;
-                                                       gettimeofday( &tv2, NULL );
-                                                       final = sub_timeofday( tv2, tv );
-                                                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                                       m_fTotalCryptanalysisTime -= fTime;
-                                               }
-                                       }
-                                       Sleep(500);
-                               }
-                       }
-                       else
-                       {
-                               printf( "\nPress 'P' to pause...\n");
-                       }
-               }
-               #else
-               int c = tty_getchar();
-               if (c >= 0) {
-                       tty_flush();
-                       if (c==112) { // = p
-                               pausing = true;
-                               printf( "\nPausing, press 'p' again to continue... ");
-
-                               timeval tv;
-                               timeval tv2;
-                               timeval final;
-                               gettimeofday( &tv, NULL );
-
-                               while (pausing)
-                               {
-                                       if ((c = tty_getchar()) >= 0)
-                                       {
-                                               tty_flush();
-                                               if (c == 112)
-                                               {
-                                                       printf( " [Continuing]\n");
-                                                       pausing = false;
-                                                       gettimeofday( &tv2, NULL );
-                                                       final = sub_timeofday( tv2, tv );
-                                                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                                       m_fTotalCryptanalysisTime -= fTime;
-                                               }
-                                       }
-                                       usleep(500*1000);
-                               }
-                       }
-                       else {
-                               printf( "\nPress 'p' to pause...\n");
-                       }
-               }
-               #endif
-               unsigned char TargetHash[MAX_HASH_LEN];
-               int nHashLen;
-               ParseHash(vHash[nHashIndex], TargetHash, nHashLen);
-               if (nHashLen != CChainWalkContext::GetHashLen())
-                       printf("debug: nHashLen mismatch\n");
-
-               // Request ChainWalk
-               bool fNewlyGenerated;
-//             printf("Requesting walk...");
-                
-
-               uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,
-                                                                                                       nHashLen,
-                                                                                                       CChainWalkContext::GetHashRoutineName(),
-                                                                                                       CChainWalkContext::GetPlainCharsetName(),
-                                                                                                       CChainWalkContext::GetPlainLenMin(),
-                                                                                                       CChainWalkContext::GetPlainLenMax(),
-                                                                                                       CChainWalkContext::GetRainbowTableIndex(),
-                                                                                                       nRainbowChainLen,
-                                                                                                       fNewlyGenerated,
-                                                                                                       debug,
-                                                                                                       sPrecalcPathName);
-//             printf("done!\n");
-//             printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",
-//                                                                                             vHash[nHashIndex].c_str());
-
-               if (fNewlyGenerated)
-               {
-                       timeval tv;
-                       timeval tv2;
-                       timeval final;
-
-                       gettimeofday( &tv, NULL );
-
-                       printf("Pre-calculating hash %lu of %lu.%-20s\r", 
-                               (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");
-                       threadPool.clear();
-                       pThreads.clear();
-                       
-                       UINT4 thread_ID;
-                       for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
-                       {
-                               rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);
-                               if (r_Thread)
-                               {
-                                       pthread_t pThread;
-                                       int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
-
-                                       if( returnValue != 0 )
-                                       {
-                                               printf("pThread creation failed, returnValue: %d\n", returnValue);
-                                       }
-                                       else
-                                       {
-                                               pThreads.push_back(pThread);
-                                       }
-
-                                       threadPool.push_back(r_Thread);
-                               }
-                               else 
-                               {
-                                       printf("r_Thread creation failed!\n");
-                               }
-                       }
-                       
-                       //printf("%d r_Threads created\t\t\n", threadPool.size());
-                       
-                       for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
-                       {
-                               pthread_t pThread = pThreads[thread_ID];
-                               int returnValue = pthread_join(pThread, NULL);
-                               if( returnValue != 0 )
-                               {
-                                       printf("pThread join failed, returnValue: %d\n", returnValue);
-                               }
-                                       
-                               rcrackiThread* rThread = threadPool[thread_ID];
-                               nChainWalkStep += rThread->GetChainWalkStep();
-                               delete rThread;
-                       }
-
-                       m_cws.StoreToFile(pStartPosIndexE, TargetHash, nHashLen);
-                       gettimeofday( &tv2, NULL );
-                       final = sub_timeofday( tv2, tv );
-                       
-                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-
-                       m_fTotalPrecalculationTime += fTime;
-                       m_fTotalCryptanalysisTime -= fTime;
-
-                       //printf("\npStartPosIndexE[0]: %s\n", uint64tostr(pStartPosIndexE[0]).c_str());
-                       //printf("\npStartPosIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pStartPosIndexE[nRainbowChainLen-2]).c_str());
-
-                       printf("%-50s\r", "");
-
-                       if ( debug )
-                               printf("pre-calculation time: %.2f s\n", fTime);
-               }
-
-               threadPool.clear();
-               pThreads.clear();
-
-               //printf("Checking false alarms for hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());
-               printf("Checking false alarms for hash %lu of %lu.%-20s\r",
-                       (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");
-
-               int i;
-               for (i = 0; i < maxThreads; i++)
-               {
-                       rcrackiThread* r_Thread = new rcrackiThread(TargetHash);
-                       threadPool.push_back(r_Thread);
-               }
-
-               UINT4 thread_ID = 0;
-               int nPos;
-               for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)
-               {
-                       uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];
-               
-                       // Search matching nIndexE
-                       RainbowChain *pChainFound = BinarySearch(pChain, nRainbowChainCount, nIndexEOfCurPos, pIndex, nIndexSize, nChainStart);
-                       if (pChainFound != NULL) // For perfected indexed tables we only recieve 1 result (huge speed increase!)
-                       {
-                               rcrackiThread* rThread = threadPool[thread_ID];
-                               rThread->AddAlarmCheck(pChainFound, nPos);
-                               if (thread_ID < (unsigned long)maxThreads - 1 ) {
-                                       thread_ID++;
-                               } else {
-                                       thread_ID = 0;
-                               }
-                       }
-               }
-
-               for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
-               {
-                       rcrackiThread* r_Thread = threadPool[thread_ID];
-                       pthread_t pThread;
-
-                       int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
-
-                       if( returnValue != 0 )
-                       {
-                               printf("pThread creation failed, returnValue: %d\n", returnValue);
-                       }
-                       else
-                       {
-                               pThreads.push_back(pThread);
-                       }
-               }
-               
-               //printf("%d r_Threads created\t\t\n", threadPool.size());
-
-               bool foundHashInThread = false;
-               for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
-               {
-                       rcrackiThread* rThread = threadPool[thread_ID];
-                       pthread_t pThread = pThreads[thread_ID];
-
-                       int returnValue = pthread_join(pThread, NULL);
-                       if( returnValue != 0 )
-                       {
-                               printf("pThread join failed, returnValue: %d\n", returnValue);
-                       }
-
-                       nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();
-                       nFalseAlarm += rThread->GetnFalseAlarm();
-
-                       if (rThread->FoundHash() && !foundHashInThread) {
-                               //printf("\t\t\t\t\t\t\r");
-                               printf("%-50s\r", "");
-                               printf("plaintext of %s is %s\n", rThread->GetHash().c_str(), rThread->GetPlain().c_str());
-                               if (writeOutput)
-                               {
-                                       if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))
-                                               printf("Couldn't write this result to file!\n");
-                               }
-                               hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());
-                               
-                               FILE* file = fopen(sSessionPathName.c_str(), "a");
-                               if (file!=NULL)
-                               {
-                                       string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";
-                                       fputs (buffer.c_str(), file);
-                                       fclose (file);
-                               }
-
-                               m_cws.DiscardWalk(pStartPosIndexE);
-                               foundHashInThread = true;
-                       }
-                       //pthread
-                       delete rThread;
-               }
-
-               pThreads.clear();
-               threadPool.clear();
-
-               //printf("\t\t\t\t\r");
-               //printf("pChainFounds: %d\n", pChainsFound.size());
-//NEXT_HASH:;
-       }
-       //printf("\t\t\t\t\t\t\t\r");
-       printf("%-50s\r", "");
-       pThreads.clear();
-       threadPool.clear();
-       pthread_attr_destroy(&attr);
-
-       //printf("debug: chain walk step: %d\n", nChainWalkStep);
-       //printf("debug: false alarm: %d\n", nFalseAlarm);
-       //printf("debug: chain walk step due to false alarm: %d\n", nChainWalkStepDueToFalseAlarm);
-
-       m_nTotalChainWalkStep += nChainWalkStep;
-       m_nTotalFalseAlarm += nFalseAlarm;
-       m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;
-}
-
-void CCrackEngine::SearchRainbowTable(string sPathName, CHashSet& hs)
-{
-       // Did we already go through this file in this session?
-       if (resumeSession)
-       {
-               vector<string> sessionFinishedPathNames;
-               if (ReadLinesFromFile(sProgressPathName.c_str(), sessionFinishedPathNames))
-               {
-                       UINT4 i;
-                       for (i = 0; i < sessionFinishedPathNames.size(); i++)
-                       {
-                               if (sessionFinishedPathNames[i] == sPathName)
-                               {
-                                       printf("Skipping %s\n", sPathName.c_str());
-                                       return;
-                               }
-                       }
-               }
-       }
-
-       // FileName
-#ifdef _WIN32
-       string::size_type nIndex = sPathName.find_last_of('\\');
-#else
-       string::size_type nIndex = sPathName.find_last_of('/');
-#endif
-       string sFileName;
-       if (nIndex != string::npos)
-               sFileName = sPathName.substr(nIndex + 1);
-       else
-               sFileName = sPathName;
-
-       // Info
-       printf("%s:\n", sFileName.c_str());
-
-       // Setup
-       int nRainbowChainLen, nRainbowChainCount;
-       if (!CChainWalkContext::SetupWithPathName(sPathName, nRainbowChainLen, nRainbowChainCount))
-               return;
-       //printf("keyspace: %llu\n", CChainWalkContext::GetPlainSpaceTotal());
-       // Already finished?
-       if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
-       {
-               printf("this table contains hashes with length %d only\n", CChainWalkContext::GetHashLen());
-               return;
-       }
-
-       // Open
-       FILE* file = fopen(sPathName.c_str(), "rb");
-       if (file != NULL)
-       {
-               // File length check
-               bool doOldFormat = CChainWalkContext::isOldFormat();
-               bool doRti2Format = CChainWalkContext::isRti2Format();
-               UINT4 sizeOfChain;
-               bool fVerified = false;
-               UINT4 nFileLen = GetFileLen(file);
-
-               if (doOldFormat)
-                       sizeOfChain = 16;
-               else
-                       sizeOfChain = 8;
-
-               //if (nFileLen % 8 != 0 || nRainbowChainCount * 8 != nFileLen)
-               if ( (nFileLen % sizeOfChain != 0 || nRainbowChainCount * sizeOfChain != nFileLen) && doRti2Format == false )
-                       printf("file length mismatch\n");
-               else
-               {
-                       fseek(file, 0, SEEK_SET);
-                       timeval tv;
-                       timeval tv2;
-                       timeval final;
-
-                       unsigned int bytesForChainWalkSet = hs.GetStatHashTotal() * (nRainbowChainLen-1) * 8;
-                       if (debug) printf("Debug: Saving %u bytes of memory for chainwalkset.\n", bytesForChainWalkSet);
-
-                       uint64 nAllocatedSize;
-
-                       if (doRti2Format || doOldFormat)
-                       {
-                               RTI2Reader *pReader = NULL;
-
-                               if(doRti2Format) {
-                                       pReader = new RTI2Reader(sPathName);
-
-                               }
-
-                               if (debug)
-                               {
-                                       if ( doOldFormat )
-                                               printf("Debug: This is a table in the old .rt format.\n");
-                                       else if ( doRti2Format )
-                                               printf("Debug: This is a table in the .rti2 format.\n");
-                               }
-
-                               static CMemoryPool mp(bytesForChainWalkSet, debug, maxMem);
-                               RainbowChainO* pChain = NULL;
-                               if(doRti2Format) {
-                                       pChain = (RainbowChainO*)mp.Allocate(pReader->GetChainsLeft() * 16, nAllocatedSize);
-                               } else {
-                                       pChain = (RainbowChainO*)mp.Allocate(nFileLen, nAllocatedSize);
-                               }
-                               #ifdef _WIN32
-                                       if (debug) printf("Allocated %I64u bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);
-                               #else
-                                       if (debug) printf("Allocated %llu bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);
-                               #endif
-
-                               if (pChain != NULL)
-                               {
-                                       nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain;            // Round to sizeOfChain boundary
-
-                                       //fseek(file, 0, SEEK_SET);
-                                       //bool fVerified = false;
-                                       while (true)    // Chunk read loop
-                                       {
-                                               if ((unsigned long)ftell(file) == nFileLen)
-                                                       break;
-
-                                               // Load table chunk
-                                               if (debug) printf("reading...\n");
-                                               unsigned int nDataRead = 0;
-                                               gettimeofday( &tv, NULL );
-                                               if ( doRti2Format )
-                                               {
-                                                       nDataRead = nAllocatedSize / 16;
-                                                       if(pReader->GetChainsLeft() <= 0) // No more data
-                                                               break; 
-                                                       pReader->ReadChains(nDataRead, (RainbowChain*)pChain);
-
-                                                       nDataRead *= 8; // Convert from chains read to bytes
-                                               }
-                                               else
-                                               {
-                                                       nDataRead = fread(pChain, 1, nAllocatedSize, file);
-                                               }
-                                               gettimeofday( &tv2, NULL );
-                                               final = sub_timeofday( tv2, tv );
-
-                                               float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                               printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
-                                               m_fTotalDiskAccessTime += fTime;
-
-                                               int nRainbowChainCountRead = nDataRead / 16;
-
-                                               if(doRti2Format) {
-                                                       nRainbowChainCountRead = nDataRead / 8;
-                                               }
-
-                                               // Verify table chunk
-                                               if (!fVerified)
-                                               {
-                                                       printf("verifying the file...\n");
-
-                                                       // Chain length test
-                                                       int nIndexToVerify = nRainbowChainCountRead / 2;
-                                                       CChainWalkContext cwc;
-                                                       cwc.SetIndex(pChain[nIndexToVerify].nIndexS);
-                                                       int nPos;
-                                                       for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
-                                                       {
-                                                               cwc.IndexToPlain();
-                                                               cwc.PlainToHash();
-                                                               cwc.HashToIndex(nPos);
-                                                       }
-                                                       if (cwc.GetIndex() != pChain[nIndexToVerify].nIndexE)
-                                                       {
-                                                               printf("rainbow chain length verify fail\n");
-                                                               break;
-                                                       }
-
-                                                       // Chain sort test
-                                                       int i;
-                                                       for (i = 0; i < nRainbowChainCountRead - 1; i++)
-                                                       {
-                                                               if (pChain[i].nIndexE > pChain[i + 1].nIndexE)
-                                                                       break;
-                                                       }
-                                                       if (i != nRainbowChainCountRead - 1)
-                                                       {
-                                                               printf("this file is not sorted\n");
-                                                               break;
-                                                       }
-
-                                                       fVerified = true;
-                                               }
-
-                                               // Search table chunk
-                                               gettimeofday( &tv, NULL );
-                                               SearchTableChunkOld(pChain, nRainbowChainLen, nRainbowChainCountRead, hs);
-                                               gettimeofday( &tv2, NULL );
-                                               final = sub_timeofday( tv2, tv );
-                                               fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                               printf("cryptanalysis time: %.2f s\n", fTime);
-                                               m_fTotalCryptanalysisTime += fTime;
-
-                                               // Already finished?
-                                               if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
-                                                       break;
-                                       }
-                               }
-                               else
-                                       printf("memory allocation fail\n");
-                               
-                               //delete pChain;
-                       }
-                       else
-                       {
-                               static CMemoryPool mpIndex(bytesForChainWalkSet, debug, maxMem);
-                               uint64 nAllocatedSizeIndex;
-
-                               //int nIndexSize = 0;
-                               //IndexChain *pIndex = NULL;
-
-                               FILE* fIndex = fopen(((string)(sPathName + string(".index"))).c_str(), "rb");
-                               if(fIndex != NULL)
-                               {
-                                       // File length check
-                                       unsigned int nFileLenIndex = GetFileLen(fIndex);
-                                       //unsigned int nRows = nFileLenIndex / 11;
-                                       //unsigned int nSize = nRows * sizeof(IndexChain);
-                                       //printf("Debug: 8\n");
-                                       if (nFileLenIndex % 11 != 0)
-                                               printf("index file length mismatch (%u bytes)\n", nFileLenIndex);
-                                       else
-                                       {
-                                               //printf("index nSize: %d\n", nSize);
-                                               //pIndex = (IndexChain*)new unsigned char[nSize];
-                                               IndexChain *pIndex = (IndexChain*)mpIndex.Allocate(nFileLenIndex, nAllocatedSizeIndex);
-                                               #ifdef _WIN32
-                                                       if (debug) printf("Debug: Allocated %I64u bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
-                                               #else
-                                                       if (debug) printf("Debug: Allocated %llu bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
-                                               #endif
-                               
-                                               static CMemoryPool mp(bytesForChainWalkSet + nAllocatedSizeIndex, debug, maxMem);
-                                               
-                                               if (pIndex != NULL && nAllocatedSizeIndex > 0)
-                                               {
-                                                       nAllocatedSizeIndex = nAllocatedSizeIndex / sizeof(IndexChain) * sizeof(IndexChain);            // Round to sizeOfIndexChain boundary
-                                               
-                                                       fseek(fIndex, 0, SEEK_SET);
-
-                                                       while ( (unsigned long)ftell(fIndex) != nFileLenIndex ) // Index chunk read loop
-                                                       {
-                                                               // Load index chunk
-#ifdef _WIN32
-                                                               if (debug) printf("Debug: Setting index to 0x00 in memory, %I64u bytes\n", nAllocatedSizeIndex);
-#else
-                                                               if (debug) printf("Debug: Setting index to 0x00 in memory, %llu bytes\n", nAllocatedSizeIndex);
-#endif
-                                                               memset(pIndex, 0x00, nAllocatedSizeIndex);
-                                                               printf("reading index... ");
-                                                               gettimeofday( &tv, NULL );
-                                                               unsigned int nDataRead = fread(pIndex, 1, nAllocatedSizeIndex, fIndex);
-                                                               gettimeofday( &tv2, NULL );
-                                                               final = sub_timeofday( tv2, tv );
-
-                                                               float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                                               printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
-                                                               m_fTotalDiskAccessTime += fTime;
-                                                       
-                                                               //nIndexSize = nFileLenIndex / 11;
-                                                               int nIndexChainCountRead = nDataRead / sizeof(IndexChain);
-                                                               //fclose(fIndex);
-                                                               unsigned int nCoveredRainbowTableChains = 0;
-                                                               for(int i = 0; i < nIndexChainCountRead; i++)
-                                                               {
-                                                                       nCoveredRainbowTableChains += pIndex[i].nChainCount;
-                                                               }
-
-                                                               //RainbowChain* pChain = (RainbowChain*)mp.Allocate(nFileLen, nAllocatedSize);
-                                                               RainbowChain* pChain = (RainbowChain*)mp.Allocate(nCoveredRainbowTableChains * sizeOfChain, nAllocatedSize);
-                                                               #ifdef _WIN32
-                                                                       if (debug) printf("Debug: Allocated %I64u bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);
-                                                               #else
-                                                                       if (debug) printf("Debug: Allocated %llu bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);
-                                                               #endif
-
-                                                               if (pChain != NULL && nAllocatedSize > 0)
-                                                               {
-                                                                       nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain;            // Round to sizeOfChain boundary
-
-                                                                       //fseek(file, 0, SEEK_SET);
-                                                                       //bool fVerified = false;
-                                                                       UINT4 nProcessedChains = 0;
-                                                                       while ( (unsigned long)ftell(file) != nFileLen 
-                                                                               && nProcessedChains < nCoveredRainbowTableChains )      // Chunk read loop
-                                                                       {
-                                                                               // Load table chunk
-                                                                               if (debug) printf("Debug: Setting pChain to 0x00 in memory\n");
-                                                                               memset(pChain, 0x00, nAllocatedSize);
-                                                                               printf("reading table... ");
-                                                                               gettimeofday( &tv, NULL );
-                                                                               unsigned int nDataRead = fread(pChain, 1, nAllocatedSize, file);
-                                                                               gettimeofday( &tv2, NULL );
-                                                                               final = sub_timeofday( tv2, tv );
-
-                                                                               float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                                                               printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
-                                                                               m_fTotalDiskAccessTime += fTime;
-                                                                               int nRainbowChainCountRead = nDataRead / sizeOfChain;
-                                                                               // Verify table chunk (Too lazy to implement this)
-                                                                               
-                                                                               if (!fVerified)
-                                                                               {
-                                                                                       printf("verifying the file... ");
-
-                                                                                       // Chain length test
-                                                                                       int nIndexToVerify = nRainbowChainCountRead / 2;
-                                                                                       CChainWalkContext cwc;
-                                                                                       uint64 nIndexS;
-                                                                                       nIndexS = pChain[nIndexToVerify].nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes
-
-                                                                                       //printf("nIndexS: %s\n", uint64tostr(nIndexS).c_str());
-                                                                                       cwc.SetIndex(nIndexS);
-                                                                                       
-                                                                                       int nPos;
-                                                                                       for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
-                                                                                       {
-                                                                                               cwc.IndexToPlain();
-                                                                                               cwc.PlainToHash();
-                                                                                               cwc.HashToIndex(nPos);
-                                                                                       }
-
-                                                                                       uint64 nEndPoint = 0;
-
-                                                                                       //for(int i = 0; i < nIndexSize; i++)
-                                                                                       for(int i = 0; i < nIndexChainCountRead; i++)
-                                                                                       {
-                                                                                               if(nIndexToVerify >= pIndex[i].nFirstChain && nIndexToVerify < pIndex[i].nFirstChain + pIndex[i].nChainCount) // We found the matching index
-                                                                                               { // Now we need to seek nIndexToVerify into the chains
-                                                                                                       nEndPoint += (pIndex[i].nPrefix & 0x000000FFFFFFFFFFULL) << 16; // & 0x000000FFFFFFFFFFULL for first 5 bytes
-                                                                                                       //printf("nPrefix: %s\n", uint64tostr(pIndex[i].nPrefix & 0x000000FFFFFFFFFF).c_str());
-                                                                                                       //printf("nFirstChain: %d\n", pIndex[i].nFirstChain);
-                                                                                                       //printf("nChainCount: %d\n", pIndex[i].nChainCount);
-                                                                                                       nEndPoint += pChain[nIndexToVerify].nIndexE;
-                                                                                                       break;
-                                                                                               }
-                                                                                       }
-
-                                                                                       if (cwc.GetIndex() != nEndPoint)
-                                                                                       {
-                                                                                               printf("rainbow chain length verify fail\n");
-                                                                                               break;
-                                                                                       }
-
-                                                                                       fVerified = true;
-                                                                                       printf("ok\n");
-                                                                               }
-
-                                                                               // Search table chunk
-                                                                               gettimeofday( &tv, NULL );
-                                                                               float preTime = m_fTotalCryptanalysisTime;
-
-                                                                               SearchTableChunk(pChain, nRainbowChainLen, nRainbowChainCountRead, hs, pIndex, nIndexChainCountRead, nProcessedChains);
-                                                                               float postTime = m_fTotalCryptanalysisTime;
-                                                                               gettimeofday( &tv2, NULL );
-                                                                               final = sub_timeofday( tv2, tv );
-
-                                                                               fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
-                                                                               printf("cryptanalysis time: %.2f s\n", fTime + postTime - preTime);
-                                                                               m_fTotalCryptanalysisTime += fTime;
-                                                                               nProcessedChains += nRainbowChainCountRead;
-                                                                               // Already finished?
-                                                                               if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
-                                                                                       break;
-                                                                       }
-                                                               }
-                                                               else printf("memory allocation failed for rainbow table\n");
-
-                                                               //delete pChain;
-                                                       }
-                                               }
-                                               else printf("memory allocation failed for index\n");
-                                       }               
-                               }
-                               else 
-                               {
-                                       printf("Can't load index\n");
-                                       return;
-                               }
-                               fclose(fIndex);
-                               
-                               //delete pIndex;
-                       }
-               }
-               fclose(file);
-
-               if (debug) printf("Debug: writing progress to %s\n", sProgressPathName.c_str());
-               FILE* file = fopen(sProgressPathName.c_str(), "a");
-               if (file!=NULL)
-               {
-                       string buffer = sPathName + "\n";
-                       fputs (buffer.c_str(), file);
-                       fclose (file);
-               }
-       }
-       else
-               printf("can't open file\n");
-}
-
-void CCrackEngine::Run(vector<string> vPathName, CHashSet& hs, int i_maxThreads, uint64 i_maxMem, bool resume, bool bDebug)
-{
-#ifndef _WIN32
-       tty_init();
-#endif
-       resumeSession = resume;
-       debug = bDebug;
-
-       maxThreads = i_maxThreads;
-       maxMem = i_maxMem;
-       // Reset statistics
-       ResetStatistics();
-
-       // Sort vPathName (CChainWalkSet need it)
-       UINT4 i, j;
-       for (i = 0; i < vPathName.size() - 1; i++)
-               for (j = 0; j < vPathName.size() - i - 1; j++)
-               {
-                       if (vPathName[j] > vPathName[j + 1])
-                       {
-                               string sTemp;
-                               sTemp = vPathName[j];
-                               vPathName[j] = vPathName[j + 1];
-                               vPathName[j + 1] = sTemp;
-                       }
-               }
-
-       // Run
-       for (i = 0; i < vPathName.size() && hs.AnyhashLeft(); i++)
-       {
-               SearchRainbowTable(vPathName[i], hs);
-               printf("\n");
-       }
-
-       // delete precalc files
-       if (!keepPrecalcFiles)
-               m_cws.removePrecalcFiles();
-
-#ifndef _WIN32
-       tty_done();
-#endif
-}
-
-void CCrackEngine::setOutputFile(string sPathName)
-{
-       writeOutput = true;
-       outputFile = sPathName;
-}
-
-void CCrackEngine::setSession(string sSession, string sProgress, string sPrecalc, bool keepPrecalc)
-{
-       sSessionPathName = sSession;
-       sProgressPathName = sProgress;
-       sPrecalcPathName = sPrecalc;
-       keepPrecalcFiles = keepPrecalc;
-}
-
-float CCrackEngine::GetStatTotalDiskAccessTime()
-{
-       return m_fTotalDiskAccessTime;
-}
-/*float CCrackEngine::GetWastedTime()
-{
-       return m_fIndexTime;
-}*/
-float CCrackEngine::GetStatTotalCryptanalysisTime()
-{
-       return m_fTotalCryptanalysisTime;
-}
-
-float CCrackEngine::GetStatTotalPrecalculationTime()
-{
-       return m_fTotalPrecalculationTime;
-}
-
-int CCrackEngine::GetStatTotalChainWalkStep()
-{
-       return m_nTotalChainWalkStep;
-}
-
-int CCrackEngine::GetStatTotalFalseAlarm()
-{
-       return m_nTotalFalseAlarm;
-}
-
-int CCrackEngine::GetStatTotalChainWalkStepDueToFalseAlarm()
-{
-       return m_nTotalChainWalkStepDueToFalseAlarm;
-}
+/*\r
+ * rcracki_mt is a multithreaded implementation and fork of the original \r
+ * RainbowCrack\r
+ *\r
+ * Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>\r
+ * Copyright 2009, 2010 Martin Westergaard Jørgensen <martinwj2005@gmail.com>\r
+ * Copyright 2009, 2010 Daniël Niggebrugge <niggebrugge@fox-it.com>\r
+ * Copyright 2009, 2010 James Nobis <frt@quelrod.net>\r
+ * Copyright 2010 uroskn\r
+ *\r
+ * This file is part of rcracki_mt.\r
+ *\r
+ * rcracki_mt is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * rcracki_mt is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with rcracki_mt.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+#if defined(_WIN32) && !defined(__GNUC__)\r
+       #pragma warning(disable : 4786 4267 4018)\r
+#endif\r
+\r
+#include "CrackEngine.h"\r
+#include "RTI2Reader.h"\r
+\r
+#ifndef _WIN32\r
+       #include <sys/resource.h>\r
+#endif\r
+\r
+CCrackEngine::CCrackEngine()\r
+{\r
+       ResetStatistics();\r
+       writeOutput = false;\r
+       resumeSession = false;\r
+       debug = false;\r
+       keepPrecalcFiles = false;\r
+\r
+       sSessionPathName = "";\r
+       sProgressPathName = "";\r
+}\r
+\r
+CCrackEngine::~CCrackEngine()\r
+{\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+void CCrackEngine::ResetStatistics()\r
+{\r
+       m_fTotalDiskAccessTime               = 0.0f;\r
+       m_fTotalCryptanalysisTime            = 0.0f;\r
+       m_fTotalPrecalculationTime           = 0.0f;\r
+       m_nTotalChainWalkStep                = 0;\r
+       m_nTotalFalseAlarm                   = 0;\r
+       m_nTotalChainWalkStepDueToFalseAlarm = 0;\r
+//     m_nTotalFalseAlarmSkipped                        = 0;\r
+}\r
+\r
+int CCrackEngine::BinarySearchOld(RainbowChainO* pChain, int nRainbowChainCount, uint64 nIndex)\r
+{\r
+       int nLow = 0;\r
+       int nHigh = nRainbowChainCount - 1;\r
+       while (nLow <= nHigh)\r
+       {\r
+               int nMid = (nLow + nHigh) / 2;\r
+               if (nIndex == pChain[nMid].nIndexE)\r
+                       return nMid;\r
+               else if (nIndex < pChain[nMid].nIndexE)\r
+                       nHigh = nMid - 1;\r
+               else\r
+                       nLow = nMid + 1;\r
+       }\r
+\r
+       return -1;\r
+}\r
+\r
+RainbowChain *CCrackEngine::BinarySearch(RainbowChain *pChain, int nChainCountRead, uint64 nIndex, IndexChain *pIndex, int nIndexSize, int nIndexStart)\r
+{\r
+       uint64 nPrefix = nIndex >> 16;\r
+       int nLow, nHigh;        \r
+       bool found = false;\r
+       //int nChains = 0;\r
+       \r
+       if(nPrefix > (pIndex[nIndexSize-1].nPrefix & 0x000000FFFFFFFFFFULL)) // check if its in the index file\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       int nBLow = 0;\r
+       int nBHigh = nIndexSize - 1;\r
+       while (nBLow <= nBHigh)\r
+       {\r
+               int nBMid = (nBLow + nBHigh) / 2;\r
+               if (nPrefix == (pIndex[nBMid].nPrefix & 0x000000FFFFFFFFFFULL))\r
+               {\r
+                       //nLow = nChains;\r
+                       //int nChains = 0;\r
+\r
+                       nLow = pIndex[nBMid].nFirstChain;\r
+                       nHigh = nLow + pIndex[nBMid].nChainCount;\r
+                       if(nLow >= nIndexStart && nLow <= nIndexStart + nChainCountRead) \r
+                       {                                       \r
+                               if(nHigh > nIndexStart + nChainCountRead)\r
+                                       nHigh = nIndexStart + nChainCountRead;\r
+                       }\r
+                       else if(nLow < nIndexStart && nHigh >= nIndexStart)\r
+                       {\r
+                               nLow = nIndexStart;\r
+                       }\r
+                       else break;                                     \r
+                       found = true;\r
+                       break;\r
+               }\r
+               else if (nPrefix < (pIndex[nBMid].nPrefix & 0x000000FFFFFFFFFFULL))\r
+                       nBHigh = nBMid - 1;\r
+               else\r
+                       nBLow = nBMid + 1;\r
+       }\r
+       if(found == true)\r
+       {\r
+               for(int i = nLow - nIndexStart; i < nHigh - nIndexStart; i++)\r
+               {\r
+                       int nSIndex = ((int)nIndex) & 0x0000FFFF;\r
+\r
+                       if (nSIndex == pChain[i].nIndexE)\r
+                       {\r
+                               return &pChain[i];\r
+                       }                               \r
+                       else if(pChain[i].nIndexE > nSIndex)\r
+                               break;\r
+               }\r
+       }       \r
+       return NULL;\r
+}\r
+\r
+// not used currently, leaving code for future checkpoints\r
+//bool CCrackEngine::CheckAlarm(RainbowChain* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs)\r
+//{\r
+//     CChainWalkContext cwc;\r
+//     //uint64 nIndexS = pChain->nIndexS >> 16;\r
+//     uint64 nIndexS = pChain->nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes\r
+//     cwc.SetIndex(nIndexS);\r
+//     int nPos;\r
+//     for (nPos = 0; nPos < nGuessedPos; nPos++)\r
+//     {\r
+//             cwc.IndexToPlain();\r
+//             cwc.PlainToHash();\r
+//             cwc.HashToIndex(nPos);\r
+//             // Not using checkpoints atm\r
+//             /*\r
+//             switch(nPos)\r
+//             {\r
+//             case 5000:\r
+//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000080) >> 7)\r
+//                             {\r
+//                                     m_nTotalFalseAlarmSkipped += 10000 - 5000;\r
+////                                   printf("CheckPoint caught false alarm at position 7600\n");\r
+//                                     return false;\r
+//                             }\r
+//                             break;\r
+//             case 6000:\r
+//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000040) >> 6)\r
+//                             {\r
+////                                   printf("CheckPoint caught false alarm at position 8200\n");\r
+//                                     m_nTotalFalseAlarmSkipped += 10000 - 6000;\r
+//                                     return false;\r
+//                             }\r
+//                             break;\r
+//\r
+//             case 7600:\r
+//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000020) >> 5)\r
+//                             {\r
+////                                   printf("CheckPoint caught false alarm at position 8700\n");\r
+//                                     m_nTotalFalseAlarmSkipped += 10000 - 7600;\r
+//                                     return false;\r
+//                             }\r
+//                             break;\r
+//\r
+//             case 8200:\r
+//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000010) >> 4)\r
+//                             {\r
+////                                   printf("CheckPoint caught false alarm at position 9000\n");\r
+//                                     m_nTotalFalseAlarmSkipped += 10000 - 8200;\r
+//                                     return false;\r
+//                             }\r
+//                             break;\r
+//\r
+//                     case 8700:\r
+//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000008) >> 3)\r
+//                             {\r
+////                                   printf("CheckPoint caught false alarm at position 9300\n");\r
+//                                     m_nTotalFalseAlarmSkipped += 10000 - 8700;\r
+//                                     return false;\r
+//                             }\r
+//\r
+//                             break;\r
+//                     case 9000:\r
+//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000004) >> 2)\r
+//                             {\r
+////                                   printf("CheckPoint caught false alarm at position 9600\n");\r
+//                                     m_nTotalFalseAlarmSkipped += 10000 - 9000;\r
+//                                     return false;\r
+//                             }\r
+//\r
+//                             break;\r
+//                     case 9300:\r
+//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000002) >> 1)\r
+//                             {\r
+////                                   printf("CheckPoint caught false alarm at position 9600\n");\r
+//                                     m_nTotalFalseAlarmSkipped += 10000 - 9300;\r
+//                                     return false;\r
+//                             }\r
+//                             break;\r
+//                     case 9600:\r
+//                             if((cwc.GetIndex() & 0x00000001) != (pChain->nCheckPoint & 0x00000001))\r
+//                             {\r
+////                                   printf("CheckPoint caught false alarm at position 9600\n");\r
+//                                     m_nTotalFalseAlarmSkipped += 10000 - 9600;\r
+//                                     return false;\r
+//                             }\r
+//                             break;\r
+//\r
+//             }*/\r
+//     }\r
+//     cwc.IndexToPlain();\r
+//     cwc.PlainToHash();\r
+//     if (cwc.CheckHash(pHash))\r
+//     {\r
+//             printf("plaintext of %s is %s\n", cwc.GetHash().c_str(), cwc.GetPlain().c_str());\r
+//             hs.SetPlain(cwc.GetHash(), cwc.GetPlain(), cwc.GetBinary());\r
+//             return true;\r
+//     }\r
+//\r
+//     return false;\r
+//}\r
+\r
+//bool CCrackEngine::CheckAlarmOld(RainbowChainO* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs)\r
+//{\r
+//     CChainWalkContext cwc;\r
+//     cwc.SetIndex(pChain->nIndexS);\r
+//     int nPos;\r
+//     for (nPos = 0; nPos < nGuessedPos; nPos++)\r
+//     {\r
+//             cwc.IndexToPlain();\r
+//             cwc.PlainToHash();\r
+//             cwc.HashToIndex(nPos);\r
+//     }\r
+//     cwc.IndexToPlain();\r
+//     cwc.PlainToHash();\r
+//     if (cwc.CheckHash(pHash))\r
+//     {\r
+//             printf("plaintext of %s is %s\n", cwc.GetHash().c_str(), cwc.GetPlain().c_str());\r
+//             hs.SetPlain(cwc.GetHash(), cwc.GetPlain(), cwc.GetBinary());\r
+//             return true;\r
+//     }\r
+//\r
+//     return false;\r
+//}\r
+\r
+void CCrackEngine::GetChainIndexRangeWithSameEndpoint(RainbowChainO* pChain,\r
+                                                                                                         int nRainbowChainCount,\r
+                                                                                                         int nMatchingIndexE,\r
+                                                                                                         int& nMatchingIndexEFrom,\r
+                                                                                                         int& nMatchingIndexETo)\r
+{\r
+       nMatchingIndexEFrom = nMatchingIndexE;\r
+       nMatchingIndexETo   = nMatchingIndexE;\r
+       while (nMatchingIndexEFrom > 0)\r
+       {\r
+               if (pChain[nMatchingIndexEFrom - 1].nIndexE == pChain[nMatchingIndexE].nIndexE)\r
+                       nMatchingIndexEFrom--;\r
+               else\r
+                       break;\r
+       }\r
+       while (nMatchingIndexETo < nRainbowChainCount - 1)\r
+       {\r
+               if (pChain[nMatchingIndexETo + 1].nIndexE == pChain[nMatchingIndexE].nIndexE)\r
+                       nMatchingIndexETo++;\r
+               else\r
+                       break;\r
+       }\r
+}\r
+\r
+void CCrackEngine::SearchTableChunkOld(RainbowChainO* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs)\r
+{\r
+       vector<string> vHash;\r
+       hs.GetLeftHashWithLen(vHash, CChainWalkContext::GetHashLen());\r
+       printf("searching for %lu hash%s...\n", (unsigned long)vHash.size(),\r
+                                                                                  vHash.size() > 1 ? "es" : "");\r
+\r
+       int nChainWalkStep = 0;\r
+       int nFalseAlarm = 0;\r
+       int nChainWalkStepDueToFalseAlarm = 0;\r
+\r
+       vector<rcrackiThread*> threadPool;\r
+       vector<pthread_t> pThreads;\r
+\r
+       #ifndef _WIN32\r
+               /*\r
+                * On linux you cannot set the priority of a thread in the non real time\r
+                * scheduling groups.  You can set the priority of the process.  In\r
+                * windows BELOW_NORMAL represents a 1/8th drop in priority and this would\r
+                * be 20 * 1/8 on linux or about 2.5\r
+                */\r
+               setpriority( PRIO_PROCESS, 0, 2 );\r
+       #endif\r
+\r
+       pthread_attr_t attr;\r
+       pthread_attr_init(&attr);\r
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);\r
+       #ifdef _WIN32\r
+       sched_param param;\r
+       /*\r
+        * windows scheduling is 0 to 32 (low to high) with 8 as normal and 7 as\r
+        * BELOW_NORMAL\r
+        */\r
+       param.sched_priority = THREAD_PRIORITY_BELOW_NORMAL;\r
+       pthread_attr_setschedparam (&attr, &param);\r
+       #endif\r
+\r
+       bool pausing = false;\r
+\r
+       uint32 nHashIndex;\r
+       for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)\r
+       {\r
+               #ifdef _WIN32\r
+               if (_kbhit())\r
+               {\r
+                       int ch = _getch();\r
+                       ch = toupper(ch);\r
+                       if (ch == 'P')\r
+                       {\r
+                               pausing = true;\r
+                               printf( "\nPausing, press P again to continue... ");\r
+\r
+                               timeval tv;\r
+                               timeval tv2;\r
+                               timeval final;\r
+                               gettimeofday( &tv, NULL );\r
+\r
+                               while (pausing)\r
+                               {\r
+                                       if (_kbhit())\r
+                                       {\r
+                                               ch = _getch();\r
+                                               ch = toupper(ch);\r
+                                               if (ch == 'P')\r
+                                               {\r
+                                                       printf( " [Continuing]\n");\r
+                                                       pausing = false;\r
+                                                       gettimeofday( &tv2, NULL );\r
+                                                       final = sub_timeofday( tv2, tv );\r
+                                                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                                       m_fTotalCryptanalysisTime -= fTime;\r
+                                               }\r
+                                       }\r
+                                       Sleep(500);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               printf( "\nPress 'P' to pause...\n");\r
+                       }\r
+               }\r
+               #else\r
+               int c = tty_getchar();\r
+               if (c >= 0) {\r
+                       tty_flush();\r
+                       if (c==112) { // = p\r
+                               pausing = true;\r
+                               printf( "\nPausing, press 'p' again to continue... ");\r
+                               \r
+                               timeval tv;\r
+                               timeval tv2;\r
+                               timeval final;\r
+                               gettimeofday( &tv, NULL );\r
+                               \r
+                               while (pausing)\r
+                               {\r
+                                       if ((c = tty_getchar()) >= 0)\r
+                                       {\r
+                                               tty_flush();\r
+                                               if (c == 112)\r
+                                               {\r
+                                                       printf( " [Continuing]\n");\r
+                                                       pausing = false;\r
+                                                       gettimeofday( &tv2, NULL );\r
+                                                       final = sub_timeofday( tv2, tv );\r
+                                                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                                       m_fTotalCryptanalysisTime -= fTime;\r
+                                               }\r
+                                       }\r
+                                       usleep(500*1000);\r
+                               }\r
+                       }\r
+                       else {\r
+                               printf( "\nPress 'p' to pause...\n");\r
+                       }\r
+               }\r
+               #endif\r
+               unsigned char TargetHash[MAX_HASH_LEN];\r
+               int nHashLen;\r
+               ParseHash(vHash[nHashIndex], TargetHash, nHashLen);\r
+               if (nHashLen != CChainWalkContext::GetHashLen())\r
+                       printf("debug: nHashLen mismatch\n");\r
+\r
+               // Rqeuest ChainWalk\r
+               bool fNewlyGenerated;\r
+               uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,\r
+                                                                                                       nHashLen,\r
+                                                                                                       CChainWalkContext::GetHashRoutineName(),\r
+                                                                                                       CChainWalkContext::GetPlainCharsetName(),\r
+                                                                                                       CChainWalkContext::GetPlainLenMin(),\r
+                                                                                                       CChainWalkContext::GetPlainLenMax(),\r
+                                                                                                       CChainWalkContext::GetRainbowTableIndex(),\r
+                                                                                                       nRainbowChainLen,\r
+                                                                                                       fNewlyGenerated,\r
+                                                                                                       debug,\r
+                                                                                                       sPrecalcPathName);\r
+               //printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",\r
+               //                                                                              vHash[nHashIndex].c_str());\r
+\r
+               // Walk\r
+               if (fNewlyGenerated)\r
+               {\r
+                       timeval tv;\r
+                       timeval tv2;\r
+                       timeval final;\r
+\r
+                       gettimeofday( &tv, NULL );\r
+\r
+                       printf("Pre-calculating hash %lu of %lu.%-20s\r",\r
+                               (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");\r
+                       threadPool.clear();\r
+                       pThreads.clear();\r
+                       \r
+                       uint32 thread_ID;\r
+                       for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)\r
+                       {\r
+                               rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);\r
+                               if (r_Thread)\r
+                               {\r
+                                       pthread_t pThread;\r
+                                       int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);\r
+\r
+                                       if( returnValue != 0 )\r
+                                       {\r
+                                               printf("pThread creation failed, returnValue: %d\n", returnValue);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pThreads.push_back(pThread);\r
+                                       }\r
+\r
+                                       threadPool.push_back(r_Thread);\r
+                               }\r
+                               else \r
+                               {\r
+                                       printf("r_Thread creation failed!\n");\r
+                               }\r
+                       }\r
+                       \r
+                       //printf("%d r_Threads created\t\t\n", threadPool.size());\r
+                       \r
+                       for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)\r
+                       {\r
+                               pthread_t pThread = pThreads[thread_ID];\r
+                               int returnValue = pthread_join(pThread, NULL);\r
+                               if( returnValue != 0 )\r
+                               {\r
+                                       printf("pThread join failed, returnValue: %d\n", returnValue);\r
+                               }\r
+                                       \r
+                               rcrackiThread* rThread = threadPool[thread_ID];\r
+                               nChainWalkStep += rThread->GetChainWalkStep();\r
+                       }\r
+\r
+                       gettimeofday( &tv2, NULL );\r
+                       final = sub_timeofday( tv2, tv );\r
+                       \r
+                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+\r
+                       m_fTotalPrecalculationTime += fTime;\r
+                       m_fTotalCryptanalysisTime -= fTime;\r
+\r
+                       printf("%-50s\r", "");\r
+\r
+                       if ( debug )\r
+                               printf("pre-calculation time: %.2f s\n", fTime);\r
+               }\r
+\r
+               //printf("Checking false alarms for hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());\r
+               printf("Checking false alarms for hash %lu of %lu.%-20s\r", \r
+                       (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");\r
+\r
+               threadPool.clear();\r
+               pThreads.clear();\r
+\r
+               int i;\r
+               for (i = 0; i < maxThreads; i++)\r
+               {\r
+                       rcrackiThread* r_Thread = new rcrackiThread(TargetHash, true);\r
+                       threadPool.push_back(r_Thread);\r
+               }\r
+\r
+               uint32 thread_ID = 0;\r
+               int nPos;\r
+               for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)\r
+               {\r
+                       uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];\r
+               \r
+                       // Search matching nIndexE\r
+                       int nMatchingIndexE = BinarySearchOld(pChain, nRainbowChainCount, nIndexEOfCurPos);\r
+                       if (nMatchingIndexE != -1)\r
+                       {\r
+                               int nMatchingIndexEFrom, nMatchingIndexETo;\r
+                               GetChainIndexRangeWithSameEndpoint(pChain, nRainbowChainCount,\r
+                                                                                                  nMatchingIndexE,\r
+                                                                                                  nMatchingIndexEFrom, nMatchingIndexETo);\r
+                               int i;\r
+                               for (i = nMatchingIndexEFrom; i <= nMatchingIndexETo; i++)\r
+                               {\r
+                                       rcrackiThread* rThread = threadPool[thread_ID];\r
+                                       rThread->AddAlarmCheckO(pChain + i, nPos);\r
+                                       if (thread_ID < (unsigned long)maxThreads - 1 ) {\r
+                                               thread_ID++;\r
+                                       } else {\r
+                                               thread_ID = 0;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)\r
+               {\r
+                       rcrackiThread* r_Thread = threadPool[thread_ID];\r
+                       pthread_t pThread;\r
+\r
+                       int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);\r
+\r
+                       if( returnValue != 0 )\r
+                       {\r
+                               printf("pThread creation failed, returnValue: %d\n", returnValue);\r
+                       }\r
+                       else\r
+                       {\r
+                               pThreads.push_back(pThread);\r
+                       }\r
+               }\r
+               \r
+               //printf("%d r_Threads created\t\t\n", threadPool.size());\r
+\r
+               bool foundHashInThread = false;\r
+               for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)\r
+               {\r
+                       rcrackiThread* rThread = threadPool[thread_ID];\r
+                       pthread_t pThread = pThreads[thread_ID];\r
+\r
+                       int returnValue = pthread_join(pThread, NULL);\r
+                       if( returnValue != 0 )\r
+                       {\r
+                               printf("pThread join failed, returnValue: %d\n", returnValue);\r
+                       }\r
+\r
+                       nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();\r
+                       nFalseAlarm += rThread->GetnFalseAlarm();\r
+\r
+                       if (rThread->FoundHash() && !foundHashInThread) {\r
+                               //printf("\t\t\t\t\t\t\r");\r
+                               printf("%-50s\r", "");\r
+\r
+                               printf("plaintext of %s is %s\n", rThread->GetHash().c_str(), rThread->GetPlain().c_str());\r
+                               if (writeOutput)\r
+                               {\r
+                                       if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))\r
+                                               printf("Couldn't write this result to file!\n");\r
+                               }\r
+                               hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());\r
+\r
+                               FILE* file = fopen(sSessionPathName.c_str(), "a");\r
+                               if (file!=NULL)\r
+                               {\r
+                                       string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";\r
+                                       fputs (buffer.c_str(), file);\r
+                                       fclose (file);\r
+                               }\r
+\r
+                               m_cws.DiscardWalk(pStartPosIndexE);\r
+                               foundHashInThread = true;\r
+                       }\r
+               }\r
+\r
+               pThreads.clear();\r
+               threadPool.clear();\r
+       }\r
+\r
+       //printf("\t\t\t\t\t\t\t\r");\r
+       printf("%-50s\r", "");\r
+       pThreads.clear();\r
+       threadPool.clear();\r
+       pthread_attr_destroy(&attr);\r
+\r
+       //printf("debug: chain walk step: %d\n", nChainWalkStep);\r
+       //printf("debug: false alarm: %d\n", nFalseAlarm);\r
+       //printf("debug: chain walk step due to false alarm: %d\n", nChainWalkStepDueToFalseAlarm);\r
+\r
+       m_nTotalChainWalkStep += nChainWalkStep;\r
+       m_nTotalFalseAlarm += nFalseAlarm;\r
+       m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;\r
+}\r
+\r
+void CCrackEngine::SearchTableChunk(RainbowChain* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs, IndexChain *pIndex, int nIndexSize, int nChainStart)\r
+{\r
+       vector<string> vHash;\r
+       //vector<uint64 *> vIndices;\r
+       //vector<RainbowChain *> vChains;\r
+       hs.GetLeftHashWithLen(vHash, CChainWalkContext::GetHashLen());\r
+       printf("searching for %lu hash%s...\n", (unsigned long)vHash.size(),\r
+                                                                                  vHash.size() > 1 ? "es" : "");\r
+\r
+       int nChainWalkStep = 0;\r
+       int nFalseAlarm = 0;\r
+       int nChainWalkStepDueToFalseAlarm = 0;\r
+\r
+       vector<rcrackiThread*> threadPool;\r
+       vector<pthread_t> pThreads;\r
+       \r
+       #ifndef _WIN32\r
+               /*\r
+                * On linux you cannot set the priority of a thread in the non real time\r
+                * scheduling groups.  You can set the priority of the process.  In\r
+                * windows BELOW_NORMAL represents a 1/8th drop in priority and this would\r
+                * be 20 * 1/8 on linux or about 2.5\r
+                */\r
+               setpriority( PRIO_PROCESS, 0, 2 );\r
+       #endif\r
+\r
+       pthread_attr_t attr;\r
+       pthread_attr_init(&attr);\r
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);\r
+       #ifdef _WIN32\r
+       sched_param param;\r
+       param.sched_priority = THREAD_PRIORITY_BELOW_NORMAL;\r
+       pthread_attr_setschedparam (&attr, &param);\r
+       #endif\r
+       // else set it to 5 or something (for linux)?\r
+\r
+       bool pausing = false;\r
+\r
+       uint32 nHashIndex;\r
+       for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)\r
+       {\r
+               #ifdef _WIN32\r
+               if (_kbhit())\r
+               {\r
+                       int ch = _getch();\r
+                       ch = toupper(ch);\r
+                       if (ch == 'P')\r
+                       {\r
+                               pausing = true;\r
+                               printf( "\nPausing, press P again to continue... ");\r
+                               \r
+                               timeval tv;\r
+                               timeval tv2;\r
+                               timeval final;\r
+                               gettimeofday( &tv, NULL );\r
+\r
+                               while (pausing)\r
+                               {\r
+                                       if (_kbhit())\r
+                                       {\r
+                                               ch = _getch();\r
+                                               ch = toupper(ch);\r
+                                               if (ch == 'P')\r
+                                               {\r
+                                                       printf( " [Continuing]\n");\r
+                                                       pausing = false;\r
+                                                       gettimeofday( &tv2, NULL );\r
+                                                       final = sub_timeofday( tv2, tv );\r
+                                                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                                       m_fTotalCryptanalysisTime -= fTime;\r
+                                               }\r
+                                       }\r
+                                       Sleep(500);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               printf( "\nPress 'P' to pause...\n");\r
+                       }\r
+               }\r
+               #else\r
+               int c = tty_getchar();\r
+               if (c >= 0) {\r
+                       tty_flush();\r
+                       if (c==112) { // = p\r
+                               pausing = true;\r
+                               printf( "\nPausing, press 'p' again to continue... ");\r
+\r
+                               timeval tv;\r
+                               timeval tv2;\r
+                               timeval final;\r
+                               gettimeofday( &tv, NULL );\r
+\r
+                               while (pausing)\r
+                               {\r
+                                       if ((c = tty_getchar()) >= 0)\r
+                                       {\r
+                                               tty_flush();\r
+                                               if (c == 112)\r
+                                               {\r
+                                                       printf( " [Continuing]\n");\r
+                                                       pausing = false;\r
+                                                       gettimeofday( &tv2, NULL );\r
+                                                       final = sub_timeofday( tv2, tv );\r
+                                                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                                       m_fTotalCryptanalysisTime -= fTime;\r
+                                               }\r
+                                       }\r
+                                       usleep(500*1000);\r
+                               }\r
+                       }\r
+                       else {\r
+                               printf( "\nPress 'p' to pause...\n");\r
+                       }\r
+               }\r
+               #endif\r
+               unsigned char TargetHash[MAX_HASH_LEN];\r
+               int nHashLen;\r
+               ParseHash(vHash[nHashIndex], TargetHash, nHashLen);\r
+               if (nHashLen != CChainWalkContext::GetHashLen())\r
+                       printf("debug: nHashLen mismatch\n");\r
+\r
+               // Request ChainWalk\r
+               bool fNewlyGenerated;\r
+//             printf("Requesting walk...");\r
+                \r
+\r
+               uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,\r
+                                                                                                       nHashLen,\r
+                                                                                                       CChainWalkContext::GetHashRoutineName(),\r
+                                                                                                       CChainWalkContext::GetPlainCharsetName(),\r
+                                                                                                       CChainWalkContext::GetPlainLenMin(),\r
+                                                                                                       CChainWalkContext::GetPlainLenMax(),\r
+                                                                                                       CChainWalkContext::GetRainbowTableIndex(),\r
+                                                                                                       nRainbowChainLen,\r
+                                                                                                       fNewlyGenerated,\r
+                                                                                                       debug,\r
+                                                                                                       sPrecalcPathName);\r
+//             printf("done!\n");\r
+//             printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",\r
+//                                                                                             vHash[nHashIndex].c_str());\r
+\r
+               if (fNewlyGenerated)\r
+               {\r
+                       timeval tv;\r
+                       timeval tv2;\r
+                       timeval final;\r
+\r
+                       gettimeofday( &tv, NULL );\r
+\r
+                       printf("Pre-calculating hash %lu of %lu.%-20s\r", \r
+                               (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");\r
+                       threadPool.clear();\r
+                       pThreads.clear();\r
+                       \r
+                       uint32 thread_ID;\r
+                       for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)\r
+                       {\r
+                               rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);\r
+                               if (r_Thread)\r
+                               {\r
+                                       pthread_t pThread;\r
+                                       int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);\r
+\r
+                                       if( returnValue != 0 )\r
+                                       {\r
+                                               printf("pThread creation failed, returnValue: %d\n", returnValue);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pThreads.push_back(pThread);\r
+                                       }\r
+\r
+                                       threadPool.push_back(r_Thread);\r
+                               }\r
+                               else \r
+                               {\r
+                                       printf("r_Thread creation failed!\n");\r
+                               }\r
+                       }\r
+                       \r
+                       //printf("%d r_Threads created\t\t\n", threadPool.size());\r
+                       \r
+                       for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)\r
+                       {\r
+                               pthread_t pThread = pThreads[thread_ID];\r
+                               int returnValue = pthread_join(pThread, NULL);\r
+                               if( returnValue != 0 )\r
+                               {\r
+                                       printf("pThread join failed, returnValue: %d\n", returnValue);\r
+                               }\r
+                                       \r
+                               rcrackiThread* rThread = threadPool[thread_ID];\r
+                               nChainWalkStep += rThread->GetChainWalkStep();\r
+                               delete rThread;\r
+                       }\r
+\r
+                       m_cws.StoreToFile(pStartPosIndexE, TargetHash, nHashLen);\r
+                       gettimeofday( &tv2, NULL );\r
+                       final = sub_timeofday( tv2, tv );\r
+                       \r
+                       float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+\r
+                       m_fTotalPrecalculationTime += fTime;\r
+                       m_fTotalCryptanalysisTime -= fTime;\r
+\r
+                       //printf("\npStartPosIndexE[0]: %s\n", uint64tostr(pStartPosIndexE[0]).c_str());\r
+                       //printf("\npStartPosIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pStartPosIndexE[nRainbowChainLen-2]).c_str());\r
+\r
+                       printf("%-50s\r", "");\r
+\r
+                       if ( debug )\r
+                               printf("pre-calculation time: %.2f s\n", fTime);\r
+               }\r
+\r
+               threadPool.clear();\r
+               pThreads.clear();\r
+\r
+               //printf("Checking false alarms for hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());\r
+               printf("Checking false alarms for hash %lu of %lu.%-20s\r",\r
+                       (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");\r
+\r
+               int i;\r
+               for (i = 0; i < maxThreads; i++)\r
+               {\r
+                       rcrackiThread* r_Thread = new rcrackiThread(TargetHash);\r
+                       threadPool.push_back(r_Thread);\r
+               }\r
+\r
+               uint32 thread_ID = 0;\r
+               int nPos;\r
+               for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)\r
+               {\r
+                       uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];\r
+               \r
+                       // Search matching nIndexE\r
+                       RainbowChain *pChainFound = BinarySearch(pChain, nRainbowChainCount, nIndexEOfCurPos, pIndex, nIndexSize, nChainStart);\r
+                       if (pChainFound != NULL) // For perfected indexed tables we only recieve 1 result (huge speed increase!)\r
+                       {\r
+                               rcrackiThread* rThread = threadPool[thread_ID];\r
+                               rThread->AddAlarmCheck(pChainFound, nPos);\r
+                               if (thread_ID < (unsigned long)maxThreads - 1 ) {\r
+                                       thread_ID++;\r
+                               } else {\r
+                                       thread_ID = 0;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)\r
+               {\r
+                       rcrackiThread* r_Thread = threadPool[thread_ID];\r
+                       pthread_t pThread;\r
+\r
+                       int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);\r
+\r
+                       if( returnValue != 0 )\r
+                       {\r
+                               printf("pThread creation failed, returnValue: %d\n", returnValue);\r
+                       }\r
+                       else\r
+                       {\r
+                               pThreads.push_back(pThread);\r
+                       }\r
+               }\r
+               \r
+               //printf("%d r_Threads created\t\t\n", threadPool.size());\r
+\r
+               bool foundHashInThread = false;\r
+               for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)\r
+               {\r
+                       rcrackiThread* rThread = threadPool[thread_ID];\r
+                       pthread_t pThread = pThreads[thread_ID];\r
+\r
+                       int returnValue = pthread_join(pThread, NULL);\r
+                       if( returnValue != 0 )\r
+                       {\r
+                               printf("pThread join failed, returnValue: %d\n", returnValue);\r
+                       }\r
+\r
+                       nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();\r
+                       nFalseAlarm += rThread->GetnFalseAlarm();\r
+\r
+                       if (rThread->FoundHash() && !foundHashInThread) {\r
+                               //printf("\t\t\t\t\t\t\r");\r
+                               printf("%-50s\r", "");\r
+                               printf("plaintext of %s is %s\n", rThread->GetHash().c_str(), rThread->GetPlain().c_str());\r
+                               if (writeOutput)\r
+                               {\r
+                                       if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))\r
+                                               printf("Couldn't write this result to file!\n");\r
+                               }\r
+                               hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());\r
+                               \r
+                               FILE* file = fopen(sSessionPathName.c_str(), "a");\r
+                               if (file!=NULL)\r
+                               {\r
+                                       string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";\r
+                                       fputs (buffer.c_str(), file);\r
+                                       fclose (file);\r
+                               }\r
+\r
+                               m_cws.DiscardWalk(pStartPosIndexE);\r
+                               foundHashInThread = true;\r
+                       }\r
+                       //pthread\r
+                       delete rThread;\r
+               }\r
+\r
+               pThreads.clear();\r
+               threadPool.clear();\r
+\r
+               //printf("\t\t\t\t\r");\r
+               //printf("pChainFounds: %d\n", pChainsFound.size());\r
+//NEXT_HASH:;\r
+       }\r
+       //printf("\t\t\t\t\t\t\t\r");\r
+       printf("%-50s\r", "");\r
+       pThreads.clear();\r
+       threadPool.clear();\r
+       pthread_attr_destroy(&attr);\r
+\r
+       //printf("debug: chain walk step: %d\n", nChainWalkStep);\r
+       //printf("debug: false alarm: %d\n", nFalseAlarm);\r
+       //printf("debug: chain walk step due to false alarm: %d\n", nChainWalkStepDueToFalseAlarm);\r
+\r
+       m_nTotalChainWalkStep += nChainWalkStep;\r
+       m_nTotalFalseAlarm += nFalseAlarm;\r
+       m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;\r
+}\r
+\r
+void CCrackEngine::SearchRainbowTable(string sPathName, CHashSet& hs)\r
+{\r
+       // Did we already go through this file in this session?\r
+       if (resumeSession)\r
+       {\r
+               vector<string> sessionFinishedPathNames;\r
+               if (ReadLinesFromFile(sProgressPathName.c_str(), sessionFinishedPathNames))\r
+               {\r
+                       uint32 i;\r
+                       for (i = 0; i < sessionFinishedPathNames.size(); i++)\r
+                       {\r
+                               if (sessionFinishedPathNames[i] == sPathName)\r
+                               {\r
+                                       printf("Skipping %s\n", sPathName.c_str());\r
+                                       return;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       // FileName\r
+#ifdef _WIN32\r
+       string::size_type nIndex = sPathName.find_last_of('\\');\r
+#else\r
+       string::size_type nIndex = sPathName.find_last_of('/');\r
+#endif\r
+       string sFileName;\r
+       if (nIndex != string::npos)\r
+               sFileName = sPathName.substr(nIndex + 1);\r
+       else\r
+               sFileName = sPathName;\r
+\r
+       // Info\r
+       printf("%s:\n", sFileName.c_str());\r
+\r
+       // Setup\r
+       int nRainbowChainLen, nRainbowChainCount;\r
+       if (!CChainWalkContext::SetupWithPathName(sPathName, nRainbowChainLen, nRainbowChainCount))\r
+               return;\r
+       //printf("keyspace: %llu\n", CChainWalkContext::GetPlainSpaceTotal());\r
+       // Already finished?\r
+       if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))\r
+       {\r
+               printf("this table contains hashes with length %d only\n", CChainWalkContext::GetHashLen());\r
+               return;\r
+       }\r
+\r
+       // Open\r
+       FILE* file = fopen(sPathName.c_str(), "rb");\r
+       if (file != NULL)\r
+       {\r
+               // File length check\r
+               bool doOldFormat = CChainWalkContext::isOldFormat();\r
+               bool doRti2Format = CChainWalkContext::isRti2Format();\r
+               uint32 sizeOfChain;\r
+               bool fVerified = false;\r
+               long nFileLen = GetFileLen(file);\r
+\r
+               if (doOldFormat)\r
+                       sizeOfChain = 16;\r
+               else\r
+                       sizeOfChain = 8;\r
+\r
+               //if (nFileLen % 8 != 0 || nRainbowChainCount * 8 != nFileLen)\r
+               if ( ( (unsigned long)nFileLen % sizeOfChain != 0 || nRainbowChainCount * sizeOfChain != (unsigned long)nFileLen) && doRti2Format == false )\r
+                       printf("file length mismatch\n");\r
+               else\r
+               {\r
+                       fseek(file, 0, SEEK_SET);\r
+                       timeval tv;\r
+                       timeval tv2;\r
+                       timeval final;\r
+\r
+                       unsigned int bytesForChainWalkSet = hs.GetStatHashTotal() * (nRainbowChainLen-1) * 8;\r
+                       if (debug) printf("Debug: Saving %u bytes of memory for chainwalkset.\n", bytesForChainWalkSet);\r
+\r
+                       uint64 nAllocatedSize;\r
+\r
+                       if (doRti2Format || doOldFormat)\r
+                       {\r
+                               RTI2Reader *pReader = NULL;\r
+\r
+                               if(doRti2Format) {\r
+                                       pReader = new RTI2Reader(sPathName);\r
+\r
+                               }\r
+\r
+                               if (debug)\r
+                               {\r
+                                       if ( doOldFormat )\r
+                                               printf("Debug: This is a table in the old .rt format.\n");\r
+                                       else if ( doRti2Format )\r
+                                               printf("Debug: This is a table in the .rti2 format.\n");\r
+                               }\r
+\r
+                               static CMemoryPool mp(bytesForChainWalkSet, debug, maxMem);\r
+                               RainbowChainO* pChain = NULL;\r
+                               if(doRti2Format) {\r
+                                       pChain = (RainbowChainO*)mp.Allocate(pReader->GetChainsLeft() * 16, nAllocatedSize);\r
+                               } else {\r
+                                       pChain = (RainbowChainO*)mp.Allocate(nFileLen, nAllocatedSize);\r
+                               }\r
+                               #if defined(_WIN32) && !defined(__GNUC__)\r
+                                       if (debug) printf("Allocated %I64 bytes, filelen %ld\n", nAllocatedSize, nFileLen);\r
+                               #else\r
+                                       if (debug) printf("Allocated %llu bytes, filelen %ld\n", nAllocatedSize, nFileLen);\r
+                               #endif\r
+\r
+                               if (pChain != NULL)\r
+                               {\r
+                                       nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain;            // Round to sizeOfChain boundary\r
+\r
+                                       //fseek(file, 0, SEEK_SET);\r
+                                       //bool fVerified = false;\r
+                                       while (true)    // Chunk read loop\r
+                                       {\r
+                                               if (ftell(file) == nFileLen)\r
+                                                       break;\r
+\r
+                                               // Load table chunk\r
+                                               if (debug) printf("reading...\n");\r
+                                               unsigned int nDataRead = 0;\r
+                                               gettimeofday( &tv, NULL );\r
+                                               if ( doRti2Format )\r
+                                               {\r
+                                                       nDataRead = nAllocatedSize / 16;\r
+                                                       if(pReader->GetChainsLeft() <= 0) // No more data\r
+                                                               break; \r
+                                                       pReader->ReadChains(nDataRead, pChain);\r
+\r
+                                                       nDataRead *= 8; // Convert from chains read to bytes\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       nDataRead = fread(pChain, 1, nAllocatedSize, file);\r
+                                               }\r
+                                               gettimeofday( &tv2, NULL );\r
+                                               final = sub_timeofday( tv2, tv );\r
+\r
+                                               float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                               printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);\r
+                                               m_fTotalDiskAccessTime += fTime;\r
+\r
+                                               int nRainbowChainCountRead = nDataRead / 16;\r
+\r
+                                               if(doRti2Format) {\r
+                                                       nRainbowChainCountRead = nDataRead / 8;\r
+                                               }\r
+\r
+                                               // Verify table chunk\r
+                                               if (!fVerified)\r
+                                               {\r
+                                                       printf("verifying the file...\n");\r
+\r
+                                                       // Chain length test\r
+                                                       int nIndexToVerify = nRainbowChainCountRead / 2;\r
+                                                       CChainWalkContext cwc;\r
+                                                       cwc.SetIndex(pChain[nIndexToVerify].nIndexS);\r
+                                                       int nPos;\r
+                                                       for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)\r
+                                                       {\r
+                                                               cwc.IndexToPlain();\r
+                                                               cwc.PlainToHash();\r
+                                                               cwc.HashToIndex(nPos);\r
+                                                       }\r
+                                                       if (cwc.GetIndex() != pChain[nIndexToVerify].nIndexE)\r
+                                                       {\r
+                                                               printf("rainbow chain length verify fail\n");\r
+                                                               break;\r
+                                                       }\r
+\r
+                                                       // Chain sort test\r
+                                                       int i;\r
+                                                       for (i = 0; i < nRainbowChainCountRead - 1; i++)\r
+                                                       {\r
+                                                               if (pChain[i].nIndexE > pChain[i + 1].nIndexE)\r
+                                                                       break;\r
+                                                       }\r
+                                                       if (i != nRainbowChainCountRead - 1)\r
+                                                       {\r
+                                                               printf("this file is not sorted\n");\r
+                                                               break;\r
+                                                       }\r
+\r
+                                                       fVerified = true;\r
+                                               }\r
+\r
+                                               // Search table chunk\r
+                                               gettimeofday( &tv, NULL );\r
+                                               SearchTableChunkOld(pChain, nRainbowChainLen, nRainbowChainCountRead, hs);\r
+                                               gettimeofday( &tv2, NULL );\r
+                                               final = sub_timeofday( tv2, tv );\r
+                                               fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                               printf("cryptanalysis time: %.2f s\n", fTime);\r
+                                               m_fTotalCryptanalysisTime += fTime;\r
+\r
+                                               // Already finished?\r
+                                               if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))\r
+                                                       break;\r
+\r
+/*\r
+       // XXX eliminated by PB - check correctness\r
+                                               // finished the current table\r
+                                               if( doRti2Format && nDataToRead > (nDataRead / 8) )\r
+                                               {\r
+                                                       delete pReader;\r
+                                                       break;\r
+                                               }\r
+*/\r
+                                       }\r
+                               }\r
+                               else\r
+                                       printf("memory allocation fail\n");\r
+                               \r
+                               //delete pChain;\r
+                       }\r
+                       else\r
+                       {\r
+                               static CMemoryPool mpIndex(bytesForChainWalkSet, debug, maxMem);\r
+                               uint64 nAllocatedSizeIndex;\r
+\r
+                               //int nIndexSize = 0;\r
+                               //IndexChain *pIndex = NULL;\r
+\r
+                               FILE* fIndex = fopen(((string)(sPathName + string(".index"))).c_str(), "rb");\r
+                               if(fIndex != NULL)\r
+                               {\r
+                                       // File length check\r
+                                       long nFileLenIndex = GetFileLen(fIndex);\r
+                                       //unsigned int nRows = nFileLenIndex / 11;\r
+                                       //unsigned int nSize = nRows * sizeof(IndexChain);\r
+                                       //printf("Debug: 8\n");\r
+                                       if (nFileLenIndex % 11 != 0)\r
+                                               printf("index file length mismatch (%ld bytes)\n", nFileLenIndex);\r
+                                       else\r
+                                       {\r
+                                               //printf("index nSize: %d\n", nSize);\r
+                                               //pIndex = (IndexChain*)new unsigned char[nSize];\r
+                                               IndexChain *pIndex = (IndexChain*)mpIndex.Allocate(nFileLenIndex, nAllocatedSizeIndex);\r
+                                               #ifdef _WIN32\r
+                                                       if (debug) printf("Debug: Allocated %I64u bytes for index with filelen %ld\n", nAllocatedSizeIndex, nFileLenIndex);\r
+                                               #else\r
+                                                       if (debug) printf("Debug: Allocated %llu bytes for index with filelen %ld\n", nAllocatedSizeIndex, nFileLenIndex);\r
+                                               #endif\r
+                               \r
+                                               static CMemoryPool mp(bytesForChainWalkSet + nAllocatedSizeIndex, debug, maxMem);\r
+                                               \r
+                                               if (pIndex != NULL && nAllocatedSizeIndex > 0)\r
+                                               {\r
+                                                       nAllocatedSizeIndex = nAllocatedSizeIndex / sizeof(IndexChain) * sizeof(IndexChain);            // Round to sizeOfIndexChain boundary\r
+                                               \r
+                                                       fseek(fIndex, 0, SEEK_SET);\r
+\r
+                                                       while ( ftell(fIndex) != nFileLenIndex )        // Index chunk read loop\r
+                                                       {\r
+                                                               // Load index chunk\r
+#ifdef _WIN32\r
+                                                               if (debug) printf("Debug: Setting index to 0x00 in memory, %I64u bytes\n", nAllocatedSizeIndex);\r
+#else\r
+                                                               if (debug) printf("Debug: Setting index to 0x00 in memory, %llu bytes\n", nAllocatedSizeIndex);\r
+#endif\r
+                                                               memset(pIndex, 0x00, nAllocatedSizeIndex);\r
+                                                               printf("reading index... ");\r
+                                                               gettimeofday( &tv, NULL );\r
+                                                               unsigned int nDataRead = fread(pIndex, 1, nAllocatedSizeIndex, fIndex);\r
+                                                               gettimeofday( &tv2, NULL );\r
+                                                               final = sub_timeofday( tv2, tv );\r
+\r
+                                                               float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                                               printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);\r
+                                                               m_fTotalDiskAccessTime += fTime;\r
+                                                       \r
+                                                               //nIndexSize = nFileLenIndex / 11;\r
+                                                               int nIndexChainCountRead = nDataRead / sizeof(IndexChain);\r
+                                                               //fclose(fIndex);\r
+                                                               unsigned int nCoveredRainbowTableChains = 0;\r
+                                                               for(int i = 0; i < nIndexChainCountRead; i++)\r
+                                                               {\r
+                                                                       nCoveredRainbowTableChains += pIndex[i].nChainCount;\r
+                                                               }\r
+\r
+                                                               //RainbowChain* pChain = (RainbowChain*)mp.Allocate(nFileLen, nAllocatedSize);\r
+                                                               RainbowChain* pChain = (RainbowChain*)mp.Allocate(nCoveredRainbowTableChains * sizeOfChain, nAllocatedSize);\r
+                                                               #ifdef _WIN32\r
+                                                                       if (debug) printf("Debug: Allocated %I64u bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);\r
+                                                               #else\r
+                                                                       if (debug) printf("Debug: Allocated %llu bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);\r
+                                                               #endif\r
+\r
+                                                               if (pChain != NULL && nAllocatedSize > 0)\r
+                                                               {\r
+                                                                       nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain;            // Round to sizeOfChain boundary\r
+\r
+                                                                       //fseek(file, 0, SEEK_SET);\r
+                                                                       //bool fVerified = false;\r
+                                                                       uint32 nProcessedChains = 0;\r
+                                                                       while ( ftell(file) != nFileLen \r
+                                                                               && nProcessedChains < nCoveredRainbowTableChains )      // Chunk read loop\r
+                                                                       {\r
+                                                                               // Load table chunk\r
+                                                                               if (debug) printf("Debug: Setting pChain to 0x00 in memory\n");\r
+                                                                               memset(pChain, 0x00, nAllocatedSize);\r
+                                                                               printf("reading table... ");\r
+                                                                               gettimeofday( &tv, NULL );\r
+                                                                               unsigned int nDataRead = fread(pChain, 1, nAllocatedSize, file);\r
+                                                                               gettimeofday( &tv2, NULL );\r
+                                                                               final = sub_timeofday( tv2, tv );\r
+\r
+                                                                               float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                                                               printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);\r
+                                                                               m_fTotalDiskAccessTime += fTime;\r
+                                                                               int nRainbowChainCountRead = nDataRead / sizeOfChain;\r
+                                                                               // Verify table chunk (Too lazy to implement this)\r
+                                                                               \r
+                                                                               if (!fVerified)\r
+                                                                               {\r
+                                                                                       printf("verifying the file... ");\r
+\r
+                                                                                       // Chain length test\r
+                                                                                       int nIndexToVerify = nRainbowChainCountRead / 2;\r
+                                                                                       CChainWalkContext cwc;\r
+                                                                                       uint64 nIndexS;\r
+                                                                                       nIndexS = pChain[nIndexToVerify].nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes\r
+\r
+                                                                                       //printf("nIndexS: %s\n", uint64tostr(nIndexS).c_str());\r
+                                                                                       cwc.SetIndex(nIndexS);\r
+                                                                                       \r
+                                                                                       int nPos;\r
+                                                                                       for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)\r
+                                                                                       {\r
+                                                                                               cwc.IndexToPlain();\r
+                                                                                               cwc.PlainToHash();\r
+                                                                                               cwc.HashToIndex(nPos);\r
+                                                                                       }\r
+\r
+                                                                                       uint64 nEndPoint = 0;\r
+\r
+                                                                                       //for(int i = 0; i < nIndexSize; i++)\r
+                                                                                       for(int i = 0; i < nIndexChainCountRead; i++)\r
+                                                                                       {\r
+                                                                                               if(nIndexToVerify >= pIndex[i].nFirstChain && nIndexToVerify < pIndex[i].nFirstChain + pIndex[i].nChainCount) // We found the matching index\r
+                                                                                               { // Now we need to seek nIndexToVerify into the chains\r
+                                                                                                       nEndPoint += (pIndex[i].nPrefix & 0x000000FFFFFFFFFFULL) << 16; // & 0x000000FFFFFFFFFFULL for first 5 bytes\r
+                                                                                                       //printf("nPrefix: %s\n", uint64tostr(pIndex[i].nPrefix & 0x000000FFFFFFFFFF).c_str());\r
+                                                                                                       //printf("nFirstChain: %d\n", pIndex[i].nFirstChain);\r
+                                                                                                       //printf("nChainCount: %d\n", pIndex[i].nChainCount);\r
+                                                                                                       nEndPoint += pChain[nIndexToVerify].nIndexE;\r
+                                                                                                       break;\r
+                                                                                               }\r
+                                                                                       }\r
+\r
+                                                                                       if (cwc.GetIndex() != nEndPoint)\r
+                                                                                       {\r
+                                                                                               printf("rainbow chain length verify fail\n");\r
+                                                                                               break;\r
+                                                                                       }\r
+\r
+                                                                                       fVerified = true;\r
+                                                                                       printf("ok\n");\r
+                                                                               }\r
+\r
+                                                                               // Search table chunk\r
+                                                                               gettimeofday( &tv, NULL );\r
+                                                                               float preTime = m_fTotalCryptanalysisTime;\r
+\r
+                                                                               SearchTableChunk(pChain, nRainbowChainLen, nRainbowChainCountRead, hs, pIndex, nIndexChainCountRead, nProcessedChains);\r
+                                                                               float postTime = m_fTotalCryptanalysisTime;\r
+                                                                               gettimeofday( &tv2, NULL );\r
+                                                                               final = sub_timeofday( tv2, tv );\r
+\r
+                                                                               fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;\r
+                                                                               printf("cryptanalysis time: %.2f s\n", fTime + postTime - preTime);\r
+                                                                               m_fTotalCryptanalysisTime += fTime;\r
+                                                                               nProcessedChains += nRainbowChainCountRead;\r
+                                                                               // Already finished?\r
+                                                                               if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))\r
+                                                                                       break;\r
+                                                                       }\r
+                                                               }\r
+                                                               else printf("memory allocation failed for rainbow table\n");\r
+\r
+                                                               //delete pChain;\r
+                                                       }\r
+                                               }\r
+                                               else printf("memory allocation failed for index\n");\r
+                                       }               \r
+                               }\r
+                               else \r
+                               {\r
+                                       printf("Can't load index\n");\r
+                                       return;\r
+                               }\r
+                               fclose(fIndex);\r
+                               \r
+                               //delete pIndex;\r
+                       }\r
+               }\r
+               fclose(file);\r
+\r
+               if (debug) printf("Debug: writing progress to %s\n", sProgressPathName.c_str());\r
+               FILE* file = fopen(sProgressPathName.c_str(), "a");\r
+               if (file!=NULL)\r
+               {\r
+                       string buffer = sPathName + "\n";\r
+                       fputs (buffer.c_str(), file);\r
+                       fclose (file);\r
+               }\r
+       }\r
+       else\r
+               printf("can't open file\n");\r
+}\r
+\r
+void CCrackEngine::Run(vector<string> vPathName, CHashSet& hs, int i_maxThreads, uint64 i_maxMem, bool resume, bool bDebug)\r
+{\r
+#ifndef _WIN32\r
+       tty_init();\r
+#endif\r
+       resumeSession = resume;\r
+       debug = bDebug;\r
+\r
+       maxThreads = i_maxThreads;\r
+       maxMem = i_maxMem;\r
+       // Reset statistics\r
+       ResetStatistics();\r
+\r
+       // Sort vPathName (CChainWalkSet need it)\r
+       uint32 i, j;\r
+       for (i = 0; i < vPathName.size() - 1; i++)\r
+               for (j = 0; j < vPathName.size() - i - 1; j++)\r
+               {\r
+                       if (vPathName[j] > vPathName[j + 1])\r
+                       {\r
+                               string sTemp;\r
+                               sTemp = vPathName[j];\r
+                               vPathName[j] = vPathName[j + 1];\r
+                               vPathName[j + 1] = sTemp;\r
+                       }\r
+               }\r
+\r
+       // Run\r
+       for (i = 0; i < vPathName.size() && hs.AnyhashLeft(); i++)\r
+       {\r
+               SearchRainbowTable(vPathName[i], hs);\r
+               printf("\n");\r
+       }\r
+\r
+       // delete precalc files\r
+       if (!keepPrecalcFiles)\r
+               m_cws.removePrecalcFiles();\r
+\r
+#ifndef _WIN32\r
+       tty_done();\r
+#endif\r
+}\r
+\r
+void CCrackEngine::setOutputFile(string sPathName)\r
+{\r
+       writeOutput = true;\r
+       outputFile = sPathName;\r
+}\r
+\r
+void CCrackEngine::setSession(string sSession, string sProgress, string sPrecalc, bool keepPrecalc)\r
+{\r
+       sSessionPathName = sSession;\r
+       sProgressPathName = sProgress;\r
+       sPrecalcPathName = sPrecalc;\r
+       keepPrecalcFiles = keepPrecalc;\r
+}\r
+\r
+float CCrackEngine::GetStatTotalDiskAccessTime()\r
+{\r
+       return m_fTotalDiskAccessTime;\r
+}\r
+/*float CCrackEngine::GetWastedTime()\r
+{\r
+       return m_fIndexTime;\r
+}*/\r
+float CCrackEngine::GetStatTotalCryptanalysisTime()\r
+{\r
+       return m_fTotalCryptanalysisTime;\r
+}\r
+\r
+float CCrackEngine::GetStatTotalPrecalculationTime()\r
+{\r
+       return m_fTotalPrecalculationTime;\r
+}\r
+\r
+int CCrackEngine::GetStatTotalChainWalkStep()\r
+{\r
+       return m_nTotalChainWalkStep;\r
+}\r
+\r
+int CCrackEngine::GetStatTotalFalseAlarm()\r
+{\r
+       return m_nTotalFalseAlarm;\r
+}\r
+\r
+int CCrackEngine::GetStatTotalChainWalkStepDueToFalseAlarm()\r
+{\r
+       return m_nTotalChainWalkStepDueToFalseAlarm;\r
+}\r