📄 afs_fmt.c
字号:
/* * This file is part of John the Ripper password cracker, * Copyright (c) 1996-98 by Solar Designer */#include <string.h>#include "arch.h"#include "misc.h"#include "params.h"#include "DES_std.h"#include "common.h"#include "formats.h"#define FORMAT_LABEL "afs"#define FORMAT_NAME "Kerberos AFS DES"#define BENCHMARK_COMMENT ""#define BENCHMARK_LENGTH 8#define PLAINTEXT_LENGTH 63#define CIPHERTEXT_LENGTH 20static struct fmt_tests tests[] = { {"$K4$e35e9294ecef926d,0123", "U*U*U*U*"}, {"$K4$64c7c2aedccd70d6,0123456789", "U*U***U*"}, {"$K4$d9e985b36268f168,01234567", "U*U***U"}, {"$K4$b9615786dfb53297,longcellname", "longpassword"}, {"$K4$a8dc8aeaa2c48a97,", ""}, {"$K4$dfda85c7619183a2,XXXXXXXX", "XXXXXXXX"}, {"$K4$e3e59de6f1d5eaf4,cell", "password355"}, {"$K4$b02cc24aefbc865b,", "thisisaverylongpassword"}, {NULL}};#define ALGORITHM_NAME DES_STD_ALGORITHM_NAME#define BINARY_SIZE (3 * ARCH_SIZE)#define SALT_SIZE 40#define MIN_KEYS_PER_CRYPT 0x80#define MAX_KEYS_PER_CRYPT 0x100#define AFS_SALT "#~..........." /* An invalid salt */#define AFS_long_key "52912979" /* "kerberos" >> 1 */#define AFS_long_IV "kerberos" /* :-) *//* * They're only using 8 characters of crypt(3) output, effectively reducing * the hash size to 48 bits... We are emulating this behavior with bitmasks. */#define AFS_MASK_16 DES_DO_SIZE_FIX(0xFFF9FFF9)#if ARCH_BITS >= 64#define AFS_BINARY_MASK \ (AFS_MASK_16 | ((ARCH_WORD)AFS_MASK_16 << 32))#else#define AFS_BINARY_MASK AFS_MASK_16#endif#define TOTAL_BINARY_MASK (DES_BINARY_MASK & AFS_BINARY_MASK)#if ARCH_LITTLE_ENDIAN#define AFS_swap(x, y) \ (y) = (x);#else#define AFS_swap(x, y) \{ \ tmp = (x); \ tmp = (tmp << 16) | (tmp >> 16); \ (y) = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); \}#endifstatic struct { union { double dummy; DES_binary binary; } aligned; int is_long; char key[PLAINTEXT_LENGTH + 1];} buffer[MAX_KEYS_PER_CRYPT];static char cell[SALT_SIZE + 8];static int cell_length;static ARCH_WORD AFS_salt_binary;static union { double dummy; DES_KS data;} AFS_long_KS;static DES_binary AFS_long_IV_binary;static void init(){ ARCH_WORD_32 block[2];#if !ARCH_LITTLE_ENDIAN ARCH_WORD_32 tmp;#endif DES_std_init(); AFS_salt_binary = DES_std_get_salt(AFS_SALT); DES_raw_set_key(AFS_long_key); memcpy(AFS_long_KS.data, DES_KS_current, sizeof(DES_KS)); memcpy(block, AFS_long_IV, 8);#if !ARCH_LITTLE_ENDIAN AFS_swap(block[0], block[0]); AFS_swap(block[1], block[1]);#endif DES_std_set_block(block[0], block[1]); memcpy(AFS_long_IV_binary, DES_IV, sizeof(DES_binary));}static int valid(char *ciphertext){ char *pos; int index, count; unsigned int value; if (strncmp(ciphertext, "$K4$", 4)) return 0; for (pos = &ciphertext[4]; atoi16[(ARCH_INDEX)*pos] != 0x7F; pos++); if (*pos != ',' || pos - ciphertext != CIPHERTEXT_LENGTH) return 0; for (index = 0; index < 16; index += 2) { value = (int)atoi16[(ARCH_INDEX)ciphertext[index + 4]] << 4; value |= atoi16[(ARCH_INDEX)ciphertext[index + 5]]; count = 0; if (value) do { count++; } while ((value &= value - 1)); if (!(count & 1)) return 0; } return 1;}static void *get_binary(char *ciphertext){ static ARCH_WORD out[6]; char base64[14]; int known_long; int index; unsigned int value; out[0] = out[1] = 0; strcpy(base64, AFS_SALT); known_long = 0; for (index = 0; index < 16; index += 2) { value = (int)atoi16[(ARCH_INDEX)ciphertext[index + 4]] << 4; value |= atoi16[(ARCH_INDEX)ciphertext[index + 5]]; out[index >> 3] |= (value | 1) << ((index << 2) & 0x18); if (atoi64[value >>= 1] == 0x7F) known_long = 1; else base64[(index >> 1) + 2] = value; } if (known_long) out[2] = ~(ARCH_WORD)0; else memcpy(&out[2], DES_std_get_binary(base64), 16); return out;}static void *salt(char *ciphertext){ static char out[SALT_SIZE + 1]; strncpy(out, &ciphertext[21], SALT_SIZE); out[SALT_SIZE] = 0; return strlwr(out);}static int binary_hash_0(void *binary){ if (((ARCH_WORD *)binary)[2] == ~(ARCH_WORD)0) return *(ARCH_WORD *)binary & 0xF; return DES_STD_HASH_0(((ARCH_WORD *)binary)[2]);}static int binary_hash_1(void *binary){ if (((ARCH_WORD *)binary)[2] == ~(ARCH_WORD)0) return *(ARCH_WORD *)binary & 0xFF; return DES_STD_HASH_1(((ARCH_WORD *)binary)[2]);}static int binary_hash_2(void *binary){ if (((ARCH_WORD *)binary)[2] == ~(ARCH_WORD)0) return *(ARCH_WORD *)binary & 0xFFF; return DES_STD_HASH_2(((ARCH_WORD *)binary)[2]);}static ARCH_WORD to_short_hash(int index){ char base64[14]; char *ptr; int pos, value; strcpy(base64, AFS_SALT); ptr = &base64[2]; for (pos = 0; pos < 8; pos++) { value = buffer[index].aligned.binary[pos >> 2]; value >>= ((pos & 3) << 3) + 1; value &= 0x7F; if (atoi64[value] == 0x7F) return ~(ARCH_WORD)0; *ptr++ = value; } return *DES_std_get_binary(base64);}static int get_hash_0(int index){ ARCH_WORD binary; if (buffer[index].is_long) { if ((binary = to_short_hash(index)) == ~(ARCH_WORD)0) return buffer[index].aligned.binary[0] & 0xF; } else binary = buffer[index].aligned.binary[0] & AFS_BINARY_MASK; return DES_STD_HASH_0(binary);}static int get_hash_1(int index){ ARCH_WORD binary; if (buffer[index].is_long) { if ((binary = to_short_hash(index)) == ~(ARCH_WORD)0) return buffer[index].aligned.binary[0] & 0xFF; } else binary = buffer[index].aligned.binary[0] & AFS_BINARY_MASK; return DES_STD_HASH_1(binary);}static int get_hash_2(int index){ ARCH_WORD binary; if (buffer[index].is_long) { if ((binary = to_short_hash(index)) == ~(ARCH_WORD)0) return buffer[index].aligned.binary[0] & 0xFFF; } else binary = buffer[index].aligned.binary[0] & AFS_BINARY_MASK; return DES_STD_HASH_2(binary);}static void set_salt(void *salt){ strnzcpy(cell, salt, SALT_SIZE); memset(&cell[cell_length = strlen(cell)], 0, 8);}static void set_key(char *key, int index){ strnzcpy(buffer[index].key, key, PLAINTEXT_LENGTH + 1);}static char *get_key(int index){ return buffer[index].key;}static void crypt_all(int count){ int index, pos, length; char xor[8]; ARCH_WORD_32 space[(PLAINTEXT_LENGTH + SALT_SIZE + 8) / 4 + 1]; ARCH_WORD_32 *ptr; ARCH_WORD space_binary[(PLAINTEXT_LENGTH + SALT_SIZE + 8) / 2 + 1]; ARCH_WORD *ptr_binary; unsigned ARCH_WORD block[2]; union { double dummy; DES_binary data; } binary; ARCH_WORD_32 key[2];#if !ARCH_LITTLE_ENDIAN ARCH_WORD_32 tmp;#endif DES_std_set_salt(AFS_salt_binary); memset(DES_IV, 0, sizeof(DES_IV)); DES_count = 25; for (index = 0; index < count; index++) if ((length = strlen(buffer[index].key)) > 8) buffer[index].is_long = length; else { buffer[index].is_long = 0; memcpy(xor, cell, 8); for (pos = 0; pos < 8 && buffer[index].key[pos]; pos++) xor[pos] ^= buffer[index].key[pos]; for (pos = 0; pos < 8; pos++) if (!xor[pos]) xor[pos] = 'X'; DES_std_set_key(xor); DES_std_crypt(DES_KS_current, buffer[index].aligned.binary); } DES_std_set_salt(0); DES_count = 1; for (index = 0; index < count; index++) if ((length = buffer[index].is_long)) { memcpy(space, buffer[index].key, length); memcpy((char *)space + length, cell, cell_length + 8); memcpy(binary.data, AFS_long_IV_binary, sizeof(binary.data)); length += cell_length; ptr = space; ptr_binary = space_binary; do { AFS_swap(*ptr++, block[0]); AFS_swap(*ptr++, block[1]); DES_std_set_block(block[0], block[1]); *ptr_binary++ = DES_IV[0]; DES_IV[0] ^= binary.data[0]; *ptr_binary++ = DES_IV[1]; DES_IV[1] ^= binary.data[1];#if ARCH_BITS < 64 *ptr_binary++ = DES_IV[2]; DES_IV[2] ^= binary.data[2]; *ptr_binary++ = DES_IV[3]; DES_IV[3] ^= binary.data[3];#endif DES_std_crypt(AFS_long_KS.data, binary.data); length -= 8; } while (length > 0); DES_std_get_block(binary.data, block); AFS_swap(block[0] >> 1, key[0]); AFS_swap(block[1] >> 1, key[1]); DES_raw_set_key((char *)key); length = buffer[index].is_long + cell_length; ptr_binary = space_binary; do { DES_IV[0] = binary.data[0] ^ *ptr_binary++; DES_IV[1] = binary.data[1] ^ *ptr_binary++;#if ARCH_BITS < 64 DES_IV[2] = binary.data[2] ^ *ptr_binary++; DES_IV[3] = binary.data[3] ^ *ptr_binary++;#endif DES_std_crypt(DES_KS_current, binary.data); length -= 8; } while (length > 0); DES_std_get_block(binary.data, block); buffer[index].aligned.binary[0] = block[0] | 0x01010101; buffer[index].aligned.binary[1] = block[1] | 0x01010101; }}static int cmp_all(void *binary, int count){ int index; for (index = 0; index < count; index++) if (buffer[index].is_long) { if (*(unsigned ARCH_WORD *)binary == buffer[index].aligned.binary[0]) return 1; } else { if (((unsigned ARCH_WORD *)binary)[2] == (buffer[index].aligned.binary[0] & TOTAL_BINARY_MASK)) return 1; } return 0;}static int cmp_one(void *binary, int index){ if (buffer[index].is_long) return *(unsigned ARCH_WORD *)binary == buffer[index].aligned.binary[0]; return ((unsigned ARCH_WORD *)binary)[2] == (buffer[index].aligned.binary[0] & TOTAL_BINARY_MASK);}static int cmp_exact(char *source, int index){ ARCH_WORD *binary; int word; binary = get_binary(source); if (buffer[index].is_long) { if ((unsigned ARCH_WORD)binary[0] != buffer[index].aligned.binary[0] || (unsigned ARCH_WORD)binary[1] != buffer[index].aligned.binary[1]) return 0; } else { for (word = 0; word < 16 / DES_SIZE; word++) if ((unsigned ARCH_WORD)binary[word + 2] != (buffer[index].aligned.binary[word] & TOTAL_BINARY_MASK)) return 0; } return 1;}struct fmt_main fmt_AFS = { { 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, salt, { binary_hash_0, binary_hash_1, binary_hash_2 }, fmt_default_salt_hash, set_salt, set_key, get_key, crypt_all, { get_hash_0, get_hash_1, get_hash_2 }, cmp_all, cmp_one, cmp_exact }};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -