Skip to content

Commit

Permalink
dynamic_generic_expressions: Got working with re-gen salts logic. #1463
Browse files Browse the repository at this point in the history
  • Loading branch information
jfoug committed Dec 5, 2015
1 parent 3ca886d commit 83d9684
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 15 deletions.
22 changes: 16 additions & 6 deletions doc/Regen-Lost-Salts.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
***************************************************************************
* JtR --regen-lost-salts code, written by JimF, 2012 and 2013, for use
* JtR --regen-lost-salts code, written by JimF, 2012-2015, 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
* null and void, then the software is Copyright (c) 2012-2015 JimF
* and it is hereby released to the general public under the following
* terms:
*
Expand Down Expand Up @@ -33,6 +33,11 @@ Usage:

--regen-lost-salts=dynamic_9:32:?d?d?d- --format=dynamic_9

Note, regen has been updated to work with dynamic generic expression compiler also.
Usage for same media-wiki as above is:

--regen-lost-salts='@dynamic=md5($s.md5($p))@:32:?d?d?d-' --format='dynamic=md5($s.md5($p))'

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
Expand All @@ -43,7 +48,7 @@ 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.
all the valid types. Also @dynamic=expression@ syntax works as expected.
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
Expand All @@ -61,8 +66,8 @@ So that 'parts' of the --regen-lost-salts are:
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.
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
Expand All @@ -86,7 +91,7 @@ Here are more details about the mask value:
?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
[Regen_Salts_UserClasses] / 0= class

With this information in hand, we can look back at that original example given:

Expand Down Expand Up @@ -136,8 +141,13 @@ 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'.

NOTE, the dyna-generic expression compiler is now supported, so dummy dynamic
formats do not have to be hand coded simply to use the regen-salts logic on
hashes where the salts were lost.
6 changes: 6 additions & 0 deletions src/dynamic_compiler_fmt_plug.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,18 @@ static char *our_split(char *ciphertext, int index, struct fmt_main *self)
ciphertext = dynamic_compile_split(ciphertext);
return ciphertext;
}
extern char *load_regen_lost_salt_Prepare(char *split_fields1);
static char *our_prepare(char **fields, struct fmt_main *self)
{
if (options.format && !strncmp(options.format, "dynamic=", 8)) {
extern const char *options_format;
char *ct;
options_format = options.format;
if (options.regen_lost_salts && !strchr(fields[1], '$')) {
char *cp = load_regen_lost_salt_Prepare(fields[1]);
if (cp)
return cp;
}
ct = dynamic_compile_prepare(fields[0], fields[1]);
return ct;
}
Expand Down
4 changes: 2 additions & 2 deletions src/dynamic_fmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,14 +480,14 @@ static int valid(char *ciphertext, struct fmt_main *pFmt)
if (strlen(&cp[cipherTextLen]) > SALT_SIZE)
return 0;
// end NOTE.
if (pPriv->dynamic_FIXED_SALT_SIZE && ciphertext[pPriv->dynamic_SALT_OFFSET-1] != '$')
if (pPriv->dynamic_FIXED_SALT_SIZE > 0 && ciphertext[pPriv->dynamic_SALT_OFFSET-1] != '$')
return 0;
if (pPriv->dynamic_FIXED_SALT_SIZE > 0 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) != pPriv->dynamic_FIXED_SALT_SIZE) {
// check if there is a 'salt-2' or 'username', etc If that is the case, then this is still valid.
if (strncmp(&ciphertext[pPriv->dynamic_SALT_OFFSET+pPriv->dynamic_FIXED_SALT_SIZE], "$$", 2))
return 0;
}
else if (pPriv->dynamic_FIXED_SALT_SIZE < -1 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) > -(pPriv->dynamic_FIXED_SALT_SIZE)) {
else if (!regen_salts_options && pPriv->dynamic_FIXED_SALT_SIZE < -1 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) > -(pPriv->dynamic_FIXED_SALT_SIZE)) {
// check if there is a 'salt-2' or 'username', etc If that is the case, then this is still 'valid'
char *cpX = mem_alloc(-(pPriv->dynamic_FIXED_SALT_SIZE) + 3);
strnzcpy(cpX, &ciphertext[pPriv->dynamic_SALT_OFFSET], -(pPriv->dynamic_FIXED_SALT_SIZE) + 3);
Expand Down
30 changes: 23 additions & 7 deletions src/fake_salts.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
// global data (Options loading uses this variable).
char *regen_salts_options;

static char *regen_schema, DynaType[24], FirstSalt[11];
static char *regen_schema, DynaType[2048], 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 */
Expand Down Expand Up @@ -190,12 +190,28 @@ int regen_lost_salt_parse_options() {
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_%d:%d:", &regen_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);
if (!strncmp(regen_salts_options, "@dynamic=", 9)) {
char *cp = strrchr(regen_salts_options, '@');
int len;
if (!cp)
bailout("Error, invalid @dynamic= signature in the -salt-regen section");
++cp;
len = cp-regen_salts_options;
if (len > sizeof(DynaType) - 1)
len = sizeof(DynaType) - 1;
regen_salts_dyna_num=6000;
if (sscanf(cp, ":%d:", &hash_len) != 1)
bailout("Error, invalid regen-lost-salts argument. Must start with @dynamic=EXPR: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, "%*.*s", len, len, regen_salts_options);
} else {
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_%d:%d:", &regen_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:
Expand Down

0 comments on commit 83d9684

Please sign in to comment.