--- ../john.c 2006-05-08 16:48:48.000000000 +0200 +++ john.c 2008-03-04 11:11:51.000000000 +0100 @@ -38,6 +38,7 @@ 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_MYSQL_fast; extern int unshadow(int argc, char **argv); extern int unafs(int argc, char **argv); @@ -64,6 +65,7 @@ john_register_one(&fmt_BF); john_register_one(&fmt_AFS); john_register_one(&fmt_LM); + john_register_one(&fmt_MYSQL_fast); if (!fmt_list) { fprintf(stderr, "Unknown ciphertext format name requested\n"); --- ../Makefile 2006-05-15 18:38:00.000000000 +0200 +++ Makefile 2008-03-04 11:15:08.000000000 +0100 @@ -28,6 +28,7 @@ BF_fmt.o BF_std.o \ AFS_fmt.o \ LM_fmt.o \ + MYSQL_fast_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 \ --- /dev/null 2008-03-04 10:30:51.996274258 +0100 +++ MYSQL_fast_fmt.c 2008-03-02 22:26:38.000000000 +0100 @@ -0,0 +1,214 @@ +/* MYSQL_half_fmt.c + * + * Copyright (c) 2008 by + * + * John the ripper MYSQL-fast module + * + * + * Note: The mysql hash's first 8byte is relevant, + * the another ones depends on the first 8. Maybe + * the passwords after 9-10character have collision + * in the first 8byte, so we have to check the full + * hash. + * + * Unbelievable good optimization by Péter Kasza + * + * http://rycon.hu/ + */ + +#include +#include +#include + +#include "arch.h" +#include "misc.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "mysql-fast" +#define FORMAT_NAME "MYSQL_fast" +#define ALGORITHM_NAME "mysql-fast" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 32 +#define CIPHERTEXT_LENGTH 16 + +#define BINARY_SIZE 8 +#define SALT_SIZE 0 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 64 + +static struct fmt_tests mysql_tests[] = { + // ciphertext, plaintext + {"445ff82636a7ba59", "probe"}, + {"60671c896665c3fa", "a"}, + {"1acbed4a27b20da3", "hash"}, + {"77ff75006118bab8", "hacker"}, + {"1b38cd9c2f809809", "hacktivity2008"}, + {"1b38cd9c2f809809", "hacktivity 2008"}, + {"6fc81597422015a8", "johnmodule"}, + {NULL} +}; + +static char crypt_key[MAX_KEYS_PER_CRYPT][BINARY_SIZE]; +static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1]; + +static int mysql_valid(char* ciphertext) +{ + unsigned int i; + + if (strlen(ciphertext) != CIPHERTEXT_LENGTH) + return 0; + + for (i = 0; i < CIPHERTEXT_LENGTH; i++) + { + if (!(((ciphertext[i] >= '0') && (ciphertext[i] <= '9')) || + ((ciphertext[i] >= 'a') && (ciphertext[i] <= 'f')))) + return 0; + } + + return 1; +} + +static void mysql_set_salt(void* salt) { } + +static void* mysql_get_binary(char* ciphertext) +{ + static unsigned char buff[BINARY_SIZE / 2]; + unsigned int i; + + for (i = 0; i < BINARY_SIZE / 2; i++) + { +#if ARCH_LITTLE_ENDIAN == 1 + buff[((BINARY_SIZE / 2) - 1) - i] = atoi16[ARCH_INDEX(ciphertext[i * 2])] * 16 + atoi16[ARCH_INDEX(ciphertext[i * 2 + 1])]; +#else + buff[i] = atoi16[ARCH_INDEX(ciphertext[i * 2])] * 16 + atoi16[ARCH_INDEX(ciphertext[i * 2 + 1])]; +#endif + } + + return buff; +} + +static void mysql_set_key(char* key, int index) +{ + strnzcpy(saved_key[index], key, PLAINTEXT_LENGTH + 1); +} + +static char* mysql_get_key(int index) +{ + return saved_key[index]; +} + +static int mysql_cmp_one(void* binary, int index) +{ + return (!(*((unsigned long*)binary) - *((unsigned long*)&crypt_key[index]))); +} + +static int mysql_cmp_all(void* binary, int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) + { + if (!(*((unsigned long*)binary) - *((unsigned long*)&crypt_key[i]))) + return 1; + } + + return 0; +} + +static int mysql_cmp_exact(char* source, int index) +{ + register unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L; + register unsigned long tmp; + char* password; + char ctmp[CIPHERTEXT_LENGTH+1]; + + password = saved_key[index]; + for (; *password; password++) + { + if (*password == ' ' || *password == '\t') + continue; + + tmp = (unsigned long) (unsigned char) *password; + nr ^= (((nr & 63) + add) * tmp) + (nr << 8); + nr2 += (nr2 << 8) ^ nr; + add += tmp; + } + + sprintf(ctmp, "%08lx%08lx", (nr & (((unsigned long) 1L << 31) -1L)), (nr2 & (((unsigned long) 1L << 31) -1L))); + return !memcmp(source, ctmp, CIPHERTEXT_LENGTH); +} + +static void mysql_crypt_all(int count) +{ + unsigned long nr, add; + unsigned long tmp; + unsigned int i; + char* password; + + for (i = 0; i < count; i++) + { + nr=1345345333L; + add=7; + + password = saved_key[i]; + for (; *password; password++) + { + if (*password == ' ' || *password == '\t') + continue; + + tmp = (unsigned long) (unsigned char) *password; + nr ^= (((nr & 63) + add) * tmp) + (nr << 8); + add += tmp; + } + + *((unsigned long*)&crypt_key[i]) = (nr & (((unsigned long) 1L << 31) -1L)); + } +} + +struct fmt_main fmt_MYSQL_fast = +{ + { + 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, + mysql_tests + }, { + fmt_default_init, + mysql_valid, + fmt_default_split, + mysql_get_binary, + fmt_default_salt, + { + fmt_default_binary_hash, + fmt_default_binary_hash, + fmt_default_binary_hash + }, + fmt_default_salt_hash, + mysql_set_salt, + mysql_set_key, + mysql_get_key, + fmt_default_clear_keys, + mysql_crypt_all, + { + fmt_default_get_hash, + fmt_default_get_hash, + fmt_default_get_hash + }, + mysql_cmp_all, + mysql_cmp_one, + mysql_cmp_exact + } +};