diff -urpN john-1.7.9.orig/src/dynamic_fmt.c john-1.7.9/src/dynamic_fmt.c --- john-1.7.9.orig/src/dynamic_fmt.c 2011-12-09 22:37:03.000000000 +0000 +++ john-1.7.9/src/dynamic_fmt.c 2011-12-09 22:23:54.000000000 +0000 @@ -597,7 +597,7 @@ static private_subformat_data curdat; *********************************************************************************/ static int valid(char *ciphertext, struct fmt_main *pFmt) { - int i, cipherTextLen; + int i, cipherTextLen, expectedSize; char *cp; private_subformat_data *pPriv = pFmt->private.data; @@ -669,48 +669,48 @@ static int valid(char *ciphertext, struc return 0; if (pPriv->dynamic_FIXED_SALT_SIZE && 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) { + if (pPriv->dynamic_FIXED_SALT_SIZE) { + // compute the real salt size if needed, which will be used in the next tests + cp = &ciphertext[pPriv->dynamic_SALT_OFFSET] ; //start of salt string + expectedSize = ( pPriv->dynamic_FIXED_SALT_SIZE > 0) ? pPriv->dynamic_FIXED_SALT_SIZE + : -pPriv->dynamic_FIXED_SALT_SIZE; + // check for HEX$ at start of salt, followed by valid hexadecimal chars + if (!strncmp(cp, "HEX$", 4)) { + cp+=4 ; + i=0 ; + while ( cp[i] && ( (('0' <= cp[i])&&(cp[i] <= '9')) || + (('a' <= cp[i])&&(cp[i] <= 'f')) || + (('A' <= cp[i])&&(cp[i] <= 'F')) ) + ) ++i ; + + if (((i % 2) == 0) && + ( (cp[i] == 0) || ( (cp[i]=='$') && + (cp[i+1]=='$') && + ((cp[i+2]=='2') || (cp[i+2]=='F') || (cp[i+2]=='U')) + ))) { + // we have a valid HEX$ string, + //it will later be converted to binary, so let's take that into account + expectedSize = 4 + 2*expectedSize; + } + } + } + if (pPriv->dynamic_FIXED_SALT_SIZE > 0 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) != expectedSize) { + // salt length should be exactly 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)) { - // do another check, just in case there is a HEX$ type salt. - if (strncmp(&ciphertext[pPriv->dynamic_SALT_OFFSET], "HEX$", 4) == 0) { - // Ok, we do have a HEX. We now want to compute it's length. - if (strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET+4]) == pPriv->dynamic_FIXED_SALT_SIZE*2) { - // Ok, check for salt-2, username, etc. - } else if (strncmp(&ciphertext[pPriv->dynamic_SALT_OFFSET+pPriv->dynamic_FIXED_SALT_SIZE*2+4], "$$", 2)) { + // aren't we 'out of bonds' with this check if the salt was too small ? + if (strncmp(&ciphertext[pPriv->dynamic_SALT_OFFSET+expectedSize], "$$", 2)) return 0; } - } else - return 0; - } - } - else if (pPriv->dynamic_FIXED_SALT_SIZE < -1 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) > -(pPriv->dynamic_FIXED_SALT_SIZE)) { + else if (pPriv->dynamic_FIXED_SALT_SIZE < -1 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) > expectedSize) { // check if there is a 'salt-2' or 'username', etc If that is the case, then this is still 'valid' - char *cpX; - if (strncmp(&ciphertext[pPriv->dynamic_SALT_OFFSET], "HEX$", 4) == 0) { - if (strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET+4]) <= -(pPriv->dynamic_FIXED_SALT_SIZE*2)) { - // ok We are only 'overlength', due to HEX$hexsalt being longer due to be 2x+4 because 1 byte becomes 2. - // Once we convert FROM the external HEX$ format, to binary format, it will be <= the max salt size, and - // thus this salt is 'safe' for this format. - } else { - cpX = mem_alloc(-(pPriv->dynamic_FIXED_SALT_SIZE*2) + 3); - strnzcpy(cpX, &ciphertext[pPriv->dynamic_SALT_OFFSET], -(pPriv->dynamic_FIXED_SALT_SIZE*2) + 3); - if (!strstr(cpX, "$$")) { - MEM_FREE(cpX); - return 0; - } - MEM_FREE(cpX); - } - } else { - cpX = mem_alloc(-(pPriv->dynamic_FIXED_SALT_SIZE) + 3); - strnzcpy(cpX, &ciphertext[pPriv->dynamic_SALT_OFFSET], -(pPriv->dynamic_FIXED_SALT_SIZE) + 3); + char *cpX = mem_alloc(expectedSize + 3); + strnzcpy(cpX, &ciphertext[pPriv->dynamic_SALT_OFFSET], expectedSize + 3); if (!strstr(cpX, "$$")) { MEM_FREE(cpX); return 0; } MEM_FREE(cpX); } - } if (pPriv->b2Salts==1 && !strstr(&ciphertext[pPriv->dynamic_SALT_OFFSET-1], "$$2")) return 0; if (pPriv->nUserName && !strstr(&ciphertext[pPriv->dynamic_SALT_OFFSET-1], "$$U")) @@ -1645,8 +1645,12 @@ static unsigned char *HashSalt(unsigned static int ConvertFromHex(unsigned char *p, int len) { unsigned char *cp; int i, x; - if (!p || memcmp(p, "HEX$", 4)) + if (!p || memcmp(p, "HEX$", 4) || (len %2)) return len; + + for (cp=p+4, x=len-4; x; --x, ++cp) { + if ( atoi16[ARCH_INDEX(*cp)] == 0x7F ) return len ; + } // Ok, do a convert, and return 'new' len. len -= 4; len >>= 1; diff -urpN john-1.7.9.orig/src/johnswap.h john-1.7.9/src/johnswap.h --- john-1.7.9.orig/src/johnswap.h 2011-12-09 22:37:03.000000000 +0000 +++ john-1.7.9/src/johnswap.h 2011-12-09 19:30:17.000000000 +0000 @@ -12,6 +12,7 @@ # endif # define JOHNSWAP(x) _byteswap_ulong((x)) #else +# include "common.h" # define JOHNSWAP(x) bswap_32((x)) # define JOHNSWAP(x) bswap_32((x)) # define JOHNSWAP(x) bswap_32((x)) # define ROTATE_LEFT(x, n) (x) = (((x)<<(n))|((ARCH_WORD_32)(x)>>(32-(n)))) static inline ARCH_WORD_32 bswap_32(ARCH_WORD_32 x)