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