From f11853b4dbc27ebdf441a473c2965108f4e06aae Mon Sep 17 00:00:00 2001 From: Dhiru Kholia Date: Mon, 20 Aug 2012 12:25:09 +0530 Subject: [PATCH] Add support for cracking MS SQL 2012 hashes --- src/mssql12_fmt_plug.c | 268 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 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..cc89ed0 --- /dev/null +++ b/src/mssql12_fmt_plug.c @@ -0,0 +1,268 @@ +/* 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" + +#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 + +#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 unsigned char *saved_key; +static ARCH_WORD_32 crypt_key[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;lmethods.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; + 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, PLAINTEXT_LENGTH + 1, + (unsigned char*)_key, strlen(_key)); + if (key_length <= 0) + key_length = strlen16((UTF16*)saved_key); + 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, PLAINTEXT_LENGTH + 1, + (unsigned char*)_key, strlen(_key)); + if (key_length <= 0) + key_length = strlen16((UTF16*)saved_key); + + key_length <<= 1; +} + +static char *get_key(int index) { + ((UTF16*)saved_key)[key_length>>1] = 0; + return (char*)utf16_to_enc((UTF16*)saved_key); +} + +static int cmp_all(void *binary, int count) { + return !memcmp(binary, crypt_key, BINARY_SIZE); +} + +static int cmp_exact(char *source, int count){ + return (1); +} + +static int cmp_one(void * binary, int index) +{ + return cmp_all(binary, index); +} + +static void crypt_all(int count) { + SHA512_CTX ctx; + memcpy(saved_key+key_length, cursalt, SALT_SIZE); + SHA512_Init( &ctx ); + SHA512_Update( &ctx, saved_key, key_length+SALT_SIZE ); + SHA512_Final( (unsigned char *) crypt_key, &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, + 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