From: Martin Westergaard Jorgensen Date: Tue, 18 Aug 2009 06:40:30 +0000 (+0200) Subject: rcracki_mt updated to rti2 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=1f5948bf50f1eafad5ab3a4737f6eb3e492999e8;p=freerainbowtables rcracki_mt updated to rti2 --- diff --git a/Client Applications/rcracki_mt/BaseRTReader.cpp b/Client Applications/rcracki_mt/BaseRTReader.cpp new file mode 100644 index 0000000..d762e26 --- /dev/null +++ b/Client Applications/rcracki_mt/BaseRTReader.cpp @@ -0,0 +1,2 @@ +#include "BaseRTReader.h" + diff --git a/Client Applications/rcracki_mt/BaseRTReader.h b/Client Applications/rcracki_mt/BaseRTReader.h new file mode 100644 index 0000000..4dbaf86 --- /dev/null +++ b/Client Applications/rcracki_mt/BaseRTReader.h @@ -0,0 +1,19 @@ +#ifndef __BASERTREADER_H__ +#define __BASERTREADER_H__ + +#include "Public.h" +#include +#ifdef WIN32 +#include +#endif +using namespace std; + +class BaseRTReader +{ +public: + virtual int ReadChains(unsigned int &numChains, RainbowChainO *pData) = 0; + virtual unsigned int GetChainsLeft() = 0; + +}; + +#endif diff --git a/Client Applications/rcracki_mt/ChainWalkContext.cpp b/Client Applications/rcracki_mt/ChainWalkContext.cpp new file mode 100644 index 0000000..f6e24b3 --- /dev/null +++ b/Client Applications/rcracki_mt/ChainWalkContext.cpp @@ -0,0 +1,612 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifdef _WIN32 + #pragma warning(disable : 4786 4267 4018) +#endif + +#include "ChainWalkContext.h" + +#include + +////////////////////////////////////////////////////////////////////// + +string CChainWalkContext::m_sHashRoutineName; +HASHROUTINE CChainWalkContext::m_pHashRoutine; +int CChainWalkContext::m_nHashLen; +int CChainWalkContext::m_nPlainLenMinTotal = 0; +int CChainWalkContext::m_nPlainLenMaxTotal = 0; +int CChainWalkContext::m_nHybridCharset = 0; +bool CChainWalkContext::isOldRtFormat = false; +bool CChainWalkContext::isNewRtFormat = false; +vector CChainWalkContext::m_vCharset; +uint64 CChainWalkContext::m_nPlainSpaceUpToX[MAX_PLAIN_LEN + 1]; +uint64 CChainWalkContext::m_nPlainSpaceTotal; +unsigned char CChainWalkContext::m_Salt[MAX_SALT_LEN]; +int CChainWalkContext::m_nSaltLen = 0; +int CChainWalkContext::m_nRainbowTableIndex; +uint64 CChainWalkContext::m_nReduceOffset; + +////////////////////////////////////////////////////////////////////// + +CChainWalkContext::CChainWalkContext() +{ +} + +CChainWalkContext::~CChainWalkContext() +{ +} + +bool CChainWalkContext::LoadCharset(string sName) +{ + m_vCharset.clear(); + if (sName == "byte") + { + stCharset tCharset; + int i; + for (i = 0x00; i <= 0xff; i++) + tCharset.m_PlainCharset[i] = i; + tCharset.m_nPlainCharsetLen = 256; + tCharset.m_sPlainCharsetName = sName; + tCharset.m_sPlainCharsetContent = "0x00, 0x01, ... 0xff"; + m_vCharset.push_back(tCharset); + return true; + } + if(sName.substr(0, 6) == "hybrid") // Hybrid charset consisting of 2 charsets + { + m_nHybridCharset = 1; + } + else + { + m_nHybridCharset = 0; + } + + bool readCharset = false; + vector vLine; + if (ReadLinesFromFile("charset.txt", vLine)) { + readCharset = true; + } + else if (ReadLinesFromFile(GetApplicationPath() + "charset.txt", vLine)) { + readCharset = true; + } + if (readCharset) + { + int i; + for (i = 0; i < vLine.size(); i++) + { + // Filter comment + if (vLine[i][0] == '#') + continue; + + vector vPart; + if (SeperateString(vLine[i], "=", vPart)) + { + // sCharsetName + string sCharsetName = TrimString(vPart[0]); + if (sCharsetName == "") + continue; + + // sCharsetName charset check + bool fCharsetNameCheckPass = true; + int j; + for (j = 0; j < sCharsetName.size(); j++) + { + if ( !isalpha(sCharsetName[j]) + && !isdigit(sCharsetName[j]) + && (sCharsetName[j] != '-')) + { + fCharsetNameCheckPass = false; + break; + } + } + if (!fCharsetNameCheckPass) + { + printf("invalid charset name %s in charset configuration file\n", sCharsetName.c_str()); + continue; + } + + // sCharsetContent + string sCharsetContent = TrimString(vPart[1]); + if (sCharsetContent == "" || sCharsetContent == "[]") + continue; + if (sCharsetContent[0] != '[' || sCharsetContent[sCharsetContent.size() - 1] != ']') + { + printf("invalid charset content %s in charset configuration file\n", sCharsetContent.c_str()); + continue; + } + sCharsetContent = sCharsetContent.substr(1, sCharsetContent.size() - 2); + if (sCharsetContent.size() > 256) + { + printf("charset content %s too long\n", sCharsetContent.c_str()); + continue; + } + + //printf("%s = [%s]\n", sCharsetName.c_str(), sCharsetContent.c_str()); + + // Is it the wanted charset? + if(m_nHybridCharset == 1) + { + vector vCharsets; + GetHybridCharsets(sName, vCharsets); + if(sCharsetName == vCharsets[m_vCharset.size()].sName) + { + stCharset tCharset = {0}; + tCharset.m_nPlainCharsetLen = sCharsetContent.size(); + memcpy(tCharset.m_PlainCharset, sCharsetContent.c_str(), tCharset.m_nPlainCharsetLen); + tCharset.m_sPlainCharsetName = sCharsetName; + tCharset.m_sPlainCharsetContent = sCharsetContent; + tCharset.m_nPlainLenMin = vCharsets[m_vCharset.size()].nPlainLenMin; + tCharset.m_nPlainLenMax = vCharsets[m_vCharset.size()].nPlainLenMax; + m_vCharset.push_back(tCharset); + if(vCharsets.size() == m_vCharset.size()) + return true; + i = 0; // Start the lookup over again for the next charset + } + } + else if (sCharsetName == sName) + { + stCharset tCharset; + tCharset.m_nPlainCharsetLen = sCharsetContent.size(); + memcpy(tCharset.m_PlainCharset, sCharsetContent.c_str(), tCharset.m_nPlainCharsetLen); + tCharset.m_sPlainCharsetName = sCharsetName; + tCharset.m_sPlainCharsetContent = sCharsetContent; + m_vCharset.push_back(tCharset); + return true; + } + } + } + printf("charset %s not found in charset.txt\n", sName.c_str()); + } + else + printf("can't open charset configuration file\n"); + return false; +} + +////////////////////////////////////////////////////////////////////// + +bool CChainWalkContext::SetHashRoutine(string sHashRoutineName) +{ + CHashRoutine hr; + hr.GetHashRoutine(sHashRoutineName, m_pHashRoutine, m_nHashLen); + if (m_pHashRoutine != NULL) + { + m_sHashRoutineName = sHashRoutineName; + return true; + } + else + return false; +} + +bool CChainWalkContext::SetPlainCharset(string sCharsetName, int nPlainLenMin, int nPlainLenMax) +{ + // m_PlainCharset, m_nPlainCharsetLen, m_sPlainCharsetName, m_sPlainCharsetContent + if (!LoadCharset(sCharsetName)) + return false; + + if(m_vCharset.size() == 1) // Not hybrid charset + { + // m_nPlainLenMin, m_nPlainLenMax + if (nPlainLenMin < 1 || nPlainLenMax > MAX_PLAIN_LEN || nPlainLenMin > nPlainLenMax) + { + printf("invalid plaintext length range: %d - %d\n", nPlainLenMin, nPlainLenMax); + return false; + } + m_vCharset[0].m_nPlainLenMin = nPlainLenMin; + m_vCharset[0].m_nPlainLenMax = nPlainLenMax; + } + // m_nPlainSpaceUpToX + m_nPlainSpaceUpToX[0] = 0; + m_nPlainLenMaxTotal = 0; + m_nPlainLenMinTotal = 0; + uint64 nTemp = 1; + int j, k = 1; + for(j = 0; j < m_vCharset.size(); j++) + { + int i; + m_nPlainLenMaxTotal += m_vCharset[j].m_nPlainLenMax; + m_nPlainLenMinTotal += m_vCharset[j].m_nPlainLenMin; + for (i = 1; i <= m_vCharset[j].m_nPlainLenMax; i++) + { + nTemp *= m_vCharset[j].m_nPlainCharsetLen; + if (i < m_vCharset[j].m_nPlainLenMin) + m_nPlainSpaceUpToX[k] = 0; + else + m_nPlainSpaceUpToX[k] = m_nPlainSpaceUpToX[k - 1] + nTemp; + k++; + } + } + // m_nPlainSpaceTotal + m_nPlainSpaceTotal = m_nPlainSpaceUpToX[m_nPlainLenMaxTotal]; + + return true; +} + +bool CChainWalkContext::SetRainbowTableIndex(int nRainbowTableIndex) +{ + if (nRainbowTableIndex < 0) + return false; + m_nRainbowTableIndex = nRainbowTableIndex; + m_nReduceOffset = 65536 * nRainbowTableIndex; + + return true; +} + +bool CChainWalkContext::SetSalt(unsigned char *Salt, int nSaltLength) +{ + memcpy(&m_Salt[0], Salt, nSaltLength); + + m_nSaltLen = nSaltLength; +// m_sSalt = sSalt; + return true; +} + +bool CChainWalkContext::SetupWithPathName(string sPathName, int& nRainbowChainLen, int& nRainbowChainCount) +{ + // something like lm_alpha#1-7_0_100x16_test.rt + +#ifdef _WIN32 + int nIndex = sPathName.find_last_of('\\'); +#else + int nIndex = sPathName.find_last_of('/'); +#endif + if (nIndex != -1) + sPathName = sPathName.substr(nIndex + 1); + + if (sPathName.size() < 3) + { + printf("%s is not a rainbow table\n", sPathName.c_str()); + return false; + } + if (sPathName.substr(sPathName.size() - 5) == ".rti2") + { + isNewRtFormat = true; + } + else if (sPathName.substr(sPathName.size() - 4) == ".rti") + { + isOldRtFormat = false; + } + else if (sPathName.substr(sPathName.size() - 3) == ".rt") + { + isOldRtFormat = true; + } + else + { + printf("%s is not a rainbow table\n", sPathName.c_str()); + return false; + } + + // Parse + vector vPart; + if (!SeperateString(sPathName, "___x_", vPart)) + { + printf("filename %s not identified\n", sPathName.c_str()); + return false; + } + + string sHashRoutineName = vPart[0]; + int nRainbowTableIndex = atoi(vPart[2].c_str()); + nRainbowChainLen = atoi(vPart[3].c_str()); + nRainbowChainCount = atoi(vPart[4].c_str()); + + // Parse charset definition + string sCharsetDefinition = vPart[1]; + string sCharsetName; + int nPlainLenMin = 0, nPlainLenMax = 0; + +// printf("Charset: %s", sCharsetDefinition.c_str()); + + if(sCharsetDefinition.substr(0, 6) == "hybrid") // Hybrid table + { + sCharsetName = sCharsetDefinition; + } + else + { + if (sCharsetDefinition.find('#') == -1) // For backward compatibility, "#1-7" is implied + { + sCharsetName = sCharsetDefinition; + nPlainLenMin = 1; + nPlainLenMax = 7; + } + else + { + vector vCharsetDefinitionPart; + if (!SeperateString(sCharsetDefinition, "#-", vCharsetDefinitionPart)) + { + printf("filename %s not identified\n", sPathName.c_str()); + return false; + } + else + { + sCharsetName = vCharsetDefinitionPart[0]; + nPlainLenMin = atoi(vCharsetDefinitionPart[1].c_str()); + nPlainLenMax = atoi(vCharsetDefinitionPart[2].c_str()); + } + } + } + // Setup + if (!SetHashRoutine(sHashRoutineName)) + { + printf("hash routine %s not supported\n", sHashRoutineName.c_str()); + return false; + } + if (!SetPlainCharset(sCharsetName, nPlainLenMin, nPlainLenMax)) + return false; + if (!SetRainbowTableIndex(nRainbowTableIndex)) + { + printf("invalid rainbow table index %d\n", nRainbowTableIndex); + return false; + } + m_nPlainSpaceTotal = m_nPlainSpaceUpToX[m_nPlainLenMaxTotal]; + return true; +} + +string CChainWalkContext::GetHashRoutineName() +{ + return m_sHashRoutineName; +} + +int CChainWalkContext::GetHashLen() +{ + return m_nHashLen; +} + +string CChainWalkContext::GetPlainCharsetName() +{ + return m_vCharset[0].m_sPlainCharsetName; +} + +string CChainWalkContext::GetPlainCharsetContent() +{ + return m_vCharset[0].m_sPlainCharsetContent; +} + +int CChainWalkContext::GetPlainLenMin() +{ + return m_vCharset[0].m_nPlainLenMin; +} + +int CChainWalkContext::GetPlainLenMax() +{ + return m_vCharset[0].m_nPlainLenMax; +} + +uint64 CChainWalkContext::GetPlainSpaceTotal() +{ + return m_nPlainSpaceTotal; +} + +int CChainWalkContext::GetRainbowTableIndex() +{ + return m_nRainbowTableIndex; +} + +void CChainWalkContext::Dump() +{ + printf("hash routine: %s\n", m_sHashRoutineName.c_str()); + printf("hash length: %d\n", m_nHashLen); + + printf("plain charset: "); + int i; + for (i = 0; i < m_vCharset[0].m_nPlainCharsetLen; i++) + { + if (isprint(m_vCharset[0].m_PlainCharset[i])) + printf("%c", m_vCharset[0].m_PlainCharset[i]); + else + printf("?"); + } + printf("\n"); + + printf("plain charset in hex: "); + for (i = 0; i < m_vCharset[0].m_nPlainCharsetLen; i++) + printf("%02x ", m_vCharset[0].m_PlainCharset[i]); + printf("\n"); + + printf("plain length range: %d - %d\n", m_vCharset[0].m_nPlainLenMin, m_vCharset[0].m_nPlainLenMax); + printf("plain charset name: %s\n", m_vCharset[0].m_sPlainCharsetName.c_str()); + //printf("plain charset content: %s\n", m_sPlainCharsetContent.c_str()); + //for (i = 0; i <= m_nPlainLenMax; i++) + // printf("plain space up to %d: %s\n", i, uint64tostr(m_nPlainSpaceUpToX[i]).c_str()); + printf("plain space total: %s\n", uint64tostr(m_nPlainSpaceTotal).c_str()); + + printf("rainbow table index: %d\n", m_nRainbowTableIndex); + printf("reduce offset: %s\n", uint64tostr(m_nReduceOffset).c_str()); + printf("\n"); +} + + +void CChainWalkContext::SetIndex(uint64 nIndex) +{ + m_nIndex = nIndex; +} + +void CChainWalkContext::SetHash(unsigned char* pHash) +{ + memcpy(m_Hash, pHash, m_nHashLen); +} + +void CChainWalkContext::IndexToPlain() +{ + int i; + m_nPlainLen = 0; + for (i = m_nPlainLenMaxTotal - 1; i >= m_nPlainLenMinTotal - 1; i--) + { + if (m_nIndex >= m_nPlainSpaceUpToX[i]) + { + m_nPlainLen = i + 1; + break; + } + } + if(m_nPlainLen == 0) + m_nPlainLen = m_nPlainLenMinTotal; + uint64 nIndexOfX = m_nIndex - m_nPlainSpaceUpToX[m_nPlainLen - 1]; + +// maybe this code should be used for some other 64 bit systems as well, added check for LP64 to try this +#if defined(_WIN64) || defined(_LP64) + + // Slow version + for (i = m_nPlainLen - 1; i >= 0; i--) + { + int nCharsetLen = 0; + for(int j = 0; j < m_vCharset.size(); i++) + { + nCharsetLen += m_vCharset[j].m_nPlainLenMax; + if(i < nCharsetLen) // We found the correct charset + { + m_Plain[i] = m_vCharset[j].m_PlainCharset[nIndexOfX % m_nPlainCharsetLen]; + nIndexOfX /= m_vCharset[j].m_nPlainCharsetLen; + } + } + } +#else + + + // Fast version + for (i = m_nPlainLen - 1; i >= 0; i--) + { +#ifdef _WIN32 + if (nIndexOfX < 0x100000000I64) + break; +#else + if (nIndexOfX < 0x100000000llu) + break; +#endif + int nCharsetLen = 0; + for(int j = 0; j < m_vCharset.size(); j++) + { + nCharsetLen += m_vCharset[j].m_nPlainLenMax; + if(i < nCharsetLen) // We found the correct charset + { + m_Plain[i] = m_vCharset[j].m_PlainCharset[nIndexOfX % m_vCharset[j].m_nPlainCharsetLen]; + nIndexOfX /= m_vCharset[j].m_nPlainCharsetLen; + break; + } + } + } + + unsigned int nIndexOfX32 = (unsigned int)nIndexOfX; + for (; i >= 0; i--) + { + int nCharsetLen = 0; + for(int j = 0; j < m_vCharset.size(); j++) + { + nCharsetLen += m_vCharset[j].m_nPlainLenMax; + if(i < nCharsetLen) // We found the correct charset + { + +// m_Plain[i] = m_PlainCharset[nIndexOfX32 % m_vCharset[j].m_nPlainCharsetLen]; +// nIndexOfX32 /= m_vCharset[j].m_nPlainCharsetLen; + + unsigned int nPlainCharsetLen = m_vCharset[j].m_nPlainCharsetLen; + unsigned int nTemp; +#ifdef _WIN32 + __asm + { + mov eax, nIndexOfX32 + xor edx, edx + div nPlainCharsetLen + mov nIndexOfX32, eax + mov nTemp, edx + } + m_Plain[i] = m_vCharset[j].m_PlainCharset[nTemp]; +#else + __asm__ __volatile__ ( "mov %2, %%eax;" + "xor %%edx, %%edx;" + "divl %3;" + "mov %%eax, %0;" + "mov %%edx, %1;" + : "=m"(nIndexOfX32), "=m"(nTemp) + : "m"(nIndexOfX32), "m"(nPlainCharsetLen) + : "%eax", "%edx" + ); + m_Plain[i] = m_vCharset[j].m_PlainCharset[nTemp]; +#endif + break; + } + } + } +#endif +} + +void CChainWalkContext::PlainToHash() +{ + m_pHashRoutine(m_Plain, m_nPlainLen, m_Hash); +} + +void CChainWalkContext::HashToIndex(int nPos) +{ + m_nIndex = (*(uint64*)m_Hash + m_nReduceOffset + nPos) % m_nPlainSpaceTotal; +} + +uint64 CChainWalkContext::GetIndex() +{ + return m_nIndex; +} +const uint64 *CChainWalkContext::GetIndexPtr() +{ + return &m_nIndex; +} + +string CChainWalkContext::GetPlain() +{ + string sRet; + int i; + for (i = 0; i < m_nPlainLen; i++) + { + char c = m_Plain[i]; + //if (c >= 32 && c <= 126) + //if (c >= 32) + sRet += c; + //else + // sRet += '?'; + } + + return sRet; +} + +string CChainWalkContext::GetBinary() +{ + return HexToStr(m_Plain, m_nPlainLen); +} +/* +string CChainWalkContext::GetPlainBinary() +{ + string sRet; + sRet += GetPlain(); + int i; + for (i = 0; i < m_nPlainLenMax - m_nPlainLen; i++) + sRet += ' '; + + sRet += "|"; + + sRet += GetBinary(); + for (i = 0; i < m_nPlainLenMax - m_nPlainLen; i++) + sRet += " "; + + return sRet; +} +*/ +string CChainWalkContext::GetHash() +{ + return HexToStr(m_Hash, m_nHashLen); +} + +bool CChainWalkContext::CheckHash(unsigned char* pHash) +{ + if (memcmp(m_Hash, pHash, m_nHashLen) == 0) + return true; + + return false; +} + +bool CChainWalkContext::isOldFormat() +{ + return isOldRtFormat; +} +bool CChainWalkContext::isNewFormat() +{ + return isNewRtFormat; +} + diff --git a/Client Applications/rcracki_mt/ChainWalkContext.h b/Client Applications/rcracki_mt/ChainWalkContext.h new file mode 100644 index 0000000..e7aea41 --- /dev/null +++ b/Client Applications/rcracki_mt/ChainWalkContext.h @@ -0,0 +1,85 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifndef _CHAINWALKCONTEXT_H +#define _CHAINWALKCONTEXT_H + +#include "HashRoutine.h" +#include "Public.h" + +typedef struct +{ + unsigned char m_PlainCharset[255]; + int m_nPlainCharsetLen; + int m_nPlainLenMin; + int m_nPlainLenMax; + string m_sPlainCharsetName; + string m_sPlainCharsetContent; +} stCharset; +class CChainWalkContext +{ +public: + CChainWalkContext(); + virtual ~CChainWalkContext(); + +private: + static string m_sHashRoutineName; + static HASHROUTINE m_pHashRoutine; // Configuration + static int m_nHashLen; // Configuration + static bool isOldRtFormat; + static bool isNewRtFormat; + static vector m_vCharset; + static int m_nPlainLenMinTotal, m_nPlainLenMaxTotal; + static uint64 m_nPlainSpaceUpToX[MAX_PLAIN_LEN + 1]; // Performance consideration + static uint64 m_nPlainSpaceTotal; // Performance consideration + static int m_nHybridCharset; + static int m_nRainbowTableIndex; // Configuration + static uint64 m_nReduceOffset; // Performance consideration + + // Context + uint64 m_nIndex; + unsigned char m_Plain[MAX_PLAIN_LEN]; + int m_nPlainLen; + unsigned char m_Hash[MAX_HASH_LEN]; + static unsigned char m_Salt[MAX_SALT_LEN]; + static int m_nSaltLen; +private: + static bool LoadCharset(string sCharset); + +public: + static bool SetHashRoutine(string sHashRoutineName); // Configuration + static bool SetPlainCharset(string sCharsetName, int nPlainLenMin, int nPlainLenMax); // Configuration + static bool SetRainbowTableIndex(int nRainbowTableIndex); + static bool SetSalt(unsigned char *Salt, int nSaltLength);// Configuration + static bool SetupWithPathName(string sPathName, int& nRainbowChainLen, int& nRainbowChainCount); // Wrapper + static string GetHashRoutineName(); + static int GetHashLen(); + static string GetPlainCharsetName(); + static string GetPlainCharsetContent(); + static int GetPlainLenMin(); + static int GetPlainLenMax(); + static uint64 GetPlainSpaceTotal(); + static int GetRainbowTableIndex(); + static void Dump(); + static bool isOldFormat(); + static bool isNewFormat(); + + void SetIndex(uint64 nIndex); + void SetHash(unsigned char* pHash); // The length should be m_nHashLen + + void IndexToPlain(); + void PlainToHash(); + void HashToIndex(int nPos); + + uint64 GetIndex(); + const uint64* GetIndexPtr(); + string GetPlain(); + string GetBinary(); + string GetHash(); + bool CheckHash(unsigned char* pHash); // The length should be m_nHashLen +}; + +#endif diff --git a/Client Applications/rcracki_mt/ChainWalkSet.cpp b/Client Applications/rcracki_mt/ChainWalkSet.cpp new file mode 100644 index 0000000..3069fee --- /dev/null +++ b/Client Applications/rcracki_mt/ChainWalkSet.cpp @@ -0,0 +1,305 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifdef _WIN32 + #pragma warning(disable : 4786) +#endif + +#include "ChainWalkSet.h" + +CChainWalkSet::CChainWalkSet() +{ + m_sHashRoutineName = ""; + m_sPlainCharsetName = ""; + m_nPlainLenMin = 0; + m_nPlainLenMax = 0; + m_nRainbowTableIndex = 0; + m_nRainbowChainLen = 0; + debug = false; + sPrecalcPathName = ""; + preCalcPart = 0; +} + +CChainWalkSet::~CChainWalkSet() +{ + DiscardAll(); +} + +void CChainWalkSet::DiscardAll() +{ + //printf("debug: discarding all walk...\n"); + + list::iterator it; + for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++) + delete it->pIndexE; + m_lChainWalk.clear(); +} + +string CChainWalkSet::CheckOrRotatePreCalcFile() +{ + char sPreCalcFileName[255]; + + // 255 files limit to be sure + for (; preCalcPart < 255; preCalcPart++) + { + sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), preCalcPart); + string sReturnPreCalcPath(sPreCalcFileName); + + unsigned int fileLen = 0; + + FILE* file = fopen(sReturnPreCalcPath.c_str(), "ab"); + if(file!=NULL) + { + fileLen = GetFileLen(file); + unsigned int nextFileLen = fileLen + (sizeof(uint64) * (m_nRainbowChainLen-1)); + // Rotate to next file if we are going to pass 2GB filesize + if (nextFileLen < ((unsigned)2 * 1024 * 1024 * 1024)) + { + // We might want to vPrecalcFiles.push_back(sReturnPreCalcPath) if we just created this file + // We don't as only newly generated chainwalksets will be stored to this new file, so we don't have to look there + if (debug) printf("Debug: Using for precalc: %s\n", sReturnPreCalcPath.c_str()); + fclose(file); + return sReturnPreCalcPath; + } + fclose(file); + } + } +} + +void CChainWalkSet::updateUsedPrecalcFiles() +{ + // we might also use this function to search a wildcard path of precalc files + vPrecalcFiles.clear(); + char sPreCalcFileName[255]; + + int i; + // 255 files max + for (i = 0; i < 255; i++) + { + sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), i); + string sTryPreCalcPath(sPreCalcFileName); + FILE* file = fopen(sTryPreCalcPath.c_str(), "rb"); + if(file!=NULL) { + vPrecalcFiles.push_back(sTryPreCalcPath); + fclose(file); + } + else { + break; + } + } +} + +void CChainWalkSet::removePrecalcFiles() +{ + if (debug) printf("Debug: Removing precalc files.\n"); + updateUsedPrecalcFiles(); + string sCurrentPrecalcPathName = ""; + string sCurrentPrecalcIndexPathName = ""; + + int i; + for (i = 0; i < (int)vPrecalcFiles.size(); i++) + { + sCurrentPrecalcPathName = vPrecalcFiles[i]; + sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index"; + + if (debug) printf("Debug: Removing precalc file: %s\n", sCurrentPrecalcPathName.c_str()); + + if (remove(sCurrentPrecalcPathName.c_str()) != 0) + if (debug) printf("Debug: Failed removing precalc file: %s\n", sCurrentPrecalcPathName.c_str()); + + if (debug) printf("Debug: Removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str()); + + if (remove(sCurrentPrecalcIndexPathName.c_str()) != 0) + if (debug) printf("Debug: Failed removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str()); + + } +} + +bool CChainWalkSet::FindInFile(uint64* pIndexE, unsigned char* pHash, int nHashLen) +{ + int gotPrecalcOnLine = -1; + char precalculationLine[255]; + sprintf(precalculationLine, "%s_%s#%d-%d_%d_%d:%s\n", m_sHashRoutineName.c_str(), m_sPlainCharsetName.c_str(), m_nPlainLenMin, m_nPlainLenMax, m_nRainbowTableIndex, m_nRainbowChainLen, HexToStr(pHash, nHashLen).c_str() ); + string precalcString(precalculationLine); + + string sCurrentPrecalcPathName = ""; + string sCurrentPrecalcIndexPathName = ""; + int offset; + + int i; + for (i = 0; i < (int)vPrecalcFiles.size() && gotPrecalcOnLine == -1; i++) + { + sCurrentPrecalcPathName = vPrecalcFiles[i]; + sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index"; + + offset = 0; + + vector precalcLines; + if (ReadLinesFromFile(sCurrentPrecalcIndexPathName.c_str(), precalcLines)) + { + int j; + for (j = 0; j < (int)precalcLines.size(); j++) + { + if (precalcString.compare(0, precalcString.size()-1, precalcLines[j]) == 0) + { + gotPrecalcOnLine = j; + break; + } + + // Parse + vector vPart; + if (SeperateString(precalcLines[j], "___:", vPart)) + { + // add to offset + offset += ((atoi(vPart[3].c_str())-1) * sizeof(uint64)); + } + else { + // corrupt file + printf("Corrupted precalculation file!\n"); + gotPrecalcOnLine = -1; + break; + } + } + } + } + + if (gotPrecalcOnLine > -1) + { + if (debug) printf("Debug: Reading pre calculations from file, line %d offset %d\n", gotPrecalcOnLine, offset); + + FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "rb"); + + if (fp!=NULL) { + fseek(fp, offset, SEEK_SET); + + // We should do some verification here, for example by recalculating the middle chain, to catch corrupted files + if(fread(pIndexE, sizeof(uint64), m_nRainbowChainLen-1, fp) != m_nRainbowChainLen-1) + printf("File read error."); + fclose(fp); + } + else + printf("Cannot open precalculation file %s.\n", sCurrentPrecalcPathName.c_str()); + + //printf("\npIndexE[0]: %s\n", uint64tostr(pIndexE[0]).c_str()); + //printf("\npIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pIndexE[m_nRainbowChainLen-2]).c_str()); + + return true; + } + + return false; + +} + +void CChainWalkSet::StoreToFile(uint64* pIndexE, unsigned char* pHash, int nHashLen) +{ + if (debug) printf("\nDebug: Storing precalc\n"); + + string sCurrentPrecalcPathName = CheckOrRotatePreCalcFile(); + string sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index"; + + FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "ab"); + if(fp!=NULL) + { + if(fwrite(pIndexE, sizeof(uint64), m_nRainbowChainLen-1, fp) != m_nRainbowChainLen-1) + printf("File write error."); + else + { + FILE* file = fopen(sCurrentPrecalcIndexPathName.c_str(), "a"); + if (file!=NULL) + { + char precalculationLine[255]; + sprintf(precalculationLine, "%s_%s#%d-%d_%d_%d:%s\n", m_sHashRoutineName.c_str(), m_sPlainCharsetName.c_str(), m_nPlainLenMin, m_nPlainLenMax, m_nRainbowTableIndex, m_nRainbowChainLen, HexToStr(pHash, nHashLen).c_str() ); + fputs (precalculationLine, file); + fclose (file); + } + } + fclose(fp); + } + else + printf("Cannot open precalculation file %s\n", sCurrentPrecalcPathName.c_str()); + +} + +uint64* CChainWalkSet::RequestWalk(unsigned char* pHash, int nHashLen, + string sHashRoutineName, + string sPlainCharsetName, int nPlainLenMin, int nPlainLenMax, + int nRainbowTableIndex, + int nRainbowChainLen, + bool& fNewlyGenerated, + bool setDebug, + string sPrecalc) +{ + debug = setDebug; + sPrecalcPathName = sPrecalc; + + if ( m_sHashRoutineName != sHashRoutineName + || m_sPlainCharsetName != sPlainCharsetName + || m_nPlainLenMin != nPlainLenMin + || m_nPlainLenMax != nPlainLenMax + || m_nRainbowTableIndex != nRainbowTableIndex + || m_nRainbowChainLen != nRainbowChainLen) + { + DiscardAll(); + + m_sHashRoutineName = sHashRoutineName; + m_sPlainCharsetName = sPlainCharsetName; + m_nPlainLenMin = nPlainLenMin; + m_nPlainLenMax = nPlainLenMax; + m_nRainbowTableIndex = nRainbowTableIndex; + m_nRainbowChainLen = nRainbowChainLen; + + ChainWalk cw; + memcpy(cw.Hash, pHash, nHashLen); + cw.pIndexE = new uint64[nRainbowChainLen - 1]; + m_lChainWalk.push_back(cw); + + // Only update this list when we search through another rainbow table + updateUsedPrecalcFiles(); + + if (!FindInFile(cw.pIndexE, pHash, nHashLen)) + fNewlyGenerated = true; + else + fNewlyGenerated = false; + return cw.pIndexE; + } + + list::iterator it; + for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++) + { + if (memcmp(it->Hash, pHash, nHashLen) == 0) + { + fNewlyGenerated = false; + return it->pIndexE; + } + } + + ChainWalk cw; + memcpy(cw.Hash, pHash, nHashLen); + cw.pIndexE = new uint64[nRainbowChainLen - 1]; + m_lChainWalk.push_back(cw); + + if (!FindInFile(cw.pIndexE, pHash, nHashLen)) + fNewlyGenerated = true; + else + fNewlyGenerated = false; + return cw.pIndexE; +} + +void CChainWalkSet::DiscardWalk(uint64* pIndexE) +{ + list::iterator it; + for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++) + { + if (it->pIndexE == pIndexE) + { + delete it->pIndexE; + m_lChainWalk.erase(it); + return; + } + } + + printf("debug: pIndexE not found\n"); +} diff --git a/Client Applications/rcracki_mt/ChainWalkSet.h b/Client Applications/rcracki_mt/ChainWalkSet.h new file mode 100644 index 0000000..05622cf --- /dev/null +++ b/Client Applications/rcracki_mt/ChainWalkSet.h @@ -0,0 +1,58 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifndef _CHAINWALKSET_H +#define _CHAINWALKSET_H + +#include "Public.h" + +struct ChainWalk +{ + unsigned char Hash[MAX_HASH_LEN]; + //int nHashLen; // Implied + uint64* pIndexE; // mapStartPosIndexE, Len = nRainbowChainLen - 1 +}; + +class CChainWalkSet +{ +public: + CChainWalkSet(); + virtual ~CChainWalkSet(); + +private: + string m_sHashRoutineName; // Discard all if not match + string m_sPlainCharsetName; // Discard all if not match + int m_nPlainLenMin; // Discard all if not match + int m_nPlainLenMax; // Discard all if not match + int m_nRainbowTableIndex; // Discard all if not match + int m_nRainbowChainLen; // Discard all if not match + list m_lChainWalk; + bool debug; + string sPrecalcPathName; + int preCalcPart; + vector vPrecalcFiles; + +private: + void DiscardAll(); + bool FindInFile(uint64* pIndexE, unsigned char* pHash, int nHashLen); + string CheckOrRotatePreCalcFile(); + void updateUsedPrecalcFiles(); + +public: + uint64* RequestWalk(unsigned char* pHash, int nHashLen, + string sHashRoutineName, + string sPlainCharsetName, int nPlainLenMin, int nPlainLenMax, + int nRainbowTableIndex, + int nRainbowChainLen, + bool& fNewlyGenerated, + bool setDebug, + string sPrecalc); + void DiscardWalk(uint64* pIndexE); + void StoreToFile(uint64* pIndexE, unsigned char* pHash, int nHashLen); + void removePrecalcFiles(); +}; + +#endif diff --git a/Client Applications/rcracki_mt/ChangeLog.txt b/Client Applications/rcracki_mt/ChangeLog.txt new file mode 100644 index 0000000..0b07cd0 --- /dev/null +++ b/Client Applications/rcracki_mt/ChangeLog.txt @@ -0,0 +1,52 @@ +[rcracki_mt ChangeLog] + +0.6.2 (2 Juli 2009, 13:37): +* Fixed linux support (tty stuff and now actually compiles) +* Fixed precalculation code + +0.6.1 (14 May 2009, 22:12): +* bug fixed where the list of rainbow tables is doubled when you resume a session and you have default RT locations in your ini + +0.6 (14 May 2009, 20:47): +* Finding .rti files recursively +* Fixed memory allocation bugs (also trying to save appropriate amount of memory for chainwalksets... these can become really large with the new tables) +* Real pause/resume function, you can resume a session with -r +* Session support, use -s session_name. Combine this with -r to resume a session other then the default +* Ini file support, store some default values such as rainbow table directories. +* Tab separated results (stdout) +* Support pause during cracking and 'skip' during unicode correction for Linux +* A readme / 'manual' ! + +0.5 (16 Apr 2009, 22:47): +* Support for the old non-indexed .rt format, it should work with both type of tables in one run... I didn't test this feature thoroughly +* Using some other pieces of code for algorithms +* Support for .lst files from Cain as input (patch from James Dickson) - use for example -c LMNT.lst +* Fixed some bugs +* Dunno anymore, left this version lying around for too long... + +0.4 (oops, a second 0.4) (13 Dec 2008, 18:20): +* Improved file reading performance + +0.4 (27 Nov 2008, 00:09): +* Source included +* Memory usage down to about 50% (tnx sc00bz for pointing out the inefficiency, tnx jci for helping with the code) +* Works under Linux! (using pthreads now instead of Windows threads) +* Speed up: implemented MD4 reference implementation, not using OpenSSL for NTLM anymore (tnx Bitweasil for supplying 98% of the code) +* Speed up: using OpenSSL a lot faster (tnx jci for pointing that out) +* Probably some more small things i forgot + +0.3 (16 Nov 2008, 01:01): +* Improved command line argument parsing (order no longer matters) +* Option to write (temporary) output to a file, use -o pick_a_nice_filename.txt +* Option to pause, press 'P' to pause/unpause (Windows only) +* For pwdump searches: unicode correction is done when case correction fails + +0.2 (28 Oct 2008, 01:42): +* False alarm checking now also multi threaded +* Search one level of subdirectories for rainbow table files + +0.1 (27 Oct 2008, 00:14): +* Initial multithreaded version, using Windows threads. +* Using multiple threads for the pre-calculation part. +* Added a simple 'progress' message, so you can see how many hashes are being pre-calculated + diff --git a/Client Applications/rcracki_mt/CrackEngine.cpp b/Client Applications/rcracki_mt/CrackEngine.cpp new file mode 100644 index 0000000..3ed82de --- /dev/null +++ b/Client Applications/rcracki_mt/CrackEngine.cpp @@ -0,0 +1,1291 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifdef _WIN32 + #pragma warning(disable : 4786 4267 4018) +#endif + +#include "CrackEngine.h" + +#include +#include "RTI2Reader.h" + +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_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 vHash; + hs.GetLeftHashWithLen(vHash, CChainWalkContext::GetHashLen()); + printf("searching for %d hash%s...\n", vHash.size(), + vHash.size() > 1 ? "es" : ""); + + int nChainWalkStep = 0; + int nFalseAlarm = 0; + int nChainWalkStepDueToFalseAlarm = 0; + + vector threadPool; + vector pThreads; + + 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; + + int 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... "); + clock_t t1 = clock(); + while (pausing) + { + if (_kbhit()) + { + ch = _getch(); + ch = toupper(ch); + if (ch == 'P') + { + printf( " [Continuing]\n"); + pausing = false; + clock_t t2 = clock(); + float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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... "); + clock_t t1 = clock(); + while (pausing) + { + if ((c = tty_getchar()) >= 0) + { + tty_flush(); + if (c == 112) + { + printf( " [Continuing]\n"); + pausing = false; + clock_t t2 = clock(); + float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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) + { + //printf("Pre-calculating hash %d of %d.\t\t\r", nHashIndex+1, vHash.size()); + printf("Pre-calculating hash %d of %d.%-20s\r", nHashIndex+1, vHash.size(), ""); + threadPool.clear(); + pThreads.clear(); + + int thread_ID; + for (thread_ID = 0; thread_ID < 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(); + } + + //printf("\t\t\t\t\r"); + printf("%-50s\r", ""); + + + } + + //printf("Checking false alarms for hash %d of %d.\t\t\r", nHashIndex+1, vHash.size()); + printf("Checking false alarms for hash %d of %d.%-20s\r", nHashIndex+1, 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); + } + + int 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 < maxThreads - 1 ) { + thread_ID++; + } else { + thread_ID = 0; + } + } + } + } + + for (thread_ID = 0; thread_ID < 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 vHash; + //vector vIndices; + //vector vChains; + hs.GetLeftHashWithLen(vHash, CChainWalkContext::GetHashLen()); + printf("searching for %d hash%s...\n", vHash.size(), + vHash.size() > 1 ? "es" : ""); + + int nChainWalkStep = 0; + int nFalseAlarm = 0; + int nChainWalkStepDueToFalseAlarm = 0; + + vector threadPool; + vector pThreads; + + 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; + + int 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... "); + clock_t t1 = clock(); + while (pausing) + { + if (_kbhit()) + { + ch = _getch(); + ch = toupper(ch); + if (ch == 'P') + { + printf( " [Continuing]\n"); + pausing = false; + clock_t t2 = clock(); + float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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... "); + clock_t t1 = clock(); + while (pausing) + { + if ((c = tty_getchar()) >= 0) + { + tty_flush(); + if (c == 112) + { + printf( " [Continuing]\n"); + pausing = false; + clock_t t2 = clock(); + float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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) + { + //printf("Pre-calculating hash %d of %d.\t\t\r", nHashIndex+1, vHash.size()); + printf("Pre-calculating hash %d of %d.%-20s\r", nHashIndex+1, vHash.size(), ""); + threadPool.clear(); + pThreads.clear(); + + int thread_ID; + for (thread_ID = 0; thread_ID < 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(); + } + + m_cws.StoreToFile(pStartPosIndexE, TargetHash, nHashLen); + + //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", ""); + + + } + + 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 %d of %d.%-20s\r", nHashIndex+1, vHash.size(), ""); + + int i; + for (i = 0; i < maxThreads; i++) + { + rcrackiThread* r_Thread = new rcrackiThread(TargetHash); + threadPool.push_back(r_Thread); + } + + int 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 < maxThreads - 1 ) { + thread_ID++; + } else { + thread_ID = 0; + } + } + } + + for (thread_ID = 0; thread_ID < 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 sessionFinishedPathNames; + if (ReadLinesFromFile(sProgressPathName.c_str(), sessionFinishedPathNames)) + { + int i; + for (i = 0; i < sessionFinishedPathNames.size(); i++) + { + if (sessionFinishedPathNames[i] == sPathName) + { + printf("Skipping %s\n", sPathName.c_str()); + return; + } + } + } + } + + // FileName +#ifdef _WIN32 + int nIndex = sPathName.find_last_of('\\'); +#else + int nIndex = sPathName.find_last_of('/'); +#endif + string sFileName; + if (nIndex != -1) + 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: %u\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 doNewFormat = CChainWalkContext::isNewFormat(); + int sizeOfChain; + bool fVerified = false; + unsigned int nFileLen = GetFileLen(file); + + if (doOldFormat) + sizeOfChain = 16; + else + sizeOfChain = 8; + + //if (nFileLen % 8 != 0 || nRainbowChainCount * 8 != nFileLen) + if ((nFileLen % sizeOfChain != 0 || nRainbowChainCount * sizeOfChain != nFileLen) && doNewFormat == false) + printf("file length mismatch\n"); + else + { + fseek(file, 0, SEEK_SET); + + unsigned int bytesForChainWalkSet = hs.GetStatHashTotal() * (nRainbowChainLen-1) * 8; + if (debug) printf("Debug: Saving %u bytes of memory for chainwalkset.\n", bytesForChainWalkSet); + + static CMemoryPool mp(bytesForChainWalkSet); + unsigned int nAllocatedSize; + if (doNewFormat || doOldFormat) + { + RTI2Reader *pReader; + if(doNewFormat) { + pReader = new RTI2Reader(sPathName); + + } + if (debug) printf("Debug: This is a table in the old .rt format.\n"); + RainbowChainO* pChain = (RainbowChainO*)mp.Allocate(nFileLen, nAllocatedSize); + if (debug) printf("Allocated %u bytes, filelen %u\n", nAllocatedSize, nFileLen); + 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 (ftell(file) == nFileLen) + break; + + // Load table chunk + if (debug) printf("reading...\n"); + unsigned int nDataRead = 0; + clock_t t1 = clock(); + if (doNewFormat) + { + nDataRead = nAllocatedSize / 16; + pReader->ReadChains(nDataRead, pChain); + nDataRead *= 8; // Convert from chains read to bytes + if(nDataRead == 0) // No more data + break; + } + else { + nDataRead = fread(pChain, 1, nAllocatedSize, file); + } + clock_t t2 = clock(); + float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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 + t1 = clock(); + SearchTableChunkOld(pChain, nRainbowChainLen, nRainbowChainCountRead, hs); + t2 = clock(); + fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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); + unsigned int 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); + if (debug) printf("Debug: Allocated %u bytes for index with filelen %u\n", nAllocatedSizeIndex, nFileLenIndex); + + if (pIndex != NULL && nAllocatedSizeIndex > 0) + { + nAllocatedSizeIndex = nAllocatedSizeIndex / sizeof(IndexChain) * sizeof(IndexChain); // Round to sizeOfIndexChain boundary + + fseek(fIndex, 0, SEEK_SET); + int nProcessedIndexChains = 0; + + while (true) // Index chunk read loop + { + if (ftell(fIndex) == nFileLenIndex) + break; + + // Load index chunk + if (debug) printf("Debug: Setting index to 0x00 in memory, %u bytes\n", nAllocatedSizeIndex); + memset(pIndex, 0x00, nAllocatedSizeIndex); + printf("reading index... "); + clock_t t1 = clock(); + unsigned int nDataRead = fread(pIndex, 1, nAllocatedSizeIndex, fIndex); + clock_t t2 = clock(); + + float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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); + if (debug) printf("Debug: Allocated %u bytes for %u chains, filelen %u\n", nAllocatedSize, nCoveredRainbowTableChains, nFileLen); + + if (pChain != NULL && nAllocatedSize > 0) + { + nAllocatedSize = nAllocatedSize / sizeOfChain * sizeOfChain; // Round to sizeOfChain boundary + + //fseek(file, 0, SEEK_SET); + //bool fVerified = false; + int nProcessedChains = 0; + while (true) // Chunk read loop + { + if (ftell(file) == nFileLen) + break; + + if (nProcessedChains >= nCoveredRainbowTableChains) + break; + + // Load table chunk + if (debug) printf("Debug: Setting pChain to 0x00 in memory\n"); + memset(pChain, 0x00, nAllocatedSize); + printf("reading table... "); + clock_t t1 = clock(); + unsigned int nDataRead = fread(pChain, 1, nAllocatedSize, file); + clock_t t2 = clock(); + + float fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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...\n"); + + // 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; + } + + // Search table chunk + t1 = clock(); + float preTime = m_fTotalCryptanalysisTime; + + SearchTableChunk(pChain, nRainbowChainLen, nRainbowChainCountRead, hs, pIndex, nIndexChainCountRead, nProcessedChains); + float postTime = m_fTotalCryptanalysisTime; + t2 = clock(); + fTime = 1.0f * (t2 - t1) / CLOCKS_PER_SEC; + 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 vPathName, CHashSet& hs, int i_maxThreads, bool resume, bool bDebug) +{ +#ifndef _WIN32 + tty_init(); +#endif + resumeSession = resume; + debug = bDebug; + + maxThreads = i_maxThreads; + // Reset statistics + ResetStatistics(); + + // Sort vPathName (CChainWalkSet need it) + int 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; +} + +int CCrackEngine::GetStatTotalChainWalkStep() +{ + return m_nTotalChainWalkStep; +} + +int CCrackEngine::GetStatTotalFalseAlarm() +{ + return m_nTotalFalseAlarm; +} + +int CCrackEngine::GetStatTotalChainWalkStepDueToFalseAlarm() +{ + return m_nTotalChainWalkStepDueToFalseAlarm; +} diff --git a/Client Applications/rcracki_mt/CrackEngine.h b/Client Applications/rcracki_mt/CrackEngine.h new file mode 100644 index 0000000..e69bb0f --- /dev/null +++ b/Client Applications/rcracki_mt/CrackEngine.h @@ -0,0 +1,75 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifndef _CRACKENGINE_H +#define _CRACKENGINE_H + +#include "Public.h" +#include "HashSet.h" +#include "ChainWalkContext.h" +#include "MemoryPool.h" +#include "ChainWalkSet.h" +#include "rcrackiThread.h" +#ifdef _WIN32 +#include +#include +#endif +#include + +class CCrackEngine +{ +public: + CCrackEngine(); + virtual ~CCrackEngine(); + +private: + CChainWalkSet m_cws; + int maxThreads; + bool writeOutput; + bool resumeSession; + string outputFile; + string sSessionPathName; + string sProgressPathName; + string sPrecalcPathName; + //string sPrecalcIndexPathName; + bool debug; + bool keepPrecalcFiles; + + // Statistics + float m_fTotalDiskAccessTime; + float m_fTotalCryptanalysisTime; + int m_nTotalChainWalkStep; + int m_nTotalFalseAlarm; + int m_nTotalChainWalkStepDueToFalseAlarm; + FILE *m_fChains; + +private: + void ResetStatistics(); + RainbowChain *BinarySearch(RainbowChain *pChain, int nChainCountRead, uint64 nIndex, IndexChain *pIndex, int nIndexSize, int nIndexStart); + int BinarySearchOld(RainbowChainO* pChain, int nRainbowChainCount, uint64 nIndex); + void GetChainIndexRangeWithSameEndpoint(RainbowChainO* pChain, + int nRainbowChainCount, + int nChainIndex, + int& nChainIndexFrom, + int& nChainIndexTo); + void SearchTableChunk(RainbowChain* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs, IndexChain *pIndex, int nIndexSize, int nChainStart); + void SearchTableChunkOld(RainbowChainO* pChain, int nRainbowChainLen, int nRainbowChainCount, CHashSet& hs); + //bool CheckAlarm(RainbowChain* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs); + //bool CheckAlarmOld(RainbowChainO* pChain, int nGuessedPos, unsigned char* pHash, CHashSet& hs); + +public: + void SearchRainbowTable(string sPathName, CHashSet& hs); + void Run(vector vPathName, CHashSet& hs, int i_maxThreads, bool resume, bool bDebug); + float GetStatTotalDiskAccessTime(); + float GetStatTotalCryptanalysisTime(); + int GetStatTotalChainWalkStep(); + int GetStatTotalFalseAlarm(); + int GetStatTotalChainWalkStepDueToFalseAlarm(); + void setOutputFile(string sPathName); + void setSession(string sSessionPathName, string sProgressPathName, string sPrecalcPathName, bool keepPrecalc); +}; + +#endif diff --git a/Client Applications/rcracki_mt/HashAlgorithm.cpp b/Client Applications/rcracki_mt/HashAlgorithm.cpp new file mode 100644 index 0000000..66513fc --- /dev/null +++ b/Client Applications/rcracki_mt/HashAlgorithm.cpp @@ -0,0 +1,414 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei + + Changes: not using OpenSSL routines the slow way anymore, as suggested by jci. +*/ + +#include "HashAlgorithm.h" + +#include "Public.h" + +#include +#include +#include +#include +#include +#include + +//#include "md5.h" +#include "fast_md5.h" +#include "md4.h" +#include "sha1.h" +#ifdef _WIN32 + #pragma comment(lib, "libeay32.lib") +#endif +#define MSCACHE_HASH_SIZE 16 +void setup_des_key(unsigned char key_56[], des_key_schedule &ks) +{ + des_cblock key; + + key[0] = key_56[0]; + key[1] = (key_56[0] << 7) | (key_56[1] >> 1); + key[2] = (key_56[1] << 6) | (key_56[2] >> 2); + key[3] = (key_56[2] << 5) | (key_56[3] >> 3); + key[4] = (key_56[3] << 4) | (key_56[4] >> 4); + key[5] = (key_56[4] << 3) | (key_56[5] >> 5); + key[6] = (key_56[5] << 2) | (key_56[6] >> 6); + key[7] = (key_56[6] << 1); + + //des_set_odd_parity(&key); + des_set_key(&key, ks); +} + +void HashLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash) +{ + /* + unsigned char data[7] = {0}; + memcpy(data, pPlain, nPlainLen > 7 ? 7 : nPlainLen); + */ + + int i; + for (i = nPlainLen; i < 7; i++) + pPlain[i] = 0; + + static unsigned char magic[] = {0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; + des_key_schedule ks; + //setup_des_key(data, ks); + setup_des_key(pPlain, ks); + des_ecb_encrypt((des_cblock*)magic, (des_cblock*)pHash, ks, DES_ENCRYPT); +} + +void HashLMCHALL(unsigned char* pPlain, int nPlainLen, unsigned char* pHash) +{ + unsigned char pass[14]; + unsigned char pre_lmresp[21]; + static unsigned char magic[] = {0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; + static unsigned char spoofed_challange[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + des_key_schedule ks; + + memset (pass,0,sizeof(pass)); + memset (pre_lmresp,0,sizeof(pre_lmresp)); + + memcpy (pass,pPlain, nPlainLen); + + setup_des_key(pass, ks); + des_ecb_encrypt((des_cblock*)magic, (des_cblock*)pre_lmresp, ks, DES_ENCRYPT); + + setup_des_key(&pass[7], ks); + des_ecb_encrypt((des_cblock*)magic, (des_cblock*)&pre_lmresp[8], ks, DES_ENCRYPT); + + setup_des_key(pre_lmresp, ks); + des_ecb_encrypt((des_cblock*)spoofed_challange, (des_cblock*)pHash, ks, DES_ENCRYPT); + + setup_des_key(&pre_lmresp[7], ks); + des_ecb_encrypt((des_cblock*)spoofed_challange, (des_cblock*)&pHash[8], ks, DES_ENCRYPT); + + setup_des_key(&pre_lmresp[14], ks); + des_ecb_encrypt((des_cblock*)spoofed_challange, (des_cblock*)&pHash[16], ks, DES_ENCRYPT); + +} + +void HashHALFLMCHALL(unsigned char* pPlain, int nPlainLen, unsigned char* pHash) +{ + unsigned char pre_lmresp[8]; + static unsigned char magic[] = {0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; + static unsigned char salt[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + + des_key_schedule ks; + unsigned char plain[8] = {0}; + memcpy(plain, pPlain, nPlainLen); + setup_des_key(plain, ks); + des_ecb_encrypt((des_cblock*)magic, (des_cblock*)pre_lmresp, ks, DES_ENCRYPT); + + setup_des_key(pre_lmresp, ks); + des_ecb_encrypt((des_cblock*)salt, (des_cblock*)pHash, ks, DES_ENCRYPT); +} + + + +void HashNTLMCHALL(unsigned char* pPlain, int nPlainLen, unsigned char* pHash) +{ + unsigned char UnicodePlain[MAX_PLAIN_LEN]; + static unsigned char spoofed_challange[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + + int len = (nPlainLen < 127) ? nPlainLen : 127; + int i; + + for (i = 0; i < len; i++) + { + UnicodePlain[i * 2] = pPlain[i]; + UnicodePlain[i * 2 + 1] = 0x00; + } + + des_key_schedule ks; + unsigned char lm[21]; + + /*MD4_CTX ctx; + MD4_Init(&ctx); + MD4_Update(&ctx, UnicodePlain, len * 2); + MD4_Final(lm, &ctx); */ + MD4_NEW(UnicodePlain, len * 2, lm); + + //MD4(UnicodePlain, len * 2, lm); + lm[16] = lm[17] = lm[18] = lm[19] = lm[20] = 0; + + setup_des_key(lm, ks); + des_ecb_encrypt((des_cblock*)spoofed_challange, (des_cblock*)pHash, ks, DES_ENCRYPT); + + setup_des_key(&lm[7], ks); + des_ecb_encrypt((des_cblock*)spoofed_challange, (des_cblock*)&pHash[8], ks, DES_ENCRYPT); + + setup_des_key(&lm[14], ks); + des_ecb_encrypt((des_cblock*)spoofed_challange, (des_cblock*)&pHash[16], ks, DES_ENCRYPT); +} + + +void HashORACLE(unsigned char* pPlain, int nPlainLen, unsigned char* pHash) +{ + char ToEncrypt[256]; + char temp[256]; + char username[256]; + + DES_cblock iv,iv2; + DES_key_schedule ks1,ks2; + unsigned char deskey_fixed[]={ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; + int i,j; + + strcpy (username, "SYS"); + int userlen = 3; + + strupr ((char*) pPlain); + memset (ToEncrypt,0,sizeof(ToEncrypt)); + + for (i=1,j=0; j ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +void _crypt_to64(char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +void HashPIX(unsigned char* pPlain, int nPlainLen, unsigned char* pHash) +{ + char temp[MD5_DIGEST_LENGTH+1]; + unsigned char final[MD5_DIGEST_LENGTH]; + char* pass = (char*) calloc (nPlainLen+MD5_DIGEST_LENGTH,sizeof(char)); + + memcpy (pass,pPlain,nPlainLen); + + /*MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, (unsigned char *) pass, MD5_DIGEST_LENGTH); + MD5_Final(final, &ctx);*/ + fast_MD5((unsigned char *) pass, MD5_DIGEST_LENGTH, final); + + char* p = (char*) temp; + _crypt_to64(p,*(unsigned long*) (final+0),4); p += 4; + _crypt_to64(p,*(unsigned long*) (final+4),4); p += 4; + _crypt_to64(p,*(unsigned long*) (final+8),4); p += 4; + _crypt_to64(p,*(unsigned long*) (final+12),4); p += 4; + *p=0; + + memcpy(pHash,temp,MD5_DIGEST_LENGTH); + + free (pass); +} + +#ifndef _WIN32 +char *strupr(char *s1) +{ + char *p = s1; + while(*p) + { + toupper(*p); + p++; + } + return s1; +} +#endif diff --git a/Client Applications/rcracki_mt/HashAlgorithm.h b/Client Applications/rcracki_mt/HashAlgorithm.h new file mode 100644 index 0000000..9958cbc --- /dev/null +++ b/Client Applications/rcracki_mt/HashAlgorithm.h @@ -0,0 +1,42 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifndef _HASHALGORITHM_H +#define _HASHALGORITHM_H + +void HashLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashNTLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashMD2(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashMD4(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashMD5(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashDoubleMD5(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashSHA1(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashRIPEMD160(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashMSCACHE(unsigned char *pPlain, int nPlainLen, unsigned char* pHash); +//**************************************************************************** +// MySQL Password Hashing +//**************************************************************************** +void HashMySQL323(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashMySQLSHA1(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); + +//**************************************************************************** +// Cisco PIX Password Hashing +//**************************************************************************** +void HashPIX(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); + +//**************************************************************************** +// (HALF) LM CHALL hashing +void HashLMCHALL(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashHALFLMCHALL(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); + +// From mao +void HashNTLMCHALL(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); +void HashORACLE(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); + +#ifndef _WIN32 +char *strupr(char *s1); +#endif +#endif diff --git a/Client Applications/rcracki_mt/HashRoutine.cpp b/Client Applications/rcracki_mt/HashRoutine.cpp new file mode 100644 index 0000000..02fbe71 --- /dev/null +++ b/Client Applications/rcracki_mt/HashRoutine.cpp @@ -0,0 +1,78 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifdef _WIN32 + #pragma warning(disable : 4786 4267 4018) +#endif + +#include "HashRoutine.h" +#include "HashAlgorithm.h" + +////////////////////////////////////////////////////////////////////// + +CHashRoutine::CHashRoutine() +{ + // Notice: MIN_HASH_LEN <= nHashLen <= MAX_HASH_LEN + + + AddHashRoutine("lm", HashLM, 8); + AddHashRoutine("ntlm", HashNTLM, 16); + AddHashRoutine("md2", HashMD2, 16); + AddHashRoutine("md4", HashMD4, 16); + AddHashRoutine("md5", HashMD5, 16); + AddHashRoutine("doublemd5", HashDoubleMD5, 16); + AddHashRoutine("sha1", HashSHA1, 20); + AddHashRoutine("ripemd160", HashRIPEMD160, 20); + AddHashRoutine("mysql323", HashMySQL323, 8); + AddHashRoutine("mysqlsha1", HashMySQLSHA1, 20); + AddHashRoutine("ciscopix", HashPIX, 16); + AddHashRoutine("mscache", HashMSCACHE, 16); + AddHashRoutine("halflmchall", HashHALFLMCHALL, 8); + + // Added from mao + AddHashRoutine("lmchall", HashLMCHALL, 24); + AddHashRoutine("ntlmchall", HashNTLMCHALL, 24); + AddHashRoutine("oracle", HashORACLE, 8); + +} + +CHashRoutine::~CHashRoutine() +{ +} + +void CHashRoutine::AddHashRoutine(string sHashRoutineName, HASHROUTINE pHashRoutine, int nHashLen) +{ + vHashRoutineName.push_back(sHashRoutineName); + vHashRoutine.push_back(pHashRoutine); + vHashLen.push_back(nHashLen); +} + +string CHashRoutine::GetAllHashRoutineName() +{ + string sRet; + int i; + for (i = 0; i < vHashRoutineName.size(); i++) + sRet += vHashRoutineName[i] + " "; + + return sRet; +} + +void CHashRoutine::GetHashRoutine(string sHashRoutineName, HASHROUTINE& pHashRoutine, int& nHashLen) +{ + int i; + for (i = 0; i < vHashRoutineName.size(); i++) + { + if (sHashRoutineName == vHashRoutineName[i]) + { + pHashRoutine = vHashRoutine[i]; + nHashLen = vHashLen[i]; + return; + } + } + + pHashRoutine = NULL; + nHashLen = 0; +} diff --git a/Client Applications/rcracki_mt/HashRoutine.h b/Client Applications/rcracki_mt/HashRoutine.h new file mode 100644 index 0000000..681fa78 --- /dev/null +++ b/Client Applications/rcracki_mt/HashRoutine.h @@ -0,0 +1,33 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifndef _HASHROUTINE_H +#define _HASHROUTINE_H + +#include +#include +using namespace std; + +typedef void (*HASHROUTINE)(unsigned char* pPlain, int nPlainLen, unsigned char* pHash); + +class CHashRoutine +{ +public: + CHashRoutine(); + virtual ~CHashRoutine(); + +private: + vector vHashRoutineName; + vector vHashRoutine; + vector vHashLen; + void AddHashRoutine(string sHashRoutineName, HASHROUTINE pHashRoutine, int nHashLen); + +public: + string GetAllHashRoutineName(); + void GetHashRoutine(string sHashRoutineName, HASHROUTINE& pHashRoutine, int& nHashLen); +}; + +#endif diff --git a/Client Applications/rcracki_mt/HashSet.cpp b/Client Applications/rcracki_mt/HashSet.cpp new file mode 100644 index 0000000..cf8afdb --- /dev/null +++ b/Client Applications/rcracki_mt/HashSet.cpp @@ -0,0 +1,164 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifdef _WIN32 + #pragma warning(disable : 4786 4267 4018) +#endif + +#include "HashSet.h" + +CHashSet::CHashSet() +{ +} + +CHashSet::~CHashSet() +{ +} + +void CHashSet::AddHash(string sHash) +{ + if (sHash == "aad3b435b51404ee") + return; + + int i; + for (i = 0; i < m_vHash.size(); i++) + { + if (m_vHash[i] == sHash) + return; + } + + //printf("debug: adding hash %s\n", sHash.c_str()); + + m_vHash.push_back(sHash); + m_vFound.push_back(false); + m_vPlain.push_back(""); + m_vBinary.push_back(""); +} + +string CHashSet::GetHashInfo(int i) +{ + string found; + if (m_vFound[i]) + found = "1"; + else + found = "0"; + + string buffer = m_vHash[i] + ":" + found + ":" + m_vPlain[i] + ":" + m_vBinary[i]; + + return buffer; +} + +bool CHashSet::AnyhashLeft() +{ + int i; + for (i = 0; i < m_vHash.size(); i++) + { + if (!m_vFound[i]) + return true; + } + + return false; +} + +bool CHashSet::AnyHashLeftWithLen(int nLen) +{ + int i; + for (i = 0; i < m_vHash.size(); i++) + { + if (!m_vFound[i]) + if (m_vHash[i].size() == nLen * 2) + return true; + } + + return false; +} + +void CHashSet::GetLeftHashWithLen(vector& vHash, int nLen) +{ + vHash.clear(); + + int i; + for (i = 0; i < m_vHash.size(); i++) + { + if (!m_vFound[i]) + if (m_vHash[i].size() == nLen * 2) + vHash.push_back(m_vHash[i]); + } +} + +void CHashSet::AddHashInfo(string sHash, bool found, string sPlain, string sBinary) +{ + int i; + for (i = 0; i < m_vHash.size(); i++) + { + if (m_vHash[i] == sHash) + return; + } + + m_vHash.push_back(sHash); + m_vFound.push_back(found); + m_vPlain.push_back(sPlain); + m_vBinary.push_back(sBinary); +} + +void CHashSet::SetPlain(string sHash, string sPlain, string sBinary) +{ + int i; + for (i = 0; i < m_vHash.size(); i++) + { + if (m_vHash[i] == sHash) + { + m_vFound[i] = true; + m_vPlain[i] = sPlain; + m_vBinary[i] = sBinary; + return; + } + } +} + +bool CHashSet::GetPlain(string sHash, string& sPlain, string& sBinary) +{ + if (sHash == "aad3b435b51404ee") + { + sPlain = ""; + sBinary = ""; + return true; + } + + int i; + for (i = 0; i < m_vHash.size(); i++) + { + if (m_vHash[i] == sHash) + { + if (m_vFound[i]) + { + sPlain = m_vPlain[i]; + sBinary = m_vBinary[i]; + return true; + } + } + } + + return false; +} + +int CHashSet::GetStatHashFound() +{ + int nHashFound = 0; + int i; + for (i = 0; i < m_vHash.size(); i++) + { + if (m_vFound[i]) + nHashFound++; + } + + return nHashFound; +} + +int CHashSet::GetStatHashTotal() +{ + return m_vHash.size(); +} diff --git a/Client Applications/rcracki_mt/HashSet.h b/Client Applications/rcracki_mt/HashSet.h new file mode 100644 index 0000000..746bb72 --- /dev/null +++ b/Client Applications/rcracki_mt/HashSet.h @@ -0,0 +1,40 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifndef _HASHSET_H +#define _HASHSET_H + +#include "Public.h" + +class CHashSet +{ +public: + CHashSet(); + virtual ~CHashSet(); + +private: + vector m_vHash; + vector m_vFound; + vector m_vPlain; + vector m_vBinary; + +public: + void AddHash(string sHash); // lowercase, len % 2 == 0, MIN_HASH_LEN * 2 <= len <= MAX_HASH_LEN * 2 + bool AnyhashLeft(); + bool AnyHashLeftWithLen(int nLen); + void GetLeftHashWithLen(vector& vHash, int nLen); + + void SetPlain(string sHash, string sPlain, string sBinary); + bool GetPlain(string sHash, string& sPlain, string& sBinary); + + int GetStatHashFound(); + int GetStatHashTotal(); + + string GetHashInfo(int i); + void AddHashInfo(string sHash, bool found, string sPlain, string sBinary); +}; + +#endif diff --git a/Client Applications/rcracki_mt/Makefile b/Client Applications/rcracki_mt/Makefile new file mode 100644 index 0000000..f6329ac --- /dev/null +++ b/Client Applications/rcracki_mt/Makefile @@ -0,0 +1,5 @@ +rcracki_mt: + g++ *.cpp -lssl -lpthread -O3 -o rcracki_mt + +clean: + rm rcracki_mt diff --git a/Client Applications/rcracki_mt/MemoryPool.cpp b/Client Applications/rcracki_mt/MemoryPool.cpp new file mode 100644 index 0000000..2129daa --- /dev/null +++ b/Client Applications/rcracki_mt/MemoryPool.cpp @@ -0,0 +1,81 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#include "MemoryPool.h" +#include "Public.h" + +CMemoryPool::CMemoryPool(unsigned int bytesForChainWalkSet) +{ + m_pMem = NULL; + m_nMemSize = 0; + + unsigned int nAvailPhys = GetAvailPhysMemorySize(); + if (nAvailPhys < 32 * 1024 * 1024) + { + nAvailPhys = 256 * 1024 * 1024; // There is atleast 256 mb available (Some Linux distros returns a really low GetAvailPhysMemorySize()) + } + + m_nMemMax = nAvailPhys - bytesForChainWalkSet; // Leave memory for CChainWalkSet + + if (m_nMemMax < 16 * 1024 * 1024) + m_nMemMax = 16 * 1024 * 1024; + +} + +CMemoryPool::~CMemoryPool() +{ + if (m_pMem != NULL) + { + delete m_pMem; + m_pMem = NULL; + m_nMemSize = 0; + } +} + +unsigned char* CMemoryPool::Allocate(unsigned int nFileLen, unsigned int& nAllocatedSize) +{ + if (nFileLen <= m_nMemSize) + { + nAllocatedSize = nFileLen; + return m_pMem; + } + + unsigned int nTargetSize; + if (nFileLen < m_nMemMax) + nTargetSize = nFileLen; + else + nTargetSize = m_nMemMax; + + // Free existing memory + if (m_pMem != NULL) + { + delete m_pMem; + m_pMem = NULL; + m_nMemSize = 0; + } + + // Allocate new memory + //printf("allocating %u bytes memory\n", nTargetSize); + m_pMem = new (nothrow) unsigned char[nTargetSize]; + while (m_pMem == NULL && nTargetSize >= 32 * 1024 * 1024 ) + { + nTargetSize -= 16 * 1024 * 1024; + m_pMem = new (nothrow) unsigned char[nTargetSize]; + } + + if (m_pMem != NULL) + { + m_nMemSize = nTargetSize; + nAllocatedSize = nTargetSize; + return m_pMem; + } + else + { + m_nMemSize = 0; + nAllocatedSize = 0; + return NULL; + } +} diff --git a/Client Applications/rcracki_mt/MemoryPool.h b/Client Applications/rcracki_mt/MemoryPool.h new file mode 100644 index 0000000..91d8214 --- /dev/null +++ b/Client Applications/rcracki_mt/MemoryPool.h @@ -0,0 +1,26 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifndef _MEMORYPOOL_H +#define _MEMORYPOOL_H + +class CMemoryPool +{ +public: + CMemoryPool(unsigned int bytesForChainWalkSet); + virtual ~CMemoryPool(); + +private: + unsigned char* m_pMem; + unsigned int m_nMemSize; + + unsigned int m_nMemMax; + +public: + unsigned char* Allocate(unsigned int nFileLen, unsigned int& nAllocatedSize); +}; + +#endif diff --git a/Client Applications/rcracki_mt/Public.cpp b/Client Applications/rcracki_mt/Public.cpp new file mode 100644 index 0000000..6b98157 --- /dev/null +++ b/Client Applications/rcracki_mt/Public.cpp @@ -0,0 +1,311 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifdef _WIN32 + #pragma warning(disable : 4786 4267 4018) +#endif + +#include "Public.h" + +#ifdef _WIN32 + #include +#else + #include +#endif + +////////////////////////////////////////////////////////////////////// + +unsigned int GetFileLen(FILE* file) +{ + unsigned int pos = ftell(file); + fseek(file, 0, SEEK_END); + unsigned int len = ftell(file); + fseek(file, pos, SEEK_SET); + + return len; +} + +string TrimString(string s) +{ + while (s.size() > 0) + { + if (s[0] == ' ' || s[0] == '\t') + s = s.substr(1); + else + break; + } + + while (s.size() > 0) + { + if (s[s.size() - 1] == ' ' || s[s.size() - 1] == '\t') + s = s.substr(0, s.size() - 1); + else + break; + } + + return s; +} +bool GetHybridCharsets(string sCharset, vector& vCharset) +{ + // Example: hybrid(mixalpha-numeric-all-space#1-6,numeric#1-4) + if(sCharset.substr(0, 6) != "hybrid") // Not hybrid charset + return false; + size_t nEnd = sCharset.rfind(')'); + size_t nStart = sCharset.rfind('('); + string sChar = sCharset.substr(nStart + 1, nEnd - nStart - 1); + vector vParts; + SeperateString(sChar, ",", vParts); + for(int i = 0; i < vParts.size(); i++) + { + tCharset stCharset; + vector vParts2; + SeperateString(vParts[i], "#", vParts2); + stCharset.sName = vParts2[0]; + vector vParts3; + SeperateString(vParts2[1], "-", vParts3); + stCharset.nPlainLenMin = atoi(vParts3[0].c_str()); + stCharset.nPlainLenMax = atoi(vParts3[1].c_str()); + vCharset.push_back(stCharset); + } + return true; +} +bool ReadLinesFromFile(string sPathName, vector& vLine) +{ + vLine.clear(); + + FILE* file = fopen(sPathName.c_str(), "rb"); + if (file != NULL) + { + unsigned int len = GetFileLen(file); + char* data = new char[len + 1]; + fread(data, 1, len, file); + data[len] = '\0'; + string content = data; + content += "\n"; + delete data; + + unsigned int i; + for (i = 0; i < content.size(); i++) + { + if (content[i] == '\r') + content[i] = '\n'; + } + + int n; + while ((n = content.find("\n", 0)) != -1) + { + string line = content.substr(0, n); + line = TrimString(line); + if (line != "") + vLine.push_back(line); + content = content.substr(n + 1); + } + + fclose(file); + } + else + return false; + + return true; +} + +bool writeResultLineToFile(string sOutputFile, string sHash, string sPlain, string sBinary) +{ + FILE* file = fopen(sOutputFile.c_str(), "a"); + if (file!=NULL) + { + string buffer = sHash + ":" + sPlain + ":" + sBinary + "\n"; + fputs (buffer.c_str(), file); + fclose (file); + return true; + } + else + return false; +} + +bool SeperateString(string s, string sSeperator, vector& vPart) +{ + vPart.clear(); + + unsigned int i; + for (i = 0; i < sSeperator.size(); i++) + { + int n = s.find(sSeperator[i]); + if (n != -1) + { + vPart.push_back(s.substr(0, n)); + s = s.substr(n + 1); + } + else + { + printf("not found: %c\n", sSeperator[i]); + printf("s: %s\n", s.c_str()); + return false; + } + } + vPart.push_back(s); + + return true; +} + +string uint64tostr(uint64 n) +{ + char str[32]; + +#ifdef _WIN32 + sprintf(str, "%I64u", n); +#else + sprintf(str, "%llu", n); +#endif + + return str; +} + +string uint64tohexstr(uint64 n) +{ + char str[32]; + +#ifdef _WIN32 + sprintf(str, "%016I64x", n); +#else + sprintf(str, "%016llx", n); +#endif + + return str; +} + +string HexToStr(const unsigned char* pData, int nLen) +{ + string sRet; + int i; + for (i = 0; i < nLen; i++) + { + char szByte[3]; + sprintf(szByte, "%02x", pData[i]); + sRet += szByte; + } + + return sRet; +} + +unsigned int GetAvailPhysMemorySize() +{ +#ifdef _WIN32 + MEMORYSTATUS ms; + GlobalMemoryStatus(&ms); + return ms.dwAvailPhys; +#else + struct sysinfo info; + sysinfo(&info); // This function is Linux-specific + return info.freeram; +#endif +} + +string GetApplicationPath() +{ + char fullPath[FILENAME_MAX]; + +#ifdef _WIN32 + GetModuleFileName(NULL, fullPath, FILENAME_MAX); +#else + char szTmp[32]; + sprintf(szTmp, "/proc/%d/exe", getpid()); + int bytes = readlink(szTmp, fullPath, FILENAME_MAX); + if(bytes >= 0) + fullPath[bytes] = '\0'; +#endif + + string sApplicationPath = fullPath; +#ifdef _WIN32 + int nIndex = sApplicationPath.find_last_of('\\'); +#else + int nIndex = sApplicationPath.find_last_of('/'); +#endif + + if (nIndex != -1) + sApplicationPath = sApplicationPath.substr(0, nIndex+1); + + //printf ("\n\nDebug: The application directory is %s\n", sApplicationPath.c_str()); + return sApplicationPath; +} + +void ParseHash(string sHash, unsigned char* pHash, int& nHashLen) +{ + int i; + for (i = 0; i < sHash.size() / 2; i++) + { + string sSub = sHash.substr(i * 2, 2); + int nValue; + sscanf(sSub.c_str(), "%02x", &nValue); + pHash[i] = (unsigned char)nValue; + } + + nHashLen = sHash.size() / 2; +} + +void Logo() +{ + printf("RainbowCrack (improved, multi-threaded) - Making a Faster Cryptanalytic Time-Memory Trade-Off\n"); + printf("by Martin Westergaard \n"); + printf("multi-threaded and enhanced by neinbrucke (version 0.6-svn)\n"); + printf("http://www.freerainbowtables.com/\n"); + printf("original code by Zhu Shuanglei \n"); + printf("http://www.antsight.com/zsl/rainbowcrack/\n\n"); +} + +// Code comes from nmap, used for the linux implementation of kbhit() +#ifndef _WIN32 + +static int tty_fd = 0; +struct termios saved_ti; + +int tty_getchar() +{ + int c, numChars; + + if (tty_fd && tcgetpgrp(tty_fd) == getpid()) { + c = 0; + numChars = read(tty_fd, &c, 1); + if (numChars > 0) return c; + } + + return -1; +} + +void tty_done() +{ + if (!tty_fd) return; + + tcsetattr(tty_fd, TCSANOW, &saved_ti); + + close(tty_fd); + tty_fd = 0; +} + +void tty_init() +{ + struct termios ti; + + if (tty_fd) + return; + + if ((tty_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK)) < 0) return; + + tcgetattr(tty_fd, &ti); + saved_ti = ti; + ti.c_lflag &= ~(ICANON | ECHO); + ti.c_cc[VMIN] = 1; + ti.c_cc[VTIME] = 0; + tcsetattr(tty_fd, TCSANOW, &ti); + + atexit(tty_done); +} + +void tty_flush(void) +{ + tcflush(tty_fd, TCIFLUSH); +} +#endif diff --git a/Client Applications/rcracki_mt/Public.h b/Client Applications/rcracki_mt/Public.h new file mode 100644 index 0000000..5e5e8d5 --- /dev/null +++ b/Client Applications/rcracki_mt/Public.h @@ -0,0 +1,118 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei +*/ + +#ifndef _PUBLIC_H +#define _PUBLIC_H + +#include +#include +#include + +#include +#include +#include +using namespace std; + +#ifdef _WIN32 + #define uint64 unsigned __int64 +#else + #ifndef u_int64_t + #define uint64 unsigned long long + #else + #define uint64 u_int64_t + #endif +#endif + +struct RainbowChainO +{ + uint64 nIndexS; + uint64 nIndexE; +}; +//struct RainbowChain +//{ +// //uint64 nChain; +// uint64 nIndexS; +// int nIndexE; +// int nCheckPoint; +//}; + +union RainbowChain +{ + //uint64 nChain; + uint64 nIndexS; + struct + { + unsigned short foo[3]; + unsigned short nIndexE; + }; + //int nCheckPoint; +}; +//struct RainbowChain +//{ +// uint64 nIndexS : 48; +// unsigned short nIndexE : 16; +//}; +//struct IndexChain +//{ +// uint64 nPrefix; +// int nFirstChain; +// int nChainCount; +// //unsigned short nChainCount; //(maybe union with nPrefix, 1 byte spoiled) +//}; +#pragma pack(1) +union IndexChain +{ + uint64 nPrefix; //5 + struct + { + unsigned char foo[5]; + int nFirstChain; //4 + unsigned short nChainCount; //2 + }; + //unsigned short nChainCount; (maybe union with nPrefix, 1 byte spoiled, no pack(1) needed) +}; +#pragma pack() +typedef struct +{ + string sName; + int nPlainLenMin; + int nPlainLenMax; +} tCharset; + +#define MAX_PLAIN_LEN 256 +#define MIN_HASH_LEN 8 +#define MAX_HASH_LEN 256 +#define MAX_SALT_LEN 256 + +// Code comes from nmap, used for the linux implementation of kbhit() +#ifndef _WIN32 +#include +#include +#include + +int tty_getchar(); +void tty_done(); +void tty_init(); +void tty_flush(void); + +#endif + + +unsigned int GetFileLen(FILE* file); +string TrimString(string s); +bool ReadLinesFromFile(string sPathName, vector& vLine); +bool SeperateString(string s, string sSeperator, vector& vPart); +string uint64tostr(uint64 n); +string uint64tohexstr(uint64 n); +string HexToStr(const unsigned char* pData, int nLen); +unsigned int GetAvailPhysMemorySize(); +string GetApplicationPath(); +void ParseHash(string sHash, unsigned char* pHash, int& nHashLen); +bool GetHybridCharsets(string sCharset, vector& vCharset); +void Logo(); +bool writeResultLineToFile(string sOutputFile, string sHash, string sPlain, string sBinary); + +#endif diff --git a/Client Applications/rcracki_mt/README.txt b/Client Applications/rcracki_mt/README.txt new file mode 100644 index 0000000..b4b8cd8 --- /dev/null +++ b/Client Applications/rcracki_mt/README.txt @@ -0,0 +1,162 @@ +[rcracki_mt README] + +USAGE +================ +example: rcracki_mt -h 5d41402abc4b2a76b9719d911017c592 -t 4 -o save.txt C:\md5 + +Start rcracki_mt without any arguments to view usage information in short. This README describes the various +options in more detail. Many options can be set to a default value by editing rcracki_mt.ini. Command line +arguments get priority over settings in the ini file. + +INPUT +---------------- +rcracki_mt takes one hash on the command line (using -h) or an input file containing the hashes. rcracki_mt supports +three formats for the input file. Use one of the following options to specify the format followed by the filename: + +-l: specify a list of hashes (one hash per line) +-f: specify a pwdump file +-c: specify a .lst file (format in which Cain stores hashes and results) + +SELECTING RAINBOW TABLES +---------------- +Any command line argument that is not an option will be interpreted as a directory to search for rainbow tables, +multiple directories can be specified. rcracki_mt recursively scans all specified directories for *.rti (indexed) +and *.rt (old/original) files. You can use .rt & .rti files at once, but this hasn't been tested thoroughly. + +You can set default locations to search for rainbow tables in rcracki_mt.ini. You need to use these in combination +with the command line argument -a [algorithm]. See the comments in the ini file for examples. + +SESSIONS & RESUMING +---------------- +Rcracki_mt has session support, which means that it stores its progress. This allows you to interrupt the session +and resume later on. This also allows sessions that stopped because of a crash (application or even system) to +resume. To use this feature, start rcracki_mt with all the options you'd like, then specify a session name with: + +-s session_name: specify a session name + +Now during cracking, all your valuable precalculations are stored to disk, as well as progress (which files have +been checked) and cracked hashes. If you decide to interrupt the session (using CTRL+C), you can resume it using +the -r option. For example: + +rcracki_mt -r -s my_personal_hashes + +While resuming rcracki_mt you can/have to specify the less important options again, like number of threads and +showing debug information. Usually you will have these settings set to a default value in the .ini file anyway. +Session are deleted after the run is completed. You can choose to keep the precalculation work on disk, for example +if you want to reuse your session later on. Use the '-k' option to enable this feature. + +Rcracki_mt has a default session which gets overwritten every time you start a new job without specifying a session +name. It might be interesting to always keep precalculation work by enabling this feature in rcracki_mt.ini. But +pay attention, these precalculations can become quite large on disk. Currently there is a maximum of around 500 GB +of storage for these precalculations. You can always decide to manually remove the .precalc and .precalc.index +files from disk. Always remove both at the same time, you will screw up your results if you don't. A possible +'todo' for development is to do some verification before using stored precalculations. + +OPTIONAL +---------------- +-t: Number of threads to use (for precalculation and false alarm checking) +Note: In Windows the crack threads run with lower priority. + +-o: specify an output file to store found hashes in a colon (:) separated format. + Hashes are saved immediately when found. Especially useful if you have a large list of hashes. + +-v: Show more information during cracking, for debugging purposes. Please use this flag if you want to show +output and report a bug. + + +EXTRA FEATURES +---------------- +You can pause a running rcracki_mt by using 'P'. It might not pause right away, it actually pauses after doing +precalculation or false alarm checking for one hash. Resume by pressing 'P' again. This pause option is different +from the session/resume feature, as this just pauses a running job, you don't stop rcracki_mt this way. + +If you are trying to crack a pwdump or Cain (.lst) file, containing both LM and NTLM hashes, rcracki_mt will try +and crack the LM hashes. The result will be an uppercase password, which rcracki_mt will then try to correct with +the right casing, using the NTLM hashes. If this fails it will try and perform Unicode correction, using a built-in +mapping. If you happen to have an LM hash coupled with the wrong NTLM hash, this attempt to perform Unicode +correction might take 'forever'. You can press 'S' to skip this step for the current hash. + + +HISTORY AND AUTHORS +================ +rcracki_mt originally started as a modification of a modification (rcracki) of the original RainbowCrack (rcrack). +These programs are all used to perform a rainbow table attack on password hashes, implementing Philippe Oechslin's +faster time-memory trade-off technique. + +Original rcrack code was written by Zhu Shuanglei . + +Martin Westergaard Jørgensen wrote rcracki (improved) to support the rainbow tables +generated by the distributed project www.freerainbowtables.com. These tables are perfected and indexed, making them +faster and smaller. Rcracki also supported hybrid tables. + +Daniël Niggebrugge further enhanced this version and made it multi threaded, creating rcracki_mt. More +features were added over time, making it less of an unofficial version with every release. + + +SUPPORTED HASH ALGORITHMS +================ +Hash types supported by rcracki_mt are: LM, NTLM, MD2, MD4, MD5, DoubleMD5, SHA1, RIPEMD160, MSCACHE, MySQL323, +MySQLSHA1, PIX, LMCHALL, HALFLMCHALL, NTLMCHALL, ORACLE + +Actual indexed&perfected tables that were generated by the Free Rainbow Tables project: LM, MD5, NTL, FASTLM, +HALFLMCHALL, SHA1 + + +SUPPORTED PLATFORMS +================ +Rcracki_mt is released both as win32 binary and as source package. Rcracki_mt should work on any Microsoft Windows system, but is only tested on a 32 bit Windows XP. The source should work on Linux versions, but this has only been tested on 32 bit Ubuntu (8.10). + +Some people have reported issues with compiling on 64 bit Linux. If you have trouble, please report details, as workaround try this suggested solution for AMD64 UBUNTU 8.10: + + sudo apt-get install ia32-libs + + +you might need to do: + cd /usr/lib32/ + sudo ln -s libstdc++.so.6 libstdc++.so + sudo ln -s libssl.so.0.9.8 libssl.so + + +add -m32 to the compilerline in the Makefile + g++ -m32 *.cpp -L/usr/lib32 -lssl -lpthread -O3 -o rcracki_mt + + +'OPTIONAL' TODO +================ +- verification of an endpoint when restoring a chainwalkset from disk. +- read multiple chainwalksets from disk at once to try and speed up this process. +- read next table (part) from disk while doing cryptanalysis + + +LINKS +================ +rcracki_mt @ SourceForge: https://sourceforge.net/projects/rcracki/ +Original rcrack: http://www.antsight.com/zsl/rainbowcrack/ +Free Rainbow Tables: http://www.freerainbowtables.com/ +My personal blog: http://blog.distracted.nl/ +Download free rainbow tables: http://tbhost.eu/ +Download free rainbow tables (mirror): http://freerainbowtables.mirror.garr.it/mirrors/freerainbowtables/ + + +THANKS +================ +the_drag0n Writing part of this README + Patch to support Cain .lst files +Joao Inacio Supplying some faster algorithm implementations + + +FAQ +================ +Q: Why do I get this message all the time? "this table contains hashes with length 8 only" +A: You are probably trying to crack LM hashes. You have to split up the hash in 2 parts of 16 hex characters each. + +Q: rcracki_mt is so slow when I'm cracking 5000 hashes, why is that? +A: Rainbow table attacks are only useful for a certain amount of hashes, mainly because of the precalculations that +are needed for every hash you are cracking. At a certain point it is faster to brute force the same key space then +to try and use rainbow tables. Especially if you use a GPU enabled brute forcer, this limit might be reached very +soon. Play around with these to find you limits. + +Q: How can I speed up rcracki_mt? +A: This depends on quite some factors. If your jobs usually comprise of disk access time, you can try and speed up +your storage. For example by using RAID and/or by using solid state disks. If you are trying to crack many hashes +at the same time, you might be better off with buying a faster CPU. diff --git a/Client Applications/rcracki_mt/RTI2Reader.cpp b/Client Applications/rcracki_mt/RTI2Reader.cpp new file mode 100644 index 0000000..d58e881 --- /dev/null +++ b/Client Applications/rcracki_mt/RTI2Reader.cpp @@ -0,0 +1,125 @@ +#include "RTI2Reader.h" + +#include +RTI2Header *RTI2Reader::m_pHeader = NULL; +RTI2Reader::RTI2Reader(string Filename) +{ + //m_pIndexPos = NULL, m_pChainPos = NULL;; + m_pIndex = NULL; + m_pFile = fopen(Filename.c_str(), "rb"); + if(m_pFile == NULL) + { + printf("Unable to open file %s", Filename.c_str()); + exit(1); + } + FILE *pFileIndex = fopen(Filename.append(".index").c_str(), "rb"); + if(pFileIndex == NULL) + { + printf("Unable to open file %s", Filename.append(".index").c_str()); + exit(1); + } + m_chainPosition = 0; + + unsigned int len = GetFileLen(pFileIndex); + fseek(pFileIndex, 0, SEEK_SET); + + m_pIndex = new unsigned char[len]; + if(fread(m_pIndex, 1, len, pFileIndex) != len) + { + printf("Error while reading index file"); + exit(1); + } + fclose(pFileIndex); + m_pHeader = new RTI2Header(); + memcpy(m_pHeader, m_pIndex, sizeof(RTI2Header)); + m_pHeader->m_cppos = (unsigned int*)(m_pIndex + 8); + m_pHeader->prefixstart = *(uint64*)(m_pIndex + 8 + (m_pHeader->rti_cplength * 4)); + m_chainsizebytes = ceil((float)(m_pHeader->rti_startptlength + m_pHeader->rti_endptlength + m_pHeader->rti_cplength) / 8); // Get the size of each chain in bytes + m_indexrowsizebytes = ceil((float)m_pHeader->rti_index_numchainslength / 8); + // Check the filesize + fseek(m_pFile, 0, SEEK_END); + len = ftell(m_pFile); + fseek(m_pFile, 0, SEEK_SET); + if(len % m_chainsizebytes > 0) + { + printf("Invalid filesize %u\n", len); + return; + } + + +} + +RTI2Reader::~RTI2Reader(void) +{ + if(m_pIndex != NULL) delete m_pIndex; + if(m_pFile != NULL) fclose(m_pFile); + +} + +unsigned int RTI2Reader::GetChainsLeft() +{ + int len = GetFileLen(m_pFile); + return len / m_chainsizebytes - m_chainPosition; +} + +int RTI2Reader::ReadChains(unsigned int &numChains, RainbowChainO *pData) +{ + if(strncmp(m_pHeader->header, "RTI2", 4) != 0) + { + numChains = 0; + return -1; + } + unsigned char *pNumChains = m_pIndex + (m_pHeader->rti_cplength * 4) + 16; // Pointer into the index containing info about how many numbers are in the first chain prefix + unsigned int i = 0; + unsigned int indexRow = 0; // Current offset into the index + unsigned int curRowPosition = 0; + + while(true) // Fast forward to current position + { + // ALERT: Possible problem here if m_indexrowsizebytes > 1 as pNumChains is a unsigned char. + unsigned int NumChainsInRow = (unsigned int)*(pNumChains + indexRow * m_indexrowsizebytes); + if(m_indexrowsizebytes > 1) { printf("Have to find a solution to this problem"); exit(2);} + if(i + NumChainsInRow > m_chainPosition) + { + curRowPosition = m_chainPosition - i; + break; // The current position is somewhere within this prefix + } + indexRow++; + i += NumChainsInRow; + } + + uint64 chainrow = 0; // Buffer to store a single read chain + unsigned int chainsProcessed = 0; // Number of chains processed + + // ALERT: same problem with unsigned char here. + unsigned int NumChainsInRow = *(pNumChains + indexRow); + while(chainsProcessed < numChains && fread(&chainrow, 1, m_chainsizebytes, m_pFile) == m_chainsizebytes) + { + if(curRowPosition >= NumChainsInRow) + { // Skip to next index row position + indexRow++; + curRowPosition = 0; + NumChainsInRow = *(pNumChains + indexRow); + } + while(NumChainsInRow == 0) // We skip forward until we hit a index with > 0 chains + { + indexRow++; + NumChainsInRow = *(pNumChains + indexRow); + curRowPosition = 0; + } + // Load the starting point from the data + pData[chainsProcessed].nIndexS = chainrow << 64 - m_pHeader->rti_startptlength; + pData[chainsProcessed].nIndexS = pData[chainsProcessed].nIndexS >> 64 - m_pHeader->rti_startptlength; + + // Load the ending point prefix + pData[chainsProcessed].nIndexE = m_pHeader->prefixstart + indexRow << m_pHeader->rti_endptlength; + // Append the ending point suffix + pData[chainsProcessed].nIndexE |= (chainrow & (0xFFFFFFFFFFFFFFFF >> m_pHeader->rti_cplength)) >> m_pHeader->rti_startptlength; + //pData[chainsProcessed].nCheckPoint = (chainrow >> m_pHeader->rti_startptlength + m_pHeader->rti_endptlength); + curRowPosition++; + chainsProcessed++; + } + numChains = chainsProcessed; + m_chainPosition += numChains; + return 0; +} diff --git a/Client Applications/rcracki_mt/RTI2Reader.h b/Client Applications/rcracki_mt/RTI2Reader.h new file mode 100644 index 0000000..6934e6c --- /dev/null +++ b/Client Applications/rcracki_mt/RTI2Reader.h @@ -0,0 +1,42 @@ +#ifndef __RTI2READER_H__ +#define __RTI2READER_H__ + +#include "Public.h" +#include +#ifdef WIN32 +#include +#endif +#include +#include "BaseRTReader.h" +using namespace std; + +typedef struct +{ + char header[4]; + unsigned char rti_startptlength, rti_endptlength, rti_cplength, rti_index_numchainslength; + uint64 prefixstart; + unsigned int *m_cppos; +} RTI2Header; + +class RTI2Reader : BaseRTReader +{ +private: + FILE *m_pFile; + unsigned int m_chainPosition; + unsigned char *m_pPos, *m_pChainPos; + static RTI2Header *m_pHeader; + unsigned char *m_pIndex; + unsigned int m_chainsizebytes; + unsigned int m_indexrowsizebytes; + + +public: + RTI2Reader(string Filename); + ~RTI2Reader(void); + int ReadChains(unsigned int &numChains, RainbowChainO *pData); + unsigned int GetChainsLeft(); + static RTI2Header *GetHeader() { return m_pHeader; } +}; + + +#endif diff --git a/Client Applications/rcracki_mt/RainbowCrack.cpp b/Client Applications/rcracki_mt/RainbowCrack.cpp new file mode 100644 index 0000000..185dd1a --- /dev/null +++ b/Client Applications/rcracki_mt/RainbowCrack.cpp @@ -0,0 +1,831 @@ +/* + RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique. + + Copyright (C) Zhu Shuanglei + + Modified by Martin Westergaard Jørgensen to support indexed and hybrid tables + + Modified by neinbrucke to support multi threading and a bunch of other stuff :) + + 2009-01-04 - - Slightly modified (or "fulhack" as we say in sweden) + to support cain .lst files. +*/ + +#ifdef _WIN32 + #pragma warning(disable : 4786 4267 4018) +#endif + +#include "CrackEngine.h" +#include "lm2ntlm.h" +#include + + + +#ifdef _WIN32 + #include +#else + #include + #include + #include + #include +#endif + +#include +#ifdef _WIN32 + #pragma comment(lib, "libeay32.lib") +#endif + +////////////////////////////////////////////////////////////////////// + +#ifdef _WIN32 +void GetTableList(string sWildCharPathName, vector& vPathName) +{ + //vPathName.clear(); + + string sPath; + int n = sWildCharPathName.find_last_of('\\'); + + if (n == (sWildCharPathName.size() - 1)) + { + sWildCharPathName = sWildCharPathName.substr(0, n); + n = sWildCharPathName.find_last_of('\\'); + } + + if (n != -1) + sPath = sWildCharPathName.substr(0, n + 1); + + _finddata_t fd; + + long handle = _findfirst(sWildCharPathName.c_str(), &fd); + if (handle != -1) + { + do + { + string sName = fd.name; + if (sName.size()>3) { + if (sName.substr(sName.size()-3, 3) == ".rt" && !(fd.attrib & _A_SUBDIR)) + { + string sPathName = sPath + sName; + vPathName.push_back(sPathName); + } + } + if (sName.size()>4) { + if (sName.substr(sName.size()-4, 4) == ".rti" && !(fd.attrib & _A_SUBDIR)) + { + string sPathName = sPath + sName; + vPathName.push_back(sPathName); + } + } + if (sName.size()>5) { + if (sName.substr(sName.size()-5, 5) == ".rti2" && !(fd.attrib & _A_SUBDIR)) + { + string sPathName = sPath + sName; + vPathName.push_back(sPathName); + } + } + + if (sName != "." && sName != ".." && (fd.attrib & _A_SUBDIR)) + { + string sPath_sub = sPath + sName + '\\'; + string sWildCharPathName_sub = sPath_sub + '*'; + GetTableList(sWildCharPathName_sub, vPathName); + } + + } while (_findnext(handle, &fd) == 0); + + _findclose(handle); + } + //printf("Found %d rainbowtables (files) in %d sub directories...\n", vPathName.size(), subDir_count); +} +#else +//void GetTableList(int argc, char* argv[], vector& vPathName) +void GetTableList(string sWildCharPathName, vector& vPathName) +{ + //vPathName.clear(); + + struct stat buf; + if (lstat(sWildCharPathName.c_str(), &buf) == 0) + { + if (S_ISDIR(buf.st_mode)) + { + DIR *dir = opendir(sWildCharPathName.c_str()); + if(dir) + { + struct dirent *pDir=NULL; + while((pDir = readdir(dir)) != NULL) + { + string filename = ""; + filename += (*pDir).d_name; + if (filename != "." && filename != "..") + { + string new_filename = sWildCharPathName + '/' + filename; + GetTableList(new_filename, vPathName); + } + } + closedir(dir); + } + } + else if (S_ISREG(buf.st_mode)) + { + if (sWildCharPathName.size()>3) + { + if (sWildCharPathName.substr(sWildCharPathName.size()-3, 3) == ".rt") + { + vPathName.push_back(sWildCharPathName); + } + } + if (sWildCharPathName.size()>4) + { + if (sWildCharPathName.substr(sWildCharPathName.size()-4, 4) == ".rti") + { + //string sPathName_sub = sPath_sub + sName_sub; + vPathName.push_back(sWildCharPathName); + //printf("sPathName_sub: %s\n", sPathName_sub.c_str()); + } + } + } + } +} +#endif + +bool NormalizeHash(string& sHash) +{ + string sNormalizedHash = sHash; + + if ( sNormalizedHash.size() % 2 != 0 + || sNormalizedHash.size() < MIN_HASH_LEN * 2 + || sNormalizedHash.size() > MAX_HASH_LEN * 2) + return false; + + // Make lower + int i; + for (i = 0; i < sNormalizedHash.size(); i++) + { + if (sNormalizedHash[i] >= 'A' && sNormalizedHash[i] <= 'F') + sNormalizedHash[i] = sNormalizedHash[i] - 'A' + 'a'; + } + + // Character check + for (i = 0; i < sNormalizedHash.size(); i++) + { + if ( (sNormalizedHash[i] < 'a' || sNormalizedHash[i] > 'f') + && (sNormalizedHash[i] < '0' || sNormalizedHash[i] > '9')) + return false; + } + + sHash = sNormalizedHash; + return true; +} + +void LoadLMHashFromPwdumpFile(string sPathName, vector& vUserName, vector& vLMHash, vector& vNTLMHash) +{ + vector vLine; + if (ReadLinesFromFile(sPathName, vLine)) + { + int i; + for (i = 0; i < vLine.size(); i++) + { + vector vPart; + if (SeperateString(vLine[i], "::::", vPart)) + { + string sUserName = vPart[0]; + string sLMHash = vPart[2]; + string sNTLMHash = vPart[3]; + + if (sLMHash.size() == 32 && sNTLMHash.size() == 32) + { + if (NormalizeHash(sLMHash) && NormalizeHash(sNTLMHash)) + { + vUserName.push_back(sUserName); + vLMHash.push_back(sLMHash); + vNTLMHash.push_back(sNTLMHash); + } + else + printf("invalid lm/ntlm hash %s:%s\n", sLMHash.c_str(), sNTLMHash.c_str()); + } + } + } + } + else + printf("can't open %s\n", sPathName.c_str()); +} + +// 2009-01-04 - james - Added this so we can load hashes from cain .LST files. +void LoadLMHashFromCainLSTFile(string sPathName, vector& vUserName, vector& vLMHash, vector& vNTLMHash) +{ + vector vLine; + if (ReadLinesFromFile(sPathName, vLine)) + { + int i; + for (i = 0; i < vLine.size(); i++) + { + vector vPart; + if (SeperateString(vLine[i], "\t\t\t\t\t\t", vPart)) + { + string sUserName = vPart[0]; + string sLMHash = vPart[4]; + string sNTLMHash = vPart[5]; + + if (sLMHash.size() == 32 && sNTLMHash.size() == 32) + { + if (NormalizeHash(sLMHash) && NormalizeHash(sNTLMHash)) + { + vUserName.push_back(sUserName); + vLMHash.push_back(sLMHash); + vNTLMHash.push_back(sNTLMHash); + } + else + printf("invalid lm/ntlm hash %s:%s\n", sLMHash.c_str(), sNTLMHash.c_str()); + } + } + } + } + else + printf("can't open %s\n", sPathName.c_str()); +} + +bool NTLMPasswordSeek(unsigned char* pLMPassword, int nLMPasswordLen, int nLMPasswordNext, + unsigned char* pNTLMHash, string& sNTLMPassword) +{ + if (nLMPasswordNext == nLMPasswordLen) + { + unsigned char md[16]; + MD4(pLMPassword, nLMPasswordLen * 2, md); + if (memcmp(md, pNTLMHash, 16) == 0) + { + sNTLMPassword = ""; + int i; + for (i = 0; i < nLMPasswordLen; i++) + sNTLMPassword += char(pLMPassword[i * 2]); + return true; + } + else + return false; + } + + if (NTLMPasswordSeek(pLMPassword, nLMPasswordLen, nLMPasswordNext + 1, pNTLMHash, sNTLMPassword)) + return true; + + if ( pLMPassword[nLMPasswordNext * 2] >= 'A' + && pLMPassword[nLMPasswordNext * 2] <= 'Z') + { + pLMPassword[nLMPasswordNext * 2] = pLMPassword[nLMPasswordNext * 2] - 'A' + 'a'; + if (NTLMPasswordSeek(pLMPassword, nLMPasswordLen, nLMPasswordNext + 1, pNTLMHash, sNTLMPassword)) + return true; + pLMPassword[nLMPasswordNext * 2] = pLMPassword[nLMPasswordNext * 2] - 'a' + 'A'; + } + + return false; +} + +bool LMPasswordCorrectCase(string sLMPassword, unsigned char* pNTLMHash, string& sNTLMPassword) +{ + if (sLMPassword.size() == 0) + { + sNTLMPassword = ""; + return true; + } + + unsigned char* pLMPassword = new unsigned char[sLMPassword.size() * 2]; + int i; + for (i = 0; i < sLMPassword.size(); i++) + { + pLMPassword[i * 2 ] = sLMPassword[i]; + pLMPassword[i * 2 + 1] = 0x00; + } + bool fRet = NTLMPasswordSeek(pLMPassword, sLMPassword.size(), 0, pNTLMHash, sNTLMPassword); + + delete pLMPassword; + + return fRet; +} + +void Usage() +{ + Logo(); + + printf("usage: rcracki_mt -h hash rainbow_table_pathname\n"); + printf(" rcracki_mt -l hash_list_file rainbow_table_pathname\n"); + printf(" rcracki_mt -f pwdump_file rainbow_table_pathname\n"); + printf(" rcracki_mt -c lst_file rainbow_table_pathname\n"); + printf("\n"); + printf("-h hash: use raw hash as input\n"); + printf("-l hash_list_file: use hash list file as input, each hash in a line\n"); + printf("-f pwdump_file: use pwdump file as input, handles lanmanager hash only\n"); + printf("-c lst_file: use .lst (cain format) file as input\n"); + printf("-r [-s session_name]: resume from previous session, optional session name\n"); + printf("rainbow_table_pathname: pathname(s) of the rainbow table(s)\n"); + printf("\n"); + printf("Extra options: -t [nr] use this amount of threads/cores, default is 1\n"); + printf(" -o [output_file] write (temporary) results to this file\n"); + printf(" -s [session_name] write session data with this name\n"); + printf(" -k keep precalculation on disk\n"); + printf(" -v show debug information\n"); + printf("\n"); +#ifdef _WIN32 + printf("example: rcracki_mt -h 5d41402abc4b2a76b9719d911017c592 -t 2 [path]\\MD5\n"); + printf(" rcracki_mt -l hash.txt [path_to_specific_table]\\*\n"); +#else + printf("example: rcracki_mt -h 5d41402abc4b2a76b9719d911017c592 -t 2 [path]/MD5\n"); + printf(" rcracki_mt -l hash.txt [path_to_specific_table]/*\n"); +#endif + printf(" rcracki_mt -f hash.txt -t 4 -o results.txt *.rti\n"); + +} + +int main(int argc, char* argv[]) +{ + if (argc < 2) + { + Usage(); + return 0; + } + + vector vPathName; + vector vDefaultRainbowTablePath; + string sWildCharPathName = ""; + string sInputType = ""; + string sInput = ""; + string outputFile = ""; + string sApplicationPath = ""; + string sIniPathName = "rcracki_mt.ini"; + bool writeOutput = false; + string sSessionPathName = "rcracki.session"; + string sProgressPathName = "rcracki.progress"; + string sPrecalcPathName = "rcracki.precalc"; + bool resumeSession = false; + bool useDefaultRainbowTablePath = false; + bool debug = false; + bool keepPrecalcFiles = false; + string sAlgorithm = ""; + int maxThreads = 1; + CHashSet hs; + + // Read defaults from ini file; + bool readFromIni = false; + vector vLine; + if (ReadLinesFromFile(sIniPathName, vLine)) { + readFromIni = true; + } + else if (ReadLinesFromFile(GetApplicationPath() + sIniPathName, vLine)) { + readFromIni = true; + } + if (readFromIni) + { + int i; + for (i = 0; i < vLine.size(); i++) + { + if (vLine[i].substr(0,1) != "#") + { + vector vPart; + if (SeperateString(vLine[i], "=", vPart)) + { + string sOption = vPart[0]; + string sValue = vPart[1]; + + if (sOption == "Threads") { + maxThreads = atoi(sValue.c_str()); + } + else if (sOption == "DefaultResultsFile") { + outputFile = sValue; + } + else if (sOption == "AlwaysStoreResultsToFile") { + if (sValue == "1") + writeOutput = true; + } + else if (sOption.substr(0,24) == "DefaultRainbowTablePath.") { + //printf("Default RT path: %s\n", sValue.c_str()); + vDefaultRainbowTablePath.push_back(vLine[i]); + } + else if (sOption == "DefaultAlgorithm") { + useDefaultRainbowTablePath = true; + sAlgorithm = sValue; + } + else if (sOption == "AlwaysDebug") { + if (sValue == "1") + debug = true; + } + else if (sOption == "AlwaysKeepPrecalcFiles") { + if (sValue == "1") + keepPrecalcFiles = true; + } + else { + printf("illegal option %s in ini file %s\n", sOption.c_str(), sIniPathName.c_str()); + return 0; + } + } + } + } + if (writeOutput && outputFile == "") + { + printf("You need to specify a 'DefaultResultsFile' with 'AlwaysStoreResultsToFile=1'\n"); + writeOutput = false; + } + } + + // Parse command line arguments + int i; + for (i = 1; i < argc; i++) + { + string cla = argv[i]; + if (cla == "-h") { + sInputType = cla; + i++; + if (i < argc) + sInput = argv[i]; + } + else if (cla == "-l") { + sInputType = cla; + i++; + if (i < argc) + sInput = argv[i]; + } + else if (cla == "-f") { + sInputType = cla; + i++; + if (i < argc) + sInput = argv[i]; + } + else if (cla == "-c") { + sInputType = cla; + i++; + if (i < argc) + sInput = argv[i]; + } + else if (cla == "-t") { + i++; + if (i < argc) + maxThreads = atoi(argv[i]); + } + else if (cla == "-o") { + writeOutput = true; + i++; + if (i < argc) + outputFile = argv[i]; + } + else if (cla == "-r") { + resumeSession = true; + } + else if (cla == "-s") { + i++; + if (i < argc) + { + sSessionPathName = argv[i]; + sSessionPathName += ".session"; + sProgressPathName = argv[i]; + sProgressPathName += ".progress"; + sPrecalcPathName = argv[i]; + sPrecalcPathName += ".precalc"; + } + } + else if (cla == "-v") { + debug = true; + } + else if (cla == "-k") { + keepPrecalcFiles = true; + } + else if (cla == "-a") { + useDefaultRainbowTablePath = true; + i++; + if (i < argc) + sAlgorithm = argv[i]; + } + else { + GetTableList(cla, vPathName); + } + } + + if (debug && !readFromIni) + printf("Debug: Couldn't read rcracki_mt.ini, continuing anyway.\n"); + + // Load session data if we are resuming + if (resumeSession) + { + vPathName.clear(); + vector sSessionData; + if (ReadLinesFromFile(sSessionPathName.c_str(), sSessionData)) + { + int i; + for (i = 0; i < sSessionData.size(); i++) + { + vector vPart; + if (SeperateString(sSessionData[i], "=", vPart)) + { + string sOption = vPart[0]; + string sValue = vPart[1]; + + if (sOption == "sPathName") { + vPathName.push_back(sValue); + } + else if (sOption == "sInputType") { + sInputType = sValue; + } + else if (sOption == "sInput") { + sInput = sValue; + } + else if (sOption == "outputFile") { + writeOutput = true; + outputFile = sValue; + } + else if (sOption == "keepPrecalcFiles") { + if (sValue == "1") + keepPrecalcFiles = true; + } + } + } + } + else { + printf("Couldn't open session file %s\n", sSessionPathName.c_str()); + return 0; + } + } + + if (maxThreads<1) + maxThreads = 1; + + // don't load these if we are resuming a session that already has a list of tables + if (useDefaultRainbowTablePath && !resumeSession) + { + int i; + for (i = 0; i < vDefaultRainbowTablePath.size(); i++) + { + vector vPart; + if (SeperateString(vDefaultRainbowTablePath[i], ".=", vPart)) + { + string lineAlgorithm = vPart[1]; + string linePath = vPart[2]; + + if (lineAlgorithm == sAlgorithm) + GetTableList(linePath, vPathName); + } + } + } + + printf("Using %d threads for pre-calculation and false alarm checking...\n", maxThreads); + + setvbuf(stdout, NULL, _IONBF,0); + if (vPathName.size() == 0) + { + printf("no rainbow table found\n"); + return 0; + } + printf("Found %d rainbowtable files...\n\n", vPathName.size()); + + bool fCrackerType; // true: hash cracker, false: lm cracker + vector vHash; // hash cracker + vector vUserName; // lm cracker + vector vLMHash; // lm cracker + vector vNTLMHash; // lm cracker + if (sInputType == "-h") + { + fCrackerType = true; + + string sHash = sInput; + if (NormalizeHash(sHash)) + vHash.push_back(sHash); + else + printf("invalid hash: %s\n", sHash.c_str()); + } + else if (sInputType == "-l") + { + fCrackerType = true; + + string sPathName = sInput; + vector vLine; + if (ReadLinesFromFile(sPathName, vLine)) + { + int i; + for (i = 0; i < vLine.size(); i++) + { + string sHash = vLine[i]; + if (NormalizeHash(sHash)) + vHash.push_back(sHash); + else + printf("invalid hash: %s\n", sHash.c_str()); + } + } + else + printf("can't open %s\n", sPathName.c_str()); + } + else if (sInputType == "-f") + { + fCrackerType = false; + + string sPathName = sInput; + LoadLMHashFromPwdumpFile(sPathName, vUserName, vLMHash, vNTLMHash); + } + else if (sInputType == "-c") + { + // 2009-01-04 - james - Added this for cain-files. + fCrackerType = false; + string sPathName = sInput; + LoadLMHashFromCainLSTFile(sPathName, vUserName, vLMHash, vNTLMHash); + } + else + { + Usage(); + return 0; + } + + if (fCrackerType && vHash.size() == 0) + { + printf("no hashes found"); + return 0; + } + if (!fCrackerType && vLMHash.size() == 0) + { + return 0; + printf("no hashes found"); + } + + if (fCrackerType) + { + int i; + for (i = 0; i < vHash.size(); i++) + hs.AddHash(vHash[i]); + } + else + { + int i; + for (i = 0; i < vLMHash.size(); i++) + { + hs.AddHash(vLMHash[i].substr(0, 16)); + hs.AddHash(vLMHash[i].substr(16, 16)); + } + } + + // Load found hashes from session file + if (resumeSession) + { + vector sSessionData; + if (ReadLinesFromFile(sSessionPathName.c_str(), sSessionData)) + { + int i; + for (i = 0; i < sSessionData.size(); i++) + { + vector vPart; + if (SeperateString(sSessionData[i], "=", vPart)) + { + string sOption = vPart[0]; + string sValue = vPart[1]; + + if (sOption == "sHash") { + vector vPartHash; + if (SeperateString(sValue, "::", vPartHash)) + { + string sHash = vPartHash[0]; + string sBinary = vPartHash[1]; + string sPlain = vPartHash[2]; + + hs.SetPlain(sHash, sPlain, sBinary); + } + } + } + } + } + } + + // (Over)write session data if we are not resuming + if (!resumeSession) + { + FILE* file = fopen(sSessionPathName.c_str(), "w"); + string buffer = ""; + + if (file!=NULL) + { + buffer += "sInputType=" + sInputType + "\n"; + buffer += "sInput=" + sInput + "\n"; + + int i; + for (i = 0; i < vPathName.size(); i++) + { + buffer += "sPathName=" + vPathName[i] + "\n"; + } + + if (writeOutput) + buffer += "outputFile=" + outputFile + "\n"; + + if (keepPrecalcFiles) + buffer += "keepPrecalcFiles=1\n"; + + fputs (buffer.c_str(), file); + fclose (file); + } + file = fopen(sProgressPathName.c_str(), "w"); + fclose (file); + } + + // Run + CCrackEngine ce; + if (writeOutput) + ce.setOutputFile(outputFile); + ce.setSession(sSessionPathName, sProgressPathName, sPrecalcPathName, keepPrecalcFiles); + ce.Run(vPathName, hs, maxThreads, resumeSession, debug); + + // Remove session files + if (debug) printf("Debug: Removing session files.\n"); + if (remove(sSessionPathName.c_str()) == 0) + remove(sProgressPathName.c_str()); + else + if (debug) printf("Debug: Failed removing session files.\n"); + + // Statistics + printf("statistics\n"); + printf("-------------------------------------------------------\n"); + printf("plaintext found: %d of %d (%.2f%%)\n", hs.GetStatHashFound(), + hs.GetStatHashTotal(), + 100.0f * hs.GetStatHashFound() / hs.GetStatHashTotal()); + printf("total disk access time: %.2f s\n", ce.GetStatTotalDiskAccessTime()); + printf("total cryptanalysis time: %.2f s\n", ce.GetStatTotalCryptanalysisTime()); + printf("total chain walk step: %d\n", ce.GetStatTotalChainWalkStep()); + printf("total false alarm: %d\n", ce.GetStatTotalFalseAlarm()); + printf("total chain walk step due to false alarm: %d\n", ce.GetStatTotalChainWalkStepDueToFalseAlarm()); +// printf("total chain walk step skipped due to checkpoints: %d\n", ce.GetStatTotalFalseAlarmSkipped()); // Checkpoints not used - yet + printf("\n"); + + // Result + printf("result\n"); + printf("-------------------------------------------------------\n"); + if (fCrackerType) + { + int i; + for (i = 0; i < vHash.size(); i++) + { + string sPlain, sBinary; + if (!hs.GetPlain(vHash[i], sPlain, sBinary)) + { + sPlain = ""; + sBinary = ""; + } + + printf("%s\t%s\thex:%s\n", vHash[i].c_str(), sPlain.c_str(), sBinary.c_str()); + } + } + else + { + int i; + for (i = 0; i < vLMHash.size(); i++) + { + string sPlain1, sBinary1; + bool fPart1Found = hs.GetPlain(vLMHash[i].substr(0, 16), sPlain1, sBinary1); + if (!fPart1Found) + { + sPlain1 = ""; + sBinary1 = ""; + } + + string sPlain2, sBinary2; + bool fPart2Found = hs.GetPlain(vLMHash[i].substr(16, 16), sPlain2, sBinary2); + if (!fPart2Found) + { + sPlain2 = ""; + sBinary2 = ""; + } + + string sPlain = sPlain1 + sPlain2; + string sBinary = sBinary1 + sBinary2; + + // Correct case + if (fPart1Found && fPart2Found) + { + unsigned char NTLMHash[16]; + int nHashLen; + ParseHash(vNTLMHash[i], NTLMHash, nHashLen); + if (nHashLen != 16) + printf("debug: nHashLen mismatch\n"); + string sNTLMPassword; + if (LMPasswordCorrectCase(sPlain, NTLMHash, sNTLMPassword)) + { + sPlain = sNTLMPassword; + sBinary = HexToStr((const unsigned char*)sNTLMPassword.c_str(), sNTLMPassword.size()); + } + else + { + printf("%-14s\t%s\thex:%s\n", vUserName[i].c_str(), sPlain.c_str(), sBinary.c_str()); + LM2NTLMcorrector corrector; + if (corrector.LMPasswordCorrectUnicode(sBinary, NTLMHash, sNTLMPassword)) + { + sPlain = sNTLMPassword; + sBinary = corrector.getBinary(); + if (writeOutput) + { + if (!writeResultLineToFile(outputFile, vNTLMHash[i].c_str(), sPlain.c_str(), sBinary.c_str())) + printf("Couldn't write final result to file!\n"); + } + } + else { + printf("case correction for password %s failed!\n", sPlain.c_str()); + } + } + } + + // Display + printf("%-14s\t%s\thex:%s\n", vUserName[i].c_str(), + sPlain.c_str(), + sBinary.c_str()); + + } + } + + return 0; +} diff --git a/Client Applications/rcracki_mt/charset.txt b/Client Applications/rcracki_mt/charset.txt new file mode 100644 index 0000000..6e749fa --- /dev/null +++ b/Client Applications/rcracki_mt/charset.txt @@ -0,0 +1,34 @@ +# charset configuration file for DistrRTgen v3.2 by Martin Westergaard (martinwj2005@gmail.com) + +byte = [] +alpha = [ABCDEFGHIJKLMNOPQRSTUVWXYZ] +alpha-space = [ABCDEFGHIJKLMNOPQRSTUVWXYZ ] +alpha-numeric = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789] +alpha-numeric-space = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ] +alpha-numeric-symbol14 = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=] +alpha-numeric-symbol14-space= [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+= ] +all = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/] +all-space = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/ ] +alpha-numeric-symbol32-space = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/ ] +lm-frt-cp437 = [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`{|}~€Ž’™š›œžŸ¥àáâãäæçèéêëî] +lm-frt-cp850 = [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`{|}~€Ž’™šœŸ¥µ¶·½¾ÇÏÑÒÓÔÕÖ×ØÞàáâãåæèéêëíï] +lm-frt-cp437-850 = [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`{|}~€Ž’™š›œžŸ¥µ¶·½¾ÇÏÑÒÓÔÕÖ×ØÞàáâãäåæçèéêëíîï] + +numeric = [0123456789] +numeric-space = [0123456789 ] +loweralpha = [abcdefghijklmnopqrstuvwxyz] +loweralpha-space = [abcdefghijklmnopqrstuvwxyz ] +loweralpha-numeric = [abcdefghijklmnopqrstuvwxyz0123456789] +loweralpha-numeric-space = [abcdefghijklmnopqrstuvwxyz0123456789 ] +loweralpha-numeric-symbol14 = [abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_+=] +loweralpha-numeric-all = [abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/] +loweralpha-numeric-symbol32-space= [abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/ ] + +mixalpha = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ] +mixalpha-space = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ] +mixalpha-numeric = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789] +mixalpha-numeric-space = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ] +mixalpha-numeric-symbol14 = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=] +mixalpha-numeric-all = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/] +mixalpha-numeric-symbol32-space = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/ ] +mixalpha-numeric-all-space = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/ ] diff --git a/Client Applications/rcracki_mt/fast_md5.cpp b/Client Applications/rcracki_mt/fast_md5.cpp new file mode 100644 index 0000000..8d60aee --- /dev/null +++ b/Client Applications/rcracki_mt/fast_md5.cpp @@ -0,0 +1,468 @@ +/* + * Fast implementation of the MD5 message-digest algorithm as per RFC + * (see http://tools.ietf.org/html/rfc1321) + * + * Author: Joao Inacio + * License: Use and share as you wish at your own risk, please keep this header ;) + * + * Optimizations: + * - For lengths < 16, transformation steps are "unrolled" using macros/defines + * - Constants used whenever possible, it's the compiler's job to sort them out + * - Padding is done on 4-byte words, and memory copied as last resort. + */ + + +typedef unsigned int UINT4; + + +/* MD5 defines as per RFC reference implementation */ + +#define AC1 0xd76aa478 +#define AC2 0xe8c7b756 +#define AC3 0x242070db +#define AC4 0xc1bdceee +#define AC5 0xf57c0faf +#define AC6 0x4787c62a +#define AC7 0xa8304613 +#define AC8 0xfd469501 +#define AC9 0x698098d8 +#define AC10 0x8b44f7af +#define AC11 0xffff5bb1 +#define AC12 0x895cd7be +#define AC13 0x6b901122 +#define AC14 0xfd987193 +#define AC15 0xa679438e +#define AC16 0x49b40821 +#define AC17 0xf61e2562 +#define AC18 0xc040b340 +#define AC19 0x265e5a51 +#define AC20 0xe9b6c7aa +#define AC21 0xd62f105d +#define AC22 0x02441453 +#define AC23 0xd8a1e681 +#define AC24 0xe7d3fbc8 +#define AC25 0x21e1cde6 +#define AC26 0xc33707d6 +#define AC27 0xf4d50d87 +#define AC28 0x455a14ed +#define AC29 0xa9e3e905 +#define AC30 0xfcefa3f8 +#define AC31 0x676f02d9 +#define AC32 0x8d2a4c8a +#define AC33 0xfffa3942 +#define AC34 0x8771f681 +#define AC35 0x6d9d6122 +#define AC36 0xfde5380c +#define AC37 0xa4beea44 +#define AC38 0x4bdecfa9 +#define AC39 0xf6bb4b60 +#define AC40 0xbebfbc70 +#define AC41 0x289b7ec6 +#define AC42 0xeaa127fa +#define AC43 0xd4ef3085 +#define AC44 0x04881d05 +#define AC45 0xd9d4d039 +#define AC46 0xe6db99e5 +#define AC47 0x1fa27cf8 +#define AC48 0xc4ac5665 +#define AC49 0xf4292244 +#define AC50 0x432aff97 +#define AC51 0xab9423a7 +#define AC52 0xfc93a039 +#define AC53 0x655b59c3 +#define AC54 0x8f0ccc92 +#define AC55 0xffeff47d +#define AC56 0x85845dd1 +#define AC57 0x6fa87e4f +#define AC58 0xfe2ce6e0 +#define AC59 0xa3014314 +#define AC60 0x4e0811a1 +#define AC61 0xf7537e82 +#define AC62 0xbd3af235 +#define AC63 0x2ad7d2bb +#define AC64 0xeb86d391 + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +#define Ca 0x67452301 +#define Cb 0xefcdab89 +#define Cc 0x98badcfe +#define Cd 0x10325476 + + +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +//#define G(x, y, z) F((z), (x), (y)) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +// md5 step +#define MD5STEP(f, a, b, c, d, AC, x, s) { \ + (a) += f ((b), (c), (d)); \ + (a) += (AC) + (x); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ +} + +// full MD5 transformation +#define MD5_steps(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { \ + \ + MD5STEP(F, a, b, c, d, AC1, w0, S11);\ + MD5STEP(F, d, a, b, c, AC2, w1, S12);\ + MD5STEP(F, c, d, a, b, AC3, w2, S13);\ + MD5STEP(F, b, c, d, a, AC4, w3, S14);\ + MD5STEP(F, a, b, c, d, AC5, w4, S11);\ + MD5STEP(F, d, a, b, c, AC6, w5, S12);\ + MD5STEP(F, c, d, a, b, AC7, w6, S13);\ + MD5STEP(F, b, c, d, a, AC8, w7, S14);\ + MD5STEP(F, a, b, c, d, AC9, w8, S11);\ + MD5STEP(F, d, a, b, c, AC10, w9, S12);\ + MD5STEP(F, c, d, a, b, AC11, w10, S13);\ + MD5STEP(F, b, c, d, a, AC12, w11, S14);\ + MD5STEP(F, a, b, c, d, AC13, w12, S11);\ + MD5STEP(F, d, a, b, c, AC14, w13, S12);\ + MD5STEP(F, c, d, a, b, AC15, w14, S13);\ + MD5STEP(F, b, c, d, a, AC16, w15, S14);\ + \ + MD5STEP(G, a, b, c, d, AC17, w1, S21);\ + MD5STEP(G, d, a, b, c, AC18, w6, S22);\ + MD5STEP(G, c, d, a, b, AC19, w11, S23);\ + MD5STEP(G, b, c, d, a, AC20, w0, S24);\ + MD5STEP(G, a, b, c, d, AC21, w5, S21);\ + MD5STEP(G, d, a, b, c, AC22, w10, S22);\ + MD5STEP(G, c, d, a, b, AC23, w15, S23);\ + MD5STEP(G, b, c, d, a, AC24, w4, S24);\ + MD5STEP(G, a, b, c, d, AC25, w9, S21);\ + MD5STEP(G, d, a, b, c, AC26, w14, S22);\ + MD5STEP(G, c, d, a, b, AC27, w3, S23);\ + MD5STEP(G, b, c, d, a, AC28, w8, S24);\ + MD5STEP(G, a, b, c, d, AC29, w13, S21);\ + MD5STEP(G, d, a, b, c, AC30, w2, S22);\ + MD5STEP(G, c, d, a, b, AC31, w7, S23);\ + MD5STEP(G, b, c, d, a, AC32, w12, S24);\ + \ + MD5STEP(H, a, b, c, d, AC33, w5, S31);\ + MD5STEP(H, d, a, b, c, AC34, w8, S32);\ + MD5STEP(H, c, d, a, b, AC35, w11, S33);\ + MD5STEP(H, b, c, d, a, AC36, w14, S34);\ + MD5STEP(H, a, b, c, d, AC37, w1, S31);\ + MD5STEP(H, d, a, b, c, AC38, w4, S32);\ + MD5STEP(H, c, d, a, b, AC39, w7, S33);\ + MD5STEP(H, b, c, d, a, AC40, w10, S34);\ + MD5STEP(H, a, b, c, d, AC41, w13, S31);\ + MD5STEP(H, d, a, b, c, AC42, w0, S32);\ + MD5STEP(H, c, d, a, b, AC43, w3, S33);\ + MD5STEP(H, b, c, d, a, AC44, w6, S34);\ + MD5STEP(H, a, b, c, d, AC45, w9, S31);\ + MD5STEP(H, d, a, b, c, AC46, w12, S32);\ + MD5STEP(H, c, d, a, b, AC47, w15, S33);\ + MD5STEP(H, b, c, d, a, AC48, w2, S34);\ + \ + MD5STEP(I, a, b, c, d, AC49, w0, S41);\ + MD5STEP(I, d, a, b, c, AC50, w7, S42);\ + MD5STEP(I, c, d, a, b, AC51, w14, S43);\ + MD5STEP(I, b, c, d, a, AC52, w5, S44);\ + MD5STEP(I, a, b, c, d, AC53, w12, S41);\ + MD5STEP(I, d, a, b, c, AC54, w3, S42);\ + MD5STEP(I, c, d, a, b, AC55, w10, S43);\ + MD5STEP(I, b, c, d, a, AC56, w1, S44);\ + MD5STEP(I, a, b, c, d, AC57, w8, S41);\ + MD5STEP(I, d, a, b, c, AC58, w15, S42);\ + MD5STEP(I, c, d, a, b, AC59, w6, S43);\ + MD5STEP(I, b, c, d, a, AC60, w13, S44);\ + MD5STEP(I, a, b, c, d, AC61, w4, S41);\ + MD5STEP(I, d, a, b, c, AC62, w11, S42);\ + MD5STEP(I, c, d, a, b, AC63, w2, S43);\ + MD5STEP(I, b, c, d, a, AC64, w9, S44);\ +} + +// len >= 56 +#define MD5_transform_add(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { \ + \ + a = wOut[0]; b = wOut[1]; c = wOut[2]; d = wOut[3];\ + \ + MD5_steps(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15);\ + \ + wOut[0] += a; wOut[1] += b; wOut[2] += c; wOut[3] += d;\ +} + +// len < 56 +#define MD5_transform_single(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { \ + \ + a = CC[0]; b=CC[1]; c=CC[2]; d=CC[3];\ + \ + MD5_steps(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15);\ + \ + wOut[0] = a+Ca; wOut[1] = b+Cb; wOut[2] = c+Cc; wOut[3] = d+Cd;\ +} + +// len < 16 +#define MD5_transform_16(w0, w1, w2, w3, w14) \ + MD5_transform_single(w0, w1, w2, w3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, w14, 0); + + +// pad word and append 0x80 at appropriate location +#define MD5_pad_w0() (0x00000080) +#define MD5_pad_w1(data) (((data) & 0x000000FF) | 0x00008000) +#define MD5_pad_w2(data) (((data) & 0x0000FFFF) | 0x00800000) +#define MD5_pad_w3(data) (((data) & 0x00FFFFFF) | 0x80000000) + + +#ifndef MD5_pad_w1 +static inline UINT4 MD5_pad_w1(UINT4 data) +{ + __asm__ ( + "movb %%al, %%cl \n\t" + "xorl %1, %1 \n\t" + "orb $128, %%ah \n\t" + "movb %%cl, %%al \n\t" + "movl %1, %0 \n\t" + : "=r" (data) + : "a" (data) + : "cl" + ); + return data; +} +#endif + +#ifndef MD5_pad_w3 +static inline UINT4 MD5_pad_w3(UINT4 data) +{ + __asm__ ( + "roll $8, %1 \n\t" + "movb $128, %%al \n\t" + "rorl $8, %1 \n\t" + "movl %1, %0 \n\t" + : "=r" (data) + : "a" (data) + ); + return data; +} +#endif + + +static inline void MD5_copy_pad_block(UINT4 *dData, UINT4 *wIn, int blocklen, int len) +{ + register int cl; + + // copy full words + for (cl = 0; cl < blocklen; cl++) + dData[cl] = wIn[cl]; + + // copy with padding + switch (len & 0x03) { + case 0: + dData[cl] = MD5_pad_w0(); + break; + case 1: + dData[cl] = MD5_pad_w1(wIn[cl]); + break; + case 2: + dData[cl] = MD5_pad_w2(wIn[cl]); + break; + case 3: + dData[cl] = MD5_pad_w3(wIn[cl]); + break; + } + // append 0's + for (cl++; cl < 14; cl++) + dData[cl] = 0; + // append len + dData[cl++] = (len << 3); + dData[cl] = (len >> 29); +} + +// fast initializer array +//__attribute__((aligned(16))) +//__declspec(align(16)) +static const UINT4 CC[4] = {Ca, Cb, Cc, Cd}; + + + +/* + * fast_MD5() + * + */ +void fast_MD5(unsigned char *pData, int len, unsigned char *pDigest) +{ + #define wIn ((UINT4 *)pData) + #define wOut ((UINT4 *)pDigest) + + register UINT4 a; + register UINT4 b; + register UINT4 c; + register UINT4 d; + + switch (len) { + case 0: + MD5_transform_16(MD5_pad_w0(), 0, 0, 0, 8*0); + return; + case 1: + MD5_transform_16(MD5_pad_w1(wIn[0]), 0, 0, 0, 8*1); + return; + case 2: + MD5_transform_16(MD5_pad_w2(wIn[0]), 0, 0, 0, 8*2); + return; + case 3: + MD5_transform_16(MD5_pad_w3(wIn[0]), 0, 0, 0, 8*3); + return; + case 4: + MD5_transform_16(wIn[0], MD5_pad_w0(), 0, 0, 8*4); + return; + case 5: + MD5_transform_16(wIn[0], MD5_pad_w1(wIn[1]), 0, 0, 8*5); + return; + case 6: + MD5_transform_16(wIn[0], MD5_pad_w2(wIn[1]), 0, 0, 8*6); + return; + case 7: + MD5_transform_16(wIn[0], MD5_pad_w3(wIn[1]), 0, 0, 8*7); + return; + case 8: + MD5_transform_16(wIn[0], wIn[1], MD5_pad_w0(), 0, 8*8); + return; + case 9: + MD5_transform_16(wIn[0], wIn[1], MD5_pad_w1(wIn[2]), 0, 8*9); + return; + case 10: + MD5_transform_16(wIn[0], wIn[1], MD5_pad_w2(wIn[2]), 0, 8*10); + return; + case 11: + MD5_transform_16(wIn[0], wIn[1], MD5_pad_w3(wIn[2]), 0, 8*11); + return; + case 12: + MD5_transform_16(wIn[0], wIn[1], wIn[2], MD5_pad_w0(), 8*12); + return; + case 13: + MD5_transform_16(wIn[0], wIn[1], wIn[2], MD5_pad_w1(wIn[3]), 8*13); + return; + case 14: + MD5_transform_16(wIn[0], wIn[1], wIn[2], MD5_pad_w2(wIn[3]), 8*14) + return; + case 15: + MD5_transform_16(wIn[0], wIn[1], wIn[2], MD5_pad_w3(wIn[3]), 8*15) + return; + } + + // data block used for padding + UINT4 dData[16]; + + if (len < 56) { + // 16 < length < 56 + + MD5_copy_pad_block(dData, wIn, (len >> 2), len); + + // redefine data input, point to padded data + #undef wIn + #define wIn dData + + MD5_transform_single ( + wIn[ 0], wIn[ 1], wIn[ 2], wIn[ 3], wIn[ 4], wIn[ 5], wIn[ 6], wIn[ 7], + wIn[ 8], wIn[ 9], wIn[10], wIn[11], wIn[12], wIn[13], wIn[14], wIn[15] + ); + + #undef wIn + return; + } else { + // len >= 56 + + #define wIn ((UINT4 *)pData) + + // original len + int tlen = len; + + // init digest for long lens + wOut[0] = Ca; wOut[1] = Cb; wOut[2] = Cc; wOut[3] = Cd; + + while (tlen >= 64) { + // Process 64-byte chunks + MD5_transform_add( + wIn[ 0], wIn[ 1], wIn[ 2], wIn[ 3], wIn[ 4], wIn[ 5], wIn[ 6], wIn[ 7], + wIn[ 8], wIn[ 9], wIn[10], wIn[11], wIn[12], wIn[13], wIn[14], wIn[15] + ); + + tlen -= 64; + pData += 64; + } + + if (tlen >= 56) { + // Process > 56-byte chunk + + int cl = (tlen >> 2); + // perform padding on last 2 byte + if (cl > 14) { + dData[14] = wIn[14]; + } else { + dData[15] = 0; + } + // copy 1 word with padding byte + switch (len & 0x03) { + case 0: + dData[cl] = MD5_pad_w0(); + break; + case 1: + dData[cl] = MD5_pad_w1(wIn[cl]); + break; + case 2: + dData[cl] = MD5_pad_w2(wIn[cl]); + break; + case 3: + dData[cl] = MD5_pad_w3(wIn[cl]); + break; + } + + // transform + MD5_transform_add( + wIn[ 0], wIn[ 1], wIn[ 2], wIn[ 3], wIn[ 4], wIn[ 5], wIn[ 6], wIn[ 7], + wIn[ 8], wIn[ 9], wIn[10], wIn[11], wIn[12], wIn[13], dData[14], dData[15] + ); + // final transform + #define w14 (len << 3) + #define w15 (len >> 29) + MD5_transform_add( + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, w14, w15 + ); + #undef w14 + #undef w15 + return; + } else { + // (len mod 64) < 56 + + MD5_copy_pad_block(dData, wIn, (tlen >> 2), len); + + #undef wIn + #define wIn dData + + // transform + MD5_transform_add( + wIn[ 0], wIn[ 1], wIn[ 2], wIn[ 3], wIn[ 4], wIn[ 5], wIn[ 6], wIn[ 7], + wIn[ 8], wIn[ 9], wIn[10], wIn[11], wIn[12], wIn[13], wIn[14], wIn[15] + ); + + #undef wIn + #define wIn ((UINT4 *)pData) + return; + } + } + + /* end of fast_MD5() */ +} + diff --git a/Client Applications/rcracki_mt/fast_md5.h b/Client Applications/rcracki_mt/fast_md5.h new file mode 100644 index 0000000..efea781 --- /dev/null +++ b/Client Applications/rcracki_mt/fast_md5.h @@ -0,0 +1,23 @@ +/* + * Fast implementation of the MD5 message-digest algorithm as per RFC + * (see http://tools.ietf.org/html/rfc1321) + * + * Author: Joao Inacio + * License: Use and share as you wish at your own risk, please keep this header ;) + * + * Optimizations: + * - For lengths < 16, transformation steps are "unrolled" using macros/defines + * - Constants used whenever possible, it's the compiler's job to sort them out + * - Padding is done on 4-byte words, and memory copied as last resort. + */ + + +#ifndef FAST_MD5_H +#define FAST_MD5_H + + +void +fast_MD5(unsigned char *pData, int len, unsigned char *pDigest); + + +#endif // FAST_MD5_H diff --git a/Client Applications/rcracki_mt/libeay32.dll b/Client Applications/rcracki_mt/libeay32.dll new file mode 100644 index 0000000..36f6d69 Binary files /dev/null and b/Client Applications/rcracki_mt/libeay32.dll differ diff --git a/Client Applications/rcracki_mt/libeay32.lib b/Client Applications/rcracki_mt/libeay32.lib new file mode 100644 index 0000000..93139c6 Binary files /dev/null and b/Client Applications/rcracki_mt/libeay32.lib differ diff --git a/Client Applications/rcracki_mt/lm2ntlm.cpp b/Client Applications/rcracki_mt/lm2ntlm.cpp new file mode 100644 index 0000000..1b80e9c --- /dev/null +++ b/Client Applications/rcracki_mt/lm2ntlm.cpp @@ -0,0 +1,2256 @@ +/* +* Copyright (C) Daniël Niggebrugge +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, [...] etc :p +*/ + +#ifdef _WIN32 + #pragma warning(disable : 4786 4267 4018) +#endif + +#include "lm2ntlm.h" + +LM2NTLMcorrector::LM2NTLMcorrector() +{ + progressCurrentCombination = 0; + totalCurrentCombination = 1; + counterOverall = 0; + countCombinations = 0; + countTotalCombinations = 0; + counter = 0; + fillMapW(); + aborting = false; + sBinary = ""; + +} + +string LM2NTLMcorrector::getBinary() +{ + return sBinary; +} + +bool LM2NTLMcorrector::LMPasswordCorrectUnicode(string hexPassword, unsigned char* pNTLMHash, string& sNTLMPassword) //, unsigned char* pLMPassword +{ + string sPlain = ""; + + int i; + for (i = 0; i < hexPassword.size() / 2; i++) + { + string sSub = hexPassword.substr(i * 2, 2); + int nValue; + sscanf(sSub.c_str(), "%02x", &nValue); + sPlain += (unsigned char)nValue; + } + + memcpy(NTLMHash, pNTLMHash, 16); + + + int tmpLength = sPlain.size() * 2; + unsigned char* pLMPassword = new unsigned char[tmpLength]; + + //printf("Searching for unicode password.\n"); + printf("Failed case correction, trying unicode correction for: %s\n", sPlain.c_str()); + //printf("NTLM hash: %s\n\n", sNTLMHash.c_str()); + + setvbuf(stdout, NULL, _IONBF,0); + + startClock = clock(); + previousClock = clock(); + +#ifndef _WIN32 + tty_init(); +#endif + + if (startCorrecting(sPlain, NTLMHash, sNTLMPassword, pLMPassword)) + { + sBinary = ByteToStr(pLMPassword, tmpLength).c_str(); + //printf("\nFound unicode password: %s\n", sNTLMPassword.c_str()); + //printf("Password in hex: %s\n", sBinary.c_str()); + writeEndStats(); +#ifndef _WIN32 + tty_done(); +#endif + return true; + } + else + { + //printf("\ncase correction for password %s fail!\n", sPlain.c_str()); + writeEndStats(); +#ifndef _WIN32 + tty_done(); +#endif + return false; + } +} + +bool LM2NTLMcorrector::startCorrecting(string sLMPassword, unsigned char* pNTLMHash, string& sNTLMPassword, unsigned char* pLMPassword) +{ + if (sLMPassword.size() == 0) + { + sNTLMPassword = ""; + return true; + } + + string muteMe = sLMPassword; + int length = muteMe.size(); + + unsigned char* pMuteMe = new unsigned char[length]; + unsigned char* pTempMute = new unsigned char[length * 2]; + + int i; + for (i = 0; i < length; i++) + { + pMuteMe[i] = muteMe[i]; + pTempMute[i * 2 ] = muteMe[i]; + pTempMute[i * 2 + 1] = 0x00; + unsigned char muteChar = pMuteMe[i]; + int sizeMapForChar = m_mapChar[muteChar].size(); + int j; + for (j = 0; j < sizeMapForChar; j++) + { + currentCharmap[i][j] = m_mapChar[muteChar][j]; + } + } + + int* jAtPos = new int[length]; + int* sizeAtPos = new int[length]; + bool* fullAtPos = new bool[length]; + + int setSize; + for (setSize = 0; setSize <= length; setSize++) + { + int cntFull = 0; + + // clear all 'fullatpos' before new setSize + int i; + for (i=0; i < length; i++) + { + fullAtPos[i] = false; + } + + //printf("Trying full unicode map for %d/%d characters...\t\t\n", setSize, length); + printf("Trying full unicode map for %d/%d characters...%-20s\n", setSize, length, ""); + + bool notFirst = true; + + // start at end and set 'full' combination + countCombinations = 0; + countTotalCombinations = calculateTotalCombinations(length, setSize); + + int sPos = length - 1; + while (sPos >= 0 && notFirst) // finding combinations for current 'setSize' + { + if (aborting) + return false; + + if (cntFull < setSize) + { + if (fullAtPos[sPos] == false) + { + fullAtPos[sPos] = true; + cntFull++; + } + sPos--; + } + else + { + if (fullAtPos[sPos] == false && setSize > 0) + { + fullAtPos[sPos] = true; + cntFull++; + + // reset positions after sPos + int k; + for (k = sPos+1; k < length; k++) + { + if (fullAtPos[k] == true) + { + fullAtPos[k] = false; + cntFull--; + } + } + // start at end again + sPos = length - 1; + } + else + { + sPos--; + } + } + // we have a combination + if (cntFull == setSize) + { + countCombinations++; + + setupCombinationAtPositions(length, pMuteMe, pTempMute, jAtPos, fullAtPos, sizeAtPos); + + if (checkPermutations(length, pMuteMe, pTempMute, jAtPos, sizeAtPos, pLMPassword, sNTLMPassword)) + { + return true; + } + } + + if (setSize == 0) + notFirst = false; + } + } + return false; +} + +// set up combination at positions +void LM2NTLMcorrector::setupCombinationAtPositions(int length, unsigned char* pMuteMe, unsigned char* pTempMute, int* jAtPos, bool* fullAtPos, int* sizeAtPos) +{ + progressCurrentCombination = 0; + totalCurrentCombination = 1; + + int i; + for (i=0; i < length; i++) + { + pTempMute[i*2] = currentCharmap[i][0]; + pTempMute[i*2+1] = currentCharmap[i][1]; // reset to first char in map + + jAtPos[i] = 0; // reset charcounter for this char (that is all chars) + + // based on combination, set full map or only upper/lowercase + if (fullAtPos[i] == true) + { + unsigned char muteChar = pMuteMe[i]; + int sizeMapForChar = m_mapChar[muteChar].size()/2; // 2 bytes per char + sizeAtPos[i] = sizeMapForChar; + } + else + { + sizeAtPos[i] = 2; + } + + totalCurrentCombination *= sizeAtPos[i]; + } + //printf("Trying %I64u passwords for current combination\t\t\r", totalCurrentCombination); +} + +// go check all permutations for this combination +bool LM2NTLMcorrector::checkPermutations(int length, unsigned char* pMuteMe, unsigned char* pTempMute, int* jAtPos, int* sizeAtPos, unsigned char* pLMPassword, string& sNTLMPassword) +{ + int pos = length - 1; + + while (pos >= 0) + { + counter++; + + pos = length - 1; + + int jAtCurPos = jAtPos[pos]; + int sizeMapForCharPos = sizeAtPos[pos]; + // move to start of string and find character with permutations left + while (jAtCurPos >= sizeMapForCharPos-1 && pos >= -1) + { + pos--; + if (pos >= 0 ) + { + jAtCurPos = jAtPos[pos]; + sizeMapForCharPos = sizeAtPos[pos]; + } + } + if (pos < 0) + continue; + + // next permutation for character + jAtCurPos++; + jAtPos[pos] = jAtCurPos; + + pTempMute[pos*2] = currentCharmap[pos][jAtCurPos*2]; + pTempMute[pos*2+1] = currentCharmap[pos][jAtCurPos*2+1]; + + // reset positions after pos + int k; + for (k = pos+1; k < length; k++) + { + jAtPos[k] = 0; + pTempMute[k*2] = currentCharmap[k][0]; // reset to first char in map + pTempMute[k*2+1] = currentCharmap[k][1]; + } + + if (checkNTLMPassword(pTempMute, length, sNTLMPassword) == true) + { + int i; + for (i = 0; i < length*2; i++) + pLMPassword[i] = pTempMute[i]; + return true; + } + + if (counter > 10000) // don't check clocks too often + { + clock_t currentClock = clock(); + float fTime = 1.0f * (currentClock - previousClock); + if (fTime > 1.0f * CLOCKS_PER_SEC) + { + float progressPercentageCurrentCombination = progressCurrentCombination * 100.0f / totalCurrentCombination; + float fTime = 1.0f * (currentClock - startClock) / CLOCKS_PER_SEC; + float currentSpeed = (counterOverall + progressCurrentCombination) / fTime / 1000000; + + //printf("%.2f%% of combination %d/%d (%.2f Mhashes/s)\t\t\t\t\r", progressPercentageCurrentCombination, countCombinations, countTotalCombinations, currentSpeed); + printf("%.2f%% of combination %d/%d (%.2f Mhashes/s)%-30s\r", progressPercentageCurrentCombination, countCombinations, countTotalCombinations, currentSpeed, ""); + + previousClock = clock(); + #ifdef _WIN32 + if (_kbhit()) + { + int ch = _getch(); + ch = toupper(ch); + if (ch == 'S') + { + aborting = true; + printf( "\nAborting unicode correction for this hash...\n"); + } + else + { + printf( "\nPress 'S' to skip unicode correction for this hash...\n"); + } + } + #else + int c = tty_getchar(); + if (c >= 0) { + tty_flush(); + if (c==115) { // = s + aborting = true; + printf( "\nAborting unicode correction for this hash...\n"); + } + else { + printf( "\nPress 's' to skip unicode correction for this hash...\n"); + } + } + #endif + if (aborting) + return false; + } + counter = 0; + } + + progressCurrentCombination++; + counterOverall++; + } + return false; +} + +// check password, maybe integrate this function in checkPermutations() for performance reasons. +bool LM2NTLMcorrector::checkNTLMPassword(unsigned char* pLMPassword, int nLMPasswordLen, string& sNTLMPassword) +{ + unsigned char md[16]; + + //MD4(pLMPassword, nLMPasswordLen * 2, md); + MD4_CTX ctx; + MD4_Init(&ctx); + MD4_Update(&ctx, pLMPassword, nLMPasswordLen * 2); + MD4_Final(md, &ctx); + + if (memcmp(md, NTLMHash, 16) == 0) + { + sNTLMPassword = ""; + int i; + for (i = 0; i < nLMPasswordLen; i++) { + sNTLMPassword += char(pLMPassword[i * 2]); + } + return true; + } + else + return false; +} + +void LM2NTLMcorrector::checkAbort() +{ +#ifdef _WIN32 + if (_kbhit()) + { + int ch = _getch(); + ch = toupper(ch); + if (ch == 'S') + { + aborting = true; + printf( "\nAborting unicode correction for this hash...\n"); + } + else + { + printf( "\nPress 'S' to skip unicode correction for this hash...\n"); + } + } +#endif +} + +void LM2NTLMcorrector::writeEndStats() +{ + clock_t endClock = clock(); + if (endClock - startClock > 0) + { + float fTime = 1.0f * (endClock - startClock) / CLOCKS_PER_SEC; + float speedOverall = counterOverall / fTime / 1000000; + printf("\nTried %s passwords in %.2f s (%.2f Mhashes/s)\n", uint64tostr(counterOverall).c_str(), fTime, speedOverall); + } + + printf("\n"); +} + +int LM2NTLMcorrector::calculateTotalCombinations(int length, int setSize) +{ + return factorial(length) / (factorial(setSize) * factorial(length-setSize)); +} + + +int LM2NTLMcorrector::factorial (int num) +{ + int result = 1; + int i; + for (i = 1; i <= num; ++i) + result *= i; + return result; +} + +// convert some bytes into a string +string LM2NTLMcorrector::ByteToStr(const unsigned char* pData, int nLen) +{ + string sRet = ""; + int i; + for (i = 0; i < nLen/2; i++) + { + char szByte[3]; + sprintf(szByte, "%02x", pData[i*2+1]); // swap 2-byte characters again + sRet += szByte; + sprintf(szByte, "%02x", pData[i*2]); + sRet += szByte; + } + + return sRet; +} + +void LM2NTLMcorrector::addToMapW(unsigned char key, unsigned char value1, unsigned char value2) +{ + int cnt = m_mapChar[key].size(); + m_mapChar[key][cnt] = value2; + m_mapChar[key][cnt+1] = value1; //reverse for endiannes +} + +// construct the mappings, would be nicer in a separate (importable) file +void LM2NTLMcorrector::fillMapW() +{ + addToMapW(0x01, 0x00, 0x01); + addToMapW(0x01, 0x26, 0x3A); + addToMapW(0x02, 0x00, 0x02); + addToMapW(0x02, 0x26, 0x3B); + addToMapW(0x03, 0x00, 0x03); + addToMapW(0x03, 0x26, 0x65); + addToMapW(0x04, 0x00, 0x04); + addToMapW(0x04, 0x26, 0x66); + addToMapW(0x05, 0x00, 0x05); + addToMapW(0x05, 0x26, 0x63); + addToMapW(0x06, 0x00, 0x06); + addToMapW(0x06, 0x26, 0x60); + addToMapW(0x07, 0x00, 0x07); + addToMapW(0x07, 0x00, 0xB7); + addToMapW(0x07, 0x20, 0x22); + addToMapW(0x07, 0x20, 0x24); + addToMapW(0x07, 0x20, 0x26); + addToMapW(0x07, 0x22, 0x19); + addToMapW(0x07, 0x22, 0xC5); + addToMapW(0x07, 0x30, 0xFB); + addToMapW(0x08, 0x00, 0x08); + addToMapW(0x08, 0x25, 0xD8); + addToMapW(0x09, 0x00, 0x09); + addToMapW(0x09, 0x20, 0xDD); + addToMapW(0x09, 0x25, 0xCB); + addToMapW(0x09, 0x30, 0x07); + addToMapW(0x0a, 0x00, 0x0A); + addToMapW(0x0a, 0x25, 0xD9); + addToMapW(0x0b, 0x00, 0x0B); + addToMapW(0x0b, 0x26, 0x42); + addToMapW(0x0c, 0x00, 0x0C); + addToMapW(0x0c, 0x26, 0x40); + addToMapW(0x0d, 0x00, 0x0D); + addToMapW(0x0d, 0x26, 0x6A); + addToMapW(0x0e, 0x00, 0x0E); + addToMapW(0x0e, 0x26, 0x6B); + addToMapW(0x0f, 0x00, 0x0F); + addToMapW(0x0f, 0x00, 0xA4); + addToMapW(0x0f, 0x26, 0x3C); + addToMapW(0x10, 0x00, 0x10); + addToMapW(0x10, 0x25, 0xBA); + addToMapW(0x11, 0x00, 0x11); + addToMapW(0x11, 0x25, 0xC4); + addToMapW(0x12, 0x00, 0x12); + addToMapW(0x12, 0x21, 0x95); + addToMapW(0x13, 0x00, 0x13); + addToMapW(0x13, 0x20, 0x3C); + addToMapW(0x14, 0x00, 0x14); + addToMapW(0x14, 0x00, 0xB6); + addToMapW(0x15, 0x00, 0x15); + addToMapW(0x15, 0x00, 0xA7); + addToMapW(0x16, 0x00, 0x16); + addToMapW(0x16, 0x02, 0xC9); + addToMapW(0x16, 0x25, 0xAC); + addToMapW(0x17, 0x00, 0x17); + addToMapW(0x17, 0x21, 0xA8); + addToMapW(0x18, 0x00, 0x18); + addToMapW(0x18, 0x21, 0x91); + addToMapW(0x19, 0x00, 0x19); + addToMapW(0x19, 0x21, 0x93); + addToMapW(0x1a, 0x00, 0x1A); + addToMapW(0x1a, 0x21, 0x92); + addToMapW(0x1b, 0x00, 0x1B); + addToMapW(0x1b, 0x21, 0x90); + addToMapW(0x1c, 0x00, 0x1C); + addToMapW(0x1c, 0x22, 0x1F); + addToMapW(0x1d, 0x00, 0x1D); + addToMapW(0x1d, 0x21, 0x94); + addToMapW(0x1e, 0x00, 0x1E); + addToMapW(0x1e, 0x25, 0xB2); + addToMapW(0x1f, 0x00, 0x1F); + addToMapW(0x1f, 0x25, 0xBC); + addToMapW(0x20, 0x00, 0x20); + addToMapW(0x20, 0x20, 0x00); + addToMapW(0x20, 0x20, 0x01); + addToMapW(0x20, 0x20, 0x02); + addToMapW(0x20, 0x20, 0x03); + addToMapW(0x20, 0x20, 0x04); + addToMapW(0x20, 0x20, 0x05); + addToMapW(0x20, 0x20, 0x06); + addToMapW(0x20, 0x30, 0x00); + addToMapW(0x21, 0x00, 0x21); + addToMapW(0x21, 0x00, 0xA1); + addToMapW(0x21, 0x01, 0xC3); + addToMapW(0x21, 0xFF, 0x01); + addToMapW(0x22, 0x00, 0x22); + addToMapW(0x22, 0x00, 0xA8); + addToMapW(0x22, 0x02, 0xBA); + addToMapW(0x22, 0x03, 0x08); + addToMapW(0x22, 0x03, 0x0E); + addToMapW(0x22, 0x20, 0x1C); + addToMapW(0x22, 0x20, 0x1D); + addToMapW(0x22, 0x20, 0x1E); + addToMapW(0x22, 0x20, 0x33); + addToMapW(0x22, 0x20, 0x35); + addToMapW(0x22, 0x27, 0x5D); + addToMapW(0x22, 0x27, 0x5E); + addToMapW(0x22, 0x30, 0x1D); + addToMapW(0x22, 0x30, 0x1E); + addToMapW(0x22, 0x30, 0x1F); + addToMapW(0x22, 0xFF, 0x02); + addToMapW(0x23, 0x00, 0x23); + addToMapW(0x23, 0xFF, 0x03); + addToMapW(0x24, 0x00, 0x24); + addToMapW(0x24, 0xFF, 0x04); + addToMapW(0x25, 0x00, 0x25); + addToMapW(0x25, 0x06, 0x6A); + addToMapW(0x25, 0x20, 0x30); + addToMapW(0x25, 0xFF, 0x05); + addToMapW(0x26, 0x00, 0x26); + addToMapW(0x26, 0xFF, 0x06); + addToMapW(0x27, 0x00, 0x27); + addToMapW(0x27, 0x00, 0xB4); + addToMapW(0x27, 0x02, 0xB9); + addToMapW(0x27, 0x02, 0xBB); + addToMapW(0x27, 0x02, 0xBC); + addToMapW(0x27, 0x02, 0xC8); + addToMapW(0x27, 0x02, 0xCA); + addToMapW(0x27, 0x02, 0xCB); + addToMapW(0x27, 0x03, 0x00); + addToMapW(0x27, 0x03, 0x01); + addToMapW(0x27, 0x20, 0x18); + addToMapW(0x27, 0x20, 0x19); + addToMapW(0x27, 0x20, 0x1A); + addToMapW(0x27, 0x20, 0x32); + addToMapW(0x27, 0x27, 0x5B); + addToMapW(0x27, 0x27, 0x5C); + addToMapW(0x27, 0xFF, 0x07); + addToMapW(0x28, 0x00, 0x28); + addToMapW(0x28, 0x23, 0x20); + addToMapW(0x28, 0xFF, 0x08); + addToMapW(0x29, 0x00, 0x29); + addToMapW(0x29, 0x23, 0x21); + addToMapW(0x29, 0xFF, 0x09); + addToMapW(0x2a, 0x00, 0x2A); + addToMapW(0x2a, 0x22, 0x17); + addToMapW(0x2a, 0xFF, 0x0A); + addToMapW(0x2b, 0x00, 0x2B); + addToMapW(0x2b, 0x00, 0xB1); + addToMapW(0x2b, 0x20, 0x20); + addToMapW(0x2b, 0x20, 0x21); + addToMapW(0x2b, 0xFF, 0x0B); + addToMapW(0x2c, 0x00, 0x2C); + addToMapW(0x2c, 0x00, 0xB8); + addToMapW(0x2c, 0x03, 0x27); + addToMapW(0x2c, 0x20, 0x1A); + addToMapW(0x2c, 0x20, 0x1E); + addToMapW(0x2c, 0xFF, 0x0C); + addToMapW(0x2d, 0x00, 0x2D); + addToMapW(0x2d, 0x00, 0xAC); + addToMapW(0x2d, 0x00, 0xAD); + addToMapW(0x2d, 0x20, 0x10); + addToMapW(0x2d, 0x20, 0x11); + addToMapW(0x2d, 0x20, 0x13); + addToMapW(0x2d, 0x20, 0x14); + addToMapW(0x2d, 0x22, 0x12); + addToMapW(0x2d, 0x22, 0x13); + addToMapW(0x2d, 0xFF, 0x0D); + addToMapW(0x2e, 0x00, 0x2E); + addToMapW(0x2e, 0x20, 0x26); + addToMapW(0x2e, 0xFF, 0x0E); + addToMapW(0x2f, 0x00, 0x2F); + addToMapW(0x2f, 0x20, 0x44); + addToMapW(0x2f, 0x22, 0x15); + addToMapW(0x2f, 0x22, 0x16); + addToMapW(0x2f, 0xFF, 0x0F); + addToMapW(0x30, 0x00, 0x30); + addToMapW(0x30, 0x20, 0x70); + addToMapW(0x30, 0x20, 0x80); + addToMapW(0x30, 0xFF, 0x10); + addToMapW(0x31, 0x00, 0x31); + addToMapW(0x31, 0x00, 0xB9); + addToMapW(0x31, 0x00, 0xBC); + addToMapW(0x31, 0x00, 0xBD); + addToMapW(0x31, 0x20, 0x81); + addToMapW(0x31, 0xFF, 0x11); + addToMapW(0x32, 0x00, 0x32); + addToMapW(0x32, 0x00, 0xB2); + addToMapW(0x32, 0x20, 0x82); + addToMapW(0x32, 0xFF, 0x12); + addToMapW(0x33, 0x00, 0x33); + addToMapW(0x33, 0x00, 0xB3); + addToMapW(0x33, 0x00, 0xBE); + addToMapW(0x33, 0x20, 0x83); + addToMapW(0x33, 0xFF, 0x13); + addToMapW(0x34, 0x00, 0x34); + addToMapW(0x34, 0x20, 0x74); + addToMapW(0x34, 0x20, 0x84); + addToMapW(0x34, 0xFF, 0x14); + addToMapW(0x35, 0x00, 0x35); + addToMapW(0x35, 0x20, 0x75); + addToMapW(0x35, 0x20, 0x85); + addToMapW(0x35, 0xFF, 0x15); + addToMapW(0x36, 0x00, 0x36); + addToMapW(0x36, 0x20, 0x76); + addToMapW(0x36, 0x20, 0x86); + addToMapW(0x36, 0xFF, 0x16); + addToMapW(0x37, 0x00, 0x37); + addToMapW(0x37, 0x20, 0x77); + addToMapW(0x37, 0x20, 0x87); + addToMapW(0x37, 0xFF, 0x17); + addToMapW(0x38, 0x00, 0x38); + addToMapW(0x38, 0x20, 0x78); + addToMapW(0x38, 0x20, 0x88); + addToMapW(0x38, 0x22, 0x1E); + addToMapW(0x38, 0xFF, 0x18); + addToMapW(0x39, 0x00, 0x39); + addToMapW(0x39, 0x20, 0x78); + addToMapW(0x39, 0x20, 0x89); + addToMapW(0x39, 0xFF, 0x19); + addToMapW(0x3a, 0x00, 0x3A); + addToMapW(0x3a, 0x05, 0x89); + addToMapW(0x3a, 0x20, 0x26); + addToMapW(0x3a, 0x22, 0x36); + addToMapW(0x3a, 0xFF, 0x1A); + addToMapW(0x3b, 0x00, 0x3B); + addToMapW(0x3b, 0x03, 0x7E); + addToMapW(0x3b, 0xFF, 0x1B); + addToMapW(0x3c, 0x00, 0x3C); + addToMapW(0x3c, 0x00, 0xAB); + addToMapW(0x3c, 0x20, 0x39); + addToMapW(0x3c, 0x23, 0x29); + addToMapW(0x3c, 0x30, 0x08); + addToMapW(0x3c, 0xFF, 0x1C); + addToMapW(0x3d, 0x00, 0x3D); + addToMapW(0x3d, 0x22, 0x61); + addToMapW(0x3d, 0x22, 0x64); + addToMapW(0x3d, 0x22, 0x65); + addToMapW(0x3d, 0xFF, 0x1D); + addToMapW(0x3e, 0x00, 0x3E); + addToMapW(0x3e, 0x00, 0xBB); + addToMapW(0x3e, 0x20, 0x3A); + addToMapW(0x3e, 0x23, 0x2A); + addToMapW(0x3e, 0x30, 0x09); + addToMapW(0x3e, 0xFF, 0x1E); + addToMapW(0x3f, 0x00, 0x3F); + addToMapW(0x40, 0x00, 0x40); + addToMapW(0x40, 0xFF, 0x20); + addToMapW(0x41, 0x00, 0x41); + addToMapW(0x41, 0x00, 0x61); + addToMapW(0x41, 0x00, 0xAA); + addToMapW(0x41, 0x00, 0xC0); + addToMapW(0x41, 0x00, 0xC1); + addToMapW(0x41, 0x00, 0xC2); + addToMapW(0x41, 0x00, 0xC3); + addToMapW(0x41, 0x00, 0xC4); + addToMapW(0x41, 0x00, 0xC5); + addToMapW(0x41, 0x00, 0xC6); + addToMapW(0x41, 0x00, 0xE0); + addToMapW(0x41, 0x00, 0xE1); + addToMapW(0x41, 0x00, 0xE2); + addToMapW(0x41, 0x00, 0xE3); + addToMapW(0x41, 0x00, 0xE4); + addToMapW(0x41, 0x00, 0xE5); + addToMapW(0x41, 0x00, 0xE6); + addToMapW(0x41, 0x01, 0x00); + addToMapW(0x41, 0x01, 0x01); + addToMapW(0x41, 0x01, 0x02); + addToMapW(0x41, 0x01, 0x03); + addToMapW(0x41, 0x01, 0x04); + addToMapW(0x41, 0x01, 0x05); + addToMapW(0x41, 0x01, 0xCD); + addToMapW(0x41, 0x01, 0xCE); + addToMapW(0x41, 0x01, 0xDE); + addToMapW(0x41, 0x01, 0xDF); + addToMapW(0x41, 0x03, 0xB1); + addToMapW(0x41, 0x21, 0x2B); + addToMapW(0x41, 0xFF, 0x21); + addToMapW(0x41, 0xFF, 0x41); + addToMapW(0x42, 0x00, 0x42); + addToMapW(0x42, 0x00, 0x62); + addToMapW(0x42, 0x01, 0x80); + addToMapW(0x42, 0x21, 0x2C); + addToMapW(0x42, 0xFF, 0x22); + addToMapW(0x42, 0xFF, 0x42); + addToMapW(0x43, 0x00, 0x43); + addToMapW(0x43, 0x00, 0x63); + addToMapW(0x43, 0x00, 0xA2); + addToMapW(0x43, 0x00, 0xA9); + addToMapW(0x43, 0x00, 0xC7); + addToMapW(0x43, 0x00, 0xE7); + addToMapW(0x43, 0x00, 0xE8); + addToMapW(0x43, 0x01, 0x06); + addToMapW(0x43, 0x01, 0x07); + addToMapW(0x43, 0x01, 0x08); + addToMapW(0x43, 0x01, 0x09); + addToMapW(0x43, 0x01, 0x0A); + addToMapW(0x43, 0x01, 0x0B); + addToMapW(0x43, 0x01, 0x0C); + addToMapW(0x43, 0x01, 0x0D); + addToMapW(0x43, 0x21, 0x02); + addToMapW(0x43, 0x21, 0x2D); + addToMapW(0x43, 0xFF, 0x23); + addToMapW(0x43, 0xFF, 0x43); + addToMapW(0x44, 0x00, 0x44); + addToMapW(0x44, 0x00, 0x64); + addToMapW(0x44, 0x00, 0xD0); + addToMapW(0x44, 0x00, 0xF0); + addToMapW(0x44, 0x01, 0x0E); + addToMapW(0x44, 0x01, 0x0F); + addToMapW(0x44, 0x01, 0x10); + addToMapW(0x44, 0x01, 0x11); + addToMapW(0x44, 0x01, 0x89); + addToMapW(0x44, 0x03, 0xB4); + addToMapW(0x44, 0x26, 0x6A); + addToMapW(0x44, 0x26, 0x6B); + addToMapW(0x44, 0xFF, 0x24); + addToMapW(0x44, 0xFF, 0x44); + addToMapW(0x45, 0x00, 0x45); + addToMapW(0x45, 0x00, 0x65); + addToMapW(0x45, 0x00, 0xC8); + addToMapW(0x45, 0x00, 0xC9); + addToMapW(0x45, 0x00, 0xCA); + addToMapW(0x45, 0x00, 0xCB); + addToMapW(0x45, 0x00, 0xE8); + addToMapW(0x45, 0x00, 0xE9); + addToMapW(0x45, 0x00, 0xEA); + addToMapW(0x45, 0x00, 0xEB); + addToMapW(0x45, 0x01, 0x12); + addToMapW(0x45, 0x01, 0x13); + addToMapW(0x45, 0x01, 0x14); + addToMapW(0x45, 0x01, 0x15); + addToMapW(0x45, 0x01, 0x16); + addToMapW(0x45, 0x01, 0x17); + addToMapW(0x45, 0x01, 0x18); + addToMapW(0x45, 0x01, 0x19); + addToMapW(0x45, 0x01, 0x1A); + addToMapW(0x45, 0x01, 0x1B); + addToMapW(0x45, 0x03, 0xB5); + addToMapW(0x45, 0x21, 0x07); + addToMapW(0x45, 0x21, 0x2E); + addToMapW(0x45, 0x21, 0x2F); + addToMapW(0x45, 0x21, 0x30); + addToMapW(0x45, 0xFF, 0x25); + addToMapW(0x45, 0xFF, 0x45); + addToMapW(0x46, 0x00, 0x46); + addToMapW(0x46, 0x00, 0x66); + addToMapW(0x46, 0x01, 0x91); + addToMapW(0x46, 0x01, 0x92); + addToMapW(0x46, 0x03, 0xA6); + addToMapW(0x46, 0x03, 0xC6); + addToMapW(0x46, 0x21, 0x31); + addToMapW(0x46, 0xFF, 0x26); + addToMapW(0x46, 0xFF, 0x46); + addToMapW(0x47, 0x00, 0x47); + addToMapW(0x47, 0x00, 0x67); + addToMapW(0x47, 0x01, 0x1C); + addToMapW(0x47, 0x01, 0x1D); + addToMapW(0x47, 0x01, 0x1E); + addToMapW(0x47, 0x01, 0x1F); + addToMapW(0x47, 0x01, 0x20); + addToMapW(0x47, 0x01, 0x21); + addToMapW(0x47, 0x01, 0x22); + addToMapW(0x47, 0x01, 0x23); + addToMapW(0x47, 0x01, 0xE4); + addToMapW(0x47, 0x01, 0xE5); + addToMapW(0x47, 0x01, 0xE6); + addToMapW(0x47, 0x01, 0xE7); + addToMapW(0x47, 0x02, 0x61); + addToMapW(0x47, 0x03, 0x93); + addToMapW(0x47, 0x21, 0x0A); + addToMapW(0x47, 0xFF, 0x27); + addToMapW(0x47, 0xFF, 0x47); + addToMapW(0x48, 0x00, 0x48); + addToMapW(0x48, 0x00, 0x68); + addToMapW(0x48, 0x01, 0x24); + addToMapW(0x48, 0x01, 0x25); + addToMapW(0x48, 0x01, 0x26); + addToMapW(0x48, 0x01, 0x27); + addToMapW(0x48, 0x04, 0xBB); + addToMapW(0x48, 0x21, 0x0B); + addToMapW(0x48, 0x21, 0x0C); + addToMapW(0x48, 0x21, 0x0D); + addToMapW(0x48, 0x21, 0x0E); + addToMapW(0x48, 0xFF, 0x28); + addToMapW(0x48, 0xFF, 0x48); + addToMapW(0x49, 0x00, 0x49); + addToMapW(0x49, 0x00, 0x69); + addToMapW(0x49, 0x00, 0xCC); + addToMapW(0x49, 0x00, 0xCD); + addToMapW(0x49, 0x00, 0xCE); + addToMapW(0x49, 0x00, 0xCF); + addToMapW(0x49, 0x00, 0xEC); + addToMapW(0x49, 0x00, 0xED); + addToMapW(0x49, 0x00, 0xEE); + addToMapW(0x49, 0x00, 0xEF); + addToMapW(0x49, 0x01, 0x28); + addToMapW(0x49, 0x01, 0x29); + addToMapW(0x49, 0x01, 0x2A); + addToMapW(0x49, 0x01, 0x2B); + addToMapW(0x49, 0x01, 0x2C); + addToMapW(0x49, 0x01, 0x2D); + addToMapW(0x49, 0x01, 0x2E); + addToMapW(0x49, 0x01, 0x2F); + addToMapW(0x49, 0x01, 0x30); + addToMapW(0x49, 0x01, 0x31); + addToMapW(0x49, 0x01, 0x97); + addToMapW(0x49, 0x01, 0xCF); + addToMapW(0x49, 0x01, 0xD0); + addToMapW(0x49, 0x21, 0x10); + addToMapW(0x49, 0x21, 0x11); + addToMapW(0x49, 0xFF, 0x29); + addToMapW(0x49, 0xFF, 0x49); + addToMapW(0x4a, 0x00, 0x4A); + addToMapW(0x4a, 0x00, 0x6A); + addToMapW(0x4a, 0x01, 0x34); + addToMapW(0x4a, 0x01, 0x35); + addToMapW(0x4a, 0x01, 0xF0); + addToMapW(0x4a, 0xFF, 0x2A); + addToMapW(0x4a, 0xFF, 0x4A); + addToMapW(0x4b, 0x00, 0x4B); + addToMapW(0x4b, 0x00, 0x6B); + addToMapW(0x4b, 0x01, 0x36); + addToMapW(0x4b, 0x01, 0x37); + addToMapW(0x4b, 0x01, 0xE8); + addToMapW(0x4b, 0x01, 0xE9); + addToMapW(0x4b, 0x21, 0x2A); + addToMapW(0x4b, 0xFF, 0x2B); + addToMapW(0x4b, 0xFF, 0x4B); + addToMapW(0x4c, 0x00, 0x4C); + addToMapW(0x4c, 0x00, 0x6C); + addToMapW(0x4c, 0x00, 0xA3); + addToMapW(0x4c, 0x01, 0x39); + addToMapW(0x4c, 0x01, 0x3A); + addToMapW(0x4c, 0x01, 0x3B); + addToMapW(0x4c, 0x01, 0x3C); + addToMapW(0x4c, 0x01, 0x3D); + addToMapW(0x4c, 0x01, 0x3E); + addToMapW(0x4c, 0x01, 0x41); + addToMapW(0x4c, 0x01, 0x42); + addToMapW(0x4c, 0x01, 0x9A); + addToMapW(0x4c, 0x20, 0xA4); + addToMapW(0x4c, 0x21, 0x12); + addToMapW(0x4c, 0x21, 0x13); + addToMapW(0x4c, 0xFF, 0x2C); + addToMapW(0x4c, 0xFF, 0x4C); + addToMapW(0x4d, 0x00, 0x4D); + addToMapW(0x4d, 0x00, 0x6D); + addToMapW(0x4d, 0x21, 0x33); + addToMapW(0x4d, 0xFF, 0x2D); + addToMapW(0x4d, 0xFF, 0x4D); + addToMapW(0x4e, 0x00, 0x4E); + addToMapW(0x4e, 0x00, 0x6E); + addToMapW(0x4e, 0x00, 0xD1); + addToMapW(0x4e, 0x00, 0xF1); + addToMapW(0x4e, 0x01, 0x43); + addToMapW(0x4e, 0x01, 0x44); + addToMapW(0x4e, 0x01, 0x45); + addToMapW(0x4e, 0x01, 0x46); + addToMapW(0x4e, 0x01, 0x47); + addToMapW(0x4e, 0x01, 0x48); + addToMapW(0x4e, 0x20, 0x7F); + addToMapW(0x4e, 0x21, 0x15); + addToMapW(0x4e, 0x22, 0x29); + addToMapW(0x4e, 0xFF, 0x2E); + addToMapW(0x4e, 0xFF, 0x4E); + addToMapW(0x4f, 0x00, 0x4F); + addToMapW(0x4f, 0x00, 0x6F); + addToMapW(0x4f, 0x00, 0xB0); + addToMapW(0x4f, 0x00, 0xBA); + addToMapW(0x4f, 0x00, 0xD2); + addToMapW(0x4f, 0x00, 0xD3); + addToMapW(0x4f, 0x00, 0xD4); + addToMapW(0x4f, 0x00, 0xD5); + addToMapW(0x4f, 0x00, 0xD6); + addToMapW(0x4f, 0x00, 0xD8); + addToMapW(0x4f, 0x00, 0xF2); + addToMapW(0x4f, 0x00, 0xF3); + addToMapW(0x4f, 0x00, 0xF4); + addToMapW(0x4f, 0x00, 0xF5); + addToMapW(0x4f, 0x00, 0xF6); + addToMapW(0x4f, 0x00, 0xF8); + addToMapW(0x4f, 0x01, 0x4C); + addToMapW(0x4f, 0x01, 0x4D); + addToMapW(0x4f, 0x01, 0x4E); + addToMapW(0x4f, 0x01, 0x4F); + addToMapW(0x4f, 0x01, 0x50); + addToMapW(0x4f, 0x01, 0x51); + addToMapW(0x4f, 0x01, 0x52); + addToMapW(0x4f, 0x01, 0x53); + addToMapW(0x4f, 0x01, 0x9F); + addToMapW(0x4f, 0x01, 0xA0); + addToMapW(0x4f, 0x01, 0xA1); + addToMapW(0x4f, 0x01, 0xD1); + addToMapW(0x4f, 0x01, 0xD2); + addToMapW(0x4f, 0x01, 0xEA); + addToMapW(0x4f, 0x01, 0xEB); + addToMapW(0x4f, 0x01, 0xEC); + addToMapW(0x4f, 0x01, 0xED); + addToMapW(0x4f, 0x03, 0xA9); + addToMapW(0x4f, 0x20, 0xDD); + addToMapW(0x4f, 0x21, 0x26); + addToMapW(0x4f, 0x21, 0x34); + addToMapW(0x4f, 0x22, 0x05); + addToMapW(0x4f, 0x30, 0x07); + addToMapW(0x4f, 0xFF, 0x2F); + addToMapW(0x4f, 0xFF, 0x4F); + addToMapW(0x50, 0x00, 0x50); + addToMapW(0x50, 0x00, 0x70); + addToMapW(0x50, 0x03, 0xC0); + addToMapW(0x50, 0x20, 0xA7); + addToMapW(0x50, 0x21, 0x18); + addToMapW(0x50, 0x21, 0x19); + addToMapW(0x50, 0xFF, 0x30); + addToMapW(0x50, 0xFF, 0x50); + addToMapW(0x51, 0x00, 0x51); + addToMapW(0x51, 0x00, 0x71); + addToMapW(0x51, 0x21, 0x1A); + addToMapW(0x51, 0xFF, 0x31); + addToMapW(0x51, 0xFF, 0x51); + addToMapW(0x52, 0x00, 0x52); + addToMapW(0x52, 0x00, 0x72); + addToMapW(0x52, 0x00, 0xAE); + addToMapW(0x52, 0x01, 0x54); + addToMapW(0x52, 0x01, 0x55); + addToMapW(0x52, 0x01, 0x56); + addToMapW(0x52, 0x01, 0x57); + addToMapW(0x52, 0x01, 0x58); + addToMapW(0x52, 0x01, 0x59); + addToMapW(0x52, 0x21, 0x1B); + addToMapW(0x52, 0x21, 0x1C); + addToMapW(0x52, 0x21, 0x1D); + addToMapW(0x52, 0xFF, 0x32); + addToMapW(0x52, 0xFF, 0x52); + addToMapW(0x53, 0x00, 0x53); + addToMapW(0x53, 0x00, 0x73); + addToMapW(0x53, 0x00, 0xDF); + addToMapW(0x53, 0x01, 0x5A); + addToMapW(0x53, 0x01, 0x5B); + addToMapW(0x53, 0x01, 0x5C); + addToMapW(0x53, 0x01, 0x5D); + addToMapW(0x53, 0x01, 0x5E); + addToMapW(0x53, 0x01, 0x5F); + addToMapW(0x53, 0x01, 0x60); + addToMapW(0x53, 0x01, 0x61); + addToMapW(0x53, 0x01, 0xA9); + addToMapW(0x53, 0x03, 0xA3); + addToMapW(0x53, 0x03, 0xC3); + addToMapW(0x53, 0x22, 0x11); + addToMapW(0x53, 0xFF, 0x33); + addToMapW(0x53, 0xFF, 0x53); + addToMapW(0x54, 0x00, 0x54); + addToMapW(0x54, 0x00, 0x74); + addToMapW(0x54, 0x00, 0xDE); + addToMapW(0x54, 0x00, 0xFE); + addToMapW(0x54, 0x01, 0x62); + addToMapW(0x54, 0x01, 0x63); + addToMapW(0x54, 0x01, 0x64); + addToMapW(0x54, 0x01, 0x65); + addToMapW(0x54, 0x01, 0x66); + addToMapW(0x54, 0x01, 0x67); + addToMapW(0x54, 0x01, 0xAB); + addToMapW(0x54, 0x01, 0xAE); + addToMapW(0x54, 0x03, 0xC4); + addToMapW(0x54, 0x21, 0x22); + addToMapW(0x54, 0xFF, 0x34); + addToMapW(0x54, 0xFF, 0x54); + addToMapW(0x55, 0x00, 0x55); + addToMapW(0x55, 0x00, 0x75); + addToMapW(0x55, 0x00, 0xB5); + addToMapW(0x55, 0x00, 0xD9); + addToMapW(0x55, 0x00, 0xDA); + addToMapW(0x55, 0x00, 0xDB); + addToMapW(0x55, 0x00, 0xDC); + addToMapW(0x55, 0x00, 0xF9); + addToMapW(0x55, 0x00, 0xFA); + addToMapW(0x55, 0x00, 0xFB); + addToMapW(0x55, 0x00, 0xFC); + addToMapW(0x55, 0x01, 0x68); + addToMapW(0x55, 0x01, 0x69); + addToMapW(0x55, 0x01, 0x6A); + addToMapW(0x55, 0x01, 0x6B); + addToMapW(0x55, 0x01, 0x6C); + addToMapW(0x55, 0x01, 0x6D); + addToMapW(0x55, 0x01, 0x6E); + addToMapW(0x55, 0x01, 0x6F); + addToMapW(0x55, 0x01, 0x70); + addToMapW(0x55, 0x01, 0x71); + addToMapW(0x55, 0x01, 0x72); + addToMapW(0x55, 0x01, 0x73); + addToMapW(0x55, 0x01, 0xAF); + addToMapW(0x55, 0x01, 0xB0); + addToMapW(0x55, 0x01, 0xD3); + addToMapW(0x55, 0x01, 0xD4); + addToMapW(0x55, 0x01, 0xD5); + addToMapW(0x55, 0x01, 0xD6); + addToMapW(0x55, 0x01, 0xD7); + addToMapW(0x55, 0x01, 0xD8); + addToMapW(0x55, 0x01, 0xD9); + addToMapW(0x55, 0x01, 0xDA); + addToMapW(0x55, 0x01, 0xDB); + addToMapW(0x55, 0x01, 0xDC); + addToMapW(0x55, 0x03, 0xBC); + addToMapW(0x55, 0xFF, 0x35); + addToMapW(0x55, 0xFF, 0x55); + addToMapW(0x56, 0x00, 0x56); + addToMapW(0x56, 0x00, 0x76); + addToMapW(0x56, 0x22, 0x1A); + addToMapW(0x56, 0x27, 0x13); + addToMapW(0x56, 0xFF, 0x36); + addToMapW(0x56, 0xFF, 0x56); + addToMapW(0x57, 0x00, 0x57); + addToMapW(0x57, 0x00, 0x77); + addToMapW(0x57, 0x01, 0x74); + addToMapW(0x57, 0x01, 0x75); + addToMapW(0x57, 0xFF, 0x37); + addToMapW(0x57, 0xFF, 0x57); + addToMapW(0x58, 0x00, 0x58); + addToMapW(0x58, 0x00, 0x78); + addToMapW(0x58, 0x00, 0xD7); + addToMapW(0x58, 0xFF, 0x38); + addToMapW(0x58, 0xFF, 0x58); + addToMapW(0x59, 0x00, 0x59); + addToMapW(0x59, 0x00, 0x79); + addToMapW(0x59, 0x00, 0xA5); + addToMapW(0x59, 0x00, 0xDD); + addToMapW(0x59, 0x00, 0xFD); + addToMapW(0x59, 0x00, 0xFF); + addToMapW(0x59, 0x01, 0x76); + addToMapW(0x59, 0x01, 0x77); + addToMapW(0x59, 0x01, 0x78); + addToMapW(0x59, 0xFF, 0x39); + addToMapW(0x59, 0xFF, 0x59); + addToMapW(0x5a, 0x00, 0x5A); + addToMapW(0x5a, 0x00, 0x7A); + addToMapW(0x5a, 0x01, 0x79); + addToMapW(0x5a, 0x01, 0x7A); + addToMapW(0x5a, 0x01, 0x7B); + addToMapW(0x5a, 0x01, 0x7C); + addToMapW(0x5a, 0x01, 0x7D); + addToMapW(0x5a, 0x01, 0x7E); + addToMapW(0x5a, 0x01, 0xB6); + addToMapW(0x5a, 0x21, 0x24); + addToMapW(0x5a, 0x21, 0x28); + addToMapW(0x5a, 0xFF, 0x3A); + addToMapW(0x5a, 0xFF, 0x5A); + addToMapW(0x5b, 0x00, 0x5B); + addToMapW(0x5b, 0x30, 0x1A); + addToMapW(0x5b, 0xFF, 0x3B); + addToMapW(0x5c, 0x00, 0x5C); + addToMapW(0x5c, 0x00, 0xA5); + addToMapW(0x5c, 0x22, 0x16); + addToMapW(0x5c, 0xFF, 0x3C); + addToMapW(0x5d, 0x00, 0x5D); + addToMapW(0x5d, 0x30, 0x1B); + addToMapW(0x5d, 0xFF, 0x3D); + addToMapW(0x5e, 0x00, 0x5E); + addToMapW(0x5e, 0x02, 0xC4); + addToMapW(0x5e, 0x02, 0xC6); + addToMapW(0x5e, 0x02, 0xC7); + addToMapW(0x5e, 0x02, 0xD8); + addToMapW(0x5e, 0x03, 0x02); + addToMapW(0x5e, 0x03, 0x06); + addToMapW(0x5e, 0x03, 0x0C); + addToMapW(0x5e, 0x23, 0x03); + addToMapW(0x5e, 0xFF, 0x3E); + addToMapW(0x5f, 0x00, 0x5F); + addToMapW(0x5f, 0x00, 0xAF); + addToMapW(0x5f, 0x00, 0xBE); + addToMapW(0x5f, 0x00, 0xDE); + addToMapW(0x5f, 0x00, 0xFE); + addToMapW(0x5f, 0x02, 0xCD); + addToMapW(0x5f, 0x03, 0x31); + addToMapW(0x5f, 0x03, 0x32); + addToMapW(0x5f, 0x20, 0x17); + addToMapW(0x5f, 0x30, 0xFC); + addToMapW(0x5f, 0xFF, 0x3F); + addToMapW(0x60, 0x00, 0x60); + addToMapW(0x60, 0x02, 0xCB); + addToMapW(0x60, 0x03, 0x00); + addToMapW(0x60, 0x20, 0x18); + addToMapW(0x60, 0x20, 0x35); + addToMapW(0x60, 0xFF, 0x40); + addToMapW(0x7b, 0x00, 0x7B); + addToMapW(0x7b, 0xFF, 0x5B); + addToMapW(0x7c, 0x00, 0x7C); + addToMapW(0x7c, 0x00, 0xA6); + addToMapW(0x7c, 0x01, 0xC0); + addToMapW(0x7c, 0x22, 0x23); + addToMapW(0x7c, 0x27, 0x58); + addToMapW(0x7c, 0xFF, 0x5C); + addToMapW(0x7d, 0x00, 0x7D); + addToMapW(0x7d, 0x30, 0x1B); + addToMapW(0x7d, 0xFF, 0x5D); + addToMapW(0x7e, 0x00, 0x7E); + addToMapW(0x7e, 0x02, 0xDC); + addToMapW(0x7e, 0x03, 0x03); + addToMapW(0x7e, 0x22, 0x3C); + addToMapW(0x7e, 0x22, 0x48); + addToMapW(0x7e, 0xFF, 0x5E); + addToMapW(0x7f, 0x00, 0x7F); + addToMapW(0x7f, 0x23, 0x02); + addToMapW(0x7f, 0x26, 0x60); + addToMapW(0x7f, 0x26, 0x63); + addToMapW(0x7f, 0x26, 0x65); + addToMapW(0x7f, 0x26, 0x66); + addToMapW(0x80, 0x00, 0x80); + addToMapW(0x80, 0x00, 0xC7); + addToMapW(0x80, 0x00, 0xE7); + addToMapW(0x80, 0x01, 0x06); + addToMapW(0x80, 0x01, 0x07); + addToMapW(0x80, 0x03, 0x91); + addToMapW(0x80, 0x03, 0xB1); + addToMapW(0x80, 0x04, 0x10); + addToMapW(0x80, 0x04, 0x30); + addToMapW(0x80, 0x05, 0xD0); + addToMapW(0x80, 0x20, 0xAC); + addToMapW(0x81, 0x00, 0x81); + addToMapW(0x81, 0x03, 0x92); + addToMapW(0x81, 0x03, 0xB2); + addToMapW(0x81, 0x04, 0x02); + addToMapW(0x81, 0x04, 0x11); + addToMapW(0x81, 0x04, 0x31); + addToMapW(0x81, 0x04, 0x52); + addToMapW(0x81, 0x05, 0xD1); + addToMapW(0x82, 0x00, 0x82); + addToMapW(0x82, 0x03, 0x93); + addToMapW(0x82, 0x03, 0xB3); + addToMapW(0x82, 0x04, 0x12); + addToMapW(0x82, 0x04, 0x32); + addToMapW(0x82, 0x05, 0xD2); + addToMapW(0x82, 0x20, 0x1A); + addToMapW(0x83, 0x00, 0x83); + addToMapW(0x83, 0x03, 0x94); + addToMapW(0x83, 0x03, 0xB4); + addToMapW(0x83, 0x04, 0x03); + addToMapW(0x83, 0x04, 0x13); + addToMapW(0x83, 0x04, 0x33); + addToMapW(0x83, 0x04, 0x53); + addToMapW(0x83, 0x05, 0xD3); + addToMapW(0x84, 0x00, 0x84); + addToMapW(0x84, 0x03, 0x95); + addToMapW(0x84, 0x03, 0xB5); + addToMapW(0x84, 0x04, 0x14); + addToMapW(0x84, 0x04, 0x34); + addToMapW(0x84, 0x05, 0xD4); + addToMapW(0x84, 0x20, 0x1E); + addToMapW(0x85, 0x03, 0x96); + addToMapW(0x85, 0x03, 0xB6); + addToMapW(0x85, 0x04, 0x01); + addToMapW(0x85, 0x04, 0x15); + addToMapW(0x85, 0x04, 0x35); + addToMapW(0x85, 0x04, 0x51); + addToMapW(0x85, 0x05, 0xD5); + addToMapW(0x85, 0x20, 0x26); + addToMapW(0x86, 0x00, 0x86); + addToMapW(0x86, 0x03, 0x97); + addToMapW(0x86, 0x03, 0xB7); + addToMapW(0x86, 0x04, 0x16); + addToMapW(0x86, 0x04, 0x36); + addToMapW(0x86, 0x05, 0xD6); + addToMapW(0x86, 0x20, 0x20); + addToMapW(0x87, 0x00, 0x87); + addToMapW(0x87, 0x03, 0x98); + addToMapW(0x87, 0x03, 0xB8); + addToMapW(0x87, 0x04, 0x04); + addToMapW(0x87, 0x04, 0x17); + addToMapW(0x87, 0x04, 0x37); + addToMapW(0x87, 0x04, 0x54); + addToMapW(0x87, 0x05, 0xD7); + addToMapW(0x87, 0x20, 0x21); + addToMapW(0x88, 0x00, 0x88); + addToMapW(0x88, 0x02, 0xC6); + addToMapW(0x88, 0x03, 0x99); + addToMapW(0x88, 0x03, 0xB9); + addToMapW(0x88, 0x04, 0x18); + addToMapW(0x88, 0x04, 0x38); + addToMapW(0x88, 0x05, 0xD8); + addToMapW(0x89, 0x00, 0x89); + addToMapW(0x89, 0x03, 0x9A); + addToMapW(0x89, 0x03, 0xBA); + addToMapW(0x89, 0x04, 0x05); + addToMapW(0x89, 0x04, 0x19); + addToMapW(0x89, 0x04, 0x39); + addToMapW(0x89, 0x04, 0x55); + addToMapW(0x89, 0x05, 0xD9); + addToMapW(0x89, 0x20, 0x30); + addToMapW(0x8a, 0x00, 0x8A); + addToMapW(0x8a, 0x01, 0x50); + addToMapW(0x8a, 0x01, 0x51); + addToMapW(0x8a, 0x01, 0x56); + addToMapW(0x8a, 0x01, 0x57); + addToMapW(0x8a, 0x03, 0x9B); + addToMapW(0x8a, 0x03, 0xBB); + addToMapW(0x8a, 0x04, 0x1A); + addToMapW(0x8a, 0x04, 0x3A); + addToMapW(0x8a, 0x05, 0xDA); + addToMapW(0x8b, 0x00, 0x8B); + addToMapW(0x8b, 0x03, 0x9C); + addToMapW(0x8b, 0x03, 0xBC); + addToMapW(0x8b, 0x04, 0x06); + addToMapW(0x8b, 0x04, 0x1B); + addToMapW(0x8b, 0x04, 0x3B); + addToMapW(0x8b, 0x04, 0x56); + addToMapW(0x8b, 0x05, 0xDB); + addToMapW(0x8b, 0x20, 0x39); + addToMapW(0x8c, 0x00, 0x8C); + addToMapW(0x8c, 0x01, 0x52); + addToMapW(0x8c, 0x01, 0x53); + addToMapW(0x8c, 0x03, 0x9D); + addToMapW(0x8c, 0x03, 0xBD); + addToMapW(0x8c, 0x04, 0x1C); + addToMapW(0x8c, 0x04, 0x3C); + addToMapW(0x8c, 0x05, 0xDC); + addToMapW(0x8d, 0x00, 0x8D); + addToMapW(0x8d, 0x01, 0x31); + addToMapW(0x8d, 0x01, 0x79); + addToMapW(0x8d, 0x01, 0x7A); + addToMapW(0x8d, 0x03, 0x9E); + addToMapW(0x8d, 0x03, 0xBE); + addToMapW(0x8d, 0x04, 0x07); + addToMapW(0x8d, 0x04, 0x1D); + addToMapW(0x8d, 0x04, 0x3D); + addToMapW(0x8d, 0x04, 0x57); + addToMapW(0x8d, 0x05, 0xDD); + addToMapW(0x8e, 0x00, 0x8E); + addToMapW(0x8e, 0x00, 0xC4); + addToMapW(0x8e, 0x00, 0xE4); + addToMapW(0x8e, 0x03, 0x9F); + addToMapW(0x8e, 0x03, 0xBF); + addToMapW(0x8e, 0x04, 0x1E); + addToMapW(0x8e, 0x04, 0x3E); + addToMapW(0x8e, 0x05, 0xDE); + addToMapW(0x8f, 0x00, 0x8F); + addToMapW(0x8f, 0x00, 0xC5); + addToMapW(0x8f, 0x00, 0xE5); + addToMapW(0x8f, 0x01, 0x06); + addToMapW(0x8f, 0x01, 0x07); + addToMapW(0x8f, 0x03, 0xA0); + addToMapW(0x8f, 0x03, 0xC0); + addToMapW(0x8f, 0x04, 0x08); + addToMapW(0x8f, 0x04, 0x1F); + addToMapW(0x8f, 0x04, 0x3F); + addToMapW(0x8f, 0x04, 0x58); + addToMapW(0x8f, 0x05, 0xDF); + addToMapW(0x8f, 0x21, 0x2B); + addToMapW(0x90, 0x00, 0x90); + addToMapW(0x90, 0x00, 0xC9); + addToMapW(0x90, 0x00, 0xE9); + addToMapW(0x90, 0x03, 0xA1); + addToMapW(0x90, 0x03, 0xC1); + addToMapW(0x90, 0x04, 0x20); + addToMapW(0x90, 0x04, 0x40); + addToMapW(0x90, 0x05, 0xE0); + addToMapW(0x91, 0x01, 0x39); + addToMapW(0x91, 0x01, 0x3A); + addToMapW(0x91, 0x03, 0xA3); + addToMapW(0x91, 0x03, 0xC2); + addToMapW(0x91, 0x03, 0xC3); + addToMapW(0x91, 0x04, 0x09); + addToMapW(0x91, 0x04, 0x21); + addToMapW(0x91, 0x04, 0x41); + addToMapW(0x91, 0x04, 0x59); + addToMapW(0x91, 0x05, 0xE1); + addToMapW(0x91, 0x06, 0x51); + addToMapW(0x91, 0x20, 0x18); + addToMapW(0x91, 0xFE, 0x7C); + addToMapW(0x91, 0xFE, 0x7D); + addToMapW(0x92, 0x00, 0xC6); + addToMapW(0x92, 0x00, 0xE6); + addToMapW(0x92, 0x03, 0xA4); + addToMapW(0x92, 0x03, 0xC4); + addToMapW(0x92, 0x04, 0x22); + addToMapW(0x92, 0x04, 0x42); + addToMapW(0x92, 0x05, 0xE2); + addToMapW(0x92, 0x06, 0x52); + addToMapW(0x92, 0x20, 0x19); + addToMapW(0x92, 0xFE, 0x7E); + addToMapW(0x92, 0xFE, 0x7F); + addToMapW(0x93, 0x03, 0xA5); + addToMapW(0x93, 0x03, 0xC5); + addToMapW(0x93, 0x04, 0x0A); + addToMapW(0x93, 0x04, 0x23); + addToMapW(0x93, 0x04, 0x43); + addToMapW(0x93, 0x04, 0x5A); + addToMapW(0x93, 0x05, 0xE3); + addToMapW(0x93, 0x20, 0x1C); + addToMapW(0x94, 0x00, 0xA4); + addToMapW(0x94, 0x03, 0xA6); + addToMapW(0x94, 0x03, 0xC6); + addToMapW(0x94, 0x04, 0x24); + addToMapW(0x94, 0x04, 0x44); + addToMapW(0x94, 0x05, 0xE4); + addToMapW(0x94, 0x20, 0x1D); + addToMapW(0x95, 0x01, 0x22); + addToMapW(0x95, 0x01, 0x23); + addToMapW(0x95, 0x01, 0x3D); + addToMapW(0x95, 0x01, 0x3E); + addToMapW(0x95, 0x03, 0xA7); + addToMapW(0x95, 0x03, 0xC7); + addToMapW(0x95, 0x04, 0x0B); + addToMapW(0x95, 0x04, 0x25); + addToMapW(0x95, 0x04, 0x45); + addToMapW(0x95, 0x04, 0x5B); + addToMapW(0x95, 0x05, 0xE5); + addToMapW(0x95, 0x06, 0x40); + addToMapW(0x95, 0x20, 0x22); + addToMapW(0x96, 0x00, 0xA2); + addToMapW(0x96, 0x03, 0xA8); + addToMapW(0x96, 0x03, 0xC8); + addToMapW(0x96, 0x04, 0x26); + addToMapW(0x96, 0x04, 0x46); + addToMapW(0x96, 0x05, 0xE6); + addToMapW(0x96, 0x20, 0x13); + addToMapW(0x97, 0x00, 0xB5); + addToMapW(0x97, 0x01, 0x5A); + addToMapW(0x97, 0x01, 0x5B); + addToMapW(0x97, 0x03, 0xA9); + addToMapW(0x97, 0x03, 0xC9); + addToMapW(0x97, 0x04, 0x0C); + addToMapW(0x97, 0x04, 0x27); + addToMapW(0x97, 0x04, 0x47); + addToMapW(0x97, 0x04, 0x5C); + addToMapW(0x97, 0x05, 0xE7); + addToMapW(0x97, 0x20, 0x14); + addToMapW(0x98, 0x00, 0x98); + addToMapW(0x98, 0x01, 0x30); + addToMapW(0x98, 0x02, 0xDC); + addToMapW(0x98, 0x04, 0x28); + addToMapW(0x98, 0x04, 0x48); + addToMapW(0x98, 0x05, 0xE8); + addToMapW(0x98, 0x06, 0x21); + addToMapW(0x98, 0xFE, 0x80); + addToMapW(0x99, 0x00, 0x99); + addToMapW(0x99, 0x00, 0xD6); + addToMapW(0x99, 0x00, 0xF6); + addToMapW(0x99, 0x04, 0x0E); + addToMapW(0x99, 0x04, 0x29); + addToMapW(0x99, 0x04, 0x49); + addToMapW(0x99, 0x04, 0x5E); + addToMapW(0x99, 0x05, 0xE9); + addToMapW(0x99, 0x06, 0x22); + addToMapW(0x99, 0x21, 0x22); + addToMapW(0x99, 0xFE, 0x81); + addToMapW(0x99, 0xFE, 0x82); + addToMapW(0x9a, 0x00, 0x9A); + addToMapW(0x9a, 0x00, 0xDC); + addToMapW(0x9a, 0x00, 0xFC); + addToMapW(0x9a, 0x04, 0x2A); + addToMapW(0x9a, 0x04, 0x4A); + addToMapW(0x9a, 0x05, 0xEA); + addToMapW(0x9a, 0x06, 0x23); + addToMapW(0x9a, 0xFE, 0x83); + addToMapW(0x9a, 0xFE, 0x84); + addToMapW(0x9b, 0x00, 0x9B); + addToMapW(0x9b, 0x00, 0xA2); + addToMapW(0x9b, 0x01, 0x64); + addToMapW(0x9b, 0x01, 0x65); + addToMapW(0x9b, 0x04, 0x0F); + addToMapW(0x9b, 0x04, 0x2B); + addToMapW(0x9b, 0x04, 0x4B); + addToMapW(0x9b, 0x04, 0x5F); + addToMapW(0x9b, 0x06, 0x24); + addToMapW(0x9b, 0x20, 0x3A); + addToMapW(0x9b, 0xFE, 0x85); + addToMapW(0x9b, 0xFE, 0x86); + addToMapW(0x9c, 0x00, 0x9C); + addToMapW(0x9c, 0x00, 0xA3); + addToMapW(0x9c, 0x04, 0x2C); + addToMapW(0x9c, 0x04, 0x4C); + addToMapW(0x9c, 0x20, 0xA4); + addToMapW(0x9d, 0x00, 0x9D); + addToMapW(0x9d, 0x00, 0xA5); + addToMapW(0x9d, 0x00, 0xD8); + addToMapW(0x9d, 0x00, 0xF8); + addToMapW(0x9d, 0x01, 0x41); + addToMapW(0x9d, 0x01, 0x42); + addToMapW(0x9d, 0x02, 0x78); + addToMapW(0x9d, 0x03, 0x98); + addToMapW(0x9d, 0x04, 0x2D); + addToMapW(0x9d, 0x04, 0x2E); + addToMapW(0x9d, 0x04, 0x4D); + addToMapW(0x9d, 0x04, 0x4E); + addToMapW(0x9d, 0x06, 0x25); + addToMapW(0x9d, 0x22, 0x05); + addToMapW(0x9d, 0xFE, 0x87); + addToMapW(0x9d, 0xFE, 0x88); + addToMapW(0x9e, 0x00, 0x9E); + addToMapW(0x9e, 0x00, 0xD7); + addToMapW(0x9e, 0x01, 0x5E); + addToMapW(0x9e, 0x01, 0x5F); + addToMapW(0x9e, 0x04, 0x2E); + addToMapW(0x9e, 0x04, 0x4E); + addToMapW(0x9e, 0x06, 0x26); + addToMapW(0x9e, 0x20, 0xA7); + addToMapW(0x9e, 0xFE, 0x89); + addToMapW(0x9e, 0xFE, 0x8A); + addToMapW(0x9e, 0xFE, 0x8B); + addToMapW(0x9e, 0xFE, 0x8C); + addToMapW(0x9f, 0x00, 0x9F); + addToMapW(0x9f, 0x00, 0xA4); + addToMapW(0x9f, 0x00, 0xFF); + addToMapW(0x9f, 0x01, 0x78); + addToMapW(0x9f, 0x01, 0x91); + addToMapW(0x9f, 0x01, 0x92); + addToMapW(0x9f, 0x04, 0x2A); + addToMapW(0x9f, 0x04, 0x2F); + addToMapW(0x9f, 0x04, 0x4A); + addToMapW(0x9f, 0x04, 0x4F); + addToMapW(0x9f, 0x06, 0x27); + addToMapW(0x9f, 0xFE, 0x8D); + addToMapW(0x9f, 0xFE, 0x8E); + addToMapW(0xa0, 0x00, 0xA0); + addToMapW(0xa0, 0x01, 0x00); + addToMapW(0xa0, 0x01, 0x01); + addToMapW(0xa0, 0x06, 0x28); + addToMapW(0xa0, 0xF8, 0xF0); + addToMapW(0xa0, 0xFE, 0x8F); + addToMapW(0xa0, 0xFE, 0x90); + addToMapW(0xa0, 0xFE, 0x91); + addToMapW(0xa0, 0xFE, 0x92); + addToMapW(0xa1, 0x00, 0xA1); + addToMapW(0xa1, 0x01, 0x2A); + addToMapW(0xa1, 0x01, 0x2B); + addToMapW(0xa1, 0x04, 0x10); + addToMapW(0xa1, 0x04, 0x30); + addToMapW(0xa1, 0x06, 0x29); + addToMapW(0xa1, 0x0E, 0x01); + addToMapW(0xa1, 0xFE, 0x93); + addToMapW(0xa1, 0xFE, 0x94); + addToMapW(0xa1, 0xFF, 0x61); + addToMapW(0xa2, 0x00, 0xA2); + addToMapW(0xa2, 0x06, 0x2A); + addToMapW(0xa2, 0x0E, 0x02); + addToMapW(0xa2, 0xFE, 0x95); + addToMapW(0xa2, 0xFE, 0x96); + addToMapW(0xa2, 0xFE, 0x97); + addToMapW(0xa2, 0xFE, 0x98); + addToMapW(0xa2, 0xFF, 0x62); + addToMapW(0xa3, 0x00, 0xA3); + addToMapW(0xa3, 0x01, 0x7B); + addToMapW(0xa3, 0x01, 0x7C); + addToMapW(0xa3, 0x04, 0x11); + addToMapW(0xa3, 0x04, 0x31); + addToMapW(0xa3, 0x06, 0x2B); + addToMapW(0xa3, 0x0E, 0x03); + addToMapW(0xa3, 0xFE, 0x99); + addToMapW(0xa3, 0xFE, 0x9A); + addToMapW(0xa3, 0xFE, 0x9B); + addToMapW(0xa3, 0xFE, 0x9C); + addToMapW(0xa3, 0xFF, 0x63); + addToMapW(0xa4, 0x00, 0xA4); + addToMapW(0xa4, 0x01, 0x04); + addToMapW(0xa4, 0x01, 0x05); + addToMapW(0xa4, 0x06, 0x2C); + addToMapW(0xa4, 0x0E, 0x04); + addToMapW(0xa4, 0xFE, 0x9D); + addToMapW(0xa4, 0xFE, 0x9E); + addToMapW(0xa4, 0xFE, 0x9F); + addToMapW(0xa4, 0xFE, 0xA0); + addToMapW(0xa4, 0xFF, 0x64); + addToMapW(0xa5, 0x00, 0xA5); + addToMapW(0xa5, 0x00, 0xD1); + addToMapW(0xa5, 0x00, 0xF1); + addToMapW(0xa5, 0x04, 0x26); + addToMapW(0xa5, 0x04, 0x46); + addToMapW(0xa5, 0x06, 0x2D); + addToMapW(0xa5, 0x0E, 0x05); + addToMapW(0xa5, 0xFE, 0xA1); + addToMapW(0xa5, 0xFE, 0xA2); + addToMapW(0xa5, 0xFE, 0xA3); + addToMapW(0xa5, 0xFE, 0xA4); + addToMapW(0xa5, 0xFF, 0x65); + addToMapW(0xa6, 0x00, 0xA6); + addToMapW(0xa6, 0x00, 0xAA); + addToMapW(0xa6, 0x01, 0x1E); + addToMapW(0xa6, 0x01, 0x1F); + addToMapW(0xa6, 0x01, 0x7D); + addToMapW(0xa6, 0x01, 0x7E); + addToMapW(0xa6, 0x06, 0x2E); + addToMapW(0xa6, 0x0E, 0x06); + addToMapW(0xa6, 0x20, 0x1D); + addToMapW(0xa6, 0xFE, 0xA5); + addToMapW(0xa6, 0xFE, 0xA6); + addToMapW(0xa6, 0xFE, 0xA7); + addToMapW(0xa6, 0xFE, 0xA8); + addToMapW(0xa6, 0xFF, 0x66); + addToMapW(0xa7, 0x00, 0xA6); + addToMapW(0xa7, 0x00, 0xA7); + addToMapW(0xa7, 0x00, 0xBA); + addToMapW(0xa7, 0x04, 0x14); + addToMapW(0xa7, 0x04, 0x34); + addToMapW(0xa7, 0x06, 0x2F); + addToMapW(0xa7, 0x0E, 0x07); + addToMapW(0xa7, 0xFE, 0xA9); + addToMapW(0xa7, 0xFE, 0xAA); + addToMapW(0xa7, 0xFF, 0x67); + addToMapW(0xa8, 0x00, 0xA8); + addToMapW(0xa8, 0x00, 0xA9); + addToMapW(0xa8, 0x00, 0xBF); + addToMapW(0xa8, 0x01, 0x18); + addToMapW(0xa8, 0x01, 0x19); + addToMapW(0xa8, 0x06, 0x30); + addToMapW(0xa8, 0x0E, 0x08); + addToMapW(0xa8, 0xFE, 0xAB); + addToMapW(0xa8, 0xFE, 0xAC); + addToMapW(0xa8, 0xFF, 0x68); + addToMapW(0xa9, 0x00, 0xA9); + addToMapW(0xa9, 0x00, 0xAE); + addToMapW(0xa9, 0x04, 0x15); + addToMapW(0xa9, 0x04, 0x35); + addToMapW(0xa9, 0x06, 0x31); + addToMapW(0xa9, 0x0E, 0x09); + addToMapW(0xa9, 0x23, 0x10); + addToMapW(0xa9, 0xFE, 0xAD); + addToMapW(0xa9, 0xFE, 0xAE); + addToMapW(0xa9, 0xFF, 0x69); + addToMapW(0xaa, 0x00, 0xAA); + addToMapW(0xaa, 0x00, 0xAC); + addToMapW(0xaa, 0x06, 0x32); + addToMapW(0xaa, 0x0E, 0x0A); + addToMapW(0xaa, 0x23, 0x10); + addToMapW(0xaa, 0xFE, 0xAF); + addToMapW(0xaa, 0xFE, 0xB0); + addToMapW(0xaa, 0xFF, 0x6A); + addToMapW(0xab, 0x00, 0xAB); + addToMapW(0xab, 0x00, 0xBD); + addToMapW(0xab, 0x04, 0x24); + addToMapW(0xab, 0x04, 0x44); + addToMapW(0xab, 0x06, 0x33); + addToMapW(0xab, 0x0E, 0x0B); + addToMapW(0xab, 0xFE, 0xB1); + addToMapW(0xab, 0xFE, 0xB2); + addToMapW(0xab, 0xFE, 0xB3); + addToMapW(0xab, 0xFE, 0xB4); + addToMapW(0xab, 0xFF, 0x6B); + addToMapW(0xac, 0x00, 0xAC); + addToMapW(0xac, 0x00, 0xBC); + addToMapW(0xac, 0x01, 0x0C); + addToMapW(0xac, 0x01, 0x0D); + addToMapW(0xac, 0x06, 0x34); + addToMapW(0xac, 0x0E, 0x0C); + addToMapW(0xac, 0xFE, 0xB5); + addToMapW(0xac, 0xFE, 0xB6); + addToMapW(0xac, 0xFE, 0xB7); + addToMapW(0xac, 0xFE, 0xB8); + addToMapW(0xac, 0xFF, 0x6C); + addToMapW(0xad, 0x00, 0xA1); + addToMapW(0xad, 0x00, 0xAD); + addToMapW(0xad, 0x01, 0x41); + addToMapW(0xad, 0x01, 0x42); + addToMapW(0xad, 0x04, 0x13); + addToMapW(0xad, 0x04, 0x33); + addToMapW(0xad, 0x06, 0x35); + addToMapW(0xad, 0x0E, 0x0D); + addToMapW(0xad, 0xFE, 0xB9); + addToMapW(0xad, 0xFE, 0xBA); + addToMapW(0xad, 0xFE, 0xBB); + addToMapW(0xad, 0xFE, 0xBC); + addToMapW(0xad, 0xFF, 0x6D); + addToMapW(0xae, 0x00, 0xAB); + addToMapW(0xae, 0x00, 0xAE); + addToMapW(0xae, 0x0E, 0x0E); + addToMapW(0xae, 0x22, 0x6A); + addToMapW(0xae, 0x30, 0x0A); + addToMapW(0xae, 0xFF, 0x6E); + addToMapW(0xaf, 0x00, 0xAF); + addToMapW(0xaf, 0x00, 0xBB); + addToMapW(0xaf, 0x0E, 0x0F); + addToMapW(0xaf, 0x22, 0x6B); + addToMapW(0xaf, 0x30, 0x0B); + addToMapW(0xaf, 0xFF, 0x6F); + addToMapW(0xb0, 0x00, 0xB0); + addToMapW(0xb0, 0x0E, 0x10); + addToMapW(0xb0, 0x25, 0x91); + addToMapW(0xb0, 0xFF, 0x70); + addToMapW(0xb1, 0x00, 0xB1); + addToMapW(0xb1, 0x0E, 0x11); + addToMapW(0xb1, 0x25, 0x92); + addToMapW(0xb1, 0xFF, 0x71); + addToMapW(0xb2, 0x00, 0xB2); + addToMapW(0xb2, 0x0E, 0x12); + addToMapW(0xb2, 0x25, 0x93); + addToMapW(0xb2, 0xFF, 0x72); + addToMapW(0xb3, 0x00, 0xA6); + addToMapW(0xb3, 0x00, 0xB3); + addToMapW(0xb3, 0x01, 0xC0); + addToMapW(0xb3, 0x0E, 0x13); + addToMapW(0xb3, 0x22, 0x23); + addToMapW(0xb3, 0x25, 0x02); + addToMapW(0xb3, 0x27, 0x58); + addToMapW(0xb3, 0xFF, 0x73); + addToMapW(0xb4, 0x00, 0xB4); + addToMapW(0xb4, 0x0E, 0x14); + addToMapW(0xb4, 0x25, 0x24); + addToMapW(0xb4, 0xFF, 0x74); + addToMapW(0xb5, 0x00, 0xB5); + addToMapW(0xb5, 0x00, 0xC1); + addToMapW(0xb5, 0x00, 0xE1); + addToMapW(0xb5, 0x01, 0x04); + addToMapW(0xb5, 0x01, 0x05); + addToMapW(0xb5, 0x0E, 0x15); + addToMapW(0xb5, 0x25, 0x61); + addToMapW(0xb5, 0xFF, 0x75); + addToMapW(0xb6, 0x00, 0xB6); + addToMapW(0xb6, 0x00, 0xC2); + addToMapW(0xb6, 0x00, 0xE2); + addToMapW(0xb6, 0x01, 0x0C); + addToMapW(0xb6, 0x01, 0x0D); + addToMapW(0xb6, 0x04, 0x25); + addToMapW(0xb6, 0x04, 0x45); + addToMapW(0xb6, 0x0E, 0x16); + addToMapW(0xb6, 0x25, 0x62); + addToMapW(0xb6, 0xFF, 0x76); + addToMapW(0xb7, 0x00, 0xB7); + addToMapW(0xb7, 0x00, 0xC0); + addToMapW(0xb7, 0x00, 0xE0); + addToMapW(0xb7, 0x01, 0x18); + addToMapW(0xb7, 0x01, 0x19); + addToMapW(0xb7, 0x01, 0x1A); + addToMapW(0xb7, 0x01, 0x1B); + addToMapW(0xb7, 0x0E, 0x17); + addToMapW(0xb7, 0x25, 0x56); + addToMapW(0xb7, 0xFF, 0x77); + addToMapW(0xb8, 0x00, 0xA9); + addToMapW(0xb8, 0x00, 0xB8); + addToMapW(0xb8, 0x01, 0x16); + addToMapW(0xb8, 0x01, 0x17); + addToMapW(0xb8, 0x01, 0x5E); + addToMapW(0xb8, 0x01, 0x5F); + addToMapW(0xb8, 0x04, 0x18); + addToMapW(0xb8, 0x04, 0x38); + addToMapW(0xb8, 0x0E, 0x18); + addToMapW(0xb8, 0x25, 0x55); + addToMapW(0xb8, 0xFF, 0x78); + addToMapW(0xb9, 0x00, 0xB9); + addToMapW(0xb9, 0x0E, 0x19); + addToMapW(0xb9, 0x25, 0x61); + addToMapW(0xb9, 0x25, 0x62); + addToMapW(0xb9, 0x25, 0x63); + addToMapW(0xb9, 0xFF, 0x79); + addToMapW(0xba, 0x00, 0xBA); + addToMapW(0xba, 0x0E, 0x1A); + addToMapW(0xba, 0x25, 0x51); + addToMapW(0xba, 0xFF, 0x7A); + addToMapW(0xbb, 0x00, 0xBB); + addToMapW(0xbb, 0x0E, 0x1B); + addToMapW(0xbb, 0x25, 0x55); + addToMapW(0xbb, 0x25, 0x56); + addToMapW(0xbb, 0x25, 0x57); + addToMapW(0xbb, 0xFF, 0x7B); + addToMapW(0xbc, 0x00, 0xBC); + addToMapW(0xbc, 0x0E, 0x1C); + addToMapW(0xbc, 0x25, 0x5B); + addToMapW(0xbc, 0x25, 0x5C); + addToMapW(0xbc, 0x25, 0x5D); + addToMapW(0xbc, 0xFF, 0x7C); + addToMapW(0xbd, 0x00, 0xA2); + addToMapW(0xbd, 0x00, 0xBD); + addToMapW(0xbd, 0x01, 0x2E); + addToMapW(0xbd, 0x01, 0x2F); + addToMapW(0xbd, 0x01, 0x7B); + addToMapW(0xbd, 0x01, 0x7C); + addToMapW(0xbd, 0x0E, 0x1D); + addToMapW(0xbd, 0x25, 0x5C); + addToMapW(0xbd, 0xFF, 0x7D); + addToMapW(0xbe, 0x00, 0xA5); + addToMapW(0xbe, 0x00, 0xBE); + addToMapW(0xbe, 0x01, 0x60); + addToMapW(0xbe, 0x01, 0x61); + addToMapW(0xbe, 0x04, 0x19); + addToMapW(0xbe, 0x04, 0x39); + addToMapW(0xbe, 0x0E, 0x1E); + addToMapW(0xbe, 0x25, 0x5B); + addToMapW(0xbe, 0xFF, 0x7E); + addToMapW(0xbf, 0x00, 0xAC); + addToMapW(0xbf, 0x00, 0xBF); + addToMapW(0xbf, 0x0E, 0x1F); + addToMapW(0xbf, 0x25, 0x10); + addToMapW(0xbf, 0xFF, 0x7F); + addToMapW(0xc0, 0x00, 0xC0); + addToMapW(0xc0, 0x00, 0xE0); + addToMapW(0xc0, 0x0E, 0x20); + addToMapW(0xc0, 0x25, 0x14); + addToMapW(0xc0, 0xFF, 0x80); + addToMapW(0xc1, 0x00, 0xC1); + addToMapW(0xc1, 0x00, 0xE1); + addToMapW(0xc1, 0x0E, 0x21); + addToMapW(0xc1, 0x25, 0x34); + addToMapW(0xc1, 0xFF, 0x81); + addToMapW(0xc2, 0x00, 0xC2); + addToMapW(0xc2, 0x00, 0xE2); + addToMapW(0xc2, 0x0E, 0x22); + addToMapW(0xc2, 0x25, 0x2C); + addToMapW(0xc2, 0xFF, 0x82); + addToMapW(0xc3, 0x01, 0x02); + addToMapW(0xc3, 0x01, 0x03); + addToMapW(0xc3, 0x0E, 0x23); + addToMapW(0xc3, 0x25, 0x1C); + addToMapW(0xc3, 0xFF, 0x83); + addToMapW(0xc4, 0x00, 0xAF); + addToMapW(0xc4, 0x00, 0xC4); + addToMapW(0xc4, 0x00, 0xE4); + addToMapW(0xc4, 0x02, 0xC9); + addToMapW(0xc4, 0x03, 0x04); + addToMapW(0xc4, 0x03, 0x05); + addToMapW(0xc4, 0x0E, 0x24); + addToMapW(0xc4, 0x25, 0x00); + addToMapW(0xc4, 0xFF, 0x84); + addToMapW(0xc5, 0x00, 0xC5); + addToMapW(0xc5, 0x00, 0xE5); + addToMapW(0xc5, 0x0E, 0x25); + addToMapW(0xc5, 0x20, 0x20); + addToMapW(0xc5, 0x20, 0x21); + addToMapW(0xc5, 0x25, 0x3C); + addToMapW(0xc5, 0xFF, 0x85); + addToMapW(0xc6, 0x00, 0xC6); + addToMapW(0xc6, 0x00, 0xE6); + addToMapW(0xc6, 0x01, 0x02); + addToMapW(0xc6, 0x01, 0x03); + addToMapW(0xc6, 0x01, 0x72); + addToMapW(0xc6, 0x01, 0x73); + addToMapW(0xc6, 0x0E, 0x26); + addToMapW(0xc6, 0x25, 0x5E); + addToMapW(0xc6, 0xFF, 0x86); + addToMapW(0xc7, 0x00, 0xC3); + addToMapW(0xc7, 0x00, 0xC7); + addToMapW(0xc7, 0x00, 0xE3); + addToMapW(0xc7, 0x00, 0xE7); + addToMapW(0xc7, 0x01, 0x6A); + addToMapW(0xc7, 0x01, 0x6B); + addToMapW(0xc7, 0x04, 0x1A); + addToMapW(0xc7, 0x04, 0x3A); + addToMapW(0xc7, 0x0E, 0x27); + addToMapW(0xc7, 0x25, 0x5F); + addToMapW(0xc7, 0xFF, 0x87); + addToMapW(0xc8, 0x00, 0xC8); + addToMapW(0xc8, 0x00, 0xE8); + addToMapW(0xc8, 0x0E, 0x28); + addToMapW(0xc8, 0x25, 0x58); + addToMapW(0xc8, 0x25, 0x59); + addToMapW(0xc8, 0x25, 0x5A); + addToMapW(0xc8, 0xFF, 0x88); + addToMapW(0xc9, 0x00, 0xC9); + addToMapW(0xc9, 0x00, 0xE9); + addToMapW(0xc9, 0x0E, 0x29); + addToMapW(0xc9, 0x25, 0x52); + addToMapW(0xc9, 0x25, 0x53); + addToMapW(0xc9, 0x25, 0x54); + addToMapW(0xc9, 0xFF, 0x89); + addToMapW(0xca, 0x00, 0xCA); + addToMapW(0xca, 0x00, 0xEA); + addToMapW(0xca, 0x0E, 0x2A); + addToMapW(0xca, 0x25, 0x67); + addToMapW(0xca, 0x25, 0x68); + addToMapW(0xca, 0x25, 0x69); + addToMapW(0xca, 0xFF, 0x8A); + addToMapW(0xcb, 0x00, 0xCB); + addToMapW(0xcb, 0x00, 0xEB); + addToMapW(0xcb, 0x0E, 0x2B); + addToMapW(0xcb, 0x25, 0x64); + addToMapW(0xcb, 0x25, 0x65); + addToMapW(0xcb, 0x25, 0x66); + addToMapW(0xcb, 0xFF, 0x8B); + addToMapW(0xcc, 0x03, 0x00); + addToMapW(0xcc, 0x0E, 0x2C); + addToMapW(0xcc, 0x25, 0x5E); + addToMapW(0xcc, 0x25, 0x5F); + addToMapW(0xcc, 0x25, 0x60); + addToMapW(0xcc, 0xFF, 0x8C); + addToMapW(0xcd, 0x00, 0xCD); + addToMapW(0xcd, 0x00, 0xED); + addToMapW(0xcd, 0x0E, 0x2D); + addToMapW(0xcd, 0x25, 0x50); + addToMapW(0xcd, 0xFF, 0x8D); + addToMapW(0xce, 0x00, 0xCE); + addToMapW(0xce, 0x00, 0xEE); + addToMapW(0xce, 0x0E, 0x2E); + addToMapW(0xce, 0x20, 0x21); + addToMapW(0xce, 0x25, 0x6A); + addToMapW(0xce, 0x25, 0x6B); + addToMapW(0xce, 0x25, 0x6C); + addToMapW(0xce, 0xFF, 0x8E); + addToMapW(0xcf, 0x00, 0xA4); + addToMapW(0xcf, 0x00, 0xCF); + addToMapW(0xcf, 0x00, 0xEF); + addToMapW(0xcf, 0x01, 0x7D); + addToMapW(0xcf, 0x01, 0x7E); + addToMapW(0xcf, 0x0E, 0x2F); + addToMapW(0xcf, 0x25, 0x67); + addToMapW(0xcf, 0xFF, 0x8F); + addToMapW(0xd0, 0x00, 0xBA); + addToMapW(0xd0, 0x01, 0x10); + addToMapW(0xd0, 0x01, 0x11); + addToMapW(0xd0, 0x0E, 0x30); + addToMapW(0xd0, 0x25, 0x68); + addToMapW(0xd0, 0xFF, 0x90); + addToMapW(0xd1, 0x00, 0xAA); + addToMapW(0xd1, 0x00, 0xD0); + addToMapW(0xd1, 0x00, 0xD1); + addToMapW(0xd1, 0x00, 0xF0); + addToMapW(0xd1, 0x00, 0xF1); + addToMapW(0xd1, 0x01, 0x10); + addToMapW(0xd1, 0x01, 0x11); + addToMapW(0xd1, 0x01, 0x89); + addToMapW(0xd1, 0x04, 0x1B); + addToMapW(0xd1, 0x04, 0x3B); + addToMapW(0xd1, 0x0E, 0x31); + addToMapW(0xd1, 0x25, 0x64); + addToMapW(0xd1, 0xFF, 0x91); + addToMapW(0xd2, 0x00, 0xCA); + addToMapW(0xd2, 0x00, 0xEA); + addToMapW(0xd2, 0x01, 0x0E); + addToMapW(0xd2, 0x01, 0x0F); + addToMapW(0xd2, 0x03, 0x09); + addToMapW(0xd2, 0x0E, 0x32); + addToMapW(0xd2, 0x25, 0x65); + addToMapW(0xd2, 0xFF, 0x92); + addToMapW(0xd3, 0x00, 0xCB); + addToMapW(0xd3, 0x00, 0xD3); + addToMapW(0xd3, 0x00, 0xEB); + addToMapW(0xd3, 0x00, 0xF3); + addToMapW(0xd3, 0x04, 0x1C); + addToMapW(0xd3, 0x04, 0x3C); + addToMapW(0xd3, 0x0E, 0x33); + addToMapW(0xd3, 0x25, 0x59); + addToMapW(0xd3, 0xFF, 0x93); + addToMapW(0xd4, 0x00, 0xC8); + addToMapW(0xd4, 0x00, 0xD4); + addToMapW(0xd4, 0x00, 0xE8); + addToMapW(0xd4, 0x00, 0xF4); + addToMapW(0xd4, 0x0E, 0x34); + addToMapW(0xd4, 0x25, 0x58); + addToMapW(0xd4, 0xFF, 0x94); + addToMapW(0xd5, 0x01, 0x31); + addToMapW(0xd5, 0x01, 0x47); + addToMapW(0xd5, 0x01, 0x48); + addToMapW(0xd5, 0x01, 0xA0); + addToMapW(0xd5, 0x01, 0xA1); + addToMapW(0xd5, 0x04, 0x1D); + addToMapW(0xd5, 0x04, 0x3D); + addToMapW(0xd5, 0x0E, 0x35); + addToMapW(0xd5, 0x25, 0x52); + addToMapW(0xd5, 0xF8, 0xBB); + addToMapW(0xd5, 0xFF, 0x95); + addToMapW(0xd6, 0x00, 0xCD); + addToMapW(0xd6, 0x00, 0xD6); + addToMapW(0xd6, 0x00, 0xED); + addToMapW(0xd6, 0x00, 0xF6); + addToMapW(0xd6, 0x0E, 0x36); + addToMapW(0xd6, 0x25, 0x53); + addToMapW(0xd6, 0xFF, 0x96); + addToMapW(0xd7, 0x00, 0xCE); + addToMapW(0xd7, 0x00, 0xD7); + addToMapW(0xd7, 0x00, 0xEE); + addToMapW(0xd7, 0x04, 0x1E); + addToMapW(0xd7, 0x04, 0x3E); + addToMapW(0xd7, 0x0E, 0x37); + addToMapW(0xd7, 0x25, 0x6B); + addToMapW(0xd7, 0xFF, 0x97); + addToMapW(0xd8, 0x00, 0xCF); + addToMapW(0xd8, 0x00, 0xD8); + addToMapW(0xd8, 0x00, 0xEF); + addToMapW(0xd8, 0x00, 0xF8); + addToMapW(0xd8, 0x0E, 0x38); + addToMapW(0xd8, 0x20, 0x21); + addToMapW(0xd8, 0x25, 0x6A); + addToMapW(0xd8, 0xFF, 0x98); + addToMapW(0xd9, 0x00, 0xD9); + addToMapW(0xd9, 0x00, 0xF9); + addToMapW(0xd9, 0x0E, 0x39); + addToMapW(0xd9, 0x25, 0x18); + addToMapW(0xd9, 0xFF, 0x99); + addToMapW(0xda, 0x00, 0xDA); + addToMapW(0xda, 0x00, 0xFA); + addToMapW(0xda, 0x0E, 0x3A); + addToMapW(0xda, 0x25, 0x0C); + addToMapW(0xda, 0xFF, 0x9A); + addToMapW(0xdb, 0x00, 0xDB); + addToMapW(0xdb, 0x00, 0xFB); + addToMapW(0xdb, 0x25, 0x88); + addToMapW(0xdb, 0x25, 0x8C); + addToMapW(0xdb, 0x25, 0x90); + addToMapW(0xdb, 0xF8, 0xC1); + addToMapW(0xdb, 0xFF, 0x9B); + addToMapW(0xdc, 0x00, 0xDC); + addToMapW(0xdc, 0x00, 0xFC); + addToMapW(0xdc, 0x25, 0x84); + addToMapW(0xdc, 0xF8, 0xC2); + addToMapW(0xdc, 0xFF, 0x9C); + addToMapW(0xdd, 0x00, 0xA6); + addToMapW(0xdd, 0x01, 0x62); + addToMapW(0xdd, 0x01, 0x63); + addToMapW(0xdd, 0x01, 0xAF); + addToMapW(0xdd, 0x01, 0xB0); + addToMapW(0xdd, 0x04, 0x1F); + addToMapW(0xdd, 0x04, 0x3F); + addToMapW(0xdd, 0x25, 0x8C); + addToMapW(0xdd, 0xF8, 0xC3); + addToMapW(0xdd, 0xFF, 0x9D); + addToMapW(0xde, 0x00, 0xCC); + addToMapW(0xde, 0x00, 0xEC); + addToMapW(0xde, 0x01, 0x6E); + addToMapW(0xde, 0x01, 0x6F); + addToMapW(0xde, 0x03, 0x03); + addToMapW(0xde, 0x25, 0x90); + addToMapW(0xde, 0xF8, 0xC4); + addToMapW(0xde, 0xFF, 0x9E); + addToMapW(0xdf, 0x00, 0xDF); + addToMapW(0xdf, 0x0E, 0x3F); + addToMapW(0xdf, 0x25, 0x80); + addToMapW(0xdf, 0xFF, 0x9F); + addToMapW(0xe0, 0x00, 0xD3); + addToMapW(0xe0, 0x00, 0xF3); + addToMapW(0xe0, 0x03, 0x91); + addToMapW(0xe0, 0x03, 0xB1); + addToMapW(0xe0, 0x04, 0x2F); + addToMapW(0xe0, 0x04, 0x4F); + addToMapW(0xe0, 0x06, 0x36); + addToMapW(0xe0, 0x0E, 0x40); + addToMapW(0xe0, 0xFE, 0xBD); + addToMapW(0xe0, 0xFE, 0xBE); + addToMapW(0xe0, 0xFE, 0xBF); + addToMapW(0xe0, 0xFE, 0xC0); + addToMapW(0xe1, 0x00, 0xDF); + addToMapW(0xe1, 0x03, 0xB2); + addToMapW(0xe1, 0x06, 0x37); + addToMapW(0xe1, 0x0E, 0x41); + addToMapW(0xe1, 0xFE, 0xC1); + addToMapW(0xe1, 0xFE, 0xC2); + addToMapW(0xe1, 0xFE, 0xC3); + addToMapW(0xe1, 0xFE, 0xC4); + addToMapW(0xe2, 0x00, 0xD4); + addToMapW(0xe2, 0x00, 0xF4); + addToMapW(0xe2, 0x01, 0x4C); + addToMapW(0xe2, 0x01, 0x4D); + addToMapW(0xe2, 0x03, 0x93); + addToMapW(0xe2, 0x04, 0x20); + addToMapW(0xe2, 0x04, 0x40); + addToMapW(0xe2, 0x06, 0x38); + addToMapW(0xe2, 0x0E, 0x42); + addToMapW(0xe2, 0xFE, 0xC5); + addToMapW(0xe2, 0xFE, 0xC6); + addToMapW(0xe2, 0xFE, 0xC7); + addToMapW(0xe2, 0xFE, 0xC8); + addToMapW(0xe3, 0x00, 0xD2); + addToMapW(0xe3, 0x00, 0xF2); + addToMapW(0xe3, 0x01, 0x43); + addToMapW(0xe3, 0x01, 0x44); + addToMapW(0xe3, 0x03, 0xA0); + addToMapW(0xe3, 0x03, 0xC0); + addToMapW(0xe3, 0x06, 0x39); + addToMapW(0xe3, 0x0E, 0x43); + addToMapW(0xe3, 0xFE, 0xC9); + addToMapW(0xe3, 0xFE, 0xCA); + addToMapW(0xe3, 0xFE, 0xCB); + addToMapW(0xe3, 0xFE, 0xCC); + addToMapW(0xe4, 0x01, 0xA9); + addToMapW(0xe4, 0x03, 0xA3); + addToMapW(0xe4, 0x03, 0xC3); + addToMapW(0xe4, 0x04, 0x21); + addToMapW(0xe4, 0x04, 0x41); + addToMapW(0xe4, 0x06, 0x3A); + addToMapW(0xe4, 0x0E, 0x44); + addToMapW(0xe4, 0x22, 0x11); + addToMapW(0xe4, 0xFE, 0xCD); + addToMapW(0xe4, 0xFE, 0xCE); + addToMapW(0xe4, 0xFE, 0xCF); + addToMapW(0xe4, 0xFE, 0xD0); + addToMapW(0xe5, 0x00, 0xD5); + addToMapW(0xe5, 0x00, 0xF5); + addToMapW(0xe5, 0x06, 0x41); + addToMapW(0xe5, 0x0E, 0x45); + addToMapW(0xe5, 0xFE, 0xD1); + addToMapW(0xe5, 0xFE, 0xD2); + addToMapW(0xe5, 0xFE, 0xD3); + addToMapW(0xe5, 0xFE, 0xD4); + addToMapW(0xe6, 0x00, 0xB5); + addToMapW(0xe6, 0x01, 0x60); + addToMapW(0xe6, 0x01, 0x61); + addToMapW(0xe6, 0x03, 0xBC); + addToMapW(0xe6, 0x04, 0x22); + addToMapW(0xe6, 0x04, 0x42); + addToMapW(0xe6, 0x0E, 0x46); + addToMapW(0xe7, 0x03, 0xA4); + addToMapW(0xe7, 0x03, 0xC4); + addToMapW(0xe7, 0x06, 0x42); + addToMapW(0xe7, 0x0E, 0x47); + addToMapW(0xe7, 0xF8, 0xBC); + addToMapW(0xe7, 0xFE, 0xD5); + addToMapW(0xe7, 0xFE, 0xD6); + addToMapW(0xe7, 0xFE, 0xD7); + addToMapW(0xe7, 0xFE, 0xD8); + addToMapW(0xe8, 0x00, 0xD7); + addToMapW(0xe8, 0x00, 0xDE); + addToMapW(0xe8, 0x00, 0xFE); + addToMapW(0xe8, 0x01, 0x36); + addToMapW(0xe8, 0x01, 0x37); + addToMapW(0xe8, 0x01, 0x54); + addToMapW(0xe8, 0x01, 0x55); + addToMapW(0xe8, 0x02, 0x78); + addToMapW(0xe8, 0x03, 0xA6); + addToMapW(0xe8, 0x03, 0xC6); + addToMapW(0xe8, 0x04, 0x23); + addToMapW(0xe8, 0x04, 0x43); + addToMapW(0xe8, 0x06, 0x43); + addToMapW(0xe8, 0x0E, 0x48); + addToMapW(0xe8, 0x22, 0x05); + addToMapW(0xe8, 0xFE, 0xD9); + addToMapW(0xe8, 0xFE, 0xDA); + addToMapW(0xe8, 0xFE, 0xDB); + addToMapW(0xe8, 0xFE, 0xDC); + addToMapW(0xe9, 0x00, 0xDA); + addToMapW(0xe9, 0x00, 0xFA); + addToMapW(0xe9, 0x03, 0x98); + addToMapW(0xe9, 0x06, 0x44); + addToMapW(0xe9, 0x0E, 0x49); + addToMapW(0xe9, 0xFE, 0xDD); + addToMapW(0xe9, 0xFE, 0xDE); + addToMapW(0xe9, 0xFE, 0xDF); + addToMapW(0xe9, 0xFE, 0xE0); + addToMapW(0xea, 0x00, 0xDB); + addToMapW(0xea, 0x00, 0xFB); + addToMapW(0xea, 0x01, 0x3B); + addToMapW(0xea, 0x01, 0x3C); + addToMapW(0xea, 0x03, 0x86); + addToMapW(0xea, 0x03, 0xA9); + addToMapW(0xea, 0x03, 0xAC); + addToMapW(0xea, 0x04, 0x16); + addToMapW(0xea, 0x04, 0x36); + addToMapW(0xea, 0x06, 0x45); + addToMapW(0xea, 0x0E, 0x4A); + addToMapW(0xea, 0x21, 0x26); + addToMapW(0xea, 0xFE, 0xE1); + addToMapW(0xea, 0xFE, 0xE2); + addToMapW(0xea, 0xFE, 0xE3); + addToMapW(0xea, 0xFE, 0xE4); + addToMapW(0xeb, 0x00, 0xD9); + addToMapW(0xeb, 0x00, 0xF9); + addToMapW(0xeb, 0x01, 0x70); + addToMapW(0xeb, 0x01, 0x71); + addToMapW(0xeb, 0x03, 0x88); + addToMapW(0xeb, 0x03, 0x94); + addToMapW(0xeb, 0x03, 0xAD); + addToMapW(0xeb, 0x03, 0xB4); + addToMapW(0xeb, 0x06, 0x46); + addToMapW(0xeb, 0x0E, 0x4B); + addToMapW(0xeb, 0xFE, 0xE5); + addToMapW(0xeb, 0xFE, 0xE6); + addToMapW(0xeb, 0xFE, 0xE7); + addToMapW(0xeb, 0xFE, 0xE8); + addToMapW(0xec, 0x03, 0x01); + addToMapW(0xec, 0x03, 0x89); + addToMapW(0xec, 0x03, 0xAE); + addToMapW(0xec, 0x04, 0x12); + addToMapW(0xec, 0x04, 0x32); + addToMapW(0xec, 0x06, 0x47); + addToMapW(0xec, 0x0E, 0x4C); + addToMapW(0xec, 0x22, 0x1E); + addToMapW(0xec, 0xFE, 0xE9); + addToMapW(0xec, 0xFE, 0xEA); + addToMapW(0xec, 0xFE, 0xEB); + addToMapW(0xec, 0xFE, 0xEC); + addToMapW(0xed, 0x00, 0xDD); + addToMapW(0xed, 0x00, 0xFD); + addToMapW(0xed, 0x01, 0x12); + addToMapW(0xed, 0x01, 0x13); + addToMapW(0xed, 0x03, 0x8A); + addToMapW(0xed, 0x03, 0xAF); + addToMapW(0xed, 0x06, 0x48); + addToMapW(0xed, 0x0E, 0x4D); + addToMapW(0xed, 0xFE, 0xED); + addToMapW(0xed, 0xFE, 0xEE); + addToMapW(0xee, 0x00, 0xAF); + addToMapW(0xee, 0x01, 0x45); + addToMapW(0xee, 0x01, 0x46); + addToMapW(0xee, 0x03, 0x04); + addToMapW(0xee, 0x03, 0x05); + addToMapW(0xee, 0x03, 0x8C); + addToMapW(0xee, 0x03, 0x95); + addToMapW(0xee, 0x03, 0xB5); + addToMapW(0xee, 0x03, 0xCC); + addToMapW(0xee, 0x04, 0x2C); + addToMapW(0xee, 0x04, 0x4C); + addToMapW(0xee, 0x06, 0x49); + addToMapW(0xee, 0x0E, 0x4E); + addToMapW(0xee, 0xFE, 0xEF); + addToMapW(0xee, 0xFE, 0xF0); + addToMapW(0xef, 0x00, 0xB4); + addToMapW(0xef, 0x02, 0xB9); + addToMapW(0xef, 0x02, 0xCA); + addToMapW(0xef, 0x03, 0x01); + addToMapW(0xef, 0x03, 0x8E); + addToMapW(0xef, 0x03, 0xCD); + addToMapW(0xef, 0x06, 0x4A); + addToMapW(0xef, 0x0E, 0x4F); + addToMapW(0xef, 0x20, 0x19); + addToMapW(0xef, 0x20, 0x32); + addToMapW(0xef, 0x20, 0x35); + addToMapW(0xef, 0x21, 0x16); + addToMapW(0xef, 0x22, 0x29); + addToMapW(0xef, 0xFE, 0xF1); + addToMapW(0xef, 0xFE, 0xF2); + addToMapW(0xef, 0xFE, 0xF3); + addToMapW(0xef, 0xFE, 0xF4); + addToMapW(0xf0, 0x00, 0xAD); + addToMapW(0xf0, 0x03, 0x8F); + addToMapW(0xf0, 0x03, 0xCE); + addToMapW(0xf0, 0x04, 0x01); + addToMapW(0xf0, 0x04, 0x51); + addToMapW(0xf0, 0x0E, 0x50); + addToMapW(0xf0, 0x22, 0x61); + addToMapW(0xf1, 0x00, 0xB1); + addToMapW(0xf1, 0x02, 0xDD); + addToMapW(0xf1, 0x06, 0x4B); + addToMapW(0xf1, 0x0E, 0x51); + addToMapW(0xf1, 0x22, 0x13); + addToMapW(0xf1, 0xFE, 0x70); + addToMapW(0xf1, 0xFE, 0x71); + addToMapW(0xf2, 0x02, 0xDB); + addToMapW(0xf2, 0x03, 0x23); + addToMapW(0xf2, 0x04, 0x04); + addToMapW(0xf2, 0x04, 0x2B); + addToMapW(0xf2, 0x04, 0x4B); + addToMapW(0xf2, 0x04, 0x54); + addToMapW(0xf2, 0x06, 0x4C); + addToMapW(0xf2, 0x0E, 0x52); + addToMapW(0xf2, 0x20, 0x17); + addToMapW(0xf2, 0x20, 0x1C); + addToMapW(0xf2, 0x22, 0x65); + addToMapW(0xf2, 0xF8, 0xBD); + addToMapW(0xf2, 0xFE, 0x72); + addToMapW(0xf3, 0x00, 0xBE); + addToMapW(0xf3, 0x02, 0xC7); + addToMapW(0xf3, 0x03, 0x0C); + addToMapW(0xf3, 0x06, 0x4D); + addToMapW(0xf3, 0x0E, 0x53); + addToMapW(0xf3, 0x22, 0x64); + addToMapW(0xf3, 0xFE, 0x74); + addToMapW(0xf4, 0x00, 0xB6); + addToMapW(0xf4, 0x02, 0xD8); + addToMapW(0xf4, 0x03, 0x06); + addToMapW(0xf4, 0x03, 0xAA); + addToMapW(0xf4, 0x03, 0xCA); + addToMapW(0xf4, 0x04, 0x07); + addToMapW(0xf4, 0x04, 0x17); + addToMapW(0xf4, 0x04, 0x37); + addToMapW(0xf4, 0x04, 0x57); + addToMapW(0xf4, 0x06, 0x4E); + addToMapW(0xf4, 0x0E, 0x54); + addToMapW(0xf4, 0x23, 0x20); + addToMapW(0xf4, 0xFE, 0x76); + addToMapW(0xf4, 0xFE, 0x77); + addToMapW(0xf5, 0x00, 0xA7); + addToMapW(0xf5, 0x03, 0xAB); + addToMapW(0xf5, 0x03, 0xCB); + addToMapW(0xf5, 0x06, 0x4F); + addToMapW(0xf5, 0x0E, 0x55); + addToMapW(0xf5, 0x23, 0x21); + addToMapW(0xf5, 0xFE, 0x78); + addToMapW(0xf5, 0xFE, 0x79); + addToMapW(0xf6, 0x00, 0xF7); + addToMapW(0xf6, 0x04, 0x0E); + addToMapW(0xf6, 0x04, 0x28); + addToMapW(0xf6, 0x04, 0x48); + addToMapW(0xf6, 0x04, 0x5E); + addToMapW(0xf6, 0x06, 0x50); + addToMapW(0xf6, 0x0E, 0x56); + addToMapW(0xf6, 0xFE, 0x7A); + addToMapW(0xf6, 0xFE, 0x7B); + addToMapW(0xf7, 0x00, 0xB8); + addToMapW(0xf7, 0x00, 0xF7); + addToMapW(0xf7, 0x02, 0xDB); + addToMapW(0xf7, 0x03, 0x27); + addToMapW(0xf7, 0x0E, 0x57); + addToMapW(0xf7, 0x20, 0x1E); + addToMapW(0xf7, 0x22, 0x48); + addToMapW(0xf8, 0x00, 0xB0); + addToMapW(0xf8, 0x02, 0xDA); + addToMapW(0xf8, 0x03, 0x0A); + addToMapW(0xf8, 0x04, 0x2D); + addToMapW(0xf8, 0x04, 0x4D); + addToMapW(0xf8, 0x0E, 0x58); + addToMapW(0xf8, 0x20, 0x70); + addToMapW(0xf8, 0x22, 0x18); + addToMapW(0xf9, 0x00, 0xA8); + addToMapW(0xf9, 0x02, 0xDD); + addToMapW(0xf9, 0x03, 0x08); + addToMapW(0xf9, 0x0E, 0x59); + addToMapW(0xf9, 0x22, 0x19); + addToMapW(0xfa, 0x00, 0xB7); + addToMapW(0xfa, 0x02, 0xD9); + addToMapW(0xfa, 0x03, 0x07); + addToMapW(0xfa, 0x04, 0x29); + addToMapW(0xfa, 0x04, 0x49); + addToMapW(0xfa, 0x0E, 0x5A); + addToMapW(0xfa, 0x20, 0x24); + addToMapW(0xfa, 0x22, 0xC5); + addToMapW(0xfa, 0x30, 0xFB); + addToMapW(0xfb, 0x00, 0xB9); + addToMapW(0xfb, 0x0E, 0x5B); + addToMapW(0xfb, 0x20, 0x81); + addToMapW(0xfb, 0x22, 0x1A); + addToMapW(0xfb, 0x27, 0x13); + addToMapW(0xfc, 0x00, 0xB3); + addToMapW(0xfc, 0x01, 0x58); + addToMapW(0xfc, 0x01, 0x59); + addToMapW(0xfc, 0x04, 0x27); + addToMapW(0xfc, 0x04, 0x47); + addToMapW(0xfc, 0x20, 0x7F); + addToMapW(0xfc, 0x20, 0x83); + addToMapW(0xfc, 0x21, 0x16); + addToMapW(0xfc, 0xF8, 0xC5); + addToMapW(0xfd, 0x00, 0xA4); + addToMapW(0xfd, 0x00, 0xA7); + addToMapW(0xfd, 0x00, 0xB2); + addToMapW(0xfd, 0x20, 0x82); + addToMapW(0xfd, 0xF8, 0xC6); + addToMapW(0xfd, 0xF8, 0xF1); + addToMapW(0xfe, 0x20, 0xAB); + addToMapW(0xfe, 0x25, 0xA0); + addToMapW(0xfe, 0xF8, 0xC7); + addToMapW(0xfe, 0xF8, 0xF2); + addToMapW(0xff, 0x00, 0xA0); + addToMapW(0xff, 0xF8, 0xC8); + addToMapW(0xff, 0xF8, 0xF3); +} diff --git a/Client Applications/rcracki_mt/lm2ntlm.h b/Client Applications/rcracki_mt/lm2ntlm.h new file mode 100644 index 0000000..ff2e42d --- /dev/null +++ b/Client Applications/rcracki_mt/lm2ntlm.h @@ -0,0 +1,55 @@ +#include +#include +#include +#ifdef _WIN32 +#include +#endif +#include "openssl/md4.h" +#include "time.h" +#include "signal.h" +#include "Public.h" +using namespace std; + +class LM2NTLMcorrector +{ +public: + LM2NTLMcorrector(); + +private: + map > m_mapChar; + uint64 progressCurrentCombination; + uint64 totalCurrentCombination; + uint64 counterOverall; + unsigned char NTLMHash[16]; + clock_t startClock; + int countCombinations; + int countTotalCombinations; + int counter; + clock_t previousClock; + unsigned char currentCharmap[16][128]; + bool aborting; + string sBinary; + +private: + bool checkNTLMPassword(unsigned char* pLMPassword, int nLMPasswordLen, string& sNTLMPassword); + bool startCorrecting(string sLMPassword, unsigned char* pNTLMHash, string& sNTLMPassword, unsigned char* pLMPassword); + void printString(unsigned char* muteThis, int length); + void setupCombinationAtPositions(int length, unsigned char* pMuteMe, unsigned char* pTempMute, int* jAtPos, bool* fullAtPos, int* sizeAtPos); + bool checkPermutations(int length, unsigned char* pMuteMe, unsigned char* pTempMute, int* jAtPos, int* sizeAtPos, unsigned char* pLMPassword, string& sNTLMPassword); + + int calculateTotalCombinations(int length, int setSize); + int factorial (int num); + + bool parseHexPassword(string hexPassword, string& sPlain); + bool NormalizeHexString(string& sHash); + void ParseHash(string sHash, unsigned char* pHash, int& nHashLen); + string ByteToStr(const unsigned char* pData, int nLen); + void addToMapW(unsigned char key, unsigned char value1, unsigned char value2); + void fillMapW(); + void checkAbort(); + void writeEndStats(); +public: + bool LMPasswordCorrectUnicode(string hexPassword, unsigned char* NTLMHash, string& sNTLMPassword); + string getBinary(); +}; + diff --git a/Client Applications/rcracki_mt/md4.cpp b/Client Applications/rcracki_mt/md4.cpp new file mode 100644 index 0000000..4e402fd --- /dev/null +++ b/Client Applications/rcracki_mt/md4.cpp @@ -0,0 +1,485 @@ +/* + * This code implements the MD4 message-digest algorithm. + * "Just the reference implementation, single stage. Hardly "optimized." Though a good bit faster than libssl's MD4, as it isn't doing nearly the same amount of work." - Bitweasil + * + * little bit optimized (or at least attempted) for NTLM (unicode) by neinbrucke + */ + + +//#include +#include +#include "md4.h" + +/* MD4 Defines as per RFC reference implementation */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#define FF(a, b, c, d, x, s) { \ + (a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define GG(a, b, c, d, x, s) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define HH(a, b, c, d, x, s) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define S11 3 +#define S12 7 +#define S13 11 +#define S14 19 +#define S21 3 +#define S22 5 +#define S23 9 +#define S24 13 +#define S31 3 +#define S32 9 +#define S33 11 +#define S34 15 +/* End MD4 Defines */ + +void MD4_NEW( unsigned char * pData, int length, unsigned char * pDigest) +{ + // access data as 4-byte word + #define uData ((UINT4 *)pData) + #define uDigest ((UINT4 *)pDigest) + + // pad word and append bit at appropriate location + #define MD4_pad_w0() (0x00000080) + #define MD4_pad_w1(data) (((data) & 0x000000FF) | 0x00008000) + #define MD4_pad_w2(data) (((data) & 0x0000FFFF) | 0x00800000) + #define MD4_pad_w3(data) (((data) & 0x00FFFFFF) | 0x80000000) + + // For the hash working space + //__attribute__((aligned(16))) UINT4 data[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + //__declspec(align(16)) UINT4 data[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + UINT4 data[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + // For the output result + UINT4 a,b,c,d; + + switch (length) + { + case 0: + { + data[ 0] = MD4_pad_w0(); + + data[14] = 0; + } + break; + case 1: + { + data[ 0] = MD4_pad_w1(uData[0]); + + data[14] = 1 << 3; + } + break; + case 2: + { + data[ 0] = MD4_pad_w2(uData[0]); + + data[14] = 2 << 3; + } + break; + case 3: + { + data[ 0] = MD4_pad_w3(uData[0]); + + data[14] = 3 << 3; + } + break; + case 4: + { + data[ 0] = uData[0]; + data[ 1] = MD4_pad_w0(); + + data[14] = 4 << 3; + } + break; + case 5: + { + data[ 0] = uData[0]; + data[ 1] = MD4_pad_w1(uData[1]); + + data[14] = 5 << 3; + } + break; + case 6: + { + data[ 0] = uData[0]; + data[ 1] = MD4_pad_w2(uData[1]); + + data[14] = 6 << 3; + } + break; + case 7: + { + data[ 0] = uData[0]; + data[ 1] = MD4_pad_w3(uData[1]); + + data[14] = 7 << 3; + } + break; + case 8: + { + data[ 0] = uData[0]; + data[ 1] = uData[1]; + data[ 2] = MD4_pad_w0(); + + data[14] = 8 << 3; + } + break; + case 9: + { + data[ 0] = uData[0]; + data[ 1] = uData[1]; + data[ 2] = MD4_pad_w1(uData[2]); + + data[14] = 9 << 3; + } + break; + case 10: + { + data[ 0] = uData[0]; + data[ 1] = uData[1]; + data[ 2] = MD4_pad_w2(uData[2]); + + data[14] = 10 << 3; + } + break; + case 11: + { + data[ 0] = uData[0]; + data[ 1] = uData[1]; + data[ 2] = MD4_pad_w3(uData[2]); + + data[14] = 11 << 3; + } + break; + case 12: + { + data[ 0] = uData[0]; + data[ 1] = uData[1]; + data[ 2] = uData[2]; + data[ 3] = MD4_pad_w0(); + + data[14] = 12 << 3; + } + break; + case 13: + { + data[ 0] = uData[0]; + data[ 1] = uData[1]; + data[ 2] = uData[2]; + data[ 3] = MD4_pad_w1(uData[3]); + + data[14] = 13 << 3; + } + break; + case 14: + { + data[ 0] = uData[0]; + data[ 1] = uData[1]; + data[ 2] = uData[2]; + data[ 3] = MD4_pad_w2(uData[3]); + + data[14] = 14 << 3; + } + break; + case 15: + { + data[ 0] = uData[0]; + data[ 1] = uData[1]; + data[ 2] = uData[2]; + data[ 3] = MD4_pad_w3(uData[3]); + + data[14] = 15 << 3; + } + break; + + default: + { + length = length % 32; // lenght >= 32 not suported + + int word = length >> 2; + + int i = 0; + while (i < word) { + data[i] = uData[i]; + i++; + } + + switch (length & 0x3) { + case 0: + { + data[word] = MD4_pad_w0(); + } + break; + case 1: + { + data[word] = MD4_pad_w1(uData[word]); + } + break; + case 2: + { + data[word] = MD4_pad_w2(uData[word]); + } + break; + case 3: + { + data[word] = MD4_pad_w3(uData[word]); + } + break; + } + + data[14] = length << 3; + } + break; + } + + a = 0x67452301; + b = 0xefcdab89; + c = 0x98badcfe; + d = 0x10325476; + + /* Round 1 */ + FF (a, b, c, d, data[ 0], S11); /* 1 */ + FF (d, a, b, c, data[ 1], S12); /* 2 */ + FF (c, d, a, b, data[ 2], S13); /* 3 */ + FF (b, c, d, a, data[ 3], S14); /* 4 */ + FF (a, b, c, d, data[ 4], S11); /* 5 */ + FF (d, a, b, c, data[ 5], S12); /* 6 */ + FF (c, d, a, b, data[ 6], S13); /* 7 */ + FF (b, c, d, a, data[ 7], S14); /* 8 */ + FF (a, b, c, d, 0, S11); /* 9 */ + FF (d, a, b, c, 0, S12); /* 10 */ + FF (c, d, a, b, 0, S13); /* 11 */ + FF (b, c, d, a, 0, S14); /* 12 */ + FF (a, b, c, d, 0, S11); /* 13 */ + FF (d, a, b, c, 0, S12); /* 14 */ + FF (c, d, a, b, data[14], S13); /* 15 */ + FF (b, c, d, a, 0, S14); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, data[ 0], S21); /* 17 */ + GG (d, a, b, c, data[ 4], S22); /* 18 */ + GG (c, d, a, b, 0, S23); /* 19 */ + GG (b, c, d, a, 0, S24); /* 20 */ + GG (a, b, c, d, data[ 1], S21); /* 21 */ + GG (d, a, b, c, data[ 5], S22); /* 22 */ + GG (c, d, a, b, 0, S23); /* 23 */ + GG (b, c, d, a, 0, S24); /* 24 */ + GG (a, b, c, d, data[ 2], S21); /* 25 */ + GG (d, a, b, c, data[ 6], S22); /* 26 */ + GG (c, d, a, b, 0, S23); /* 27 */ + GG (b, c, d, a, data[14], S24); /* 28 */ + GG (a, b, c, d, data[ 3], S21); /* 29 */ + GG (d, a, b, c, data[ 7], S22); /* 30 */ + GG (c, d, a, b, 0, S23); /* 31 */ + GG (b, c, d, a, 0, S24); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, data[ 0], S31); /* 33 */ + HH (d, a, b, c, 0, S32); /* 34 */ + HH (c, d, a, b, data[ 4], S33); /* 35 */ + HH (b, c, d, a, 0, S34); /* 36 */ + HH (a, b, c, d, data[ 2], S31); /* 37 */ + HH (d, a, b, c, 0, S32); /* 38 */ + HH (c, d, a, b, data[ 6], S33); /* 39 */ + HH (b, c, d, a, data[14], S34); /* 40 */ + HH (a, b, c, d, data[ 1], S31); /* 41 */ + HH (d, a, b, c, 0, S32); /* 42 */ + HH (c, d, a, b, data[ 5], S33); /* 43 */ + HH (b, c, d, a, 0, S34); /* 44 */ + HH (a, b, c, d, data[ 3], S31); /* 45 */ + HH (d, a, b, c, 0, S32); /* 46 */ + HH (c, d, a, b, data[ 7], S33); /* 47 */ + HH (b, c, d, a, 0, S34); /* 48 */ + + // Finally, add initial values, as this is the only pass we make. + a += 0x67452301; + b += 0xefcdab89; + c += 0x98badcfe; + d += 0x10325476; + + uDigest[0] = a; + uDigest[1] = b; + uDigest[2] = c; + uDigest[3] = d; +} + +//void MD4_NEW( unsigned char * pData, int length, unsigned char * pDigest) +//{ +// // For the hash working space +// UINT4 b0,b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15; +// +// // For the output result +// UINT4 a,b,c,d; +// +// b0 = 0x00000000; +// b1 = 0x00000000; +// b2 = 0x00000000; +// b3 = 0x00000000; +// b4 = 0x00000000; +// b5 = 0x00000000; +// b6 = 0x00000000; +// b7 = 0x00000000; +// b8 = 0x00000000; +// b9 = 0x00000000; +// b10 = 0x00000000; +// b11 = 0x00000000; +// b12 = 0x00000000; +// b13 = 0x00000000; +// b14 = 0x00000000; +// b15 = 0x00000000; +// +// // LOAD DATA INTO b0 ... whatever here. +// switch (length) +// { +// case 2: +// { +// unsigned char in[4]; +// memcpy(in, pData, length); +// in[2] = 0x80; +// in[3] = 0x00; +// UINT4 * pUiIn = (UINT4 *) in; +// b0 = pUiIn[0]; +// } +// break; +// case 4: +// { +// unsigned char in[4]; +// memcpy(in, pData, length); +// UINT4 * pUiIn = (UINT4 *) in; +// b0 = pUiIn[0]; +// b1 = 0x00000080; +// } +// break; +// case 6: +// { +// unsigned char in[8]; +// memcpy(in, pData, length); +// in[6] = 0x80; +// in[7] = 0x00; +// UINT4 * pUiIn = (UINT4 *) in; +// b0 = pUiIn[0]; +// b1 = pUiIn[1]; +// } +// break; +// case 8: +// { +// unsigned char in[8]; +// memcpy(in, pData, length); +// UINT4 * pUiIn = (UINT4 *) in; +// b0 = pUiIn[0]; +// b1 = pUiIn[1]; +// b2 = 0x00000080; +// } +// break; +// case 10: +// { +// unsigned char in[12]; +// memcpy(in, pData, length); +// in[10] = 0x80; +// in[11] = 0x00; +// UINT4 * pUiIn = (UINT4 *) in; +// b0 = pUiIn[0]; +// b1 = pUiIn[1]; +// b2 = pUiIn[2]; +// } +// break; +// default: +// { +// unsigned char in[32]; +// memcpy(in, pData, length); +// in[length] = 0x80; +// memset(in + length + 1, 0, 32 - length - 1); +// UINT4 * pUiIn = (UINT4 *) in; +// b0 = pUiIn[0]; +// b1 = pUiIn[1]; +// b2 = pUiIn[2]; +// b3 = pUiIn[3]; +// b4 = pUiIn[4]; +// b5 = pUiIn[5]; +// b6 = pUiIn[6]; +// b7 = pUiIn[7]; // max 14 2byte chars (ntlm) +// b8 = pUiIn[8]; +// } +// break; +// } +// +// b14 = length << 3; +// +// a = 0x67452301; +// b = 0xefcdab89; +// c = 0x98badcfe; +// d = 0x10325476; +// +// /* Round 1 */ +// FF (a, b, c, d, b0, S11); /* 1 */ +// FF (d, a, b, c, b1, S12); /* 2 */ +// FF (c, d, a, b, b2, S13); /* 3 */ +// FF (b, c, d, a, b3, S14); /* 4 */ +// FF (a, b, c, d, b4, S11); /* 5 */ +// FF (d, a, b, c, b5, S12); /* 6 */ +// FF (c, d, a, b, b6, S13); /* 7 */ +// FF (b, c, d, a, b7, S14); /* 8 */ +// FF (a, b, c, d, 0, S11); /* 9 */ +// FF (d, a, b, c, 0, S12); /* 10 */ +// FF (c, d, a, b, 0, S13); /* 11 */ +// FF (b, c, d, a, 0, S14); /* 12 */ +// FF (a, b, c, d, 0, S11); /* 13 */ +// FF (d, a, b, c, 0, S12); /* 14 */ +// FF (c, d, a, b, b14, S13); /* 15 */ +// FF (b, c, d, a, 0, S14); /* 16 */ +// +// /* Round 2 */ +// GG (a, b, c, d, b0, S21); /* 17 */ +// GG (d, a, b, c, b4, S22); /* 18 */ +// GG (c, d, a, b, 0, S23); /* 19 */ +// GG (b, c, d, a, 0, S24); /* 20 */ +// GG (a, b, c, d, b1, S21); /* 21 */ +// GG (d, a, b, c, b5, S22); /* 22 */ +// GG (c, d, a, b, 0, S23); /* 23 */ +// GG (b, c, d, a, 0, S24); /* 24 */ +// GG (a, b, c, d, b2, S21); /* 25 */ +// GG (d, a, b, c, b6, S22); /* 26 */ +// GG (c, d, a, b, 0, S23); /* 27 */ +// GG (b, c, d, a, b14, S24); /* 28 */ +// GG (a, b, c, d, b3, S21); /* 29 */ +// GG (d, a, b, c, b7, S22); /* 30 */ +// GG (c, d, a, b, 0, S23); /* 31 */ +// GG (b, c, d, a, 0, S24); /* 32 */ +// +// /* Round 3 */ +// HH (a, b, c, d, b0, S31); /* 33 */ +// HH (d, a, b, c, 0, S32); /* 34 */ +// HH (c, d, a, b, b4, S33); /* 35 */ +// HH (b, c, d, a, 0, S34); /* 36 */ +// HH (a, b, c, d, b2, S31); /* 37 */ +// HH (d, a, b, c, 0, S32); /* 38 */ +// HH (c, d, a, b, b6, S33); /* 39 */ +// HH (b, c, d, a, b14, S34); /* 40 */ +// HH (a, b, c, d, b1, S31); /* 41 */ +// HH (d, a, b, c, 0, S32); /* 42 */ +// HH (c, d, a, b, b5, S33); /* 43 */ +// HH (b, c, d, a, 0, S34); /* 44 */ +// HH (a, b, c, d, b3, S31); /* 45 */ +// HH (d, a, b, c, 0, S32); /* 46 */ +// HH (c, d, a, b, b7, S33); /* 47 */ +// HH (b, c, d, a, 0, S34); /* 48 */ +// +// // Finally, add initial values, as this is the only pass we make. +// a += 0x67452301; +// b += 0xefcdab89; +// c += 0x98badcfe; +// d += 0x10325476; +// +// UINT4 buf[4] = { a, b, c, d}; +// memcpy(pDigest, buf, 16); +// +// return; +//} diff --git a/Client Applications/rcracki_mt/md4.h b/Client Applications/rcracki_mt/md4.h new file mode 100644 index 0000000..8a5c428 --- /dev/null +++ b/Client Applications/rcracki_mt/md4.h @@ -0,0 +1,10 @@ +#ifndef MD4_H +#define MD4_H + +//typedef unsigned long uint32; +typedef unsigned long UINT4; + +//Main function +void MD4_NEW( unsigned char * buf, int len, unsigned char * pDigest); + +#endif /* !MD4_H */ diff --git a/Client Applications/rcracki_mt/pthreadVC2.dll b/Client Applications/rcracki_mt/pthreadVC2.dll new file mode 100644 index 0000000..93f562b Binary files /dev/null and b/Client Applications/rcracki_mt/pthreadVC2.dll differ diff --git a/Client Applications/rcracki_mt/pthreadVC2.lib b/Client Applications/rcracki_mt/pthreadVC2.lib new file mode 100644 index 0000000..13f47f4 Binary files /dev/null and b/Client Applications/rcracki_mt/pthreadVC2.lib differ diff --git a/Client Applications/rcracki_mt/rcrackiThread.cpp b/Client Applications/rcracki_mt/rcrackiThread.cpp new file mode 100644 index 0000000..9dc1f14 --- /dev/null +++ b/Client Applications/rcracki_mt/rcrackiThread.cpp @@ -0,0 +1,239 @@ +#ifdef _WIN32 + #pragma warning(disable : 4786 4267 4018) +#endif + +#include "rcrackiThread.h" + +// create job for pre-calculation +rcrackiThread::rcrackiThread(unsigned char* TargetHash, int thread_id, int nRainbowChainLen, int thread_count, uint64* pStartPosIndexE) +{ + t_TargetHash = TargetHash; + t_nRainbowChainLen = nRainbowChainLen; + t_ID = thread_id; + t_count = thread_count; + t_pStartPosIndexE = pStartPosIndexE; + t_nChainWalkStep = 0; + falseAlarmChecker = false; + falseAlarmCheckerO = false; +} + +// create job for false alarm checking +rcrackiThread::rcrackiThread(unsigned char* pHash) +{ + falseAlarmChecker = true; + falseAlarmCheckerO = false; + t_pChainsFound.clear(); + t_nGuessedPoss.clear(); + t_pHash = pHash; + t_nChainWalkStepDueToFalseAlarm = 0; + t_nFalseAlarm = 0; + foundHash = false; +} + +// create job for false alarm checking OLD format +rcrackiThread::rcrackiThread(unsigned char* pHash, bool oldFormat) +{ + falseAlarmChecker = true; + falseAlarmCheckerO = true; + t_pChainsFoundO.clear(); + t_nGuessedPoss.clear(); + t_pHash = pHash; + t_nChainWalkStepDueToFalseAlarm = 0; + t_nFalseAlarm = 0; + foundHash = false; +} + + +void rcrackiThread::AddAlarmCheck(RainbowChain* pChain, int nGuessedPos) +{ + t_pChainsFound.push_back(pChain); + t_nGuessedPoss.push_back(nGuessedPos); +} + +void rcrackiThread::AddAlarmCheckO(RainbowChainO* pChain, int nGuessedPos) +{ + t_pChainsFoundO.push_back(pChain); + t_nGuessedPoss.push_back(nGuessedPos); +} + +// Windows (beginthreadex) way of threads +//unsigned __stdcall rcrackiThread::rcrackiThreadStaticEntryPoint(void * pThis) +//{ +// rcrackiThread* pTT = (rcrackiThread*)pThis; +// pTT->rcrackiThreadEntryPoint(); +// _endthreadex( 2 ); +// return 2; +//} + +// entry point for the posix thread +void * rcrackiThread::rcrackiThreadStaticEntryPointPthread(void * pThis) +{ + rcrackiThread* pTT = (rcrackiThread*)pThis; + pTT->rcrackiThreadEntryPoint(); + pthread_exit(NULL); + return NULL; +} + +// start processing of jobs +void rcrackiThread::rcrackiThreadEntryPoint() +{ + if (falseAlarmChecker) { + if (falseAlarmCheckerO) { + CheckAlarmO(); + } + else { + CheckAlarm(); + } + } + else { + PreCalculate(); + } +} + +uint64 rcrackiThread::GetIndex(int nPos) +{ + uint64 t_index = t_vStartPosIndexE[nPos - t_ID]; + return t_index; +} + +int rcrackiThread::GetChainWalkStep() +{ + return t_nChainWalkStep; +} + +int rcrackiThread::GetIndexCount() +{ + return t_vStartPosIndexE.size(); +} + +rcrackiThread::~rcrackiThread(void) +{ +} + +void rcrackiThread::PreCalculate() +{ + for (t_nPos = t_nRainbowChainLen - 2 - t_ID; t_nPos >= 0; t_nPos -= t_count) + { + t_cwc.SetHash(t_TargetHash); + t_cwc.HashToIndex(t_nPos); + int i; + for (i = t_nPos + 1; i <= t_nRainbowChainLen - 2; i++) + //for (i = t_nPos + 1; i <= 10; i++) + { + t_cwc.IndexToPlain(); + t_cwc.PlainToHash(); + t_cwc.HashToIndex(i); + } + t_pStartPosIndexE[t_nPos] = t_cwc.GetIndex(); + t_nChainWalkStep += t_nRainbowChainLen - 2 - t_nPos; + } +} + +void rcrackiThread::CheckAlarm() +{ + int i; + for (i = 0; i < t_pChainsFound.size(); i++) + { + RainbowChain* t_pChain = t_pChainsFound[i]; + int t_nGuessedPos = t_nGuessedPoss[i]; + + CChainWalkContext cwc; + //uint64 nIndexS = t_pChain->nIndexS & 0x0000FFFFFFFFFFFF; // for first 6 bytes + //uint64 nIndexS = t_pChain->nIndexS >> 16; + uint64 nIndexS = t_pChain->nIndexS & 0x0000FFFFFFFFFFFFULL; // for first 6 bytes + cwc.SetIndex(nIndexS); + //cwc.SetIndex(t_pChain->nIndexS); + int nPos; + for (nPos = 0; nPos < t_nGuessedPos; nPos++) + { + cwc.IndexToPlain(); + cwc.PlainToHash(); + cwc.HashToIndex(nPos); + } + cwc.IndexToPlain(); + cwc.PlainToHash(); + if (cwc.CheckHash(t_pHash)) + { + t_Hash = cwc.GetHash(); + t_Plain = cwc.GetPlain(); + t_Binary = cwc.GetBinary(); + + foundHash = true; + break; + } + else { + foundHash = false; + t_nChainWalkStepDueToFalseAlarm += t_nGuessedPos + 1; + t_nFalseAlarm++; + } + } +} + +void rcrackiThread::CheckAlarmO() +{ + int i; + for (i = 0; i < t_pChainsFoundO.size(); i++) + { + RainbowChainO* t_pChain = t_pChainsFoundO[i]; + int t_nGuessedPos = t_nGuessedPoss[i]; + + CChainWalkContext cwc; + + uint64 nIndexS = t_pChain->nIndexS; + cwc.SetIndex(nIndexS); + + int nPos; + for (nPos = 0; nPos < t_nGuessedPos; nPos++) + { + cwc.IndexToPlain(); + cwc.PlainToHash(); + cwc.HashToIndex(nPos); + } + cwc.IndexToPlain(); + cwc.PlainToHash(); + if (cwc.CheckHash(t_pHash)) + { + t_Hash = cwc.GetHash(); + t_Plain = cwc.GetPlain(); + t_Binary = cwc.GetBinary(); + + foundHash = true; + break; + } + else { + foundHash = false; + t_nChainWalkStepDueToFalseAlarm += t_nGuessedPos + 1; + t_nFalseAlarm++; + } + } +} + +bool rcrackiThread::FoundHash() +{ + return foundHash; +} + +int rcrackiThread::GetChainWalkStepDueToFalseAlarm() +{ + return t_nChainWalkStepDueToFalseAlarm; +} + +int rcrackiThread::GetnFalseAlarm() +{ + return t_nFalseAlarm; +} + +string rcrackiThread::GetHash() +{ + return t_Hash; +} + +string rcrackiThread::GetPlain() +{ + return t_Plain; +} + +string rcrackiThread::GetBinary() +{ + return t_Binary; +} diff --git a/Client Applications/rcracki_mt/rcrackiThread.h b/Client Applications/rcracki_mt/rcrackiThread.h new file mode 100644 index 0000000..74b96dc --- /dev/null +++ b/Client Applications/rcracki_mt/rcrackiThread.h @@ -0,0 +1,60 @@ +#pragma once +#include "ChainWalkContext.h" +#include "Public.h" +#include "HashSet.h" +//#include +#include + +class rcrackiThread +{ +private: + unsigned char* t_TargetHash; + int t_nPos; + int t_nRainbowChainLen; + CChainWalkContext t_cwc; + vector t_vStartPosIndexE; + int t_ID; + int t_count; + uint64* t_pStartPosIndexE; + int t_nChainWalkStep; + bool falseAlarmChecker; + bool falseAlarmCheckerO; + vector t_pChainsFound; + vector t_pChainsFoundO; + vector t_nGuessedPoss; + unsigned char* t_pHash; + bool foundHash; + int t_nChainWalkStepDueToFalseAlarm; + int t_nFalseAlarm; + string t_Hash; + string t_Plain; + string t_Binary; + +public: + rcrackiThread(unsigned char* TargetHash, int thread_id, int nRainbowChainLen, int thread_count, uint64* pStartPosIndexE); + rcrackiThread(unsigned char* pHash); + rcrackiThread(unsigned char* pHash, bool oldFormat); + rcrackiThread(void); + ~rcrackiThread(void); + + //void SetWork(unsigned char* TargetHash, int nPos, int nRainbowChainLen); + //static unsigned __stdcall rcrackiThread::rcrackiThreadStaticEntryPoint(void * pThis); + static void * rcrackiThreadStaticEntryPointPthread(void * pThis); + int GetIndexCount(); + int GetChainWalkStep(); + uint64 GetIndex(int nPos); + bool FoundHash(); + void AddAlarmCheck(RainbowChain* pChain, int nGuessedPos); + void AddAlarmCheckO(RainbowChainO* pChain, int nGuessedPos); + int GetChainWalkStepDueToFalseAlarm(); + int GetnFalseAlarm(); + string GetHash(); + string GetPlain(); + string GetBinary(); + +private: + void rcrackiThreadEntryPoint(); + void PreCalculate(); + void CheckAlarm(); + void CheckAlarmO(); +}; diff --git a/Client Applications/rcracki_mt/rcracki_mt.exe b/Client Applications/rcracki_mt/rcracki_mt.exe new file mode 100644 index 0000000..2de1ad6 Binary files /dev/null and b/Client Applications/rcracki_mt/rcracki_mt.exe differ diff --git a/Client Applications/rcracki_mt/rcracki_mt.ini b/Client Applications/rcracki_mt/rcracki_mt.ini new file mode 100644 index 0000000..17edb0a --- /dev/null +++ b/Client Applications/rcracki_mt/rcracki_mt.ini @@ -0,0 +1,33 @@ +# Default settings for rcracki_mt +# Command line arguments override these defaults + +# Specify default amount of threads +Threads=1 + +# Set a default file to store temporary results. +# Set AlwaysStoreResultsToFile=1 or use -o to actually store results. +DefaultResultsFile=e:\default_rcracki_results.txt + +# This option requires DefaultResultsFile to be set to a file +#AlwaysStoreResultsToFile=1 + +# Set some default file locations to search for rainbow tables. +# You need to use these in combination with the command line argument -a [algorithm] +# Or you can set a default algorithm here with 'DefaultAlgorithm'. +# Algorithm is the name you use as specifier after 'DefaultRainbowTablesPath.' +# You can specify multiple lines per algorithm, one path/directory per line. +# Any locations you specify on the command line will be added to the list as well. +# For Windows users: locations in this file with a different case +# as on the command line are treated as separate locations (run through twice) +#DefaultRainbowTablePath.MD5=X:\RTI\MD5 +#DefaultRainbowTablePath.NTLM=X:\RTI\NTLM\ntlm_loweralpha-space#1-9_* + +# This option requires at least one 'DefaultRainbowTablePath.[algorithm]' to be set +#DefaultAlgorithm=MD5 + +# Always show debugging infomation (command line option -v) +# AlwaysDebug=1 + +# Always keep precalculation files after cracking, don't remove them. +# These files are saved by session name. So you can store precalculations over multiple jobs. +#AlwaysKeepPrecalcFiles=1 \ No newline at end of file diff --git a/Client Applications/rcracki_mt/rcracki_mt.sln b/Client Applications/rcracki_mt/rcracki_mt.sln new file mode 100644 index 0000000..d323c38 --- /dev/null +++ b/Client Applications/rcracki_mt/rcracki_mt.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rcracki_mt", "rcracki_mt.vcproj", "{D484ABA1-C117-4AB1-B361-22E5EA62FA00}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D484ABA1-C117-4AB1-B361-22E5EA62FA00}.Debug|Win32.ActiveCfg = Debug|Win32 + {D484ABA1-C117-4AB1-B361-22E5EA62FA00}.Debug|Win32.Build.0 = Debug|Win32 + {D484ABA1-C117-4AB1-B361-22E5EA62FA00}.Release|Win32.ActiveCfg = Release|Win32 + {D484ABA1-C117-4AB1-B361-22E5EA62FA00}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Client Applications/rcracki_mt/rcracki_mt.suo b/Client Applications/rcracki_mt/rcracki_mt.suo new file mode 100644 index 0000000..12af4a6 Binary files /dev/null and b/Client Applications/rcracki_mt/rcracki_mt.suo differ diff --git a/Client Applications/rcracki_mt/rcracki_mt.vcproj b/Client Applications/rcracki_mt/rcracki_mt.vcproj new file mode 100644 index 0000000..53f7498 --- /dev/null +++ b/Client Applications/rcracki_mt/rcracki_mt.vcproj @@ -0,0 +1,317 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Client Applications/rcracki_mt/sha1.cpp b/Client Applications/rcracki_mt/sha1.cpp new file mode 100644 index 0000000..339ebb9 --- /dev/null +++ b/Client Applications/rcracki_mt/sha1.cpp @@ -0,0 +1,355 @@ +//#include +#if defined(WIN32) +#include +#endif +#include + + + +#define SHA1CircularShift(bits,word) (((word) << (bits)) | ((word) >> (32-(bits)))) + +// this rotate isn't faster with me +#if defined(WIN32) +#define ROTATE(a,n) _lrotl(a,n) +#else +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* A nice byte order reversal from Wei Dai */ +#if defined(WIN32) +/* 5 instructions with rotate instruction, else 9 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ + } +#else +/* 6 instructions with rotate instruction, else 8 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ + (a)=ROTATE(l,16L); \ + } +#endif + +#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) +#define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) +#define F_60_79(b,c,d) F_20_39(b,c,d) + +#define K0 0x5A827999 +#define K1 0x6ED9EBA1 +#define K2 0x8F1BBCDC +#define K3 0xCA62C1D6 + +#define H0 0x67452301 +#define H1 0xEFCDAB89 +#define H2 0x98BADCFE +#define H3 0x10325476 +#define H4 0xC3D2E1F0 + +typedef unsigned int UINT4; +#define SHA1HashSize 20 + +void SHA1_NEW( unsigned char * pData, int length, unsigned char * pDigest) +{ + if (length > 16) + return; + + UINT4 Message_Block_Index = 0; + + union + { + unsigned char Message_Block[64]; + UINT4 Message_Block_W[16]; + }; + + Message_Block_W[0] = 0x00000000; + Message_Block_W[1] = 0x00000000; + Message_Block_W[2] = 0x00000000; + Message_Block_W[3] = 0x00000000; + Message_Block_W[4] = 0x00000000; + + UINT4 Intermediate_Hash[5] = { H0, H1, H2, H3, H4 }; + + memcpy(Message_Block, pData, length); + Message_Block_Index += length; + + //padMessage + Message_Block[length] = 0x80; + + UINT4 W_15 = length << 3; + + int t; /* Loop counter */ + UINT4 temp; /* Temporary word value */ + UINT4 W[80]; /* Word sequence */ + UINT4 A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + + #define INIT_OLD(x) \ + W[x] = (Message_Block[(x) * 4] << 24) | \ + (Message_Block[(x) * 4 + 1] << 16) | \ + (Message_Block[(x) * 4 +2] << 8) | \ + (Message_Block[(x) * 4 +3]) + + #define INIT(x) W[x] = Message_Block_W[x]; + + #define INIT_NULL(x) W[x] = 0; + + + Endian_Reverse32(Message_Block_W[0]); + INIT(0); + + #define INIT_NULL_1_14 \ + INIT_NULL(1); INIT_NULL_2_14; + + #define INIT_NULL_2_14 \ + INIT_NULL(2); INIT_NULL_3_14; + + #define INIT_NULL_3_14 \ + INIT_NULL(3); INIT_NULL_4_14; + + #define INIT_NULL_4_14 \ + INIT_NULL(4); INIT_NULL_5_14; + + #define INIT_NULL_5_14 \ + INIT_NULL(5); INIT_NULL(6); INIT_NULL(7); \ + INIT_NULL(8); INIT_NULL(9); INIT_NULL(10); INIT_NULL(11); \ + INIT_NULL(12); INIT_NULL(13); INIT_NULL(14); + + #define ROTATE1_NULL_1_14 \ + ROTATE1_NULL; ROTATE1_NULL_2_14; + + #define ROTATE1_NULL_2_14 \ + ROTATE1_NULL; ROTATE1_NULL_3_14; + + #define ROTATE1_NULL_3_14 \ + ROTATE1_NULL; ROTATE1_NULL_4_14; + + #define ROTATE1_NULL_4_14 \ + ROTATE1_NULL; ROTATE1_NULL_5_14; + + #define ROTATE1_NULL_5_14 \ + ROTATE1_NULL; ROTATE1_NULL; ROTATE1_NULL; \ + ROTATE1_NULL; ROTATE1_NULL; ROTATE1_NULL; ROTATE1_NULL; \ + ROTATE1_NULL; ROTATE1_NULL; ROTATE1_NULL; + + + #define EXPAND(t) \ + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); \ + + #define EXPAND_3(t) W[t] = SHA1CircularShift(1,W[t-3]); + #define EXPAND_16(t) W[t] = SHA1CircularShift(1,W[t-16]); + #define EXPAND_3_8(t) W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8]); + + + if (length < 4) { + INIT_NULL_1_14; + W[15] = W_15; + EXPAND_16(16); + W[17] = 0; + W[18] = W_15<<1; + } + else if (length < 8) { + Endian_Reverse32(Message_Block_W[1]); + INIT(1); + INIT_NULL_2_14; + W[15] = W_15; + EXPAND_16(16); + EXPAND_16(17); + W[18] = W_15<<1; + } + else { + Endian_Reverse32(Message_Block_W[1]); + Endian_Reverse32(Message_Block_W[2]); + Endian_Reverse32(Message_Block_W[3]); + Endian_Reverse32(Message_Block_W[4]); + INIT(1); INIT(2); INIT(3); INIT(4); + INIT_NULL_5_14; + W[15] = W_15; + EXPAND(16); + EXPAND(17); + EXPAND(18); + } + + + if (length < 12) { + EXPAND_3(19); + } + else { + EXPAND(19); + } + + if (length < 16) { + EXPAND_3(20); + } + else { + EXPAND(20); + } + EXPAND_3(21); EXPAND_3(22); + EXPAND(23); + + EXPAND(24); EXPAND(25); EXPAND_3_8(26); EXPAND_3_8(27); + EXPAND(28); EXPAND(29); EXPAND(30); EXPAND(31); + EXPAND(32); EXPAND(33); EXPAND(34); EXPAND(35); + EXPAND(36); EXPAND(37); EXPAND(38); EXPAND(39); + EXPAND(40); EXPAND(41); EXPAND(42); EXPAND(43); + EXPAND(44); EXPAND(45); EXPAND(46); EXPAND(47); + EXPAND(48); EXPAND(49); EXPAND(50); EXPAND(51); + EXPAND(52); EXPAND(53); EXPAND(54); EXPAND(55); + EXPAND(56); EXPAND(57); EXPAND(58); EXPAND(59); + EXPAND(60); EXPAND(61); EXPAND(62); EXPAND(63); + EXPAND(64); EXPAND(65); EXPAND(66); EXPAND(67); + EXPAND(68); EXPAND(69); EXPAND(70); EXPAND(71); + EXPAND(72); EXPAND(73); EXPAND(74); EXPAND(75); + EXPAND(76); EXPAND(77); EXPAND(78); EXPAND(79); + + + #define ROTATE1(t) \ + temp = SHA1CircularShift(5,A) + F_00_19(B,C,D) + E + W[t] + K0; \ + E = D; D = C; \ + C = SHA1CircularShift(30,B); \ + B = A; A = temp; \ + + #define ROTATE1_NEW(a, b, c, d, e, x) \ + e += SHA1CircularShift(5,a) + F_00_19(b,c,d) + x + K0; \ + b = SHA1CircularShift(30,b); + + #define ROTATE1_W(w) \ + temp = SHA1CircularShift(5,A) + F_00_19(B,C,D) + E + w + K0; \ + E = D; D = C; \ + C = SHA1CircularShift(30,B); \ + B = A; A = temp; + + #define ROTATE1_NULL \ + temp = SHA1CircularShift(5,A) + F_00_19(B,C,D) + E + K0; \ + E = D; D = C; \ + C = SHA1CircularShift(30,B); \ + B = A; A = temp; \ + + #define ROTATE2_NEW(a, b, c, d, e, x) \ + e += SHA1CircularShift(5,a) + F_20_39(b,c,d) + x + K1; \ + b = SHA1CircularShift(30,b); + + #define ROTATE2(t) \ + temp = SHA1CircularShift(5,A) + F_20_39(B,C,D) + E + W[t] + K1; \ + E = D; D = C; \ + C = SHA1CircularShift(30,B); \ + B = A; A = temp; + + #define ROTATE2_W(w) \ + temp = SHA1CircularShift(5,A) + F_20_39(B,C,D) + E + w + K1; \ + E = D; D = C; \ + C = SHA1CircularShift(30,B); \ + B = A; A = temp; + + #define ROTATE3(t) \ + temp = SHA1CircularShift(5,A) + F_40_59(B,C,D) + E + W[t] + K2; \ + E = D; D = C; \ + C = SHA1CircularShift(30,B); \ + B = A; A = temp; + + #define ROTATE4(t) \ + temp = SHA1CircularShift(5,A) + F_60_79(B,C,D) + E + W[t] + K3; \ + E = D; D = C; \ + C = SHA1CircularShift(30,B); \ + B = A; A = temp; + + A = H0; + B = H1; + C = H2; + D = H3; + E = H4; + + + E = H2; + //D = 2079550178; + //C = 1506887872; + B = 2679412915 + W[0]; + if (length < 4) { + A = SHA1CircularShift(5,B) + 1722862861; + } + else { + A = SHA1CircularShift(5,B) + 1722862861 + W[1]; + } + + if (length < 8) { + temp = SHA1CircularShift(5,A) + ((((1506887872) ^ (2079550178)) & (B)) ^ (2079550178)) + H2 + K0; + } + else { + temp = SHA1CircularShift(5,A) + (((572662306) & (B)) ^ (2079550178)) + H2 + K0 + W[2]; + } + C = SHA1CircularShift(30,B); //SHA1CircularShift(30,(2679412915 + W[0])); + B = A; + A = temp; + + if (length < 12) { + temp = SHA1CircularShift(5,A) + ((((C) ^ (1506887872)) & (B)) ^ (1506887872)) + 2079550178 + K0; + } + else { + temp = SHA1CircularShift(5,A) + ((((C) ^ (1506887872)) & (B)) ^ (1506887872)) + 2079550178 + K0 + W[3]; + } + E = 1506887872; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + + if (length < 16) { + temp = SHA1CircularShift(5,A) + F_00_19(B,C,D) + 1506887872 + K0; + } + else { + temp = SHA1CircularShift(5,A) + F_00_19(B,C,D) + 1506887872 + K0 + W[4]; + } + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + + ROTATE1_NULL_5_14; + + ROTATE1_NEW( A, B, C, D, E, W_15 ); + ROTATE1_NEW( E, A, B, C, D, W[16] ); + ROTATE1_NEW( D, E, A, B, C, W[17] ); + ROTATE1_NEW( C, D, E, A, B, W[18] ); + ROTATE1_NEW( B, C, D, E, A, W[19] ); + + for(t = 20; t < 40; t++) + { + if (t == 21 && length < 8) { + ROTATE2_W((length<<5)); // *32 + } + else { + ROTATE2(t); + } + } + + for(t = 40; t < 60; t++) + { + ROTATE3(t); + } + + for(t = 60; t < 80; t++) + { + ROTATE4(t); + } + + Intermediate_Hash[0] += A; + Intermediate_Hash[1] += B; + Intermediate_Hash[2] += C; + Intermediate_Hash[3] += D; + Intermediate_Hash[4] += E; + + Endian_Reverse32(Intermediate_Hash[0]); + Endian_Reverse32(Intermediate_Hash[1]); + Endian_Reverse32(Intermediate_Hash[2]); + Endian_Reverse32(Intermediate_Hash[3]); + Endian_Reverse32(Intermediate_Hash[4]); + + memcpy(pDigest, Intermediate_Hash, 20); +} diff --git a/Client Applications/rcracki_mt/sha1.h b/Client Applications/rcracki_mt/sha1.h new file mode 100644 index 0000000..e10a64b --- /dev/null +++ b/Client Applications/rcracki_mt/sha1.h @@ -0,0 +1 @@ +void SHA1_NEW( unsigned char * pData, int length, unsigned char * pDigest);