diff -ruN src/Makefile mscash_src/Makefile --- src/Makefile 2006-05-15 18:38:00.000000000 +0200 +++ mscash_src/Makefile 2007-02-21 22:49:49.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 src/john.c mscash_src/john.c --- src/john.c 2006-05-08 16:48:48.000000000 +0200 +++ mscash_src/john.c 2007-02-21 22:49:49.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 src/loader.c mscash_src/loader.c --- src/loader.c 2005-11-08 14:03:20.000000000 +0100 +++ mscash_src/loader.c 2007-02-21 22:49:49.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 src/mscash_fmt.c mscash_src/mscash_fmt.c --- src/mscash_fmt.c 1970-01-01 01:00:00.000000000 +0100 +++ mscash_src/mscash_fmt.c 2007-03-20 14:14:04.000000000 +0100 @@ -0,0 +1,525 @@ +/* MSCASH patch for john (performance improvement) + * + * Written by Alain Espinosa in 2007 + * and placed in the public domain. + */ + +#include +#include "arch.h" +#include "misc.h" +#include "memory.h" +#include "common.h" +#include "formats.h" + +#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 "Generic 1x" + +#define BINARY_SIZE 16 +#define SALT_SIZE (11*4) + +#define MS_NUM_KEYS 64 +#define MIN_KEYS_PER_CRYPT MS_NUM_KEYS +#define MAX_KEYS_PER_CRYPT MS_NUM_KEYS + + +unsigned int ms_buffer1x[16*MS_NUM_KEYS]; +unsigned int output1x[4*MS_NUM_KEYS]; + +unsigned int crypt[4*MS_NUM_KEYS]; +unsigned int last[4*MS_NUM_KEYS]; + +unsigned int last_i[MS_NUM_KEYS]; +char saved_plain[32*MS_NUM_KEYS]; + +unsigned int *salt_buffer; +unsigned 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(ms_buffer1x,0,64*MS_NUM_KEYS); + memset(last_i,0,4*MS_NUM_KEYS); + new_key=1; +} + +static int valid(char *ciphertext) +{ + unsigned int i; + unsigned 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 (atoi16[ARCH_INDEX(ciphertext[i])] == 0x7F) + 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]; + unsigned int md4_size=0; + + memset(out,0,44); + + ciphertext+=2; + + for(;;md4_size++) + if(ciphertext[md4_size]!='#' && md4_size < 19) + { + md4_size++; + + out[md4_size>>1] = ciphertext[md4_size-1] | ((ciphertext[md4_size]!='#') ? (ciphertext[md4_size]<<16) : 0x800000); + + if(ciphertext[md4_size]=='#') + break; + } + else + { + out[md4_size>>1] = 0x80; + break; + } + + out[10] = (8 + md4_size) << 4; + + return out; +} + +static void *get_binary(char *ciphertext) +{ + static unsigned int out[4]; + unsigned int i=0; + unsigned int temp; + unsigned int * salt=get_salt(ciphertext); + + for(;ciphertext[0]!='#';ciphertext++); + + ciphertext++; + + for(; i<4 ;i++) + { + temp = (atoi16[ARCH_INDEX(ciphertext[i*8+0])])<<4; + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+1])]); + + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+2])])<<12; + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+3])])<<8; + + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+4])])<<20; + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+5])])<<16; + + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+6])])<<28; + temp |= (atoi16[ARCH_INDEX(ciphertext[i*8+7])])<<24; + + out[i]=temp; + } + + out[0] -= INIT_A; + out[1] -= INIT_B; + out[2] -= INIT_C; + out[3] -= INIT_D; + + // Reversed b += (c ^ d ^ a) + salt_buffer[11] + SQRT_3; b = (b << 15) | (b >> 17); + out[1] = (out[1] >> 15) | (out[1] << 17); + out[1] -= SQRT_3 + (out[2] ^ out[3] ^ out[0]); + // Reversed c += (d ^ a ^ b) + salt_buffer[3] + SQRT_3; c = (c << 11) | (c >> 21); + out[2] = (out[2] << 21) | (out[2] >> 11); + out[2]-= SQRT_3 + (out[3] ^ out[0] ^ out[1]) + salt[3]; + // Reversed d += (a ^ b ^ c) + salt_buffer[7] + SQRT_3; d = (d << 9 ) | (d >> 23); + out[3] = (out[3] << 23) | (out[3] >> 9); + out[3] -= SQRT_3 + (out[0] ^ out[1] ^ out[2]) + salt[7]; + //+ SQRT_3; d = (d << 9 ) | (d >> 23); + out[3]=(out[3] << 23 ) | (out[3] >> 9); + out[3]-=SQRT_3; + + return out; +} + +static int binary_hash_0(void *binary) +{ + return ((unsigned int*)binary)[3] & 0x0F; +} + +static int binary_hash_1(void *binary) +{ + return ((unsigned int*)binary)[3] & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return ((unsigned int*)binary)[3] & 0x0FFF; +} + +static int get_hash_0(int index) +{ + return output1x[4*index+3] & 0x0F; +} + +static int get_hash_1(int index) +{ + return output1x[4*index+3] & 0xFF; +} + +static int get_hash_2(int index) +{ + return output1x[4*index+3] & 0x0FFF; +} + +void nt_hash(void) +{ + unsigned int a; + unsigned int b; + unsigned int c; + unsigned int d; + unsigned int i=0; + + for(;i> 29); + d = INIT_D + (INIT_C ^ (a & 0x77777777)) + ms_buffer1x[16*i+1];d = (d << 7 ) | (d >> 25); + c = INIT_C + (INIT_B ^ (d & (a ^ INIT_B)))+ ms_buffer1x[16*i+2];c = (c << 11) | (c >> 21); + b = INIT_B + (a ^ (c & (d ^ a))) + ms_buffer1x[16*i+3];b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + ms_buffer1x[16*i+4] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + ms_buffer1x[16*i+5] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + ms_buffer1x[16*i+6] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + ms_buffer1x[16*i+7] ;b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + ms_buffer1x[16*i+8] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + ms_buffer1x[16*i+9] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + ms_buffer1x[16*i+10] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a))) + ms_buffer1x[16*i+11] ;b = (b << 19) | (b >> 13); + + a += (d ^ (b & (c ^ d))) + ms_buffer1x[16*i+12] ;a = (a << 3 ) | (a >> 29); + d += (c ^ (a & (b ^ c))) + ms_buffer1x[16*i+13] ;d = (d << 7 ) | (d >> 25); + c += (b ^ (d & (a ^ b))) + ms_buffer1x[16*i+14] ;c = (c << 11) | (c >> 21); + b += (a ^ (c & (d ^ a)))/*+ms_buffer1x[16*i+15]*/;b = (b << 19) | (b >> 13); + + /* Round 2 */ + a += ((b & (c | d)) | (c & d)) + ms_buffer1x[16*i+0] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + ms_buffer1x[16*i+4] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + ms_buffer1x[16*i+8] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + ms_buffer1x[16*i+12] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + ms_buffer1x[16*i+1] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + ms_buffer1x[16*i+5] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + ms_buffer1x[16*i+9] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + ms_buffer1x[16*i+13] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + ms_buffer1x[16*i+2] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + ms_buffer1x[16*i+6] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + ms_buffer1x[16*i+10] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a)) + ms_buffer1x[16*i+14] + SQRT_2; b = (b << 13) | (b >> 19); + + a += ((b & (c | d)) | (c & d)) + ms_buffer1x[16*i+3] + SQRT_2; a = (a << 3 ) | (a >> 29); + d += ((a & (b | c)) | (b & c)) + ms_buffer1x[16*i+7] + SQRT_2; d = (d << 5 ) | (d >> 27); + c += ((d & (a | b)) | (a & b)) + ms_buffer1x[16*i+11] + SQRT_2; c = (c << 9 ) | (c >> 23); + b += ((c & (d | a)) | (d & a))/*+ms_buffer1x[16*i+15]*/+SQRT_2; b = (b << 13) | (b >> 19); + + /* Round 3 */ + a += (b ^ c ^ d) + ms_buffer1x[16*i+0] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + ms_buffer1x[16*i+8] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + ms_buffer1x[16*i+4] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + ms_buffer1x[16*i+12] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + ms_buffer1x[16*i+2] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + ms_buffer1x[16*i+10] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + ms_buffer1x[16*i+6] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + ms_buffer1x[16*i+14] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + ms_buffer1x[16*i+1] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + ms_buffer1x[16*i+9] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + ms_buffer1x[16*i+5] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) + ms_buffer1x[16*i+13] + SQRT_3; b = (b << 15) | (b >> 17); + + a += (b ^ c ^ d) + ms_buffer1x[16*i+3] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + ms_buffer1x[16*i+11] + SQRT_3; d = (d << 9 ) | (d >> 23); + c += (d ^ a ^ b) + ms_buffer1x[16*i+7] + SQRT_3; c = (c << 11) | (c >> 21); + b += (c ^ d ^ a) /*+ ms_buffer1x[16*i+15] */+ SQRT_3; b = (b << 15) | (b >> 17); + + crypt[4*i+0] = a + INIT_A; + crypt[4*i+1] = b + INIT_B; + crypt[4*i+2] = c + INIT_C; + crypt[4*i+3] = d + INIT_D; + + //Another MD4_crypt for the salt + /* Round 1 */ + a= 0xFFFFFFFF +crypt[4*i+0]; a=(a<<3 )|(a>>29); + d=INIT_D + ( INIT_C ^ ( a & 0x77777777)) +crypt[4*i+1]; d=(d<<7 )|(d>>25); + c=INIT_C + ( INIT_B ^ ( d & ( a ^ INIT_B))) +crypt[4*i+2]; c=(c<<11)|(c>>21); + b=INIT_B + ( a ^ ( c & ( d ^ a ))) +crypt[4*i+3]; b=(b<<19)|(b>>13); + + last[4*i+0]=a; + last[4*i+1]=b; + last[4*i+2]=c; + last[4*i+3]=d; + } +} + +static void crypt_all(int count) +{ + unsigned int a; + unsigned int b; + unsigned int c; + unsigned int d; + unsigned int i=0; + + if(new_key) + { + new_key=0; + nt_hash(); + } + + for(;i> 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[4*i+0] + 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[4*i+1] + 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[4*i+2] + 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[4*i+3] + 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[4*i+0] + 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[4*i+2] + 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[4*i+1] + SQRT_3; a = (a << 3 ) | (a >> 29); + d += (a ^ b ^ c) + salt_buffer[5]; + + output1x[4*i+0]=a; + output1x[4*i+1]=b; + output1x[4*i+2]=c; + output1x[4*i+3]=d; + } +} + +static int cmp_all(void *binary, int count) +{ + unsigned int i=0; + unsigned int d=((unsigned int *)binary)[3]; + + for(;i> 23); + + c += (d ^ a ^ b) + salt_buffer[1] + SQRT_3; c = (c << 11) | (c >> 21); + if(c!=t[2]) + return 0; + + b += (c ^ d ^ a) + salt_buffer[9] + SQRT_3; b = (b << 15) | (b >> 17); + if(b!=t[1]) + return 0; + + a += (b ^ c ^ d) + crypt[4*index+3]+ SQRT_3; a = (a << 3 ) | (a >> 29); + return (a==t[0]); +} + +static int cmp_exact(char *source, int index) +{ + // This check its for the unreal case of collisions. + // It verify that the salts its the same. + unsigned int *salt=get_salt(source); + unsigned int i=0; + for(;i<11;i++) + if(salt[i]!=salt_buffer[i]) + return 0; + return 1; +} + +static void set_key(char *key, int index) +{ + unsigned int md4_size=0; + unsigned int i=0; + unsigned int temp; + unsigned int saved_base=index<<5; + unsigned int buff_base=index<<4; + + for(;key[md4_size] && md4_size>1; + + ms_buffer1x[buff_base+14] = md4_size << 4; + + //new password_candidate + new_key=1; +} + +static char *get_key(int index) +{ + return saved_plain+(index<<5); +} + +int salt_hash(void *salt) +{ + return ((unsigned char*)salt)[0]; +} + +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 src/options.c mscash_src/options.c --- src/options.c 2006-01-09 15:35:00.000000000 +0100 +++ mscash_src/options.c 2007-02-21 22:49:49.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)