From 12d2ce87e13995ccc5097ae4f8c4eed2ac171dbc Mon Sep 17 00:00:00 2001 From: Dhiru Kholia Date: Mon, 20 Aug 2012 19:34:55 +0530 Subject: [PATCH] Add support for cracking MS SQL 2012 hashes --- src/mssql12_fmt_plug.c | 294 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 src/mssql12_fmt_plug.c diff --git a/src/mssql12_fmt_plug.c b/src/mssql12_fmt_plug.c new file mode 100644 index 0000000..40f68f8 --- /dev/null +++ b/src/mssql12_fmt_plug.c @@ -0,0 +1,294 @@ +/* Modified in August, 2012 by Dhiru Kholia (dhiru at openwall.com) for MS SQL 2012 + * + * This software is Copyright (c) 2010 bartavelle, , + * and it is hereby released to the general public under the following terms: + * Redistribution and use in source and binary forms, with or without modification, are permitted. + * + * Modified by Mathieu Perrin (mathieu at tpfh.org) 09/06 + * Microsoft MS-SQL05 password cracker + * + * UTF-8 support and use of intrinsics by magnum 2011, same terms as above */ + +#include +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "common.h" +#include "formats.h" +#include "options.h" +#include "unicode.h" +#include "sha.h" +#ifdef _OPENMP +static int omp_t = 1; +#include +#define OMP_SCALE 64 +#endif + +#define FORMAT_LABEL "mssql12" +#define FORMAT_NAME "MS SQL 2012 SHA512" +#define ALGORITHM_NAME "ms-sql12" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH 0 + +#define PLAINTEXT_LENGTH 25 +#define CIPHERTEXT_LENGTH 54 + 44 * 2 + +#define BINARY_SIZE 64 +#define SALT_SIZE 4 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +static struct fmt_tests tests[] = { + {"0x0200F733058A07892C5CACE899768F89965F6BD1DED7955FE89E1C9A10E27849B0B213B5CE92CC9347ECCB34C3EFADAF2FD99BFFECD8D9150DD6AACB5D409A9D2652A4E0AF16", "Password1!"}, + {NULL} +}; + +static unsigned char cursalt[SALT_SIZE]; +static char (*saved_key)[PLAINTEXT_LENGTH*2 + 1 + SALT_SIZE]; +static ARCH_WORD_32 (*crypt_out)[BINARY_SIZE / 4]; +static int key_length; + +static int valid(char *ciphertext, struct fmt_main *self) +{ + if(memcmp(ciphertext, "0x0200", 6)) + return 0; + return 1; +} + +// Handle full hashes (old and new in one long string) as well. This means the +// [other] mssql format should be registered before this one. If there are +// old-style hashes we should crack them first using that format, then run +// mssql05 with -ru:nt just like LM -> NT format +static char *prepare(char *split_fields[10], struct fmt_main *self) +{ + if (strlen(split_fields[1]) == CIPHERTEXT_LENGTH) + return split_fields[1]; + + if (!memcmp(split_fields[1], "0x0100", 6) && strlen(split_fields[1]) == 94) { + char cp[CIPHERTEXT_LENGTH + 1]; + strnzcpy(cp, split_fields[1], CIPHERTEXT_LENGTH + 1); + + if (valid(cp,self)) { + char *cp2 = str_alloc_copy(cp); + return cp2; + } + } + return split_fields[1]; +} + +static void set_salt(void *salt) +{ + memcpy(cursalt, salt, SALT_SIZE); +} + +static void * get_salt(char * ciphertext) +{ + static unsigned char *out2; + int l; + + if (!out2) out2 = mem_alloc_tiny(SALT_SIZE, MEM_ALIGN_WORD); + + for(l=0;lparams.min_keys_per_crypt *= omp_t; + omp_t *= OMP_SCALE; + self->params.max_keys_per_crypt *= omp_t; +#endif + saved_key = mem_calloc_tiny(sizeof(*saved_key) * + self->params.max_keys_per_crypt, MEM_ALIGN_NONE); + crypt_out = mem_calloc_tiny(sizeof(*crypt_out) * self->params.max_keys_per_crypt, MEM_ALIGN_WORD); + if (options.utf8) { + self->methods.set_key = set_key_utf8; + self->params.plaintext_length = PLAINTEXT_LENGTH * 3; + } + else if (options.iso8859_1 || options.ascii) { + ; // do nothing + } + else { + self->methods.set_key = set_key_CP; + } +} + +// ISO-8859-1 to UCS-2, directly into vector key buffer +static void set_key(char *_key, int index) +{ + UTF8 *s = (UTF8*)_key; + UTF16 *d = (UTF16*)saved_key[index]; + for (key_length = 0; s[key_length]; key_length++) + d[key_length] = s[key_length]; + d[key_length] = 0; + key_length <<= 1; + +} + +// Legacy codepage to UCS-2, directly into vector key buffer +static void set_key_CP(char *_key, int index) +{ + key_length = enc_to_utf16((UTF16*)saved_key[index], PLAINTEXT_LENGTH + 1, + (unsigned char*)_key, strlen(_key)); + if (key_length <= 0) + key_length = strlen16((UTF16*)saved_key[index]); + key_length <<= 1; +} + +// UTF-8 to UCS-2, directly into vector key buffer +static void set_key_utf8(char *_key, int index) +{ + key_length = utf8_to_utf16((UTF16*)saved_key[index], PLAINTEXT_LENGTH + 1, + (unsigned char*)_key, strlen(_key)); + if (key_length <= 0) + key_length = strlen16((UTF16*)saved_key[index]); + + key_length <<= 1; +} + +static char *get_key(int index) { + ((UTF16*)saved_key[index])[key_length>>1] = 0; + return (char*)utf16_to_enc((UTF16*)saved_key[index]); +} + +static int cmp_all(void *binary, int count) { + int index = 0; +#ifdef _OPENMP + for (; index < count; index++) +#endif + if (!memcmp(binary, crypt_out[index], BINARY_SIZE)) + return 1; + return 0; +} + +static int cmp_exact(char *source, int count) { + return (1); +} + +static int cmp_one(void * binary, int index) +{ + return !memcmp(binary, crypt_out[index], BINARY_SIZE); +} + +static void crypt_all(int count) { + int index = 0; +#ifdef _OPENMP +#pragma omp parallel for + for (index = 0; index < count; index++) +#endif + { + SHA512_CTX ctx; + memcpy(saved_key[index]+key_length, cursalt, SALT_SIZE); + SHA512_Init(&ctx ); + SHA512_Update(&ctx, saved_key[index], key_length+SALT_SIZE ); + SHA512_Final((unsigned char *)crypt_out[index], &ctx); + } +} + +static void * binary(char *ciphertext) +{ + static char *realcipher; + int i; + + if(!realcipher) realcipher = mem_alloc_tiny(BINARY_SIZE, MEM_ALIGN_WORD); + + for(i=0;i> 8) & (SALT_HASH_SIZE - 1); +} + +struct fmt_main fmt_mssql12 = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, +#if FMT_MAIN_VERSION > 9 + DEFAULT_ALIGN, +#endif + SALT_SIZE, +#if FMT_MAIN_VERSION > 9 + DEFAULT_ALIGN, +#endif + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT | FMT_UNICODE | FMT_UTF8 | FMT_OMP, + tests + }, { + init, + prepare, + valid, + fmt_default_split, + binary, + get_salt, +#if FMT_MAIN_VERSION > 9 + fmt_default_source, +#endif + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + binary_hash_5, + binary_hash_6 + }, + salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + get_hash_3, + get_hash_4, + get_hash_5, + get_hash_6 + }, + cmp_all, + cmp_one, + cmp_exact + } +}; -- 1.7.11.5