1 /*
2  * freerainbowtables is a multithreaded implementation and fork of the original
3  * RainbowCrack
4  *
5  * Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>
6  * Copyright Martin Westergaard Jørgensen <martinwj2005@gmail.com>
7  * Copyright 2009, 2010 Daniël Niggebrugge <niggebrugge@fox-it.com>
8  * Copyright 2009, 2010, 2011, 2012 James Nobis <quel@quelrod.net>
9  * Copyright 2010 Yngve AAdlandsvik
10  * Copyright 2008, 2009, 2010, 2011 Steve Thomas (Sc00bz)
11  *
12  * This file is part of freerainbowtables.
13  *
14  * freerainbowtables is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation, either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * freerainbowtables is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with freerainbowtables.  If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include "ChainWalkContext.h"
29 
30 #include <ctype.h>
31 
32 //////////////////////////////////////////////////////////////////////
33 
34 std::string CChainWalkContext::m_sHashRoutineName;
35 HASHROUTINE CChainWalkContext::m_pHashRoutine;
36 int CChainWalkContext::m_nHashLen;
37 uint8_t CChainWalkContext::RTfileFormatId;
38 int CChainWalkContext::m_nPlainLenMinTotal = 0;
39 int CChainWalkContext::m_nPlainLenMaxTotal = 0;
40 int CChainWalkContext::m_nHybridCharset = 0;
41 std::vector<stCharset> CChainWalkContext::m_vCharset;
42 uint64_t CChainWalkContext::m_nPlainSpaceUpToX[MAX_PLAIN_LEN];
43 uint64_t CChainWalkContext::m_nPlainSpaceTotal;
44 unsigned char CChainWalkContext::m_Salt[MAX_SALT_LEN];
45 int CChainWalkContext::m_nSaltLen = 0;
46 int CChainWalkContext::m_nRainbowTableIndex;
47 uint64_t CChainWalkContext::m_nReduceOffset;
48 KeySpace *CChainWalkContext::m_ks = NULL;
49 
50 //////////////////////////////////////////////////////////////////////
51 
CChainWalkContext()52 CChainWalkContext::CChainWalkContext()
53 {
54 }
55 
~CChainWalkContext()56 CChainWalkContext::~CChainWalkContext()
57 {
58 }
59 
LoadCharset(std::string sName)60 bool CChainWalkContext::LoadCharset( std::string sName )
61 {
62 	m_vCharset.clear();
63 	if (sName == "byte")
64 	{
65 		stCharset tCharset;
66 		int i;
67 		for (i = 0x00; i <= 0xff; i++)
68 			tCharset.m_PlainCharset[i] = (unsigned char) i;
69 		tCharset.m_nPlainCharsetLen = MAX_PLAIN_LEN;
70 		tCharset.m_sPlainCharsetName = sName;
71 		tCharset.m_sPlainCharsetContent = "0x00, 0x01, ... 0xff";
72 		m_vCharset.push_back(tCharset);
73 		return true;
74 	}
75 	if(sName.substr(0, 6) == "hybrid") // Hybrid charset consisting of 2 charsets
76 	{
77 		if (sName.substr(6, 2) == "3(")
78 		{
79 			size_t pos = sName.find_last_of(')');
80 			if (pos == std::string::npos)
81 				return false;
82 			m_ks = KeySpace::load(sName.substr(8, pos - 8).c_str(), CE_ASCII_BIN8 | CE_NULL_PADDED); // hybrid3(file name)#0-0
83 			if (m_ks == NULL)
84 				return false;
85 			m_nHybridCharset = 3;
86 			return true;
87 		}
88 		else if (sName.substr(6, 2) == "2(")
89 			m_nHybridCharset = 2;
90 		else if (sName.substr(6, 1) == "(")
91 			m_nHybridCharset = 1;
92 		else
93 		{
94 			printf("hybrid version not supported\n");
95 			return false;
96 		}
97 	}
98 	else
99 		m_nHybridCharset = 0;
100 
101 	bool readCharset = false;
102 	std::vector<std::string> vLine;
103 	std::vector<std::string> internal_charset;
104 
105 	vLine.clear();
106 	internal_charset.clear();
107 	internal_charset.push_back("byte                        = []");
108 	internal_charset.push_back("alpha                       = [ABCDEFGHIJKLMNOPQRSTUVWXYZ]");
109 	internal_charset.push_back("alpha-space                 = [ABCDEFGHIJKLMNOPQRSTUVWXYZ ]");
110 	internal_charset.push_back("alpha-numeric               = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]");
111 	internal_charset.push_back("alpha-numeric-space         = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ]");
112 	internal_charset.push_back("alpha-numeric-symbol14      = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D]");
113 	internal_charset.push_back("alpha-numeric-symbol14-space= [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x20]");
114 	internal_charset.push_back("all                         = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F]");
115 	internal_charset.push_back("all-space                   = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
116 	internal_charset.push_back("alpha-numeric-symbol32-space = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
117 	internal_charset.push_back("lm-frt-cp437                = [\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x7B\x7C\x7D\x7E\x80\x8E\x8F\x90\x92\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA5\xE0\xE1\xE2\xE3\xE4\xE6\xE7\xE8\xE9\xEA\xEB\xEE]");
118 	internal_charset.push_back("lm-frt-cp850                = [\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x7B\x7C\x7D\x7E\x80\x8E\x8F\x90\x92\x99\x9A\x9C\x9D\x9F\xA5\xB5\xB6\xB7\xBD\xBE\xC7\xCF\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xDE\xE0\xE1\xE2\xE3\xE5\xE6\xE8\xE9\xEA\xEB\xED\xEF]");
119 	internal_charset.push_back("lm-frt-cp437-850            = [\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x7B\x7C\x7D\x7E\x80\x8E\x8F\x90\x92\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA5\xB5\xB6\xB7\xBD\xBE\xC7\xCF\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xDE\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xED\xEE\xEF]");
120 	internal_charset.push_back("numeric                     = [0123456789]");
121 	internal_charset.push_back("numeric-space               = [0123456789 ]");
122 	internal_charset.push_back("loweralpha                  = [abcdefghijklmnopqrstuvwxyz]");
123 	internal_charset.push_back("loweralpha-space            = [abcdefghijklmnopqrstuvwxyz ]");
124 	internal_charset.push_back("loweralpha-numeric          = [abcdefghijklmnopqrstuvwxyz0123456789]");
125 	internal_charset.push_back("loweralpha-numeric-space    = [abcdefghijklmnopqrstuvwxyz0123456789 ]");
126 	internal_charset.push_back("loweralpha-numeric-symbol14 = [abcdefghijklmnopqrstuvwxyz0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D]");
127 	internal_charset.push_back("loweralpha-numeric-all      = [abcdefghijklmnopqrstuvwxyz0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F]");
128 	internal_charset.push_back("loweralpha-numeric-symbol32-space= [abcdefghijklmnopqrstuvwxyz0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
129 	internal_charset.push_back("mixalpha                    = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]");
130 	internal_charset.push_back("mixalpha-space              = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ]");
131 	internal_charset.push_back("mixalpha-numeric            = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]");
132 	internal_charset.push_back("mixalpha-numeric-space      = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ]");
133 	internal_charset.push_back("mixalpha-numeric-symbol14   = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D]");
134 	internal_charset.push_back("mixalpha-numeric-all        = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F]");
135 	internal_charset.push_back("mixalpha-numeric-symbol32-space  = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
136 	internal_charset.push_back("mixalpha-numeric-all-space  = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\x21\x40\x23\x24\x25\x5E\x26\x2A\x28\x29\x2D\x5F\x2B\x3D\x7E\x60\x5B\x5D\x7B\x7D\x7C\x5C\x3A\x3B\x22\x27\x3C\x3E\x2C\x2E\x3F\x2F\x20]");
137 #ifdef USE_INTEGRATED_CHARSET
138 	vLine = internal_charset;
139 	readCharset = true;
140 #else
141 	#ifdef BOINC
142 		if ( boinc_ReadLinesFromFile( "charset.txt", vLine ) )
143 			readCharset = true;
144 		else
145 		{
146 			vLine = internal_charset;
147 			readCharset = true;
148 		}
149 	#else
150 		if ( ReadLinesFromFile("charset.txt", vLine) )
151 			readCharset = true;
152 		else if ( ReadLinesFromFile(GetApplicationPath() + "charset.txt", vLine) )
153 			readCharset = true;
154 		else
155 		{
156 			vLine = internal_charset;
157 			readCharset = true;
158 		}
159 	#endif
160 #endif
161 
162 	if ( readCharset )
163 	{
164 		int i;
165 		for (i = 0; (uint32_t)i < vLine.size(); i++)
166 		{
167 			// Filter comment
168 			if (vLine[i][0] == '#')
169 				continue;
170 
171 			std::vector<std::string> vPart;
172 			if (SeperateString(vLine[i], "=", vPart))
173 			{
174 				// sCharsetName
175 				std::string sCharsetName = TrimString(vPart[0]);
176 				if (sCharsetName == "")
177 					continue;
178 
179 				// sCharsetName charset check
180 				bool fCharsetNameCheckPass = true;
181 				uint32_t j;
182 				for (j = 0; j < sCharsetName.size(); j++)
183 				{
184 					if (   !isalpha(sCharsetName[j])
185 						&& !isdigit(sCharsetName[j])
186 						&& (sCharsetName[j] != '-'))
187 					{
188 						fCharsetNameCheckPass = false;
189 						break;
190 					}
191 				}
192 				if (!fCharsetNameCheckPass)
193 				{
194 					printf("invalid charset name %s in charset configuration file\n", sCharsetName.c_str());
195 					continue;
196 				}
197 
198 				// sCharsetContent
199 				std::string sCharsetContent = TrimString(vPart[1]);
200 				if (sCharsetContent == "" || sCharsetContent == "[]")
201 					continue;
202 				if (sCharsetContent[0] != '[' || sCharsetContent[sCharsetContent.size() - 1] != ']')
203 				{
204 					printf("invalid charset content %s in charset configuration file\n", sCharsetContent.c_str());
205 					continue;
206 				}
207 				sCharsetContent = sCharsetContent.substr(1, sCharsetContent.size() - 2);
208 				if (sCharsetContent.size() > MAX_PLAIN_LEN)
209 				{
210 					printf("charset content %s too long\n", sCharsetContent.c_str());
211 					continue;
212 				}
213 
214 				//printf("%s = [%s]\n", sCharsetName.c_str(), sCharsetContent.c_str());
215 
216 				// Is it a hybrid?
217 				if( m_nHybridCharset != 0 )
218 				{
219 					std::vector<tCharset> vCharsets;
220 
221 					if ( !GetHybridCharsets(sName, vCharsets) )
222 					{
223 						std::cout << "Failed to GetHybridCharsets: "
224 							<< sName << std::endl;
225 						return false;
226 					}
227 
228 					if(sCharsetName == vCharsets[m_vCharset.size()].sName)
229 					{
230 						stCharset tCharset;
231 						tCharset.m_nPlainCharsetLen = sCharsetContent.size();
232 						memcpy(tCharset.m_PlainCharset, sCharsetContent.c_str(), tCharset.m_nPlainCharsetLen);
233 						tCharset.m_sPlainCharsetName = sCharsetName;
234 						tCharset.m_sPlainCharsetContent = sCharsetContent;
235 						tCharset.m_nPlainLenMin = vCharsets[m_vCharset.size()].nPlainLenMin;
236 						tCharset.m_nPlainLenMax = vCharsets[m_vCharset.size()].nPlainLenMax;
237 						m_vCharset.push_back(tCharset);
238 						if(vCharsets.size() == m_vCharset.size())
239 							return true;
240 						//i = 0; // Start the lookup over again for the next charset
241 						// Sc00bz indicates this fixes a bug of skipping line 1
242 						// of charset.txt
243 						i = -1; // Start the lookup over again for the next charset
244 					}
245 				}
246 				else if (sCharsetName == sName)
247 				{
248 					stCharset tCharset;
249 					tCharset.m_nPlainCharsetLen = sCharsetContent.size();
250 					memcpy(tCharset.m_PlainCharset, sCharsetContent.c_str(), tCharset.m_nPlainCharsetLen);
251 					tCharset.m_sPlainCharsetName = sCharsetName;
252 					tCharset.m_sPlainCharsetContent = sCharsetContent;
253 					m_vCharset.push_back(tCharset);
254 					return true;
255 				}
256 			}
257 		}
258 		printf("charset %s not found in charset.txt\n", sName.c_str());
259 	}
260 	else
261 		printf("can't open charset configuration file\n");
262 
263 	return false;
264 }
265 
266 //////////////////////////////////////////////////////////////////////
267 
SetHashRoutine(std::string sHashRoutineName)268 bool CChainWalkContext::SetHashRoutine( std::string sHashRoutineName )
269 {
270 	CHashRoutine hr;
271 	hr.GetHashRoutine(sHashRoutineName, m_pHashRoutine, m_nHashLen);
272 	if (m_pHashRoutine != NULL)
273 	{
274 		m_sHashRoutineName = sHashRoutineName;
275 		return true;
276 	}
277 	else
278 		return false;
279 }
280 
SetPlainCharset(std::string sCharsetName,int nPlainLenMin,int nPlainLenMax)281 bool CChainWalkContext::SetPlainCharset( std::string sCharsetName, int nPlainLenMin, int nPlainLenMax)
282 {
283 	// m_PlainCharset, m_nPlainCharsetLen, m_sPlainCharsetName, m_sPlainCharsetContent
284 	if (!LoadCharset(sCharsetName))
285 		return false;
286 
287 	if(m_nHybridCharset == 3) // hybrid3 is already loaded into m_ks
288 	{
289 		m_nPlainSpaceTotal = m_ks->getKeySpace();
290 		return true;
291 	}
292 	if(m_nHybridCharset == 0) // Not hybrid charset
293 	{
294 		// m_nPlainLenMin, m_nPlainLenMax
295 		if (nPlainLenMin < 1 || nPlainLenMax > MAX_PLAIN_LEN || nPlainLenMin > nPlainLenMax)
296 		{
297 			printf("invalid plaintext length range: %d - %d\n", nPlainLenMin, nPlainLenMax);
298 			return false;
299 		}
300 		m_vCharset[0].m_nPlainLenMin = nPlainLenMin;
301 		m_vCharset[0].m_nPlainLenMax = nPlainLenMax;
302 	}
303 	// m_nPlainSpaceUpToX
304 	m_nPlainSpaceUpToX[0] = 0;
305 	m_nPlainLenMaxTotal = 0;
306 	m_nPlainLenMinTotal = 0;
307 	m_nPlainSpaceTotal = 0;
308 	uint64_t nTemp = 1;
309 	uint32_t j, k = 1;
310 	int i = 1;
311 	for(j = 0; j < m_vCharset.size(); j++)
312 	{
313 		m_nPlainLenMaxTotal += m_vCharset[j].m_nPlainLenMax;
314 		m_nPlainLenMinTotal += m_vCharset[j].m_nPlainLenMin;
315 		m_vCharset[j].m_nPlainSpaceUpToX[0] = 0;
316 		uint64_t nTemp2 = 1;
317 
318 		for (i = 1; i <= m_vCharset[j].m_nPlainLenMax; i++)
319 		{
320 			nTemp *= m_vCharset[j].m_nPlainCharsetLen;
321 			nTemp2 *= m_vCharset[j].m_nPlainCharsetLen;
322 
323 			if (i < m_vCharset[j].m_nPlainLenMin)
324 			{
325 				m_nPlainSpaceUpToX[k] = 0;
326 				m_vCharset[j].m_nPlainSpaceUpToX[i] = 0;
327 			}
328 			else
329 			{
330 				// special case of the last keyspace in a hybrid2 set
331 				if ( i == 1 && j > 1 && m_vCharset[j].m_nPlainCharsetLen != 1
332 					&& j == m_vCharset.size() - 1 )
333 				{
334 					m_nPlainSpaceUpToX[k] = nTemp;
335 				}
336 				else
337 				{
338 					m_nPlainSpaceUpToX[k] = m_nPlainSpaceUpToX[k - 1] + nTemp;
339 				}
340 
341 				m_vCharset[j].m_nPlainSpaceUpToX[i] = m_vCharset[j].m_nPlainSpaceUpToX[i - 1] + nTemp2;
342 			}
343 
344 			k++;
345 		}
346 
347 		m_vCharset[j].m_nPlainSpaceTotal = m_vCharset[j].m_nPlainSpaceUpToX[i-1];
348 
349 		if ( m_nPlainSpaceTotal == 0 )
350 			m_nPlainSpaceTotal = m_vCharset[j].m_nPlainSpaceTotal;
351 		else
352 			m_nPlainSpaceTotal *= m_vCharset[j].m_nPlainSpaceTotal;
353 	}
354 
355 	return true;
356 }
357 
SetRainbowTableIndex(int nRainbowTableIndex)358 bool CChainWalkContext::SetRainbowTableIndex(int nRainbowTableIndex)
359 {
360 	if (nRainbowTableIndex < 0)
361 		return false;
362 	m_nRainbowTableIndex = nRainbowTableIndex;
363 	m_nReduceOffset = 65536 * nRainbowTableIndex;
364 
365 	return true;
366 }
367 
SetSalt(unsigned char * Salt,int nSaltLength)368 bool CChainWalkContext::SetSalt(unsigned char *Salt, int nSaltLength)
369 {
370 	memcpy(&m_Salt[0], Salt, nSaltLength);
371 
372 	m_nSaltLen = nSaltLength;
373 //	m_sSalt = sSalt;
374 	return true;
375 }
376 
SetupWithPathName(std::string sPathName,int & nRainbowChainLen,int & nRainbowChainCount)377 bool CChainWalkContext::SetupWithPathName( std::string sPathName, int& nRainbowChainLen, int& nRainbowChainCount)
378 {
379 	// something like lm_alpha#1-7_0_100x16_test.rt
380 
381 #ifdef _WIN32
382 	std::string::size_type nIndex = sPathName.find_last_of('\\');
383 #else
384 	std::string::size_type nIndex = sPathName.find_last_of('/');
385 #endif
386 	if (nIndex != std::string::npos)
387 		sPathName = sPathName.substr(nIndex + 1);
388 
389 	if (sPathName.size() < 3)
390 	{
391 		printf("%s is not a rainbow table\n", sPathName.c_str());
392 		return false;
393 	}
394 	if (sPathName.substr(sPathName.size() - 5) == ".rti2")
395 	{
396 		RTfileFormatId = getRTfileFormatId( "RTI2" );
397 	}
398 	else if (sPathName.substr(sPathName.size() - 4) == ".rti")
399 	{
400 		RTfileFormatId = getRTfileFormatId( "RTI" );
401 	}
402 	else if (sPathName.substr(sPathName.size() - 3) == ".rt")
403 	{
404 		RTfileFormatId = getRTfileFormatId( "RT" );
405 	}
406 	else
407 	{
408 		printf("%s is not a rainbow table\n", sPathName.c_str());
409 		return false;
410 	}
411 
412 	// Parse
413 	std::vector<std::string> vPart;
414 	if (!SeperateString(sPathName, "___x_", vPart))
415 	{
416 		printf("filename %s not identified\n", sPathName.c_str());
417 		return false;
418 	}
419 
420 	std::string sHashRoutineName   = vPart[0];
421 	int nRainbowTableIndex    = atoi(vPart[2].c_str());
422 	nRainbowChainLen          = atoi(vPart[3].c_str());
423 	nRainbowChainCount        = atoi(vPart[4].c_str());
424 
425 	// Parse charset definition
426 	std::string sCharsetDefinition = vPart[1];
427 	std::string sCharsetName;
428 	int nPlainLenMin = 0, nPlainLenMax = 0;
429 
430 //	printf("Charset: %s", sCharsetDefinition.c_str());
431 
432 	if(sCharsetDefinition.substr(0, 6) == "hybrid") // Hybrid table
433 	{
434 		sCharsetName = sCharsetDefinition;
435 	}
436 	else
437 	{
438 		if ( sCharsetDefinition.find('#') == std::string::npos )		// For backward compatibility, "#1-7" is implied
439 		{
440 			sCharsetName = sCharsetDefinition;
441 			nPlainLenMin = 1;
442 			nPlainLenMax = 7;
443 		}
444 		else
445 		{
446 			std::vector<std::string> vCharsetDefinitionPart;
447 			if (!SeperateString(sCharsetDefinition, "#-", vCharsetDefinitionPart))
448 			{
449 				printf("filename %s not identified\n", sPathName.c_str());
450 				return false;
451 			}
452 			else
453 			{
454 				sCharsetName = vCharsetDefinitionPart[0];
455 				nPlainLenMin = atoi(vCharsetDefinitionPart[1].c_str());
456 				nPlainLenMax = atoi(vCharsetDefinitionPart[2].c_str());
457 			}
458 		}
459 	}
460 	// Setup
461 	if (!SetHashRoutine(sHashRoutineName))
462 	{
463 		printf("hash routine %s not supported\n", sHashRoutineName.c_str());
464 		return false;
465 	}
466 	if (!SetPlainCharset(sCharsetName, nPlainLenMin, nPlainLenMax))
467 		return false;
468 	if (!SetRainbowTableIndex(nRainbowTableIndex))
469 	{
470 		printf("invalid rainbow table index %d\n", nRainbowTableIndex);
471 		return false;
472 	}
473 
474 	return true;
475 }
476 
GetHashRoutineName()477 std::string CChainWalkContext::GetHashRoutineName()
478 {
479 	return m_sHashRoutineName;
480 }
481 
GetHashLen()482 int CChainWalkContext::GetHashLen()
483 {
484 	return m_nHashLen;
485 }
486 
GetPlainCharsetName()487 std::string CChainWalkContext::GetPlainCharsetName()
488 {
489 	/*
490 	 * XXX dumb hack to return the hybrid character set name
491 	 * in rcracki_mt the call to CChainWalkContext::SetupWithPathname is static
492 	 * can't modify a static std::string there
493 	 */
494 	if ( m_nHybridCharset != 0 )
495 	{
496 		std::string characterSet = "hybrid";
497 
498 		if ( m_nHybridCharset == 3 )
499 		{
500 			characterSet += "3(";
501 			characterSet += m_ks->getName();
502 		}
503 		else
504 		{
505 			if ( m_nHybridCharset == 2 )
506 				characterSet += "2";
507 
508 			characterSet += "(";
509 
510 			for ( unsigned int i = 0; i < m_vCharset.size(); i++ )
511 			{
512 				char tempCharsetMerge[255];
513 				sprintf( tempCharsetMerge, "%s#%d-%d,"
514 					, m_vCharset[i].m_sPlainCharsetName.c_str()
515 					, m_vCharset[i].m_nPlainLenMin, m_vCharset[i].m_nPlainLenMax );
516 
517 				characterSet += tempCharsetMerge;
518 			}
519 
520 			// removing trailing ,
521 			characterSet = characterSet.substr( 0, characterSet.length() - 1 );
522 		}
523 		characterSet += ")";
524 
525 		return characterSet;
526 	}
527 
528 	return m_vCharset[0].m_sPlainCharsetName;
529 }
530 
GetPlainCharsetContent()531 std::string CChainWalkContext::GetPlainCharsetContent()
532 {
533 	return m_vCharset[0].m_sPlainCharsetContent;
534 }
535 
GetPlainLenMin()536 int CChainWalkContext::GetPlainLenMin()
537 {
538 	if ( m_nHybridCharset != 0 )
539 		return 0;
540 
541 	return m_vCharset[0].m_nPlainLenMin;
542 }
543 
GetPlainLenMax()544 int CChainWalkContext::GetPlainLenMax()
545 {
546 	if ( m_nHybridCharset != 0 )
547 		return 0;
548 
549 	return m_vCharset[0].m_nPlainLenMax;
550 }
551 
GetPlainSpaceTotal()552 uint64_t CChainWalkContext::GetPlainSpaceTotal()
553 {
554 	return m_nPlainSpaceTotal;
555 }
556 
GetRainbowTableIndex()557 int CChainWalkContext::GetRainbowTableIndex()
558 {
559 	return m_nRainbowTableIndex;
560 }
561 
Dump()562 void CChainWalkContext::Dump()
563 {
564 	printf("hash routine: %s\n", m_sHashRoutineName.c_str());
565 	printf("hash length: %d\n", m_nHashLen);
566 
567 	for ( uint32_t i = 0; i < m_vCharset.size(); i++ )
568 	{
569 		printf( "m_vCharset[%d].m_nPlainCharSetLen: %d\n", i, m_vCharset[i].m_nPlainCharsetLen );
570 
571 		printf("plain charset: ");
572 
573 		for ( uint32_t j = 0; j < m_vCharset[i].m_nPlainCharsetLen; j++ )
574 		{
575 			if (isprint(m_vCharset[i].m_PlainCharset[j]))
576 				printf("%c", m_vCharset[i].m_PlainCharset[j]);
577 			else
578 				printf("?");
579 		}
580 		printf("\n");
581 
582 		for ( int j = 0; j <= m_vCharset[i].m_nPlainLenMax; j++ )
583 		{
584 			printf( "m_vCharset[%d].m_nPlainSpaceUpToX[%d]: %"PRIu64"\n"
585 				, i, j, m_vCharset[i].m_nPlainSpaceUpToX[j] );
586 		}
587 
588 		printf("plain charset in hex: ");
589 
590 		for ( uint32_t j = 0; j < m_vCharset[i].m_nPlainCharsetLen; j++ )
591 			printf("%02x ", m_vCharset[i].m_PlainCharset[j]);
592 		printf("\n");
593 
594 		printf("plain length range: %d - %d\n", m_vCharset[i].m_nPlainLenMin, m_vCharset[i].m_nPlainLenMax);
595 		printf("plain charset name: %s\n", m_vCharset[i].m_sPlainCharsetName.c_str());
596 		printf("plain subkey space total: %s\n", uint64tostr(m_vCharset[i].m_nPlainSpaceTotal).c_str());
597 	}
598 
599 	for ( int i = 0; i <= m_nPlainLenMaxTotal; i++ )
600 	{
601 		printf( "m_nPlainSpaceUpToX[%d]: %"PRIu64"\n"
602 			, i, m_nPlainSpaceUpToX[i] );
603 	}
604 
605 	//printf("plain charset content: %s\n", m_sPlainCharsetContent.c_str());
606 	//for (i = 0; i <= m_nPlainLenMax; i++)
607 	//	printf("plain space up to %d: %s\n", i, uint64tostr(m_nPlainSpaceUpToX[i]).c_str());
608 	printf("plain space total: %s\n", uint64tostr(m_nPlainSpaceTotal).c_str());
609 
610 	printf("rainbow table index: %d\n", m_nRainbowTableIndex);
611 	printf("reduce offset: %s\n", uint64tostr(m_nReduceOffset).c_str());
612 	printf("\n");
613 }
614 
SetIndex(uint64_t nIndex)615 void CChainWalkContext::SetIndex(uint64_t nIndex)
616 {
617 	m_nIndex = nIndex;
618 }
619 
SetHash(unsigned char * pHash)620 void CChainWalkContext::SetHash(unsigned char* pHash)
621 {
622 	memcpy(m_Hash, pHash, m_nHashLen);
623 }
624 
normalIndexToPlain(uint64_t index,uint64_t * plainSpaceUpToX,unsigned char * charSet,int charSetLen,int min,int max,unsigned char * plain)625 int CChainWalkContext::normalIndexToPlain(uint64_t index, uint64_t *plainSpaceUpToX, unsigned char *charSet, int charSetLen, int min, int max, unsigned char *plain)
626 {
627 	int a;
628 
629 	for ( a = max - 1; a >= min; a-- )
630 	{
631 		if ( index >= plainSpaceUpToX[a])
632 			break;
633 	}
634 
635 	uint32_t plainLen = a + 1;
636 
637 	index -= plainSpaceUpToX[a]; // plainLen - 1 == a
638 
639 	for ( a = plainLen - 1; a >= 0; a-- )
640 	{
641 		// XXX this is optimized for 32-bit platforms
642 #if defined(_WIN32) && !defined(__GNUC__)
643 		if (index < 0x100000000I64)
644 			break;
645 #else
646 		if (index < 0x100000000llu)
647 			break;
648 #endif
649 		plain[a] = charSet[index % charSetLen];
650 		index /= charSetLen;
651 	}
652 
653 	unsigned int index32 = (unsigned int) index;
654 	for ( ; a >= 0; a-- )
655 	{
656 		// remarks from Sc00bz
657 		// Note the lack of assembly code.
658 		// Assembly code is not needed since all the variables are in the stack.
659 		// If you add in assembly code it will be slower than the compiler's code.
660 
661 		plain[a] = charSet[index32 % charSetLen];
662 		index32 /= charSetLen;
663 	}
664 
665 	return plainLen;
666 }
667 
IndexToPlain()668 void CChainWalkContext::IndexToPlain()
669 {
670 	if (m_nHybridCharset == 3)
671 	{
672 		m_nPlainLen = m_ks->get((char*) m_Plain, m_nIndex);
673 	}
674 	else
675 	{
676 		m_nPlainLen = 0;
677 		uint64_t indexTmp = m_nIndex;
678 
679 		uint32_t numKeySpaces = m_vCharset.size();
680 
681 		for ( uint32_t a = 0; a < numKeySpaces - 1; a++ )
682 		{
683 			m_vCharset[a].m_nIndexX = indexTmp % m_vCharset[a].m_nPlainSpaceTotal;
684 			indexTmp /= m_vCharset[a].m_nPlainSpaceTotal;
685 			m_nPlainLen += normalIndexToPlain(m_vCharset[a].m_nIndexX, m_vCharset[a].m_nPlainSpaceUpToX, m_vCharset[a].m_PlainCharset, m_vCharset[a].m_nPlainCharsetLen, m_vCharset[a].m_nPlainLenMin, m_vCharset[a].m_nPlainLenMax, m_Plain + m_nPlainLen);
686 		}
687 
688 		m_vCharset[numKeySpaces-1].m_nIndexX = indexTmp;
689 		m_nPlainLen += normalIndexToPlain(m_vCharset[numKeySpaces-1].m_nIndexX, m_vCharset[numKeySpaces-1].m_nPlainSpaceUpToX, m_vCharset[numKeySpaces-1].m_PlainCharset, m_vCharset[numKeySpaces-1].m_nPlainCharsetLen, m_vCharset[numKeySpaces-1].m_nPlainLenMin, m_vCharset[numKeySpaces-1].m_nPlainLenMax, m_Plain + m_nPlainLen);
690 	}
691 }
692 
693 
694 /*
695 void CChainWalkContext::IndexToPlain()
696 {
697 	int i;
698 	m_nPlainLen = 0;
699 	for (i = m_nPlainLenMaxTotal - 1; i >= m_nPlainLenMinTotal - 1; i--)
700 	{
701 		if (m_nIndex >= m_nPlainSpaceUpToX[i])
702 		{
703 			m_nPlainLen = i + 1;
704 			break;
705 		}
706 	}
707 	if(m_nPlainLen == 0)
708 		m_nPlainLen = m_nPlainLenMinTotal;
709 	uint64_t nIndexOfX = m_nIndex - m_nPlainSpaceUpToX[m_nPlainLen - 1];
710 
711 // this is the generic code for non x86/x86_64 platforms
712 #if !defined(_M_X64) && !defined(_M_IX86) && !defined(__i386__) && !defined(__x86_64__)
713 
714 	// generic version (slow for non 64-bit platforms and gcc < 4.5.x)
715 	for (i = m_nPlainLen - 1; i >= 0; i--)
716 	{
717 		int nCharsetLen = 0;
718 		for(uint32_t j = 0; j < m_vCharset.size(); j++)
719 		{
720 			nCharsetLen += m_vCharset[j].m_nPlainLenMax;
721 			if(i < nCharsetLen) // We found the correct charset
722 			{
723 				m_Plain[i] = m_vCharset[j].m_PlainCharset[nIndexOfX % m_vCharset[j].m_nPlainCharsetLen];
724 				nIndexOfX /= m_vCharset[j].m_nPlainCharsetLen;
725 				break;
726 			}
727 		}
728 	}
729 
730 #elif defined(_M_X64) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)
731 
732 	// Fast ia32 version
733 	for (i = m_nPlainLen - 1; i >= 0; i--)
734 	{
735 		// 0x100000000 = 2^32
736 #ifdef _M_IX86
737 		if (nIndexOfX < 0x100000000I64)
738 			break;
739 #else
740 		if (nIndexOfX < 0x100000000llu)
741 			break;
742 #endif
743 
744 		int nCharsetLen = 0;
745 		for(uint32_t j = 0; j < m_vCharset.size(); j++)
746 		{
747 			nCharsetLen += m_vCharset[j].m_nPlainLenMax;
748 			if(i < nCharsetLen) // We found the correct charset
749 			{
750 				m_Plain[i] = m_vCharset[j].m_PlainCharset[nIndexOfX % m_vCharset[j].m_nPlainCharsetLen];
751 				nIndexOfX /= m_vCharset[j].m_nPlainCharsetLen;
752 				break;
753 			}
754 		}
755 	}
756 
757 	uint32_t nIndexOfX32 = (uint32_t)nIndexOfX;
758 	for (; i >= 0; i--)
759 	{
760 		int nCharsetLen = 0;
761 		for(uint32_t j = 0; j < m_vCharset.size(); j++)
762 		{
763 			nCharsetLen += m_vCharset[j].m_nPlainLenMax;
764 			if(i < nCharsetLen) // We found the correct charset
765 			{
766 
767 				m_Plain[i] = m_vCharset[j].m_PlainCharset[nIndexOfX % m_vCharset[j].m_nPlainCharsetLen];
768 				nIndexOfX /= m_vCharset[j].m_nPlainCharsetLen;
769 				break;
770 			}
771 		}
772 	}
773 
774 	uint32_t nIndexOfX32 = (uint32_t)nIndexOfX;
775 	for (; i >= 0; i--)
776 	{
777 		int nCharsetLen = 0;
778 		for(uint32_t j = 0; j < m_vCharset.size(); j++)
779 		{
780 			nCharsetLen += m_vCharset[j].m_nPlainLenMax;
781 			if(i < nCharsetLen) // We found the correct charset
782 			{
783 
784 //		m_Plain[i] = m_vCharset[j].m_PlainCharset[nIndexOfX32 % m_vCharset[j].m_nPlainCharsetLen];
785 //		nIndexOfX32 /= m_vCharset[j].m_nPlainCharsetLen;
786 
787 //	moving nPlainCharsetLen into the asm body and avoiding the extra temp
788 //	variable results in a performance gain
789 //				unsigned int nPlainCharsetLen = m_vCharset[j].m_nPlainCharsetLen;
790 				unsigned int nTemp;
791 
792 #if defined(_WIN32) && !defined(__GNUC__)
793 		// VC++ still needs this
794 		unsigned int nPlainCharsetLen = m_vCharset[j].m_nPlainCharsetLen;
795 
796 		__asm
797 		{
798 			mov eax, nIndexOfX32
799 			xor edx, edx
800 			div nPlainCharsetLen
801 			mov nIndexOfX32, eax
802 			mov nTemp, edx
803 		}
804 		m_Plain[i] = m_vCharset[j].m_PlainCharset[nTemp];
805 #else
806 		__asm__ __volatile__ ("xor %%edx, %%edx;"
807 								"divl %3;"
808 								: "=a"(nIndexOfX32), "=d"(nTemp)
809 								: "a"(nIndexOfX32), "rm"(m_vCharset[j].m_nPlainCharsetLen)
810 								: );
811 		m_Plain[i] = m_vCharset[j].m_PlainCharset[nTemp];
812 #endif
813 		break;
814 			}
815 		}
816 	}
817 #endif
818 }
819 */
820 
PlainToHash()821 void CChainWalkContext::PlainToHash()
822 {
823 	m_pHashRoutine(m_Plain, m_nPlainLen, m_Hash);
824 }
825 
HashToIndex(int nPos)826 void CChainWalkContext::HashToIndex(int nPos)
827 {
828 	// breaks strict aliasing
829 	//m_nIndex = (*(uint64_t*)m_Hash + m_nReduceOffset + nPos) % m_nPlainSpaceTotal;
830 
831 	memcpy( m_Hash_alias.m_Hash, m_Hash, 8 );
832 
833 	m_nIndex = (m_Hash_alias.alias + m_nReduceOffset + nPos) % m_nPlainSpaceTotal;
834 }
835 
GetIndex()836 uint64_t CChainWalkContext::GetIndex()
837 {
838 	return m_nIndex;
839 }
GetIndexPtr()840 const uint64_t *CChainWalkContext::GetIndexPtr()
841 {
842 	return &m_nIndex;
843 }
844 
GetPlain()845 std::string CChainWalkContext::GetPlain()
846 {
847 	std::string sRet;
848 	int i;
849 	for (i = 0; i < m_nPlainLen; i++)
850 	{
851 		char c = m_Plain[i];
852 		if (c >= 32 && c <= 126)
853 			sRet += c;
854 		else
855 			sRet += '?';
856 	}
857 
858 	return sRet;
859 }
860 
GetBinary()861 std::string CChainWalkContext::GetBinary()
862 {
863 	return HexToStr(m_Plain, m_nPlainLen);
864 }
865 
GetHash()866 std::string CChainWalkContext::GetHash()
867 {
868 	return HexToStr(m_Hash, m_nHashLen);
869 }
870 
CheckHash(unsigned char * pHash)871 bool CChainWalkContext::CheckHash(unsigned char* pHash)
872 {
873 	if (memcmp(m_Hash, pHash, m_nHashLen) == 0)
874 		return true;
875 
876 	return false;
877 }
878 
getRTfileFormat()879 uint8_t CChainWalkContext::getRTfileFormat()
880 {
881 	return RTfileFormatId;
882 }
883