]> git.sesse.net Git - freerainbowtables/blobdiff - Client Applications/rcracki_mt/CrackEngine.cpp
test
[freerainbowtables] / Client Applications / rcracki_mt / CrackEngine.cpp
index 1e00fce729b8a17b08db54b1293b762c6849b08a..7640a6310211340cdd4aef3b69aa75ccd34bbbae 100644 (file)
-/*\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 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
-       UINT4 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
-                       UINT4 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
-               UINT4 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
-       UINT4 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
-                       UINT4 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
-               UINT4 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
-                       UINT4 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
-               UINT4 sizeOfChain;\r
-               bool fVerified = false;\r
-               UINT4 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 ( (nFileLen % sizeOfChain != 0 || nRainbowChainCount * sizeOfChain != 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 = (RainbowChainO*)mp.Allocate(nFileLen, nAllocatedSize);\r
-                               #ifdef _WIN32\r
-                                       if (debug) printf("Allocated %I64u bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);\r
-                               #else\r
-                                       if (debug) printf("Allocated %llu bytes, filelen %lu\n", nAllocatedSize, (unsigned long)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 ((unsigned long)ftell(file) == nFileLen)\r
-                                                       break;\r
-\r
-                                               // Load table chunk\r
-                                               if (debug) printf("reading...\n");\r
-                                               unsigned int nDataRead = 0, nDataToRead = 0;\r
-                                               gettimeofday( &tv, NULL );\r
-                                               if ( doRti2Format )\r
-                                               {\r
-                                                       nDataToRead = nAllocatedSize / 16;\r
-                                                       nDataRead = nDataToRead;\r
-                                                       pReader->ReadChains(nDataRead, pChain);\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
-                                               // 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
-                                               // finished the current table\r
-                                               if( doRti2Format && nDataToRead > (nDataRead / 8) )\r
-                                               {\r
-                                                       delete pReader;\r
-                                                       break;\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
-                                       unsigned int 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 (%u 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 %u\n", nAllocatedSizeIndex, nFileLenIndex);\r
-                                               #else\r
-                                                       if (debug) printf("Debug: Allocated %llu bytes for index with filelen %u\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 ( (unsigned long)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
-                                                                       UINT4 nProcessedChains = 0;\r
-                                                                       while ( (unsigned long)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
-       UINT4 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
+/*
+ * 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 = (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, nDataToRead = 0;
+                                               gettimeofday( &tv, NULL );
+                                               if ( doRti2Format )
+                                               {
+                                                       nDataToRead = nAllocatedSize / 16;
+                                                       nDataRead = nDataToRead;
+                                                       pReader->ReadChains(nDataRead, 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;
+
+                                               // 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;
+
+                                               // finished the current table
+                                               if( doRti2Format && nDataToRead > (nDataRead / 8) )
+                                               {
+                                                       delete pReader;
+                                                       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;
+}