diff -ruN john-1.7.2/src/Makefile john-1.7.2_mscash/src/Makefile --- john-1.7.2/src/Makefile 2006-05-15 18:38:00.000000000 +0200 +++ john-1.7.2_mscash/src/Makefile 2007-02-05 15:20:59.000000000 +0100 @@ -28,6 +28,7 @@ BF_fmt.o BF_std.o \ AFS_fmt.o \ LM_fmt.o \ + mscash_fmt.o \ batch.o bench.o charset.o common.o compiler.o config.o cracker.o \ crc32.o external.o formats.o getopt.o idle.o inc.o john.o list.o \ loader.o logger.o math.o memory.o misc.o options.o params.o path.o \ diff -ruN john-1.7.2/src/john.c john-1.7.2_mscash/src/john.c --- john-1.7.2/src/john.c 2006-05-08 16:48:48.000000000 +0200 +++ john-1.7.2_mscash/src/john.c 2007-02-05 15:20:25.000000000 +0100 @@ -37,7 +37,7 @@ #endif extern struct fmt_main fmt_DES, fmt_BSDI, fmt_MD5, fmt_BF; -extern struct fmt_main fmt_AFS, fmt_LM; +extern struct fmt_main fmt_AFS, fmt_LM, fmt_mscash; extern int unshadow(int argc, char **argv); extern int unafs(int argc, char **argv); @@ -64,6 +64,7 @@ john_register_one(&fmt_BF); john_register_one(&fmt_AFS); john_register_one(&fmt_LM); + john_register_one(&fmt_mscash); if (!fmt_list) { fprintf(stderr, "Unknown ciphertext format name requested\n"); diff -ruN john-1.7.2/src/loader.c john-1.7.2_mscash/src/loader.c --- john-1.7.2/src/loader.c 2005-11-08 14:03:20.000000000 +0100 +++ john-1.7.2_mscash/src/loader.c 2007-02-05 15:27:30.000000000 +0100 @@ -286,6 +286,7 @@ struct db_password *current_pw, *last_pw; struct list_main *words; size_t pw_size, salt_size; + extern struct fmt_main fmt_mscash; count = ldr_split_line(&login, &ciphertext, &gecos, &home, NULL, &db->format, db->options, line); @@ -311,7 +312,13 @@ } for (index = 0; index < count; index++) { - piece = format->methods.split(ciphertext, index); + if (db->format == &fmt_mscash) + { + piece = (char *) mem_alloc(strlen(login) + strlen(ciphertext) + 4); + sprintf(piece, "M$%s#%s", login, ciphertext); + } + else + piece = format->methods.split(ciphertext, index); binary = format->methods.binary(piece); pw_hash = LDR_HASH_FUNC(binary); @@ -643,6 +650,7 @@ int pass, found, chars; int hash; struct db_cracked *current; + extern struct fmt_main fmt_mscash; format = NULL; count = ldr_split_line(&login, &ciphertext, &gecos, &home, @@ -654,6 +662,12 @@ if (format) { split = format->methods.split; unify = format->params.flags & FMT_SPLIT_UNIFIES_CASE; + if(format == &fmt_mscash) + { + char * ciphertext2 = (char *) mem_alloc(strlen(login) + strlen(ciphertext) + 4); + sprintf(ciphertext2, "M$%s#%s", login, ciphertext); + ciphertext = ciphertext2; + } } else { split = fmt_default_split; count = 1; diff -ruN john-1.7.2/src/mscash_fmt.c john-1.7.2_mscash/src/mscash_fmt.c --- john-1.7.2/src/mscash_fmt.c 1970-01-01 01:00:00.000000000 +0100 +++ john-1.7.2_mscash/src/mscash_fmt.c 2007-02-05 15:15:30.000000000 +0100 @@ -0,0 +1,465 @@ +/* + * MSCASH patch for john (performance improvement) + * + * Written by Alain Espinosa in 2007 + * and placed in the public domain. + * + * This patch asume little endian memory + */ + +#include +#include "arch.h" +#include "memory.h" +#include "common.h" +#include "formats.h" + +#ifndef uchar +#define uchar unsigned char +#endif + +#define FORMAT_LABEL "mscash" +#define FORMAT_NAME "M$ Cache Hash" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH 0 + +#define PLAINTEXT_LENGTH 27 +#define CIPHERTEXT_LENGTH (BINARY_SIZE + 19 + 5) + + +static struct fmt_tests tests[] = { + {"M$test1#64cd29e36a8431a2b111378564a10631", "test1" }, + {"M$test2#ab60bdb4493822b175486810ac2abe63", "test2" }, + {"M$test3#14dd041848e12fc48c0aa7a416a4a00c", "test3" }, + {"M$test4#b945d24866af4b01a6d89b9d932a153c", "test4" }, + {NULL} +}; + +#define ALGORITHM_NAME "Rapid MS Cash" + +#define BINARY_SIZE 16 +#define SALT_SIZE (11*4) + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +char saved_plain[PLAINTEXT_LENGTH+1]; + +unsigned int a; +unsigned int b; +unsigned int c; +unsigned int d; + +unsigned int crypt_a; +unsigned int crypt_b; +unsigned int crypt_c; +unsigned int crypt_d; + +unsigned int last_a; +unsigned int last_b; +unsigned int last_c; +unsigned int last_d; + + +unsigned int md4_buffer[16]; +unsigned int *salt_buffer; + +int last_size; +int new_key; + +//Init values +#define INIT_A 0x67452301 +#define INIT_B 0xefcdab89 +#define INIT_C 0x98badcfe +#define INIT_D 0x10325476 + +#define SQRT_2 0x5a827999 +#define SQRT_3 0x6ed9eba1 + +static void init(void) +{ + memset(md4_buffer,0,64); + last_size=0; + new_key=1; +} + +static int valid(char *ciphertext) +{ + int i; + int l; + + /* + * 2 cases + * 1 - it comes from the disk, and does not have M$ + salt + * 2 - it comes from memory, and has got M$ + salt + # + blah + */ + + if (!memcmp(ciphertext, "M$", 2)) + { + l = strlen(ciphertext) - 32; + if(ciphertext[l-1]!='#') + return 0; + } + else + { + if(strlen(ciphertext)!=32) + return 0; + l = 0; + } + for (i = l; i < l + 32; i++){ + if (!( (('0' <= ciphertext[i])&&(ciphertext[i] <= '9')) || + (('a' <= ciphertext[i])&&(ciphertext[i] <= 'f')) + || (('A' <= ciphertext[i])&&(ciphertext[i] <= 'F')))) + return 0; + } + + return 1; + +} + +static void set_salt(void *salt) { + salt_buffer=salt; +} + +static void * get_salt(char * ciphertext) +{ + //lenght=11 for save memory + //last position = 0 + //4 first position are crypt_? + static unsigned int out[11]; + + uchar * buffer=(uchar *)out; + int md4_size=0; + + memset(out,0,11*4); + + /*Salt must be converted to NT unicode + and lesser than SALT_SIZE bytes*/ + for(;ciphertext[md4_size+2]!='#' && md4_size < 19;md4_size++) + buffer[md4_size<<1] = ciphertext[md4_size+2]; + + buffer[md4_size<<1] = 0x80; + + out[10] = (8 + md4_size) << 4; + + return out; +} + +static void *get_binary(char *ciphertext) +{ + static uchar realcipher[BINARY_SIZE]; + unsigned int *t=(unsigned int *)realcipher; + int i; + + int l = strlen(ciphertext); + for(i=0; i> 15) | (t[1] << 17); + t[1] -= SQRT_3 + (t[2] ^ t[3] ^ t[0]); + t[1] = (t[1] >> 15) | (t[1] << 17); + t[1] -= SQRT_3; + + return (void *)realcipher; +} + +static int binary_hash_0(void *binary) +{ + return ((unsigned int*)binary)[1] & 0x0F; +} + +static int binary_hash_1(void *binary) +{ + return ((unsigned int*)binary)[1] & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return ((unsigned int*)binary)[1] & 0x0FFF; +} + +static int get_hash_0(int index) +{ + return b & 0x0F; +} + +static int get_hash_1(int index) +{ + return b & 0xFF; +} + +static int get_hash_2(int index) +{ + return b & 0x0FFF; +} + +static void crypt_all(int count) +{ + //if (new password_candiate) + // calculate values + //else + // load values first calculate + // + //......continue with the work.......... + + if(new_key) + { + new_key=0; + + /* Round 1 */ + a = 0xFFFFFFFF + md4_buffer[0];a = (a << 3 ) | (a >> 29); + d = INIT_D + (INIT_C ^ (a & 0x77777777)) + md4_buffer[1];d = (d << 7 ) | (d >> 25); + c = INIT_C + (INIT_B ^ (d & (a ^ INIT_B))) + md4_buffer[2];c = (c << 11) | (c >> 21); + b = INIT_B + (a ^ (c & (d ^ a))) + md4_buffer[3];b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + md4_buffer[4] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + md4_buffer[5] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + md4_buffer[6] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + md4_buffer[7] ;b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + md4_buffer[8] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + md4_buffer[9] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + md4_buffer[10] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + md4_buffer[11] ;b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + md4_buffer[12] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + md4_buffer[13] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + md4_buffer[14] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + md4_buffer[15] ;b = (b << 19) | (b >> 13); + + /* Round 2 */ + a += ((b & (c | d)) | (c & d)) + md4_buffer[0] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + md4_buffer[4] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + md4_buffer[8] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + md4_buffer[12] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + md4_buffer[1] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + md4_buffer[5] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + md4_buffer[9] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + md4_buffer[13] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + md4_buffer[2] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + md4_buffer[6] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + md4_buffer[10] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + md4_buffer[14] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + md4_buffer[3] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + md4_buffer[7] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + md4_buffer[11] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + md4_buffer[15] + SQRT_2; b = (b << 13) | (b >> 19); + + /* Round 3 */ + a += (b ^ c ^ d) + md4_buffer[0] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + md4_buffer[8] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + md4_buffer[4] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + md4_buffer[12] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + md4_buffer[2] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + md4_buffer[10] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + md4_buffer[6] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + md4_buffer[14] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + md4_buffer[1] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + md4_buffer[9] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + md4_buffer[5] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + md4_buffer[13] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + md4_buffer[3] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + md4_buffer[11] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + md4_buffer[7] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + md4_buffer[15] + SQRT_3; b = (b << 15) | (b >> 17); + + crypt_a = a + INIT_A; + crypt_b = b + INIT_B; + crypt_c = c + INIT_C; + crypt_d = d + INIT_D; + + + //Another MD4_crypt for the salt + /* Round 1 */ + last_a= 0xFFFFFFFF +crypt_a;last_a=(last_a<<3 )|(last_a>>29); + last_d=INIT_D+(INIT_C^(last_a& 0x77777777)) +crypt_b;last_d=(last_d<<7 )|(last_d>>25); + last_c=INIT_C+(INIT_B^(last_d&(last_a^INIT_B)))+crypt_c;last_c=(last_c<<11)|(last_c>>21); + last_b=INIT_B+(last_a^(last_c&(last_d^last_a)))+crypt_d;last_b=(last_b<<19)|(last_b>>13); + + } + + a = last_a; + b = last_b; + c = last_c; + d = last_d; + + a += (d ^ (b & (c ^ d))) + salt_buffer[0] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + salt_buffer[1] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + salt_buffer[2] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + salt_buffer[3] ;b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + salt_buffer[4] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + salt_buffer[5] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + salt_buffer[6] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + salt_buffer[7] ;b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + salt_buffer[8] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + salt_buffer[9] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + salt_buffer[10] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a)))/*+salt_buffer[11]*/;b = (b << 19) | (b >> 13); + + /* Round 2 */ + a += ((b & (c | d)) | (c & d)) + crypt_a + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + salt_buffer[0] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + salt_buffer[4] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + salt_buffer[8] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + crypt_b + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + salt_buffer[1] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + salt_buffer[5] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + salt_buffer[9] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + crypt_c + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + salt_buffer[2] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + salt_buffer[6] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + salt_buffer[10] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + crypt_d + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + salt_buffer[3] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + salt_buffer[7] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a))/*+ salt_buffer[11]*/+ SQRT_2; b = (b << 13) | (b >> 19); + + /* Round 3 */ + a += (b ^ c ^ d) + crypt_a + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + salt_buffer[4] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + salt_buffer[0] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + salt_buffer[8] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + crypt_c + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + salt_buffer[6] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + salt_buffer[2] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + salt_buffer[10] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + crypt_b + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + salt_buffer[5] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + salt_buffer[1] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + salt_buffer[9];//+ SQRT_3; b = (b << 15) | (b >> 17); + +// a += (b ^ c ^ d) + crypt_d + SQRT_3; a = (a << 3 ) | (a >> 29); +// d += (a ^ b ^ c) + salt_buffer[7] + SQRT_3; d = (d << 9 ) | (d >> 23); +// c += (d ^ a ^ b) + salt_buffer[3] + SQRT_3; c = (c << 11) | (c >> 21); +// b += (c ^ d ^ a) + salt_buffer[11] + SQRT_3; b = (b << 15) | (b >> 17); +} + +static int cmp_all(void *binary, int count) +{ + return b==((unsigned int *)binary)[1]; +} + +static int cmp_one(void * binary, int index) +{ + unsigned int *t=(unsigned int *)binary; + + b += SQRT_3;b = (b << 15) | (b >> 17); + a += (b ^ c ^ d) + crypt_d + SQRT_3; a = (a << 3 ) | (a >> 29); + if(a!=t[0]) + return 0; + + d += (a ^ b ^ c) + salt_buffer[7]+ SQRT_3; d = (d << 9 ) | (d >> 23); + if(d!=t[3]) + return 0; + + c += (d ^ a ^ b) + salt_buffer[3] + SQRT_3; c = (c << 11) | (c >> 21); + return c==t[2]; +} + +static int cmp_exact(char *source, int index) +{ + return 1; +} + +static void set_key(char *key, int index) +{ + uchar *buffer=(uchar*)md4_buffer; + int md4_size=0; + int clean; + + /*Password must be converted to NT unicode + and lesser than PLAINTEXT_LENGTH bytes*/ + for(;key[md4_size] && md4_size < PLAINTEXT_LENGTH;md4_size++) + { + buffer[md4_size<<1] =key[md4_size]; + saved_plain[md4_size]=key[md4_size]; + } + saved_plain[md4_size]=0; + + buffer[md4_size<<1] = 0x80; + + md4_buffer[14] = md4_size << 4; + + //Cleaning + clean=md4_size+1; + + for(;clean<=last_size;clean++) + buffer[clean<<1]=0; + + last_size=md4_size; + + //new password_candidate + new_key=1; +} + +static char *get_key(int index) +{ + return saved_plain; +} + +int salt_hash(void *salt) +{ + return ((uchar*)salt)[16]; +} + +struct fmt_main fmt_mscash = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + SALT_SIZE, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT, + tests + }, { + init, + valid, + fmt_default_split, + get_binary, + get_salt, + { + binary_hash_0, + binary_hash_1, + binary_hash_2 + }, + salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2 + }, + cmp_all, + cmp_one, + cmp_exact + } +}; diff -ruN john-1.7.2/src/options.c john-1.7.2_mscash/src/options.c --- john-1.7.2/src/options.c 2006-01-09 15:35:00.000000000 +0100 +++ john-1.7.2_mscash/src/options.c 2007-02-05 15:22:35.000000000 +0100 @@ -60,7 +60,7 @@ {"salts", FLG_SALTS, FLG_SALTS, FLG_PASSWD, OPT_REQ_PARAM, "%d", &options.loader.min_pps}, {"format", FLG_FORMAT, FLG_FORMAT, - FLG_CRACKING_SUP, + 0, FLG_MAKECHR_CHK | FLG_STDOUT | OPT_REQ_PARAM, OPT_FMT_STR_ALLOC, &options.format}, {"save-memory", FLG_SAVEMEM, FLG_SAVEMEM, 0, OPT_REQ_PARAM, @@ -101,7 +101,7 @@ "--salts=[-]COUNT load salts with[out] at least COUNT passwords " \ "only\n" \ "--format=NAME force ciphertext format NAME: " \ - "DES/BSDI/MD5/BF/AFS/LM\n" \ + "DES/BSDI/MD5/BF/AFS/LM/mscash\n" \ "--save-memory=LEVEL enable memory saving, at LEVEL 1..3\n" void opt_init(char *name, int argc, char **argv)