//Based on the work by Tim Medin //Port from his Pythonscript to John by Michael Kramer (SySS GmbH) //Copyright 2015 Michael Kramer /*Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #if FMT_EXTERNS_H extern struct fmt_main fmt_krb5tgs; #elif FMT_REGISTERS_H john_register_one(&fmt_krb5tgs); #else #include #include #include #include #include "misc.h" #include "formats.h" #include "common.h" #include "memdbg.h" #define FORMAT_LABEL "krb5tgs" #define FORMAT_NAME "Kerberos5 TGS" #define ALGORITHM_NAME "NTLM/HMAC/RC4Crypt" #define BENCHMARK_COMMENT "" #define BENCHMARK_LENGTH -1 #define PLAINTEXT_LENGTH 32 #define CIPHERTEXT_LENGTH 1500 #define BINARY_SIZE 1500 #define SALT_SIZE 16 #define BINARY_ALIGN 1 #define SALT_ALIGN 1 #define MIN_KEYS_PER_CRYPT 1 #define MAX_KEYS_PER_CRYPT 1 //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 struct fmt_tests tests[] = { }; static unsigned char (*crypt_key)[SALT_SIZE]; static char (*saved_key)[PLAINTEXT_LENGTH + 1]; static unsigned char cursalt[SALT_SIZE]; unsigned char realcipher[BINARY_SIZE]; static int edata2len; static void init(struct fmt_main *self) { crypt_key = mem_calloc_tiny( (sizeof(*crypt_key) + sizeof(*saved_key)) * self->params.max_keys_per_crypt, MEM_ALIGN_CACHE); saved_key = (void *)((char *)crypt_key + sizeof(*crypt_key) * self->params.max_keys_per_crypt); } // ntlm_crypt function from the JTR site static void ntlm_crypt(char *key, unsigned int *output) { unsigned int nt_buffer[16]; int i=0; int length=strlen(key); memset(nt_buffer,0,16*4); //The length of key need to be <= 27 for(;i> 29); d += (c ^ (a & (b ^ c))) + nt_buffer[1] ;d = (d << 7 ) | (d >> 25); c += (b ^ (d & (a ^ b))) + nt_buffer[2] ;c = (c << 11) | (c >> 21); b += (a ^ (c & (d ^ a))) + nt_buffer[3] ;b = (b << 19) | (b >> 13); a += (d ^ (b & (c ^ d))) + nt_buffer[4] ;a = (a << 3 ) | (a >> 29); d += (c ^ (a & (b ^ c))) + nt_buffer[5] ;d = (d << 7 ) | (d >> 25); c += (b ^ (d & (a ^ b))) + nt_buffer[6] ;c = (c << 11) | (c >> 21); b += (a ^ (c & (d ^ a))) + nt_buffer[7] ;b = (b << 19) | (b >> 13); a += (d ^ (b & (c ^ d))) + nt_buffer[8] ;a = (a << 3 ) | (a >> 29); d += (c ^ (a & (b ^ c))) + nt_buffer[9] ;d = (d << 7 ) | (d >> 25); c += (b ^ (d & (a ^ b))) + nt_buffer[10] ;c = (c << 11) | (c >> 21); b += (a ^ (c & (d ^ a))) + nt_buffer[11] ;b = (b << 19) | (b >> 13); a += (d ^ (b & (c ^ d))) + nt_buffer[12] ;a = (a << 3 ) | (a >> 29); d += (c ^ (a & (b ^ c))) + nt_buffer[13] ;d = (d << 7 ) | (d >> 25); c += (b ^ (d & (a ^ b))) + nt_buffer[14] ;c = (c << 11) | (c >> 21); b += (a ^ (c & (d ^ a))) + nt_buffer[15] ;b = (b << 19) | (b >> 13); /* Round 2 */ a += ((b & (c | d)) | (c & d)) + nt_buffer[0] +SQRT_2; a = (a<<3 ) | (a>>29); d += ((a & (b | c)) | (b & c)) + nt_buffer[4] +SQRT_2; d = (d<<5 ) | (d>>27); c += ((d & (a | b)) | (a & b)) + nt_buffer[8] +SQRT_2; c = (c<<9 ) | (c>>23); b += ((c & (d | a)) | (d & a)) + nt_buffer[12]+SQRT_2; b = (b<<13) | (b>>19); a += ((b & (c | d)) | (c & d)) + nt_buffer[1] +SQRT_2; a = (a<<3 ) | (a>>29); d += ((a & (b | c)) | (b & c)) + nt_buffer[5] +SQRT_2; d = (d<<5 ) | (d>>27); c += ((d & (a | b)) | (a & b)) + nt_buffer[9] +SQRT_2; c = (c<<9 ) | (c>>23); b += ((c & (d | a)) | (d & a)) + nt_buffer[13]+SQRT_2; b = (b<<13) | (b>>19); a += ((b & (c | d)) | (c & d)) + nt_buffer[2] +SQRT_2; a = (a<<3 ) | (a>>29); d += ((a & (b | c)) | (b & c)) + nt_buffer[6] +SQRT_2; d = (d<<5 ) | (d>>27); c += ((d & (a | b)) | (a & b)) + nt_buffer[10]+SQRT_2; c = (c<<9 ) | (c>>23); b += ((c & (d | a)) | (d & a)) + nt_buffer[14]+SQRT_2; b = (b<<13) | (b>>19); a += ((b & (c | d)) | (c & d)) + nt_buffer[3] +SQRT_2; a = (a<<3 ) | (a>>29); d += ((a & (b | c)) | (b & c)) + nt_buffer[7] +SQRT_2; d = (d<<5 ) | (d>>27); c += ((d & (a | b)) | (a & b)) + nt_buffer[11]+SQRT_2; c = (c<<9 ) | (c>>23); b += ((c & (d | a)) | (d & a)) + nt_buffer[15]+SQRT_2; b = (b<<13) | (b>>19); /* Round 3 */ a += (d ^ c ^ b) + nt_buffer[0] + SQRT_3; a = (a << 3 ) | (a >> 29); d += (c ^ b ^ a) + nt_buffer[8] + SQRT_3; d = (d << 9 ) | (d >> 23); c += (b ^ a ^ d) + nt_buffer[4] + SQRT_3; c = (c << 11) | (c >> 21); b += (a ^ d ^ c) + nt_buffer[12] + SQRT_3; b = (b << 15) | (b >> 17); a += (d ^ c ^ b) + nt_buffer[2] + SQRT_3; a = (a << 3 ) | (a >> 29); d += (c ^ b ^ a) + nt_buffer[10] + SQRT_3; d = (d << 9 ) | (d >> 23); c += (b ^ a ^ d) + nt_buffer[6] + SQRT_3; c = (c << 11) | (c >> 21); b += (a ^ d ^ c) + nt_buffer[14] + SQRT_3; b = (b << 15) | (b >> 17); a += (d ^ c ^ b) + nt_buffer[1] + SQRT_3; a = (a << 3 ) | (a >> 29); d += (c ^ b ^ a) + nt_buffer[9] + SQRT_3; d = (d << 9 ) | (d >> 23); c += (b ^ a ^ d) + nt_buffer[5] + SQRT_3; c = (c << 11) | (c >> 21); b += (a ^ d ^ c) + nt_buffer[13] + SQRT_3; b = (b << 15) | (b >> 17); a += (d ^ c ^ b) + nt_buffer[3] + SQRT_3; a = (a << 3 ) | (a >> 29); d += (c ^ b ^ a) + nt_buffer[11] + SQRT_3; d = (d << 9 ) | (d >> 23); c += (b ^ a ^ d) + nt_buffer[7] + SQRT_3; c = (c << 11) | (c >> 21); b += (a ^ d ^ c) + nt_buffer[15] + SQRT_3; b = (b << 15) | (b >> 17); output[0] = a + INIT_A; output[1] = b + INIT_B; output[2] = c + INIT_C; output[3] = d + INIT_D; } static void * binary (char *ciphertext) { int i; edata2len = (strlen(ciphertext)-33)/2; for (i=0; i < edata2len; i++){ realcipher[i] = atoi16[ARCH_INDEX(ciphertext[i*2+33])]*16 + atoi16[ARCH_INDEX(ciphertext[i*2+1+33])]; } return ((void *) realcipher); } static void *get_salt(char *ciphertext) { int i; static unsigned char realsalt[SALT_SIZE]; for (i=0; i < SALT_SIZE; i++){ realsalt[i]=atoi16[ARCH_INDEX(ciphertext[i*2])]*16 + atoi16[ARCH_INDEX(ciphertext[i*2+1])]; } return realsalt; } static int salt_hash(void *salt){ return 0; } static void set_salt(void *salt){ memcpy(cursalt, salt, SALT_SIZE); int i; } static int valid (char *ciphertext, struct fmt_main *self) { char h = '$'; if (ciphertext[32]!=h){ return 0; } return 1; } static void set_key (char *key, int index) { strnzcpy (saved_key[index], key, PLAINTEXT_LENGTH + 1); } static char * get_key (int index) { return saved_key[index]; } static int cmp_all (void *binary, int count) { unsigned char K1[SALT_SIZE]; unsigned char K2[SALT_SIZE]; unsigned char* K3; unsigned char edata1[SALT_SIZE]; unsigned char edata2[edata2len]; unsigned char* checksum; unsigned char ddata[edata2len]; int i; memcpy(K1, crypt_key[0], SALT_SIZE); memcpy(K2, crypt_key[0], SALT_SIZE); memcpy(edata1, cursalt, SALT_SIZE); memcpy(edata2, binary, edata2len); K3 = HMAC(EVP_md5(), K1, 16, edata1, 16, NULL, NULL); RC4_KEY key; RC4_set_key(&key, 16, K3); RC4(&key, edata2len, edata2, ddata); checksum = HMAC(EVP_md5(), K2, 16, ddata, edata2len, NULL, NULL); if (!memcmp(edata1,checksum,16)){ return 1; } return 0; } static int cmp_one (void *binary, int index) { return 1; } static int cmp_exact (char *source, int index) { return 1; } static int crypt_all(int *pcount, struct db_salt *salt) { unsigned int output[4]; ntlm_crypt(saved_key[0], output); unsigned char* key = (unsigned char*) output; char data[4] = {2,0,0,0}; unsigned char* K1; int i; K1 = HMAC(EVP_md5(), key, 16, data, 4, NULL, NULL); memcpy(crypt_key[0], K1, SALT_SIZE); return 1; } static int get_hash1(int index) { return crypt_key[index][0] & 0xf; } static int get_hash2(int index) { return crypt_key[index][0] & 0xff; } static int get_hash3(int index) { return crypt_key[index][0] & 0xfff; } static int get_hash4(int index) { return crypt_key[index][0] & 0xffff; } static int get_hash5(int index) { return crypt_key[index][0] & 0xfffff; } static int get_hash6(int index) { return crypt_key[index][0] & 0xffffff; } static int get_hash7(int index) { return crypt_key[index][0] & 0x7ffffff; } static int binary_hash1(void * binary) { return *(ARCH_WORD_32 *)binary & 0xf; } static int binary_hash2(void * binary) { return *(ARCH_WORD_32 *)binary & 0xff; } static int binary_hash3(void * binary) { return *(ARCH_WORD_32 *)binary & 0xfff; } static int binary_hash4(void * binary) { return *(ARCH_WORD_32 *)binary & 0xffff; } static int binary_hash5(void * binary) { return *(ARCH_WORD_32 *)binary & 0xfffff; } static int binary_hash6(void * binary) { return *(ARCH_WORD_32 *)binary & 0xffffff; } static int binary_hash7(void * binary) { return *(ARCH_WORD_32 *)binary & 0x7ffffff; } struct fmt_main fmt_krb5tgs = { { FORMAT_LABEL, FORMAT_NAME, ALGORITHM_NAME, BENCHMARK_COMMENT, BENCHMARK_LENGTH, PLAINTEXT_LENGTH, BINARY_SIZE, BINARY_ALIGN, SALT_SIZE, SALT_ALIGN, MIN_KEYS_PER_CRYPT, MAX_KEYS_PER_CRYPT, FMT_CASE | FMT_8_BIT | FMT_OMP, #if FMT_MAIN_VERSION > 11 { NULL }, #endif tests }, { init, fmt_default_done, fmt_default_reset, fmt_default_prepare, valid, fmt_default_split, binary, get_salt, #if FMT_MAIN_VERSION > 11 { NULL }, #endif fmt_default_source, { binary_hash1, binary_hash2, binary_hash3, binary_hash4, binary_hash5, binary_hash6, binary_hash7 }, salt_hash, set_salt, set_key, get_key, fmt_default_clear_keys, crypt_all, { get_hash1, get_hash2, get_hash3, get_hash4, get_hash5, get_hash6, get_hash7 }, cmp_all, cmp_one, cmp_exact } }; #endif