diff -rpN -C 2 memdbg2/doc/OPTIONS memdbg1/doc/OPTIONS *** memdbg2/doc/OPTIONS 2013-05-17 12:11:35.033147800 -0500 --- memdbg1/doc/OPTIONS 2013-05-17 11:26:38.526954400 -0500 *************** The different variants of list externals *** 333,366 **** overridden. ! --regen-lost-salts=N Try to find password AND salt in a set of raw hashes. ! ! This option will allow certain types (with short salts), to be found, when ! they are present in a set of raw hashes, but where we have lost the salt value. ! Normally, without the salt, JtR would not be able to do anything with the hash, ! and could not find the password. In this mode, JtR will load the hashes, giving ! each a 'fake' salt (but all get the same salt). JtR then builds all of the ! possible salt values for this format, and associates every hash with each one ! of these salts. So, JtR will now run, and find passwords using all possible ! salts for each of the hashes, thus recreating the salt (and finding the passwords). ! There are only a few types supported. To properly run, you MUST use one of the ! proper types in the -format=type command, AND use the -regen-lost-salts=N with ! N being set properly. The valid N's are: ! --regen-lost-salts=1 --format=PHPS (form md5($p.$s) s is 3 bytes) ! --regen-lost-salts=2 --format=OSC (form md5($s.$p) s is 2 bytes) ! --regen-lost-salts=3 --format=mediawiki (user id's from 0 to 999) ! --regen-lost-salts=4 --format=mediawiki (user id's from 1000 to 9999) ! --regen-lost-salts=5 --format=mediawiki (user id's from 10000 to 99999) ! For types 3, 4, 5, we only look for numeric user id's, of the type: ! md5($u.'-'.md5($p)) Mediawiki made some changes to use longer 8 byte hex strings ! as salts. This salt is too long to try to find, so JtR only focuses on the older ! type $B$ with the shorter numeric user id's. The found lines in john.pot will ! be output as type $dynamic_2$ for the found PHPS (with the salts filled in). It ! will be $dynamic_4$ for the OSC (with salt), and $dynamic_9$ (with user id as ! salt), for the mediawiki items. ! NOTE, normally the salt is preserved with the hash, and thus JtR can properly ! find them using 'normal' methods. This new functionality was added to handle ! leaked hashes where the original salt has been lost. It is VERY slow to run ! in this manner, due to JtR having to check every possible salt, but it does ! allow these hashes to be cracked 'properly'. Additional utilities (compiled/installed along with John). --- 333,341 ---- overridden. ! --regen-lost-salts=type:hash_sz:mask ! Finds passwords AND salts in a set of raw hashes. ! This function has been changed, and now is 'generic'. ! See the file Regen-Lost-Salts.txt for information. ! Additional utilities (compiled/installed along with John). diff -rpN -C 2 memdbg2/doc/Regen-Lost-Salts.txt memdbg1/doc/Regen-Lost-Salts.txt *** memdbg2/doc/Regen-Lost-Salts.txt 1969-12-31 18:00:00.000000000 -0600 --- memdbg1/doc/Regen-Lost-Salts.txt 2013-05-17 12:10:19.553554900 -0500 *************** *** 0 **** --- 1,143 ---- + *************************************************************************** + * JtR --regen-lost-salts code, written by JimF, 2012 and 2013, for use + * within the salted dynamic formats. + * + * No copyright is claimed, and the software is hereby + * placed in the public domain. In case this attempt to disclaim + * copyright and place the software in the public domain is deemed + * null and void, then the software is Copyright (c) 2012-2013 JimF + * and it is hereby released to the general public under the following + * terms: + * + * This software may be modified, redistributed, and used for any + * purpose, in source and binary forms, with or without modification. + *************************************************************************** + + + --regen-lost-salts=type:hash_sz:mask + + This option will allow certain types (with short salts), to be found, when + they are present in a set of raw hashes, but where we have lost the salt value. + Normally, without the salt, JtR would not be able to do anything with the hash, + and could not find the password. In this mode, JtR will load the hashes, giving + each a 'fake' salt (but all get the same salt). JtR then builds all of the + possible salt values for this format, and associates every hash with each one + of these salts. So, JtR will now run, and find passwords using all possible + salts for each of the hashes, thus recreating the salt (and finding the passwords). + + This function has recently been re-written. The prior way of usage is still supported + (limited), and should be considered depricated. See the end of this document for + the *** NOTE section. + + Usage: + + --regen-lost-salts=dynamic_9:32:?d?d?d- --format=dynamic_9 + + The above command will run on a set of 32 byte 'raw' hashes, but which are known + to contain media-wiki hashes. Media-wiki is of the format md5(salt.-.md5(pass)) + the salt is a decimal number (it actually was the user id of the wiki user). There + is a dash separating the salt and the md5(pass) part. What this regen-lost-salts + line does, is checks all 3 digit salts (appending the '-' char also), and uses + the dynamic format 9 (which is md5($s.md5($p)) that is 'almost' correct. By our + adding the '-' character to the salt as a constant, dynamic_9 works just fine. + + So that 'parts' of the --regen-lost-salts are: + type - this will be some dynamic type. dynamic_4, dynamic_9, dynamic_1234 are + all the valid types. + hash_sz - this is the hex length of the data. It MUST match the proper input + size for the format AND must match the data being processed (hashes + where the salts were lost). If the data is only 32 bytes long, but + the hashes were from sha256($s.$p), then a proper dynamic script would + have to be created, that only used 32 bytes of input. There are examples + of this in dynamic.conf at the present time. + mask - this is a mask of the salt. The user will have to know how the salts + were laid out for this format. The user will need to know if there are + any 'constant' values, know the range of possible bytes in other positions + and other things. NOTE, only shorter hashes will be able to be found, + and ones where smaller ranges of values. JtR, when run in this mode, + will load all hashes, and create ALL possible salts and link up every + single input candidate to ALL possible hashes. So if there are 6 byte + salts, and these are all decimal digits, then there will be 10^6 salt + records created (1 million, each taking 12+ bytes of memory, plus other + memory overhead). If this was a 6 digit salt, that used 95 possible + characters each, then it would require 95^6 salt records, which is + 735 BILLION salts, or almost 9 TRILLION bytes of memory. The regen + salt code will NOT work for salts this large. + + Here are more details about the mask value: + - mask can contain static bytes. These will simply always be output. The example + above did this with the '-' character in the last spot. + - the mask can use different 'character class' bytes. These are similar to the + character types within JtR rules. To set a 'class' for a specific byte location, + simply use 2 characters, a question mark, and the class character. + Here are the classes. + ?? - becomes a single ? char (2 question marks mean a literal question mark) + ?d - decimal digits [0-9] ** very common salt ** + ?l - lower case letters [a-z] (only ANSI lower case, does not take encodings + into account) + ?u - upper case letters [A-Z] + ?a - upper / lower case letters [a-zA-Z] + ?h - hex lower case [0-9a-f] ** common salt ** + ?H - hex upper case [0-9A-F] + ?x - hex upper and lower case [0-9a-fA-F] + ?b - binary 0 or 1 (text 0x30 or 0x31) + ?o - octal [0-7] + ?n - upper / lower case letters and numbers [a-zA-Z0-9] + ?y - 95 byte ASCII [ -~] (from space to ~ chars). ** very common salt ** + ?# - # is a digit, from 0 to 9 This will load a 'user defined' character class + from the john.conf file. so ?0 will load the this user class: + [Regen_Salts_UserClasses] / 0= class + + With this information in hand, we can look back at that original example given: + + --regen-lost-salts=dynamic_9:32:?d?d?d- --format=dynamic_9 + + We can optimize this, with a little insite (speeding things up 10% in the process). + Knowing that mediawiki assigns the user account number as the salt, we know that we + will never have these salts 000- to 099- So we can redo this regen in this manner. + + in john.conf, add a 1= line to Regen_Salts_UserClasses like this: + + [Regen_Salts_UserClasses] + 1 = [1-9] + + now, use this command line for john: + + --regen-lost-salts=dynamic_9:32:?1?d?d- --format=dynamic_9 + + This will use the user class-1 for the first byte, then digits for the other 2. + This means our salt will start from 100- and go to 999- which skips 10% of the + salts, and speeds things up by 10%. This is due to the user-class-1 not having + the '0' byte in it. + + + At this time, only a fixed length salt is handled. Doing a variable sized salt + regen, simply adds too much complexity, and does slow things down, just a touch. + This is different than the older --regen-lost-salts=3 This 'used to do 0- to 9- + then 00- to 99- then 000- to 999- The 'depricated' --regen-lost-salts=3 now only + does 000- to 999- and would require running 2 more regen-salt runs to cover the + entire salt range. + + ****************************************************************************** + + *** NOTE, depricated method (still works, but should not be used) + There are only a few types supported. To properly run, you MUST use one of the + proper types in the -format=type command, AND use the -regen-lost-salts=N with + N being set properly. The valid N's are: + --regen-lost-salts=1 --format=PHPS (form md5($p.$s) s is 3 bytes) + --regen-lost-salts=2 --format=OSC (form md5($s.$p) s is 2 bytes) + --regen-lost-salts=3 --format=mediawiki (user id's from 0 to 999) + --regen-lost-salts=4 --format=mediawiki (user id's from 1000 to 9999) + --regen-lost-salts=5 --format=mediawiki (user id's from 10000 to 99999) + For types 3, 4, 5, we only look for numeric user id's, of the type: + md5($u.'-'.md5($p)) Mediawiki made some changes to use longer 8 byte hex strings + as salts. This salt is too long to try to find, so JtR only focuses on the older + type $B$ with the shorter numeric user id's. The found lines in john.pot will + be output as type $dynamic_2$ for the found PHPS (with the salts filled in). It + will be $dynamic_4$ for the OSC (with salt), and $dynamic_9$ (with user id as + salt), for the mediawiki items. + NOTE, normally the salt is preserved with the hash, and thus JtR can properly + find them using 'normal' methods. This new functionality was added to handle + leaked hashes where the original salt has been lost. It is VERY slow to run + in this manner, due to JtR having to check every possible salt, but it does + allow these hashes to be cracked 'properly'. diff -rpN -C 2 memdbg2/run/john.conf memdbg1/run/john.conf *** memdbg2/run/john.conf 2013-05-17 12:11:35.259193000 -0500 --- memdbg1/run/john.conf 2013-05-13 10:23:58.000000000 -0500 *************** MkvMaxLen = 12 *** 189,192 **** --- 189,199 ---- 2 = \x09 + # these are user defined character sets. There purpose is to allow custom salt + # values to be used within the salt_regen logic. These will be the characters + # to use for this character within the salt. So if we had a salt that was 4 + # characters, and 0-9a-m, we can easily do this by 0 = [0-9a-m] If this is used, + # the regen salt value would be ?0?0?0?0 and salts such as a47m 2kd5 would be valid. + [Regen_Salts_UserClasses] + 0 = [0-9a-m\x09] # A "no rules" rule for Single mode diff -rpN -C 2 memdbg2/src/cracker.c memdbg1/src/cracker.c *** memdbg2/src/cracker.c 2013-05-17 12:11:35.687278600 -0500 --- memdbg1/src/cracker.c 2013-05-17 12:11:35.000000000 -0500 *************** *** 28,31 **** --- 28,32 ---- #include "unicode.h" #include "john.h" + #include "fake_salts.h" #ifdef HAVE_MPI #include "john-mpi.h" *************** static void crk_remove_salt(struct db_sa *** 150,174 **** } - /* this utility function is used by cracker.c AND loader.c. Since media-wiki has a variable width salt, of which - in regen_lost_salts mode, we only handle 0 to 99999 as salts, we built a function that will assign the salt from - one buffer into another */ - void mediawiki_fix_salt(char *Buf, char *source_to_fix, char *salt_rec, int max_salt_len) { - char *cp = source_to_fix; - char *cp2 = salt_rec; - int i = 0; - - strncpy(Buf, cp, 11+32+1); - Buf += (11+32+1); - cp += (11+32+1); - cp2 += 6; - while (++i < max_salt_len && *cp2 != '-') { - *Buf++ = *cp2++; - ++cp; - } - ++cp; - *Buf++ = *cp2++; - *Buf = 0; - } - /* * Updates the database after a password has been cracked. --- 151,154 ---- *************** static int crk_process_guess(struct db_s *** 271,306 **** // Ok, FIX the salt ONLY if -regen-lost-salts=X was used. ! if (options.regen_lost_salts) { ! if (options.regen_lost_salts == 1) ! { ! // 3 byte PHPS salt, the hash is in $dynamic_6$ format. ! char *cp = pw->source; ! char *cp2 = *(char**)(salt->salt); ! memcpy(cp+11+32+1, cp2+6, 3); ! } ! else if (options.regen_lost_salts == 2) ! { ! // 2 byte osCommerce salt, the hash is in $dynamic_4$ format. ! char *cp = pw->source; ! char *cp2 = *(char**)(salt->salt); ! memcpy(cp+11+32+1, cp2+6, 2); ! } ! else if (options.regen_lost_salts >= 3 && options.regen_lost_salts <= 5) ! { ! // Media wiki. Salt len is not known, but 5 bytes or less, and WILL fit into pw-source even after being fixed.. $dynamic_9$ format. ! char Buf[256]; ! char *cp2 = *(char**)(salt->salt); ! extern void mediawiki_fix_salt(char *Buf, char *source_to_fix, char *salt_rec, int max_salt_len); ! mediawiki_fix_salt(Buf, pw->source, cp2, options.regen_lost_salts+1); ! strcpy(pw->source, Buf); ! } ! else if (options.regen_lost_salts == 6) ! { ! // formspring sha256($s.$p), $dynamic_61$, where $s is ?d?d (2 digits). ! char *cp = pw->source; ! char *cp2 = *(char**)(salt->salt); ! memcpy(cp+12+64+1, cp2+6, 2); ! } ! } log_guess(crk_db->options->flags & DB_LOGIN ? replogin : "?", dupe ? NULL : crk_methods.source(pw->source, pw->binary), repkey, key, crk_db->options->field_sep_char); --- 251,257 ---- // Ok, FIX the salt ONLY if -regen-lost-salts=X was used. ! if (options.regen_lost_salts) ! crk_guess_fixup_salt(pw->source, *(char**)(salt->salt)); ! log_guess(crk_db->options->flags & DB_LOGIN ? replogin : "?", dupe ? NULL : crk_methods.source(pw->source, pw->binary), repkey, key, crk_db->options->field_sep_char); diff -rpN -C 2 memdbg2/src/dynamic_fmt.c memdbg1/src/dynamic_fmt.c *** memdbg2/src/dynamic_fmt.c 2013-05-17 12:11:35.837808700 -0500 --- memdbg1/src/dynamic_fmt.c 2013-05-17 12:11:35.000000000 -0500 *************** static DYNAMIC_primitive_funcp _Funcs_1[ *** 53,61 **** * the same for whirlpool. This does not give much room for growth. But these buffers * should not be made to be 'too' much larger than needed. This is an issue that needs ! * to be looked into. * ! * 3. sha512(sha512($p).sha512($p) does tripple crypts when it should only do 2 of them. ! * need to create an append_input2_input2 and use it, I think. * */ --- 53,83 ---- * the same for whirlpool. This does not give much room for growth. But these buffers * should not be made to be 'too' much larger than needed. This is an issue that needs ! * to be looked into. NOTE, we might want to go to 3 input buffers. That way, we ! * could make input buffer 1 be 128 bytes, input buffer2 256 and input buffer3 be ! * 512. This would allow us to use a smaller buffer (buffer1), IF 128 bytes is ! * enough, and hopefully reduce working set. But then have a double length buffer ! * and a new quad length buffer IF we need them (for large hashes if there are multiple ! * appended hashes). This may add a BUNCH of extra functions. NOTE, I have seen slowdowns ! * in current setup (2 buffers), if buffersize is 260 bytes, vs 256 bytes. I am sure this ! * is due to page swapping, since this crosses 2 256 byte blocks. * ! * 3. Add SHA2 intrinsic code. Also, make a 'plan' on how to do SSE code for the other ! * large hash types (and get SHA1 working 'better'). NOTE there are OMP implications ! * which make this harder. Switching in/out of SSE buffers is very expensive. * + * 4. optimize the SHA1 vs MD5 (sse). Possibly keep SHA1 in SSE buffers, and have a + * a method to switch the buffer into LE md5/4 sse buffer space. Same may go for + * other BE 64 byte hashes. There will be no way to switch back and forth 'easily' + * between 128 byte hashes, into 64 byte, unless they contain 55 characters or + * less. Also, the length constrains on the 128 byte buffers is much less, for a + * single block crypt. 64 byte hashes, can do 55 passwords (8 needed for length + 1 for + * the 0x80). 128 byte hashes can do 111 byte passwords (16 needed for length + 1 + * for 0x80). But on large hashes, if we allow over 55 byte passwords, we lose ability + * to switch into 64 byte SSE hash space. NOTE that md4/md5 are the same. sha1, sha224 + * and sha256 are the same. The size of ALL of these are the same, but they differ in + * endianity. sha384, sha512 are the same, but they are 128 byte vs 64 byte per limb. + * + * 5. Change regen-salts to be generic. Add the logic to dynamic_fmt.c proper, and change + * the fake-salts.c, and options so that 'generic' regen-salts can be done. */ *************** static DYNAMIC_primitive_funcp _Funcs_1[ *** 85,88 **** --- 107,111 ---- #include "pkzip.h" #include "aligned.h" + #include "fake_salts.h" #ifdef _OPENMP *************** static char *prepare(char *split_fields[ *** 863,867 **** if (pFmt->params.salt_size && !strchr(split_fields[1], '$')) { ! if (!pPriv->nUserName && !pPriv->FldMask) return split_fields[1]; } --- 886,890 ---- if (pFmt->params.salt_size && !strchr(split_fields[1], '$')) { ! if (!pPriv->nUserName && !pPriv->FldMask && options.regen_lost_salts == 0) return split_fields[1]; } *************** static char *prepare(char *split_fields[ *** 887,892 **** // at this point max length is still < 512. 491 + strlen($dynamic_xxxxx$) is 506 ! if (strncmp(cpBuilding, "$dynamic_", 9)) return split_fields[1]; if ( (pPriv->pSetup->flags&MGF_SALTED) == 0) --- 910,922 ---- // at this point max length is still < 512. 491 + strlen($dynamic_xxxxx$) is 506 ! if (strncmp(cpBuilding, "$dynamic_", 9)) { ! // ok, here we add the 'generic' regen salt code ! if (options.regen_lost_salts && !strchr(cpBuilding, '$')) { ! char *cp = load_regen_lost_salt_Prepare(cpBuilding); ! if (cp) ! return cp; ! } return split_fields[1]; + } if ( (pPriv->pSetup->flags&MGF_SALTED) == 0) *************** static char *prepare(char *split_fields[ *** 961,964 **** --- 991,995 ---- } } + return cpBuilding; } diff -rpN -C 2 memdbg2/src/fake_salts.c memdbg1/src/fake_salts.c *** memdbg2/src/fake_salts.c 2013-05-17 12:11:35.869815100 -0500 --- memdbg1/src/fake_salts.c 2013-05-17 12:41:37.000000000 -0500 *************** *** 1,8 **** /* ! * This software was written by Jim Fougeron jfoug AT cox dot net ! * in 2012. No copyright is claimed, and the software is hereby * placed in the public domain. In case this attempt to disclaim * copyright and place the software in the public domain is deemed ! * null and void, then the software is Copyright (c) 2012 Jim Fougeron * and it is hereby released to the general public under the following * terms: --- 1,8 ---- /* ! * This software was written by JimF jfoug AT cox dot net ! * in 2012-2013. No copyright is claimed, and the software is hereby * placed in the public domain. In case this attempt to disclaim * copyright and place the software in the public domain is deemed ! * null and void, then the software is Copyright (c) 2012-2013 JimF * and it is hereby released to the general public under the following * terms: *************** *** 21,207 **** #include #include "memory.h" #include "options.h" void build_fake_salts_for_regen_lost(struct db_salt *salts) { ! if (options.regen_lost_salts == 1) // this is for PHPS, with a raw 32 byte hash input file (i.e. missing the salts) ! { ! struct db_salt *sp, *fake_salts; ! int i, j, k, idx=0; ! char *buf, *cp; ! unsigned long *ptr; ! ! fake_salts = mem_calloc_tiny(sizeof(struct db_salt) * (('~'-' '+1)*('~'-' '+1)*('~'-' '+1)+1), MEM_ALIGN_WORD); ! ! // Find the 'real' salt. We loaded ALL of the file into 1 salt. ! // we then take THAT salt record, and build a list pointing to these fake salts, ! // AND build 'proper' dynamic salts for all of our data. ! sp = salts; ! while (sp->next) { ! sp = sp->next; ! } ! // a dynamic salt is 030000[3-byte-salt] for ALL of the salts. ! buf = mem_alloc_tiny(('~'-' '+1)*('~'-' '+1)*('~'-' '+1)*9+1, MEM_ALIGN_NONE); ! cp = buf; ! for (i = ' '; i <= '~'; ++i) { ! for (j = ' '; j <= '~'; ++j) { ! for (k = ' '; k <= '~'; ++k) { ! sprintf(cp, "030000%c%c%c", i, j, k); ! sp->next = &fake_salts[idx]; ! fake_salts[idx].next = NULL; ! fake_salts[idx].count = sp->count; ! fake_salts[idx].hash = sp->hash; ! fake_salts[idx].hash_size = sp->hash_size; ! fake_salts[idx].index = sp->index; ! fake_salts[idx].keys = sp->keys; ! fake_salts[idx].list = sp->list; ! ptr=mem_alloc_tiny(sizeof(char*), MEM_ALIGN_WORD); ! *ptr = (unsigned long) (buf + (cp-buf)); ! fake_salts[idx].salt = ptr; ! ++idx; ! cp += 9; ! sp = sp->next; ! } ! } } } ! else if (options.regen_lost_salts == 2) // this is for osCommerce, with a raw 32 byte hash input file (i.e. missing the salts) ! { ! struct db_salt *sp, *fake_salts; ! int i, j, idx=0; ! char *buf, *cp; ! unsigned long *ptr; ! ! fake_salts = mem_calloc_tiny(sizeof(struct db_salt) * (('~'-' '+1)*('~'-' '+1)+1), MEM_ALIGN_WORD); ! ! // Find the 'real' salt. We loaded ALL of the file into 1 salt. ! // we then take THAT salt record, and build a list pointing to these fake salts, ! // AND build 'proper' dynamic salts for all of our data. ! sp = salts; ! while (sp->next) { ! sp = sp->next; ! } ! // a dynamic salt is 020000[2-byte-salt] for ALL of the salts. ! buf = mem_alloc_tiny(('~'-' '+1)*('~'-' '+1)*8+1, MEM_ALIGN_NONE); ! cp = buf; ! for (i = ' '; i <= '~'; ++i) { ! for (j = ' '; j <= '~'; ++j) { ! sprintf(cp, "020000%c%c", i, j); ! sp->next = &fake_salts[idx]; ! fake_salts[idx].next = NULL; ! fake_salts[idx].count = sp->count; ! fake_salts[idx].hash = sp->hash; ! fake_salts[idx].hash_size = sp->hash_size; ! fake_salts[idx].index = sp->index; ! fake_salts[idx].keys = sp->keys; ! fake_salts[idx].list = sp->list; ! ptr=mem_alloc_tiny(sizeof(char*), MEM_ALIGN_WORD); ! *ptr = (unsigned long) (buf + (cp-buf)); ! fake_salts[idx].salt = ptr; ! ++idx; ! cp += 8; ! sp = sp->next; ! } ! } } ! else if (options.regen_lost_salts >= 3 && options.regen_lost_salts <= 5) // this is for media-wiki, with a raw 32 byte hash input file (i.e. missing the salts) ! { ! // 3 gets salts from 0- to 999- 4 salts from 1000- to 9999- 5 salts from 10000- to 99999- ! struct db_salt *sp, *fake_salts; ! int i, idx=0; ! char *buf, *cp; ! unsigned long *ptr; ! int max, min; ! // Find the 'real' salt. We loaded ALL of the file into 1 salt. ! // we then take THAT salt record, and build a list pointing to these fake salts, ! // AND build 'proper' dynamic salts for all of our data. ! sp = salts; ! while (sp->next) { ! sp = sp->next; ! } ! max = 1000; ! min = 0; ! switch(options.regen_lost_salts) { ! case 4: ! max = 10000; ! min = 1000; ! break; ! case 5: ! max = 100000; ! min = 10000; ! break; ! } ! fake_salts = mem_calloc_tiny( ((max-min)+1) * sizeof(struct db_salt), MEM_ALIGN_WORD); ! // for type 3, we do not use 100% of this buffer, but we do use 'most' of it. ! buf = mem_alloc_tiny(((max-min)+1)*(7+options.regen_lost_salts), MEM_ALIGN_NONE); ! cp = buf; ! for (i = min; i < max; ++i) { ! int l; ! char *cp2 = cp; ! if (i > 9999) l = 6; ! else if (i > 999) l = 5; ! else if (i > 99) l = 4; ! else if (i > 9) l = 3; ! else l = 2; ! cp += sprintf(cp, "0%d0000%d-", l, i); ! sp->next = &fake_salts[idx]; ! fake_salts[idx].next = NULL; ! fake_salts[idx].count = sp->count; ! fake_salts[idx].hash = sp->hash; ! fake_salts[idx].hash_size = sp->hash_size; ! fake_salts[idx].index = sp->index; ! fake_salts[idx].keys = sp->keys; ! fake_salts[idx].list = sp->list; ! ptr=mem_alloc_tiny(sizeof(char*), MEM_ALIGN_WORD); ! *ptr = (unsigned long) (buf + (cp2-buf)); ! fake_salts[idx].salt = ptr; ! ++idx; ! sp = sp->next; ! } } - else if (options.regen_lost_salts == 6) // this is for osCommerce, with a raw 32 byte hash input file (i.e. missing the salts) - { - struct db_salt *sp, *fake_salts; - int i, j, idx=0; - char *buf, *cp; - unsigned long *ptr; - - fake_salts = mem_calloc_tiny(sizeof(struct db_salt) * (('9'-'0'+1)*('9'-'0'+1)+1), MEM_ALIGN_WORD); - - // Find the 'real' salt. We loaded ALL of the file into 1 salt. - // we then take THAT salt record, and build a list pointing to these fake salts, - // AND build 'proper' dynamic salts for all of our data. - sp = salts; - while (sp->next) { - sp = sp->next; - } ! // a dynamic salt is 020000[2-byte-salt] for ALL of the salts. ! buf = mem_alloc_tiny(('9'-'0'+1)*('9'-'0'+1)*8+1, MEM_ALIGN_NONE); ! cp = buf; ! for (i = '0'; i <= '9'; ++i) { ! for (j = '0'; j <= '9'; ++j) { ! sprintf(cp, "020000%c%c", i, j); ! sp->next = &fake_salts[idx]; ! fake_salts[idx].next = NULL; ! fake_salts[idx].count = sp->count; ! fake_salts[idx].hash = sp->hash; ! fake_salts[idx].hash_size = sp->hash_size; ! fake_salts[idx].index = sp->index; ! fake_salts[idx].keys = sp->keys; ! fake_salts[idx].list = sp->list; ! ptr=mem_alloc_tiny(sizeof(char*), MEM_ALIGN_WORD); ! *ptr = (unsigned long) (buf + (cp-buf)); ! fake_salts[idx].salt = ptr; ! ++idx; ! cp += 8; ! sp = sp->next; } } } } --- 21,316 ---- #include + #include "config.h" + #include "john.h" #include "memory.h" #include "options.h" + // global data (Options loading uses this variable). + char *regen_salts_options; + + static char *regen_schema, DynaType[24], FirstSalt[11]; + static int hash_len, DynaTypeLen; + static int salt_len, total_regen_salts_count; + static int loc_cnt[10] = {0}; /* how many chars are used for each location */ + static int cur_cnt[10] = {0}; /* this is a complex number, we use to permute all values. */ + static char *candi[10] = {0}; /* This is the valid chars, for each salt character position. */ + + static void bailout(const char *str) { + if (john_main_process) + fprintf(stderr, "%s\n", str); + error(); + } + + /* this has been made 'generic', and not built for a set of specific formats */ void build_fake_salts_for_regen_lost(struct db_salt *salts) { ! struct db_salt *sp, *fake_salts; ! int i; ! char dyna_salt_header[7], *buf, *cp; ! unsigned long *ptr; ! ! fake_salts = mem_calloc_tiny(sizeof(struct db_salt) * (total_regen_salts_count+1), MEM_ALIGN_WORD); ! ! // Find the 'real' salt. We loaded ALL of the file into 1 salt. ! // we then take THAT salt record, and build a list pointing to these fake salts, ! // AND build 'proper' dynamic salts for all of our data. ! sp = salts; ! while (sp->next) { ! sp = sp->next; ! } ! // a dynamic salt is 0x0000[salt_len-byte-salt] for ALL of the salts. ! buf = mem_alloc_tiny(total_regen_salts_count*(6+salt_len)+1, MEM_ALIGN_NONE); ! cp = buf; ! ! sprintf(dyna_salt_header, "%02d0000", salt_len); ! // we start from salt 1, (all hashes should already be salted to salt0) ! for (i = 1; i < total_regen_salts_count; ++i) { ! int j = 0; ! char *cp2 = cp; ! ! // Now compute next salt NOTE, we start from salt1 not salt0, so we first need ! // to increment out 'complex' number, prior to using it. ! cur_cnt[j=0]++; ! while (cur_cnt[j] >= loc_cnt[j]) { ! cur_cnt[j++] = 0; ! if (j==10) ! break; // done, but we should never get here (i should be == total_regen_salts_count before we hit this) ! ++cur_cnt[j]; } + + strcpy(cp2, dyna_salt_header); + cp2 += 6; + for (j = 0; j < salt_len; ++j) + *cp2++ = candi[j][cur_cnt[j]]; + // now link in this salt struct + sp->next = &fake_salts[i]; + fake_salts[i].next = NULL; + fake_salts[i].count = sp->count; + fake_salts[i].hash = sp->hash; + fake_salts[i].hash_size = sp->hash_size; + fake_salts[i].index = sp->index; + fake_salts[i].keys = sp->keys; + fake_salts[i].list = sp->list; + fake_salts[i].bitmap = sp->bitmap; // 'bug' fix when we went to bitmap. Old code was not copying this. + ptr=mem_alloc_tiny(sizeof(char*), MEM_ALIGN_WORD); + *ptr = (unsigned long) (buf + (cp-buf)); + fake_salts[i].salt = ptr; + cp = cp2; + sp = sp->next; } ! } ! /* this is called from dynamic prepare() function, whenever we have a 'raw' hash, and when we are in re-gen salts mode */ ! char *load_regen_lost_salt_Prepare(char *split_fields1) { ! char *cp = split_fields1, *Prep, *pPrep; ! int len; ! ! if (cp && *cp == '$' && !strncmp(cp, DynaType, DynaTypeLen)) ! cp += DynaTypeLen; ! if (!cp) ! return NULL; ! ! len = strlen(cp); ! if (len != hash_len) ! return NULL; ! ! Prep = mem_alloc_tiny(DynaTypeLen+hash_len+1+salt_len+1, MEM_ALIGN_NONE); ! pPrep = Prep; ! // add a the 'first' salt that is the proper. So, once loaded, there will ! // be only ONE salt, but ALL candidates will use this salt. We then load ! // all possible salt structures, and link all input candidates to ALL of them. ! pPrep += sprintf(Prep, "%s%s$%s", DynaType, cp, FirstSalt); ! ! return Prep; ! } ! ! /* this is called from cracker.c crk_process_guess() function, and here we FIX the crack with the */ ! /* proper found salt. When the data was loaded, it was assigned the 'first' salt, but likely we */ ! /* cracked this hash with a different salt (the real one). Here we fix it before writing to .pot */ ! void crk_guess_fixup_salt(char *source, char *salt) { ! // salt is : 0N0000REAL_SALT_STRING (real salt string is N bytes long). ! int real_salt_len = salt[1]-'0'; ! memcpy(source+DynaTypeLen+hash_len+1, &salt[6], real_salt_len); ! source[DynaTypeLen+hash_len+1+real_salt_len] = 0; ! } ! ! /* this is called from loader.c ldr_load_pot_line() function. During loading of the .pot file, */ ! /* the prepare has lost the proper salt. We now need to fix that to the 'correct' salt. */ ! void ldr_pot_possible_fixup_salt(char *source, char *ciphertext) { ! if (!strncmp(source, DynaType, DynaTypeLen)) { ! memcpy(&(source[DynaTypeLen+hash_len+1]), &(ciphertext[DynaTypeLen+hash_len+1]), salt_len); } ! } ! /* Load a custom user class string from john.pot from the [Regen_Salts_UserClasses] section. */ ! /* NOTE, we have to init the config file, since this will be called within option loading */ ! static char *LoadUserClass(char which, int i) { ! // Load user-defined character classes ?0 .. ?9 from john.conf ! char user_class_num[2]; ! char *user_class; ! static int loaded=0; ! user_class_num[0] = which; ! user_class_num[1] = 0; ! ! // The config has not been loaded, so we have to load it now, if we want to 'check' ! // and show any user set md5-generic functions. ! if (!loaded) { ! #if JOHN_SYSTEMWIDE ! cfg_init(CFG_PRIVATE_FULL_NAME, 1); ! cfg_init(CFG_PRIVATE_ALT_NAME, 1); ! #endif ! cfg_init(CFG_FULL_NAME, 1); ! cfg_init(CFG_ALT_NAME, 0); ! loaded = 1; ! } ! if ((user_class = cfg_get_param("Regen_Salts_UserClasses", NULL, user_class_num))) { ! extern char *userclass_expand(const char *src); /* found in rules.c */ ! return userclass_expand(user_class); ! } ! return NULL; ! } ! /* at the end of options loading, this function is called. It will return 0 or 1. If the user did NOT */ ! /* use the --regen-lost-salts option or not. If the user used it, but it was not valid, then we abort with */ ! /* an error message. Once this function is done, and returns a 1, then all data should be setup and ready */ ! int regen_lost_salt_parse_options() { ! char *cp; ! int i, regen_salts_dyna_num; ! ! if (regen_salts_options==NULL) return 0; ! if (!strcmp(regen_salts_options, "1")) regen_salts_options="dynamic_6:32:?y?y?y"; ! else if (!strcmp(regen_salts_options, "2")) regen_salts_options="dynamic_4:32:?y?y"; ! // NOTE mediawiki 3 here is not doing ?d- or ?d?d- I am not implementing 'variable' length regen ! // var length would add a LOT of complexity and may reduce speed a little. ! else if (!strcmp(regen_salts_options, "3")) regen_salts_options="dynamic_9:32:?d?d?d-"; ! else if (!strcmp(regen_salts_options, "4")) regen_salts_options="dynamic_9:32:?d?d?d?d-"; ! else if (!strcmp(regen_salts_options, "5")) regen_salts_options="dynamic_9:32:?d?d?d?d?d-"; ! else if (!strcmp(regen_salts_options, "6")) regen_salts_options="dynamic_61:64:?d?d"; ! ! if (strncmp(regen_salts_options, "dynamic_", 8)) ! bailout("Error, invalid regen-lost-salts argument. Must start with dynamic_# value\nSee docs/REGEN-LOST-SALTS document"); ! if (sscanf(regen_salts_options, "dynamic_%u:%u:", ®en_salts_dyna_num, &hash_len) != 2) ! bailout("Error, invalid regen-lost-salts argument. Must start with dynamic_#:hash_len: value\nSee docs/REGEN-LOST-SALTS document"); ! // at this point in the JtR loading, we do not know if $dynamic_`regen_salts_dyna_num`$ is valid. We have to check later. ! sprintf(DynaType, "$dynamic_%d$", regen_salts_dyna_num); ! DynaTypeLen = strlen(DynaType); ! ! // do 'some' sanity checking on input length. Only known valid input lengths for raw hashes are: ! // (we are only handling hex at this time) 2 times: 16, 20, 24, 28, 32, 40, 48, 64 bytes. ! switch(hash_len) { ! case 32: case 40: case 48: case 56: case 64: ! case 80: case 96: case 128: ! break; ! default: ! bailout("Error, invalid regen-lost-salts argument. Hash_length not valid\nSee docs/REGEN-LOST-SALTS document"); } ! // Ok, now parse the string, making sure it is valid. NOTE, since the sscanf gave us a 2 above, ! // we know the string has 2 : in it, so we do not need NULL pointer checking here. ! cp = strchr(regen_salts_options, ':'); ! cp = strchr(&cp[1], ':'); ! ++cp; ! regen_schema = cp; ! ! i = 0; ! while (*cp) { ! // d=dec h=hex H=HEX x=hHeExX b=binary o=oct a=a-zA-Z l=a-z u=A-Z n=a-zA-Z0-9 y=' '-~ (95 chars) ! if (*cp == '?') { ! switch(cp[1]) { ! case 'd': ! loc_cnt[i] = 10; ! candi[i] = "0123456789"; ! break; ! case 'h': ! candi[i] = "0123456789abcdef"; ! loc_cnt[i] = 16; ! break; ! case 'H': ! candi[i] = "0123456789ABCDEF"; ! loc_cnt[i] = 16; ! break; ! case 'x': ! candi[i] = "0123456789abcdefABCDEF"; ! loc_cnt[i] = 22; ! break; ! case 'b': ! candi[i] = "01"; ! loc_cnt[i] = 2; ! break; ! case 'o': ! candi[i] = "012345678"; ! loc_cnt[i] = 8; ! break; ! case 'a': ! candi[i] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; ! loc_cnt[i] = 52; ! break; ! case 'l': ! candi[i] = "abcdefghijklmnopqrstuvwxyz"; ! loc_cnt[i] = 26; ! break; ! case 'u': ! candi[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; ! loc_cnt[i] = 26; ! break; ! case 'n': ! candi[i] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; ! loc_cnt[i] = 62; ! break; ! case 'y': ! candi[i] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 `~!@#$%^&*()_-+=[{]};:,<.>/?|\\'\""; ! loc_cnt[i] = 95; ! break; ! case '?': ! loc_cnt[i] = 1; ! candi[i] = mem_alloc_tiny(2,1); ! candi[i][0] = cp[1]; ! candi[i][1] = 0; ! break; ! // need to handle user types also. ! case '0': ! case '1': ! case '2': ! case '3': ! case '4': ! case '5': ! case '6': ! case '7': ! case '8': ! case '9': ! { ! char *classData = LoadUserClass(cp[1], i); ! if (!classData) ! bailout("Error, invalid regen-lost-salts argument. Invalid class character in salt schema\nSee docs/REGEN-LOST-SALTS document"); ! candi[i] = classData; ! loc_cnt[i] = strlen(classData); ! break; ! } ! default: ! bailout("Error, invalid regen-lost-salts argument. Invalid class character in salt schema\nSee docs/REGEN-LOST-SALTS document"); } + ++cp; + } else { + loc_cnt[i] = 1; + candi[i] = mem_alloc_tiny(2,1); + candi[i][0] = cp[0]; + candi[i][1] = 0; } + ++cp; + ++salt_len; + FirstSalt[i] = candi[i][0]; + ++i; + } + FirstSalt[i] = 0; + if (salt_len > 9) { + bailout("Error, invalid regen-lost-salts argument. The max length salt can only be 99 bytes long\nSee docs/REGEN-LOST-SALTS document"); + } + total_regen_salts_count = 1; + for (i = 0; i < salt_len; ++i) { + if (total_regen_salts_count * loc_cnt[i] < total_regen_salts_count) + bailout("too many re-gen salt values requested to be able to allocate them\n"); + total_regen_salts_count *= loc_cnt[i]; } + return 1; } diff -rpN -C 2 memdbg2/src/fake_salts.h memdbg1/src/fake_salts.h *** memdbg2/src/fake_salts.h 1969-12-31 18:00:00.000000000 -0600 --- memdbg1/src/fake_salts.h 2013-05-17 09:45:48.458182600 -0500 *************** *** 0 **** --- 1,60 ---- + /* + * This software was written by JimF jfoug AT cox dot net + * in 2013. No copyright is claimed, and the software is hereby + * placed in the public domain. In case this attempt to disclaim + * copyright and place the software in the public domain is deemed + * null and void, then the software is Copyright (c) 2013 JimF + * and it is hereby released to the general public under the following + * terms: + * + * This software may be modified, redistributed, and used for any + * purpose, in source and binary forms, with or without modification. + * + * Salt finder. This will allow JtR to process a few salted type + * hashes, if the original salt has been lost. The only 2 types + * done at this time, are PHPS (VB), and osCommerce. PHPS is dynamic_6 + * which is md5(md5($p).$s) with a 3 byte salt. osCommerce is dynamic_4 + * of md5($s.$p) with a 2 type salt. + * + * this was made 'generic' now, so it will work for dynamic salted formats + * in 'general'. + * + + Data needed for --regen_salts: + + --regen_salts=# (depricated. valid values are 1, 2, 3, 4, 5, 6 and will get 'converted' into proper regen_salts= value) + or + --regen_salts=type:hash_len:mask + + --regen_salts=1 == --regen_salts=dynamic_6:32:?y?y?y + --regen_salts=2 == --regen_salts=dynamic_4:32:?y?y + --regen_salts=3 == --regen_salts=dynamic_9:32:?d?d?d- + --regen_salts=4 == --regen_salts=dynamic_9:32:?d?d?d?d- + --regen_salts=5 == --regen_salts=dynamic_9:32:?d?d?d?d?d- + --regen_salts=6 == --regen_salts=dynamic_61:64:?d?d + + Options: + + options.regen_lost_salts (now only 0 or 1) + + ?d – 0123456789 + ?l – abcdefghijklmnopqrstuvwxyz + ?u – ABCDEFGHIJKLMNOPQRSTUVWXYZ + ?s – !@#$%^&*()`~-_=+\|[]{};:'",.<>/? + ?h = 0123456789abcdef + ?y = all + ?a = a-zA-Z + [?d?l] = 0123456789abcdefghijklmnopqrstuvwxyz + ?z = \x1-\x255 + + From jtr rules. Using ! instead of ? means 'optional' character. So ?d?d?d?d- is 1 to 4 digit characters with a '-' char always being appended (like media wiki) + + */ + + extern char *regen_salts_options; + + extern int regen_lost_salt_parse_options(); + extern char *load_regen_lost_salt_Prepare(char *split_fields1); + extern void crk_guess_fixup_salt(char *source, char *salt); + extern void ldr_pot_possible_fixup_salt(char *source, char *ciphertext); + extern void build_fake_salts_for_regen_lost(struct db_salt *); diff -rpN -C 2 memdbg2/src/formspring_fmt_plug.c memdbg1/src/formspring_fmt_plug.c *** memdbg2/src/formspring_fmt_plug.c 2013-05-17 12:11:35.879817100 -0500 --- memdbg1/src/formspring_fmt_plug.c 2013-05-17 09:45:48.444679900 -0500 *************** static char *our_prepare(char *split_fie *** 78,92 **** int i = strlen(split_fields[1]); get_ptr(); - /* this 'special' code added to do a 'DEEP' test of hashes which have lost their salts */ - /* in this type run, we load the passwords, then run EVERY salt against them, as though*/ - /* all of the hashes were available for ALL salts. We also only want 1 salt */ - if (options.regen_lost_salts == 6 && i == 64) { - char *Ex = mem_alloc_tiny(CIPHERTEXT_LENGTH+1, MEM_ALIGN_NONE); - // add a 'garbage' placeholder salt to this candidate. However, we want ALL of them to - // be setup as the exact same salt (so that all candidate get dumped into one salt block. - // We use ' ' as the salt (2 spaces). - sprintf(Ex, "%s$ ", split_fields[1]); - return Ex; - } return pDynamic_61->methods.prepare(split_fields, self); } --- 78,81 ---- *************** static int formspring_valid(char *cipher *** 100,112 **** get_ptr(); i = strlen(ciphertext); - /* this 'special' code added to do a 'DEEP' test of hashes which have lost their salts */ - /* in this type run, we load the passwords, then run EVERY salt against them, as though*/ - /* all of the hashes were available for ALL salts. We also only want 1 salt */ - if (options.regen_lost_salts == 6 && i == 64) { - static char Ex[CIPHERTEXT_LENGTH+1]; - sprintf(Ex, "%s$ ", ciphertext); - ciphertext = Ex; - i = CIPHERTEXT_LENGTH; - } if (i != CIPHERTEXT_LENGTH) --- 89,92 ---- diff -rpN -C 2 memdbg2/src/john.c memdbg1/src/john.c *** memdbg2/src/john.c 2013-05-17 12:11:35.973335800 -0500 --- memdbg1/src/john.c 2013-05-13 10:24:00.000000000 -0500 *************** static int john_omp_threads_new; *** 57,60 **** --- 57,61 ---- #include "batch.h" #include "dynamic.h" + #include "fake_salts.h" #include "listconf.h" #ifdef HAVE_MPI *************** static void john_load(void) *** 881,890 **** } - if (options.regen_lost_salts) { - extern void build_fake_salts_for_regen_lost(struct db_salt *); - build_fake_salts_for_regen_lost(database.salts); - } - if ((options.flags & FLG_PWD_REQ) && !database.salts) exit(0); } --- 882,889 ---- } if ((options.flags & FLG_PWD_REQ) && !database.salts) exit(0); + + if (options.regen_lost_salts) + build_fake_salts_for_regen_lost(database.salts); } diff -rpN -C 2 memdbg2/src/loader.c memdbg1/src/loader.c *** memdbg2/src/loader.c 2013-05-17 12:11:36.127866700 -0500 --- memdbg1/src/loader.c 2013-05-15 08:47:22.000000000 -0500 *************** *** 34,36 **** --- 34,37 ---- #include "unicode.h" #include "dynamic.h" + #include "fake_salts.h" #include "john.h" *************** static void ldr_load_pot_line(struct db_ *** 697,719 **** if ((current = db->password_hash[hash])) do { ! if (db->options->regen_lost_salts) { ! if (db->options->regen_lost_salts == 1 && !strncmp(current->source, "$dynamic_6$", 11)) { ! char *cp = current->source; ! memcpy(&(cp[44]), &(ciphertext[44]), 3); ! } else if (db->options->regen_lost_salts == 2 && !strncmp(current->source, "$dynamic_4$", 11)) { ! char *cp = current->source; ! memcpy(&(cp[44]), &(ciphertext[44]), 2); ! } ! else if (db->options->regen_lost_salts >= 3 && db->options->regen_lost_salts <= 5 && !strncmp(current->source, "$dynamic_9$", 11)) { ! char Buf[256]; ! extern void mediawiki_fix_salt(char *Buf, char *source_to_fix, char *salt_rec, int max_salt_len); ! mediawiki_fix_salt(Buf, current->source, &(ciphertext[44-6]), db->options->regen_lost_salts+1); ! strcpy(current->source, Buf); ! } else if (db->options->regen_lost_salts == 6 && !strncmp(current->source, "$dynamic_61$", 12)) { ! char *cp = current->source; ! memcpy(&(cp[77]), &(ciphertext[77]), 2); ! } ! //else if (db->options->regen_lost_salts == 7 && !strncmp(current->source, "???????????", 11)) ! } if (!current->binary) /* already marked for removal */ continue; --- 698,703 ---- if ((current = db->password_hash[hash])) do { ! if (db->options->regen_lost_salts) ! ldr_pot_possible_fixup_salt(current->source, ciphertext); if (!current->binary) /* already marked for removal */ continue; diff -rpN -C 2 memdbg2/src/loader.h memdbg1/src/loader.h *** memdbg2/src/loader.h 2013-05-17 12:11:36.131367400 -0500 --- memdbg1/src/loader.h 2013-05-13 10:24:00.000000000 -0500 *************** struct db_options { *** 200,207 **** /* This is a 'special' flag. It causes john to add 'extra' code to search for some salted types, when we have */ ! /* only the hashes. The only type supported is PHPS (at this time.). So PHPS will set this to a 1. OTherwise */ ! /* it will always be zero. LIKELY we will add the same type logic for the OSC (mscommerse) type, which has only */ ! /* a 2 byte salt. That will set this field to be a 2. If we add other types, then we will have other values */ ! /* which can be assigned to this variable. This var is set by the undocummented --regen_lost_salts=# */ int regen_lost_salts; --- 200,204 ---- /* This is a 'special' flag. It causes john to add 'extra' code to search for some salted types, when we have */ ! /* only the hashes. This var is set by the undocummented --regen_lost_salts=[string] and code within fake_salts.c */ int regen_lost_salts; diff -rpN -C 2 memdbg2/src/mediawiki_fmt_plug.c memdbg1/src/mediawiki_fmt_plug.c *** memdbg2/src/mediawiki_fmt_plug.c 2013-05-17 12:11:36.180877300 -0500 --- memdbg1/src/mediawiki_fmt_plug.c 2013-05-17 09:45:48.504191800 -0500 *************** static char *our_prepare(char *split_fie *** 116,129 **** int i = strlen(split_fields[1]); get_ptr(); - /* this 'special' code added to do a 'DEEP' test of hashes which have lost their salts */ - /* in this type run, we load the passwords, then run EVERY salt against them, as though*/ - /* all of the hashes were available for ALL salts. We also only want 1 salt */ - if ( (options.regen_lost_salts >= 3 && options.regen_lost_salts <= 5) && i == 32) { - char *Ex = mem_alloc_tiny((3+options.regen_lost_salts+1+MD5_HEX_SIZE)+1, MEM_ALIGN_NONE); - // add a 'garbage' placeholder salt that is the proper 'max' size for salt. NOTE - // the real saltlen is not known at this time. We are simply making sure there is ENOUGH room. - sprintf(Ex, "$B$000%s%s$%s", options.regen_lost_salts>3?"0":"", options.regen_lost_salts>4?"0":"", split_fields[1]); - return Ex; - } return pDynamic_9->methods.prepare(split_fields, self); } --- 116,119 ---- *************** static int mediawiki_valid(char *ciphert *** 140,152 **** i = strlen(ciphertext); - /* this 'special' code added to do a 'DEEP' test of hashes which have lost their salts */ - /* in this type run, we load the passwords, then run EVERY salt against them, as though*/ - /* all of the hashes were available for ALL salts. We also only want 1 salt */ - - if ( (options.regen_lost_salts >= 3 && options.regen_lost_salts <= 5) && i == 32) { - static char Ex[(1+1+1+5+1+MD5_HEX_SIZE)+1]; - sprintf(Ex, "$B$000%s%s$%s", options.regen_lost_salts>3?"0":"", options.regen_lost_salts>4?"0":"", ciphertext); - ciphertext = Ex; - } if (strncmp(ciphertext, "$B$", 3) != 0) { --- 130,133 ---- diff -rpN -C 2 memdbg2/src/options.c memdbg1/src/options.c *** memdbg2/src/options.c 2013-05-17 12:11:36.525446200 -0500 --- memdbg1/src/options.c 2013-05-15 08:47:22.000000000 -0500 *************** *** 28,31 **** --- 28,32 ---- #include "dynamic.h" #include "unicode.h" + #include "fake_salts.h" #ifdef HAVE_MPI #include "john-mpi.h" *************** static struct opt_entry opt_list[] = { *** 156,160 **** "%u", &options.status_interval}, {"regen-lost-salts", FLG_NONE, FLG_NONE, 0, OPT_REQ_PARAM, ! "%u", &options.regen_lost_salts}, {"raw-always-valid", FLG_NONE, FLG_NONE, 0, OPT_REQ_PARAM, "%c", &options.dynamic_raw_hashes_always_valid}, --- 157,161 ---- "%u", &options.status_interval}, {"regen-lost-salts", FLG_NONE, FLG_NONE, 0, OPT_REQ_PARAM, ! OPT_FMT_STR_ALLOC, ®en_salts_options}, {"raw-always-valid", FLG_NONE, FLG_NONE, 0, OPT_REQ_PARAM, "%c", &options.dynamic_raw_hashes_always_valid}, *************** void opt_init(char *name, int argc, char *** 655,659 **** options.dynamic_raw_hashes_always_valid = 'N'; ! options.loader.regen_lost_salts = options.regen_lost_salts; if (field_sep_char_string != NULL) --- 656,660 ---- options.dynamic_raw_hashes_always_valid = 'N'; ! options.loader.regen_lost_salts = options.regen_lost_salts = regen_lost_salt_parse_options(); if (field_sep_char_string != NULL) diff -rpN -C 2 memdbg2/src/osc_fmt_plug.c memdbg1/src/osc_fmt_plug.c *** memdbg2/src/osc_fmt_plug.c 2013-05-17 12:11:36.538948900 -0500 --- memdbg1/src/osc_fmt_plug.c 2013-05-17 09:45:48.493689700 -0500 *************** static char *our_prepare(char *split_fie *** 98,112 **** int i = strlen(split_fields[1]); get_ptr(); - /* this 'special' code added to do a 'DEEP' test of hashes which have lost their salts */ - /* in this type run, we load the passwords, then run EVERY salt against them, as though*/ - /* all of the hashes were available for ALL salts. We also only want 1 salt */ - if (options.regen_lost_salts == 2 && i == 32) { - char *Ex = mem_alloc_tiny(CIPHERTEXT_LENGTH+1, MEM_ALIGN_NONE); - // add a 'garbage' placeholder salt to this candidate. However, we want ALL of them to - // be setup as the exact same salt (so that all candidate get dumped into one salt block. - // We use ' ' as the salt (3 spaces). - sprintf(Ex, "$OSC$2020$%s", split_fields[1]); - return Ex; - } return pDynamic_4->methods.prepare(split_fields, self); } --- 98,101 ---- *************** static int osc_valid(char *ciphertext, s *** 120,132 **** get_ptr(); i = strlen(ciphertext); - /* this 'special' code added to do a 'DEEP' test of hashes which have lost their salts */ - /* in this type run, we load the passwords, then run EVERY salt against them, as though*/ - /* all of the hashes were available for ALL salts. We also only want 1 salt */ - if (options.regen_lost_salts == 2 && i == 32) { - static char Ex[CIPHERTEXT_LENGTH+1]; - sprintf(Ex, "$OSC$2020$%s", ciphertext); - ciphertext = Ex; - i = CIPHERTEXT_LENGTH; - } if (i != CIPHERTEXT_LENGTH) { --- 109,112 ---- diff -rpN -C 2 memdbg2/src/PHPS_fmt_plug.c memdbg1/src/PHPS_fmt_plug.c *** memdbg2/src/PHPS_fmt_plug.c 2013-05-17 12:11:35.519245000 -0500 --- memdbg1/src/PHPS_fmt_plug.c 2013-05-17 09:45:48.479686900 -0500 *************** static char *our_prepare(char *split_fie *** 109,123 **** int i = strlen(split_fields[1]); get_ptr(); - /* this 'special' code added to do a 'DEEP' test of hashes which have lost their salts */ - /* in this type run, we load the passwords, then run EVERY salt against them, as though*/ - /* all of the hashes were available for ALL salts. We also only want 1 salt */ - if (options.regen_lost_salts == 1 && i == 32) { - char *Ex = mem_alloc_tiny(CIPHERTEXT_LENGTH+1, MEM_ALIGN_NONE); - // add a 'garbage' placeholder salt to this candidate. However, we want ALL of them to - // be setup as the exact same salt (so that all candidate get dumped into one salt block. - // We use ' ' as the salt (3 spaces). - sprintf(Ex, "$PHPS$202020$%s", split_fields[1]); - return Ex; - } return pDynamic_6->methods.prepare(split_fields, self); } --- 109,112 ---- *************** static int phps_valid(char *ciphertext, *** 131,143 **** get_ptr(); i = strlen(ciphertext); - /* this 'special' code added to do a 'DEEP' test of hashes which have lost their salts */ - /* in this type run, we load the passwords, then run EVERY salt against them, as though*/ - /* all of the hashes were available for ALL salts. We also only want 1 salt */ - if (options.regen_lost_salts == 1 && i == 32) { - static char Ex[CIPHERTEXT_LENGTH+1]; - sprintf(Ex, "$PHPS$202020$%s", ciphertext); - ciphertext = Ex; - i = CIPHERTEXT_LENGTH; - } if (i != CIPHERTEXT_LENGTH) { --- 120,123 ---- diff -rpN -C 2 memdbg2/src/rules.c memdbg1/src/rules.c *** memdbg2/src/rules.c 2013-05-17 12:11:36.710983300 -0500 --- memdbg1/src/rules.c 2013-05-17 10:22:39.000000000 -0500 *************** static void rules_init_class(char name, *** 240,247 **** } ! static char *userclass_expand(const char *src) { ! unsigned const char *src2 = (unsigned char*)src; ! char *dst_tmp = mem_alloc(0x200); char *dst = dst_tmp, *dstend = &dst_tmp[0x100]; int j, br = 0; --- 240,253 ---- } ! /* function used in fake_salts.c, to load user class data from john.conf */ ! /* note there 'used' to be a very nasty thing in this function, where we */ ! /* modified the data contents of our const src input param. This has been */ ! /* changed, so we have a separate buffer to memcpy to, instead of blasting */ ! /* a buffer that we had assured would not be destroyed. Also unneeded */ ! /* allocation was removed (JimF, 2013) */ ! char *userclass_expand(const char *src) { ! unsigned char _src2[0x100], *src2=_src2; ! char dst_tmp[0x200]; char *dst = dst_tmp, *dstend = &dst_tmp[0x100]; int j, br = 0; *************** static char *userclass_expand(const char *** 269,273 **** continue; } else { - MEM_FREE(dst_tmp); return NULL; } --- 275,278 ---- *************** static char *userclass_expand(const char *** 302,310 **** *dst = 0; if (br) { - MEM_FREE(dst_tmp); return NULL; } dst = str_alloc_copy(dst_tmp); - MEM_FREE(dst_tmp); return dst; } --- 307,313 ----