-/*\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, ¶m);\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, ¶m);\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, ¶m);
+ #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, ¶m);
+ #endif
+ // else set it to 5 or something (for linux)?
+
+ bool pausing = false;
+
+ UINT4 nHashIndex;
+ for (nHashIndex = 0; nHashIndex < vHash.size(); nHashIndex++)
+ {
+ #ifdef _WIN32
+ if (_kbhit())
+ {
+ int ch = _getch();
+ ch = toupper(ch);
+ if (ch == 'P')
+ {
+ pausing = true;
+ printf( "\nPausing, press P again to continue... ");
+
+ timeval tv;
+ timeval tv2;
+ timeval final;
+ gettimeofday( &tv, NULL );
+
+ while (pausing)
+ {
+ if (_kbhit())
+ {
+ ch = _getch();
+ ch = toupper(ch);
+ if (ch == 'P')
+ {
+ printf( " [Continuing]\n");
+ pausing = false;
+ gettimeofday( &tv2, NULL );
+ final = sub_timeofday( tv2, tv );
+ float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
+ m_fTotalCryptanalysisTime -= fTime;
+ }
+ }
+ Sleep(500);
+ }
+ }
+ else
+ {
+ printf( "\nPress 'P' to pause...\n");
+ }
+ }
+ #else
+ int c = tty_getchar();
+ if (c >= 0) {
+ tty_flush();
+ if (c==112) { // = p
+ pausing = true;
+ printf( "\nPausing, press 'p' again to continue... ");
+
+ timeval tv;
+ timeval tv2;
+ timeval final;
+ gettimeofday( &tv, NULL );
+
+ while (pausing)
+ {
+ if ((c = tty_getchar()) >= 0)
+ {
+ tty_flush();
+ if (c == 112)
+ {
+ printf( " [Continuing]\n");
+ pausing = false;
+ gettimeofday( &tv2, NULL );
+ final = sub_timeofday( tv2, tv );
+ float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
+ m_fTotalCryptanalysisTime -= fTime;
+ }
+ }
+ usleep(500*1000);
+ }
+ }
+ else {
+ printf( "\nPress 'p' to pause...\n");
+ }
+ }
+ #endif
+ unsigned char TargetHash[MAX_HASH_LEN];
+ int nHashLen;
+ ParseHash(vHash[nHashIndex], TargetHash, nHashLen);
+ if (nHashLen != CChainWalkContext::GetHashLen())
+ printf("debug: nHashLen mismatch\n");
+
+ // Request ChainWalk
+ bool fNewlyGenerated;
+// printf("Requesting walk...");
+
+
+ uint64* pStartPosIndexE = m_cws.RequestWalk(TargetHash,
+ nHashLen,
+ CChainWalkContext::GetHashRoutineName(),
+ CChainWalkContext::GetPlainCharsetName(),
+ CChainWalkContext::GetPlainLenMin(),
+ CChainWalkContext::GetPlainLenMax(),
+ CChainWalkContext::GetRainbowTableIndex(),
+ nRainbowChainLen,
+ fNewlyGenerated,
+ debug,
+ sPrecalcPathName);
+// printf("done!\n");
+// printf("debug: using %s walk for %s\n", fNewlyGenerated ? "newly generated" : "existing",
+// vHash[nHashIndex].c_str());
+
+ if (fNewlyGenerated)
+ {
+ timeval tv;
+ timeval tv2;
+ timeval final;
+
+ gettimeofday( &tv, NULL );
+
+ printf("Pre-calculating hash %lu of %lu.%-20s\r",
+ (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");
+ threadPool.clear();
+ pThreads.clear();
+
+ UINT4 thread_ID;
+ for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
+ {
+ rcrackiThread* r_Thread = new rcrackiThread(TargetHash, thread_ID, nRainbowChainLen, maxThreads, pStartPosIndexE);
+ if (r_Thread)
+ {
+ pthread_t pThread;
+ int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
+
+ if( returnValue != 0 )
+ {
+ printf("pThread creation failed, returnValue: %d\n", returnValue);
+ }
+ else
+ {
+ pThreads.push_back(pThread);
+ }
+
+ threadPool.push_back(r_Thread);
+ }
+ else
+ {
+ printf("r_Thread creation failed!\n");
+ }
+ }
+
+ //printf("%d r_Threads created\t\t\n", threadPool.size());
+
+ for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
+ {
+ pthread_t pThread = pThreads[thread_ID];
+ int returnValue = pthread_join(pThread, NULL);
+ if( returnValue != 0 )
+ {
+ printf("pThread join failed, returnValue: %d\n", returnValue);
+ }
+
+ rcrackiThread* rThread = threadPool[thread_ID];
+ nChainWalkStep += rThread->GetChainWalkStep();
+ delete rThread;
+ }
+
+ m_cws.StoreToFile(pStartPosIndexE, TargetHash, nHashLen);
+ gettimeofday( &tv2, NULL );
+ final = sub_timeofday( tv2, tv );
+
+ float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
+
+ m_fTotalPrecalculationTime += fTime;
+ m_fTotalCryptanalysisTime -= fTime;
+
+ //printf("\npStartPosIndexE[0]: %s\n", uint64tostr(pStartPosIndexE[0]).c_str());
+ //printf("\npStartPosIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pStartPosIndexE[nRainbowChainLen-2]).c_str());
+
+ printf("%-50s\r", "");
+
+ if ( debug )
+ printf("pre-calculation time: %.2f s\n", fTime);
+ }
+
+ threadPool.clear();
+ pThreads.clear();
+
+ //printf("Checking false alarms for hash %d of %d.\t\t\r", nHashIndex+1, vHash.size());
+ printf("Checking false alarms for hash %lu of %lu.%-20s\r",
+ (unsigned long)nHashIndex+1, (unsigned long)vHash.size(), "");
+
+ int i;
+ for (i = 0; i < maxThreads; i++)
+ {
+ rcrackiThread* r_Thread = new rcrackiThread(TargetHash);
+ threadPool.push_back(r_Thread);
+ }
+
+ UINT4 thread_ID = 0;
+ int nPos;
+ for (nPos = nRainbowChainLen - 2; nPos >= 0; nPos--)
+ {
+ uint64 nIndexEOfCurPos = pStartPosIndexE[nPos];
+
+ // Search matching nIndexE
+ RainbowChain *pChainFound = BinarySearch(pChain, nRainbowChainCount, nIndexEOfCurPos, pIndex, nIndexSize, nChainStart);
+ if (pChainFound != NULL) // For perfected indexed tables we only recieve 1 result (huge speed increase!)
+ {
+ rcrackiThread* rThread = threadPool[thread_ID];
+ rThread->AddAlarmCheck(pChainFound, nPos);
+ if (thread_ID < (unsigned long)maxThreads - 1 ) {
+ thread_ID++;
+ } else {
+ thread_ID = 0;
+ }
+ }
+ }
+
+ for (thread_ID = 0; thread_ID < (unsigned long)maxThreads; thread_ID++)
+ {
+ rcrackiThread* r_Thread = threadPool[thread_ID];
+ pthread_t pThread;
+
+ int returnValue = pthread_create( &pThread, &attr, rcrackiThread::rcrackiThreadStaticEntryPointPthread, (void *) r_Thread);
+
+ if( returnValue != 0 )
+ {
+ printf("pThread creation failed, returnValue: %d\n", returnValue);
+ }
+ else
+ {
+ pThreads.push_back(pThread);
+ }
+ }
+
+ //printf("%d r_Threads created\t\t\n", threadPool.size());
+
+ bool foundHashInThread = false;
+ for (thread_ID = 0; thread_ID < threadPool.size(); thread_ID++)
+ {
+ rcrackiThread* rThread = threadPool[thread_ID];
+ pthread_t pThread = pThreads[thread_ID];
+
+ int returnValue = pthread_join(pThread, NULL);
+ if( returnValue != 0 )
+ {
+ printf("pThread join failed, returnValue: %d\n", returnValue);
+ }
+
+ nChainWalkStepDueToFalseAlarm += rThread->GetChainWalkStepDueToFalseAlarm();
+ nFalseAlarm += rThread->GetnFalseAlarm();
+
+ if (rThread->FoundHash() && !foundHashInThread) {
+ //printf("\t\t\t\t\t\t\r");
+ printf("%-50s\r", "");
+ printf("plaintext of %s is %s\n", rThread->GetHash().c_str(), rThread->GetPlain().c_str());
+ if (writeOutput)
+ {
+ if (!writeResultLineToFile(outputFile, rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary()))
+ printf("Couldn't write this result to file!\n");
+ }
+ hs.SetPlain(rThread->GetHash(), rThread->GetPlain(), rThread->GetBinary());
+
+ FILE* file = fopen(sSessionPathName.c_str(), "a");
+ if (file!=NULL)
+ {
+ string buffer = "sHash=" + rThread->GetHash() + ":" + rThread->GetBinary() + ":" + rThread->GetPlain() + "\n";
+ fputs (buffer.c_str(), file);
+ fclose (file);
+ }
+
+ m_cws.DiscardWalk(pStartPosIndexE);
+ foundHashInThread = true;
+ }
+ //pthread
+ delete rThread;
+ }
+
+ pThreads.clear();
+ threadPool.clear();
+
+ //printf("\t\t\t\t\r");
+ //printf("pChainFounds: %d\n", pChainsFound.size());
+//NEXT_HASH:;
+ }
+ //printf("\t\t\t\t\t\t\t\r");
+ printf("%-50s\r", "");
+ pThreads.clear();
+ threadPool.clear();
+ pthread_attr_destroy(&attr);
+
+ //printf("debug: chain walk step: %d\n", nChainWalkStep);
+ //printf("debug: false alarm: %d\n", nFalseAlarm);
+ //printf("debug: chain walk step due to false alarm: %d\n", nChainWalkStepDueToFalseAlarm);
+
+ m_nTotalChainWalkStep += nChainWalkStep;
+ m_nTotalFalseAlarm += nFalseAlarm;
+ m_nTotalChainWalkStepDueToFalseAlarm += nChainWalkStepDueToFalseAlarm;
+}
+
+void CCrackEngine::SearchRainbowTable(string sPathName, CHashSet& hs)
+{
+ // Did we already go through this file in this session?
+ if (resumeSession)
+ {
+ vector<string> sessionFinishedPathNames;
+ if (ReadLinesFromFile(sProgressPathName.c_str(), sessionFinishedPathNames))
+ {
+ UINT4 i;
+ for (i = 0; i < sessionFinishedPathNames.size(); i++)
+ {
+ if (sessionFinishedPathNames[i] == sPathName)
+ {
+ printf("Skipping %s\n", sPathName.c_str());
+ return;
+ }
+ }
+ }
+ }
+
+ // FileName
+#ifdef _WIN32
+ string::size_type nIndex = sPathName.find_last_of('\\');
+#else
+ string::size_type nIndex = sPathName.find_last_of('/');
+#endif
+ string sFileName;
+ if (nIndex != string::npos)
+ sFileName = sPathName.substr(nIndex + 1);
+ else
+ sFileName = sPathName;
+
+ // Info
+ printf("%s:\n", sFileName.c_str());
+
+ // Setup
+ int nRainbowChainLen, nRainbowChainCount;
+ if (!CChainWalkContext::SetupWithPathName(sPathName, nRainbowChainLen, nRainbowChainCount))
+ return;
+ //printf("keyspace: %llu\n", CChainWalkContext::GetPlainSpaceTotal());
+ // Already finished?
+ if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
+ {
+ printf("this table contains hashes with length %d only\n", CChainWalkContext::GetHashLen());
+ return;
+ }
+
+ // Open
+ FILE* file = fopen(sPathName.c_str(), "rb");
+ if (file != NULL)
+ {
+ // File length check
+ bool doOldFormat = CChainWalkContext::isOldFormat();
+ bool doRti2Format = CChainWalkContext::isRti2Format();
+ UINT4 sizeOfChain;
+ bool fVerified = false;
+ UINT4 nFileLen = GetFileLen(file);
+
+ if (doOldFormat)
+ sizeOfChain = 16;
+ else
+ sizeOfChain = 8;
+
+ //if (nFileLen % 8 != 0 || nRainbowChainCount * 8 != nFileLen)
+ if ( (nFileLen % sizeOfChain != 0 || nRainbowChainCount * sizeOfChain != nFileLen) && doRti2Format == false )
+ printf("file length mismatch\n");
+ else
+ {
+ fseek(file, 0, SEEK_SET);
+ timeval tv;
+ timeval tv2;
+ timeval final;
+
+ unsigned int bytesForChainWalkSet = hs.GetStatHashTotal() * (nRainbowChainLen-1) * 8;
+ if (debug) printf("Debug: Saving %u bytes of memory for chainwalkset.\n", bytesForChainWalkSet);
+
+ uint64 nAllocatedSize;
+
+ if (doRti2Format || doOldFormat)
+ {
+ RTI2Reader *pReader = NULL;
+
+ if(doRti2Format) {
+ pReader = new RTI2Reader(sPathName);
+
+ }
+
+ if (debug)
+ {
+ if ( doOldFormat )
+ printf("Debug: This is a table in the old .rt format.\n");
+ else if ( doRti2Format )
+ printf("Debug: This is a table in the .rti2 format.\n");
+ }
+
+ static CMemoryPool mp(bytesForChainWalkSet, debug, maxMem);
+ RainbowChainO* pChain = NULL;
+ if(doRti2Format) {
+ pChain = (RainbowChainO*)mp.Allocate(pReader->GetChainsLeft() * 16, nAllocatedSize);
+ } else {
+ pChain = (RainbowChainO*)mp.Allocate(nFileLen, nAllocatedSize);
+ }
+ #ifdef _WIN32
+ if (debug) printf("Allocated %I64u bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);
+ #else
+ if (debug) printf("Allocated %llu bytes, filelen %lu\n", nAllocatedSize, (unsigned long)nFileLen);
+ #endif
+
+ if (pChain != NULL)
+ {
+ nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain; // Round to sizeOfChain boundary
+
+ //fseek(file, 0, SEEK_SET);
+ //bool fVerified = false;
+ while (true) // Chunk read loop
+ {
+ if ((unsigned long)ftell(file) == nFileLen)
+ break;
+
+ // Load table chunk
+ if (debug) printf("reading...\n");
+ unsigned int nDataRead = 0;
+ gettimeofday( &tv, NULL );
+ if ( doRti2Format )
+ {
+ nDataRead = nAllocatedSize / 16;
+ if(pReader->GetChainsLeft() <= 0) // No more data
+ break;
+ pReader->ReadChains(nDataRead, (RainbowChain*)pChain);
+
+ nDataRead *= 8; // Convert from chains read to bytes
+ }
+ else
+ {
+ nDataRead = fread(pChain, 1, nAllocatedSize, file);
+ }
+ gettimeofday( &tv2, NULL );
+ final = sub_timeofday( tv2, tv );
+
+ float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
+ printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
+ m_fTotalDiskAccessTime += fTime;
+
+ int nRainbowChainCountRead = nDataRead / 16;
+
+ if(doRti2Format) {
+ nRainbowChainCountRead = nDataRead / 8;
+ }
+
+ // Verify table chunk
+ if (!fVerified)
+ {
+ printf("verifying the file...\n");
+
+ // Chain length test
+ int nIndexToVerify = nRainbowChainCountRead / 2;
+ CChainWalkContext cwc;
+ cwc.SetIndex(pChain[nIndexToVerify].nIndexS);
+ int nPos;
+ for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
+ {
+ cwc.IndexToPlain();
+ cwc.PlainToHash();
+ cwc.HashToIndex(nPos);
+ }
+ if (cwc.GetIndex() != pChain[nIndexToVerify].nIndexE)
+ {
+ printf("rainbow chain length verify fail\n");
+ break;
+ }
+
+ // Chain sort test
+ int i;
+ for (i = 0; i < nRainbowChainCountRead - 1; i++)
+ {
+ if (pChain[i].nIndexE > pChain[i + 1].nIndexE)
+ break;
+ }
+ if (i != nRainbowChainCountRead - 1)
+ {
+ printf("this file is not sorted\n");
+ break;
+ }
+
+ fVerified = true;
+ }
+
+ // Search table chunk
+ gettimeofday( &tv, NULL );
+ SearchTableChunkOld(pChain, nRainbowChainLen, nRainbowChainCountRead, hs);
+ gettimeofday( &tv2, NULL );
+ final = sub_timeofday( tv2, tv );
+ fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
+ printf("cryptanalysis time: %.2f s\n", fTime);
+ m_fTotalCryptanalysisTime += fTime;
+
+ // Already finished?
+ if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
+ break;
+ }
+ }
+ else
+ printf("memory allocation fail\n");
+
+ //delete pChain;
+ }
+ else
+ {
+ static CMemoryPool mpIndex(bytesForChainWalkSet, debug, maxMem);
+ uint64 nAllocatedSizeIndex;
+
+ //int nIndexSize = 0;
+ //IndexChain *pIndex = NULL;
+
+ FILE* fIndex = fopen(((string)(sPathName + string(".index"))).c_str(), "rb");
+ if(fIndex != NULL)
+ {
+ // File length check
+ unsigned int nFileLenIndex = GetFileLen(fIndex);
+ //unsigned int nRows = nFileLenIndex / 11;
+ //unsigned int nSize = nRows * sizeof(IndexChain);
+ //printf("Debug: 8\n");
+ if (nFileLenIndex % 11 != 0)
+ printf("index file length mismatch (%u bytes)\n", nFileLenIndex);
+ else
+ {
+ //printf("index nSize: %d\n", nSize);
+ //pIndex = (IndexChain*)new unsigned char[nSize];
+ IndexChain *pIndex = (IndexChain*)mpIndex.Allocate(nFileLenIndex, nAllocatedSizeIndex);
+ #ifdef _WIN32
+ if (debug) printf("Debug: Allocated %I64u bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
+ #else
+ if (debug) printf("Debug: Allocated %llu bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex);
+ #endif
+
+ static CMemoryPool mp(bytesForChainWalkSet + nAllocatedSizeIndex, debug, maxMem);
+
+ if (pIndex != NULL && nAllocatedSizeIndex > 0)
+ {
+ nAllocatedSizeIndex = nAllocatedSizeIndex / sizeof(IndexChain) * sizeof(IndexChain); // Round to sizeOfIndexChain boundary
+
+ fseek(fIndex, 0, SEEK_SET);
+
+ while ( (unsigned long)ftell(fIndex) != nFileLenIndex ) // Index chunk read loop
+ {
+ // Load index chunk
+#ifdef _WIN32
+ if (debug) printf("Debug: Setting index to 0x00 in memory, %I64u bytes\n", nAllocatedSizeIndex);
+#else
+ if (debug) printf("Debug: Setting index to 0x00 in memory, %llu bytes\n", nAllocatedSizeIndex);
+#endif
+ memset(pIndex, 0x00, nAllocatedSizeIndex);
+ printf("reading index... ");
+ gettimeofday( &tv, NULL );
+ unsigned int nDataRead = fread(pIndex, 1, nAllocatedSizeIndex, fIndex);
+ gettimeofday( &tv2, NULL );
+ final = sub_timeofday( tv2, tv );
+
+ float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
+ printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
+ m_fTotalDiskAccessTime += fTime;
+
+ //nIndexSize = nFileLenIndex / 11;
+ int nIndexChainCountRead = nDataRead / sizeof(IndexChain);
+ //fclose(fIndex);
+ unsigned int nCoveredRainbowTableChains = 0;
+ for(int i = 0; i < nIndexChainCountRead; i++)
+ {
+ nCoveredRainbowTableChains += pIndex[i].nChainCount;
+ }
+
+ //RainbowChain* pChain = (RainbowChain*)mp.Allocate(nFileLen, nAllocatedSize);
+ RainbowChain* pChain = (RainbowChain*)mp.Allocate(nCoveredRainbowTableChains * sizeOfChain, nAllocatedSize);
+ #ifdef _WIN32
+ if (debug) printf("Debug: Allocated %I64u bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);
+ #else
+ if (debug) printf("Debug: Allocated %llu bytes for %u chains, filelen %lu\n", nAllocatedSize, nCoveredRainbowTableChains, (unsigned long)nFileLen);
+ #endif
+
+ if (pChain != NULL && nAllocatedSize > 0)
+ {
+ nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain; // Round to sizeOfChain boundary
+
+ //fseek(file, 0, SEEK_SET);
+ //bool fVerified = false;
+ UINT4 nProcessedChains = 0;
+ while ( (unsigned long)ftell(file) != nFileLen
+ && nProcessedChains < nCoveredRainbowTableChains ) // Chunk read loop
+ {
+ // Load table chunk
+ if (debug) printf("Debug: Setting pChain to 0x00 in memory\n");
+ memset(pChain, 0x00, nAllocatedSize);
+ printf("reading table... ");
+ gettimeofday( &tv, NULL );
+ unsigned int nDataRead = fread(pChain, 1, nAllocatedSize, file);
+ gettimeofday( &tv2, NULL );
+ final = sub_timeofday( tv2, tv );
+
+ float fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
+ printf("%u bytes read, disk access time: %.2f s\n", nDataRead, fTime);
+ m_fTotalDiskAccessTime += fTime;
+ int nRainbowChainCountRead = nDataRead / sizeOfChain;
+ // Verify table chunk (Too lazy to implement this)
+
+ if (!fVerified)
+ {
+ printf("verifying the file... ");
+
+ // Chain length test
+ int nIndexToVerify = nRainbowChainCountRead / 2;
+ CChainWalkContext cwc;
+ uint64 nIndexS;
+ nIndexS = pChain[nIndexToVerify].nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes
+
+ //printf("nIndexS: %s\n", uint64tostr(nIndexS).c_str());
+ cwc.SetIndex(nIndexS);
+
+ int nPos;
+ for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
+ {
+ cwc.IndexToPlain();
+ cwc.PlainToHash();
+ cwc.HashToIndex(nPos);
+ }
+
+ uint64 nEndPoint = 0;
+
+ //for(int i = 0; i < nIndexSize; i++)
+ for(int i = 0; i < nIndexChainCountRead; i++)
+ {
+ if(nIndexToVerify >= pIndex[i].nFirstChain && nIndexToVerify < pIndex[i].nFirstChain + pIndex[i].nChainCount) // We found the matching index
+ { // Now we need to seek nIndexToVerify into the chains
+ nEndPoint += (pIndex[i].nPrefix & 0x000000FFFFFFFFFFULL) << 16; // & 0x000000FFFFFFFFFFULL for first 5 bytes
+ //printf("nPrefix: %s\n", uint64tostr(pIndex[i].nPrefix & 0x000000FFFFFFFFFF).c_str());
+ //printf("nFirstChain: %d\n", pIndex[i].nFirstChain);
+ //printf("nChainCount: %d\n", pIndex[i].nChainCount);
+ nEndPoint += pChain[nIndexToVerify].nIndexE;
+ break;
+ }
+ }
+
+ if (cwc.GetIndex() != nEndPoint)
+ {
+ printf("rainbow chain length verify fail\n");
+ break;
+ }
+
+ fVerified = true;
+ printf("ok\n");
+ }
+
+ // Search table chunk
+ gettimeofday( &tv, NULL );
+ float preTime = m_fTotalCryptanalysisTime;
+
+ SearchTableChunk(pChain, nRainbowChainLen, nRainbowChainCountRead, hs, pIndex, nIndexChainCountRead, nProcessedChains);
+ float postTime = m_fTotalCryptanalysisTime;
+ gettimeofday( &tv2, NULL );
+ final = sub_timeofday( tv2, tv );
+
+ fTime = 1.0f * final.tv_sec + 1.0f * final.tv_usec / 1000000;
+ printf("cryptanalysis time: %.2f s\n", fTime + postTime - preTime);
+ m_fTotalCryptanalysisTime += fTime;
+ nProcessedChains += nRainbowChainCountRead;
+ // Already finished?
+ if (!hs.AnyHashLeftWithLen(CChainWalkContext::GetHashLen()))
+ break;
+ }
+ }
+ else printf("memory allocation failed for rainbow table\n");
+
+ //delete pChain;
+ }
+ }
+ else printf("memory allocation failed for index\n");
+ }
+ }
+ else
+ {
+ printf("Can't load index\n");
+ return;
+ }
+ fclose(fIndex);
+
+ //delete pIndex;
+ }
+ }
+ fclose(file);
+
+ if (debug) printf("Debug: writing progress to %s\n", sProgressPathName.c_str());
+ FILE* file = fopen(sProgressPathName.c_str(), "a");
+ if (file!=NULL)
+ {
+ string buffer = sPathName + "\n";
+ fputs (buffer.c_str(), file);
+ fclose (file);
+ }
+ }
+ else
+ printf("can't open file\n");
+}
+
+void CCrackEngine::Run(vector<string> vPathName, CHashSet& hs, int i_maxThreads, uint64 i_maxMem, bool resume, bool bDebug)
+{
+#ifndef _WIN32
+ tty_init();
+#endif
+ resumeSession = resume;
+ debug = bDebug;
+
+ maxThreads = i_maxThreads;
+ maxMem = i_maxMem;
+ // Reset statistics
+ ResetStatistics();
+
+ // Sort vPathName (CChainWalkSet need it)
+ UINT4 i, j;
+ for (i = 0; i < vPathName.size() - 1; i++)
+ for (j = 0; j < vPathName.size() - i - 1; j++)
+ {
+ if (vPathName[j] > vPathName[j + 1])
+ {
+ string sTemp;
+ sTemp = vPathName[j];
+ vPathName[j] = vPathName[j + 1];
+ vPathName[j + 1] = sTemp;
+ }
+ }
+
+ // Run
+ for (i = 0; i < vPathName.size() && hs.AnyhashLeft(); i++)
+ {
+ SearchRainbowTable(vPathName[i], hs);
+ printf("\n");
+ }
+
+ // delete precalc files
+ if (!keepPrecalcFiles)
+ m_cws.removePrecalcFiles();
+
+#ifndef _WIN32
+ tty_done();
+#endif
+}
+
+void CCrackEngine::setOutputFile(string sPathName)
+{
+ writeOutput = true;
+ outputFile = sPathName;
+}
+
+void CCrackEngine::setSession(string sSession, string sProgress, string sPrecalc, bool keepPrecalc)
+{
+ sSessionPathName = sSession;
+ sProgressPathName = sProgress;
+ sPrecalcPathName = sPrecalc;
+ keepPrecalcFiles = keepPrecalc;
+}
+
+float CCrackEngine::GetStatTotalDiskAccessTime()
+{
+ return m_fTotalDiskAccessTime;
+}
+/*float CCrackEngine::GetWastedTime()
+{
+ return m_fIndexTime;
+}*/
+float CCrackEngine::GetStatTotalCryptanalysisTime()
+{
+ return m_fTotalCryptanalysisTime;
+}
+
+float CCrackEngine::GetStatTotalPrecalculationTime()
+{
+ return m_fTotalPrecalculationTime;
+}
+
+int CCrackEngine::GetStatTotalChainWalkStep()
+{
+ return m_nTotalChainWalkStep;
+}
+
+int CCrackEngine::GetStatTotalFalseAlarm()
+{
+ return m_nTotalFalseAlarm;
+}
+
+int CCrackEngine::GetStatTotalChainWalkStepDueToFalseAlarm()
+{
+ return m_nTotalChainWalkStepDueToFalseAlarm;
+}