Differences

This shows you the differences between two versions of the page.

Link to this comparison view

MSCash2 [2010/12/26 12:03] (current)
The_S3nf created
Line 1: Line 1:
 +==== MSCash2 Algorithm ====
  
 +=== Description ===
 +
 +Domain cached credentials (DCC) are cached domain logon information that are stored locally in the [[wp>​Windows_Registry|Windows registry]] of Windows operating systems (cf. [[MSCash Algorithm]]). With the release of the Windows Vista operating system, [[wp>​Microsoft|Microsoft]] introduced a new hash algorithm for generating these Domain Cached Credentials. This new algorithm increased the cost of password guessing attacks by several orders of magnitude.
 +
 +=== Algorithm ===
 +
 +**Parameters**:​
 +  * username (login name)\\ ​
 +  * password\\ ​
 +**Output**: Hash value which is a 128-bit value (4 integers of 32 bits)
 +
 +  - Apply [[NTLM]] to the password
 +  - Convert the lower-case username to Unicode
 +  - Append the Unicode username to the calculated NTLM hash and apply [[MD4]]
 +  - The resulting hash value is the old DCC hash (cf. [[MSCash Algorithm]])
 +  - Apply PBKDF2 with SHA1 as HMAC, an iteration count of 10240, the old DCC hash as password and the Unicode username as salt in order to generate the DCC2 (MSCash2) hash. Only the first 128 bits of the resulting 160 bits are used.
 +
 +In short: DCC2 = PBKDF2(HMAC-SHA1,​ 10240, DCC1, username)
 +
 +=== Weakness ===
 +
 +None so far. It is really expensive to generate a single DCC2 hash, even on modern computer hardware.
 +
 +=== Secure message length ===
 +
 +The far from optimized MSCash2 algorithm provided in the sample code below and used in the corresponding MSCash2 JtR patch generates about 330 DCC2 hashes/sec (MSCash2) on an Intel Core2 Quad CPU Q6700, compared to 58.8 millon DCC1 hashes/sec (MSCash).
 +
 +In other words, incremental brute-force attacking for different search spaces, depending on the character set and the password length, will take ages. So it is a good idea to do some intelligent password guessing when attacking DCC2 hashes, i.e. rule-based dictionary and probabilistic attacks.
 +
 +=== Implementation'​s optimizations ====
 +
 +None.
 +
 +=== Sample Code ===
 +<code c>
 +/* Domain Cached Credentials 2 (MSCash2) example ​
 + * written by S3nf <thes3nf at googlemail.com>​ in 2010
 + * a slow but working implementation
 + *
 + * Generating Domain Cached Credentials for modern Windows operating systems, supporting:
 + ​* ​    - Windows Vista
 + ​* ​    - Windows 7
 + ​* ​    - Windows Server 2008
 + *
 + * This software is based on:
 + ​* ​    - the MSCASH patch for john written by Alain Espinosa <​alainesp at gmail.com>​ in 2007
 + ​* ​    - RFC 1320 - The MD4 Message-Digest Algorithm
 + ​* ​    - RFC 2104 - HMAC: Keyed-Hashing for Message Authentication
 + ​* ​    - RFC 3174 - US Secure Hash Algorithm 1 (SHA1)
 + ​* ​    - the HMAC-SHA1 implementation of the PolarSSL open source cryptagraphic library (http://​polarssl.org/​) ​
 + *
 + * This software was written by S3nf in 2010. No copyright is claimed, and the software is hereby placed in
 + * the public domain. In case this attempt to disclaim copyright and place the software in the public domain
 + * is deemed null and void, then the software is Copyright (c) 2010 S3nf 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.
 + *
 + */
 +
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +#include <​string.h>​
 +
 +#define ITERATIONS ​                 10240
 +
 +#define INIT_MD4_A ​                 0x67452301
 +#define INIT_MD4_B ​                 0xefcdab89
 +#define INIT_MD4_C ​                 0x98badcfe
 +#define INIT_MD4_D ​                 0x10325476
 + 
 +#define SQRT_2 ​                     0x5a827999
 +#define SQRT_3 ​                     0x6ed9eba1
 + 
 +#define SHA1_DIGEST_LENGTH ​         20
 +
 +#define INIT_SHA1_A ​                ​0x67452301
 +#define INIT_SHA1_B ​                ​0xEFCDAB89
 +#define INIT_SHA1_C ​                ​0x98BADCFE
 +#define INIT_SHA1_D ​                ​0x10325476
 +#define INIT_SHA1_E ​                ​0xC3D2E1F0
 +
 +#ifndef GET_WORD_32_BE
 +#define GET_WORD_32_BE(n,​b,​i) ​                          \
 +{                                                       \
 +    (n) = ( (unsigned long) (b)[(i) ​   ] << 24 )        \
 +        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
 +        | ( (unsigned long) (b)[(i) + 2] << ​ 8 )        \
 +        | ( (unsigned long) (b)[(i) + 3]       ​); ​      \
 +}
 +#endif
 +
 +#ifndef PUT_WORD_32_BE
 +#define PUT_WORD_32_BE(n,​b,​i) ​                          \
 +{                                                       \
 +    (b)[(i) ​   ] = (unsigned char) ( (n) >> 24 );       \
 +    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
 +    (b)[(i) + 2] = (unsigned char) ( (n) >> ​ 8 );       \
 +    (b)[(i) + 3] = (unsigned char) ( (n)       ​); ​      \
 +}
 +#endif
 +
 +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
 +
 +#define R(t)                                            \
 +(                                                       \
 +    temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \
 +           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F], ​     \
 +    ( W[t & 0x0F] = S(temp,1) )                         \
 +)
 +
 +#define P(a,​b,​c,​d,​e,​x) ​                                 \
 +{                                                       \
 +    e += S(a,5) + F(b,c,d) + K + x; b = S(b,​30); ​       \
 +}
 +
 +
 +/*
 + * byte2hexstring
 + * convert byte array to hex string
 + */
 +unsigned char *byte2hexstring(unsigned char * byte, unsigned int len) {
 +    unsigned int i;
 +    unsigned char *hexstring;
 +
 +    hexstring = malloc(len * 2 + 1);
 +    bzero(hexstring,​ 2 * len + 1);
 +
 +    for (i = 0; i < len; i++)
 +        sprintf(&​hexstring[2 * i], "​%02x",​ byte[i]);
 +
 +    return hexstring;
 +}
 +
 +
 +/*
 + * hmac_sha1
 + * based on RFC 2104, RFC 3174 and the HMAC-SHA1 implementation of the PolarSSL ​
 + * open source cryptographic library (http://​www.polarssl.org)
 + */
 +static void hmac_sha1(const unsigned char *key, unsigned int keylen, const unsigned char *input, unsigned int inputlen, unsigned char *output)
 +{
 +    unsigned int i, temp, W[16];
 +    unsigned int A, B, C, D, E, state[5];
 +    unsigned char buf[64];
 +    unsigned char ipad[64];
 +    unsigned char opad[64];
 +
 +    memset(ipad,​ 0x36, 64);
 +    memset(opad,​ 0x5C, 64);
 +    memset(buf, 0, 64);
 +    ​
 +    // step 1: append zeros to the end of K to create a B Byte string
 +    memcpy(buf, input, inputlen);
 +    buf[inputlen] = 0x80;
 +    PUT_WORD_32_BE((64 + inputlen) << 3, buf, 60);
 +
 +    // step 2: XOR (bitwise exclusive-OR) the B byte string computed in step 1 with ipad
 +    // step 5: XOR (bitwise exclusive-OR) the B byte string computed in step 1 with opad    ​
 +    for(i = 0; i < keylen; i++)
 +    {
 +        ipad[i] = ipad[i] ^ key[i];
 +        opad[i] = opad[i] ^ key[i];
 +    }
 +
 +    // step 3: append the stream of data '​text'​ to the B byte sting resulting from step 2
 +    // first part of stream (64 bytes) is ipad, second part of stream (64 bytes) is buf
 +    ​
 +    // step 4: apply H to the stream (ipad & buf) generated in step 3
 +    GET_WORD_32_BE(W[ 0], ipad,  0);
 +    GET_WORD_32_BE(W[ 1], ipad,  4);
 +    GET_WORD_32_BE(W[ 2], ipad,  8);
 +    GET_WORD_32_BE(W[ 3], ipad, 12);
 +    GET_WORD_32_BE(W[ 4], ipad, 16);
 +    GET_WORD_32_BE(W[ 5], ipad, 20);
 +    GET_WORD_32_BE(W[ 6], ipad, 24);
 +    GET_WORD_32_BE(W[ 7], ipad, 28);
 +    GET_WORD_32_BE(W[ 8], ipad, 32);
 +    GET_WORD_32_BE(W[ 9], ipad, 36);
 +    GET_WORD_32_BE(W[10],​ ipad, 40);
 +    GET_WORD_32_BE(W[11],​ ipad, 44);
 +    GET_WORD_32_BE(W[12],​ ipad, 48);
 +    GET_WORD_32_BE(W[13],​ ipad, 52);
 +    GET_WORD_32_BE(W[14],​ ipad, 56);
 +    GET_WORD_32_BE(W[15],​ ipad, 60);
 +
 +    A = INIT_SHA1_A;​
 +    B = INIT_SHA1_B;​
 +    C = INIT_SHA1_C;​
 +    D = INIT_SHA1_D;​
 +    E = INIT_SHA1_E;​
 +
 +#define F(x,y,z) (z ^ (x & (y ^ z)))
 +#define K 0x5A827999
 +
 +    P(A, B, C, D, E, W[0] );
 +    P(E, A, B, C, D, W[1] );
 +    P(D, E, A, B, C, W[2] );
 +    P(C, D, E, A, B, W[3] );
 +    P(B, C, D, E, A, W[4] );
 +    P(A, B, C, D, E, W[5] );
 +    P(E, A, B, C, D, W[6] );
 +    P(D, E, A, B, C, W[7] );
 +    P(C, D, E, A, B, W[8] );
 +    P(B, C, D, E, A, W[9] );
 +    P(A, B, C, D, E, W[10]);
 +    P(E, A, B, C, D, W[11]);
 +    P(D, E, A, B, C, W[12]);
 +    P(C, D, E, A, B, W[13]);
 +    P(B, C, D, E, A, W[14]);
 +    P(A, B, C, D, E, W[15]);
 +    P(E, A, B, C, D, R(16));
 +    P(D, E, A, B, C, R(17));
 +    P(C, D, E, A, B, R(18));
 +    P(B, C, D, E, A, R(19));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) (x ^ y ^ z)
 +#define K 0x6ED9EBA1
 +    ​
 +    P(A, B, C, D, E, R(20));
 +    P(E, A, B, C, D, R(21));
 +    P(D, E, A, B, C, R(22));
 +    P(C, D, E, A, B, R(23));
 +    P(B, C, D, E, A, R(24));
 +    P(A, B, C, D, E, R(25));
 +    P(E, A, B, C, D, R(26));
 +    P(D, E, A, B, C, R(27));
 +    P(C, D, E, A, B, R(28));
 +    P(B, C, D, E, A, R(29));
 +    P(A, B, C, D, E, R(30));
 +    P(E, A, B, C, D, R(31));
 +    P(D, E, A, B, C, R(32));
 +    P(C, D, E, A, B, R(33));
 +    P(B, C, D, E, A, R(34));
 +    P(A, B, C, D, E, R(35));
 +    P(E, A, B, C, D, R(36));
 +    P(D, E, A, B, C, R(37));
 +    P(C, D, E, A, B, R(38));
 +    P(B, C, D, E, A, R(39));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) ((x & y) | (z & (x | y)))
 +#define K 0x8F1BBCDC
 +
 +    P(A, B, C, D, E, R(40));
 +    P(E, A, B, C, D, R(41));
 +    P(D, E, A, B, C, R(42));
 +    P(C, D, E, A, B, R(43));
 +    P(B, C, D, E, A, R(44));
 +    P(A, B, C, D, E, R(45));
 +    P(E, A, B, C, D, R(46));
 +    P(D, E, A, B, C, R(47));
 +    P(C, D, E, A, B, R(48));
 +    P(B, C, D, E, A, R(49));
 +    P(A, B, C, D, E, R(50));
 +    P(E, A, B, C, D, R(51));
 +    P(D, E, A, B, C, R(52));
 +    P(C, D, E, A, B, R(53));
 +    P(B, C, D, E, A, R(54));
 +    P(A, B, C, D, E, R(55));
 +    P(E, A, B, C, D, R(56));
 +    P(D, E, A, B, C, R(57));
 +    P(C, D, E, A, B, R(58));
 +    P(B, C, D, E, A, R(59));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) (x ^ y ^ z)
 +#define K 0xCA62C1D6
 +
 +    P(A, B, C, D, E, R(60));
 +    P(E, A, B, C, D, R(61));
 +    P(D, E, A, B, C, R(62));
 +    P(C, D, E, A, B, R(63));
 +    P(B, C, D, E, A, R(64));
 +    P(A, B, C, D, E, R(65));
 +    P(E, A, B, C, D, R(66));
 +    P(D, E, A, B, C, R(67));
 +    P(C, D, E, A, B, R(68));
 +    P(B, C, D, E, A, R(69));
 +    P(A, B, C, D, E, R(70));
 +    P(E, A, B, C, D, R(71));
 +    P(D, E, A, B, C, R(72));
 +    P(C, D, E, A, B, R(73));
 +    P(B, C, D, E, A, R(74));
 +    P(A, B, C, D, E, R(75));
 +    P(E, A, B, C, D, R(76));
 +    P(D, E, A, B, C, R(77));
 +    P(C, D, E, A, B, R(78));
 +    P(B, C, D, E, A, R(79));
 +
 +#undef K
 +#undef F
 +
 +    A += INIT_SHA1_A;​
 +    B += INIT_SHA1_B;​
 +    C += INIT_SHA1_C;​
 +    D += INIT_SHA1_D;​
 +    E += INIT_SHA1_E;​
 +
 +    state[0] = A;
 +    state[1] = B;
 +    state[2] = C;
 +    state[3] = D;
 +    state[4] = E;
 +
 +    // process buf (2nd part of stream)
 +    GET_WORD_32_BE(W[ 0], buf,  0);
 +    GET_WORD_32_BE(W[ 1], buf,  4);
 +    GET_WORD_32_BE(W[ 2], buf,  8);
 +    GET_WORD_32_BE(W[ 3], buf, 12);
 +    GET_WORD_32_BE(W[ 4], buf, 16);
 +    GET_WORD_32_BE(W[ 5], buf, 20);
 +    GET_WORD_32_BE(W[ 6], buf, 24);
 +    GET_WORD_32_BE(W[ 7], buf, 28);
 +    GET_WORD_32_BE(W[ 8], buf, 32);
 +    GET_WORD_32_BE(W[ 9], buf, 36);
 +    GET_WORD_32_BE(W[10],​ buf, 40);
 +    GET_WORD_32_BE(W[11],​ buf, 44);
 +    GET_WORD_32_BE(W[12],​ buf, 48);
 +    GET_WORD_32_BE(W[13],​ buf, 52);
 +    GET_WORD_32_BE(W[14],​ buf, 56);
 +    GET_WORD_32_BE(W[15],​ buf, 60);
 +
 +#define F(x,y,z) (z ^ (x & (y ^ z)))
 +#define K 0x5A827999
 +
 +    P(A, B, C, D, E, W[0] );
 +    P(E, A, B, C, D, W[1] );
 +    P(D, E, A, B, C, W[2] );
 +    P(C, D, E, A, B, W[3] );
 +    P(B, C, D, E, A, W[4] );
 +    P(A, B, C, D, E, W[5] );
 +    P(E, A, B, C, D, W[6] );
 +    P(D, E, A, B, C, W[7] );
 +    P(C, D, E, A, B, W[8] );
 +    P(B, C, D, E, A, W[9] );
 +    P(A, B, C, D, E, W[10]);
 +    P(E, A, B, C, D, W[11]);
 +    P(D, E, A, B, C, W[12]);
 +    P(C, D, E, A, B, W[13]);
 +    P(B, C, D, E, A, W[14]);
 +    P(A, B, C, D, E, W[15]);
 +    P(E, A, B, C, D, R(16));
 +    P(D, E, A, B, C, R(17));
 +    P(C, D, E, A, B, R(18));
 +    P(B, C, D, E, A, R(19));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) (x ^ y ^ z)
 +#define K 0x6ED9EBA1
 +
 +    P(A, B, C, D, E, R(20));
 +    P(E, A, B, C, D, R(21));
 +    P(D, E, A, B, C, R(22));
 +    P(C, D, E, A, B, R(23));
 +    P(B, C, D, E, A, R(24));
 +    P(A, B, C, D, E, R(25));
 +    P(E, A, B, C, D, R(26));
 +    P(D, E, A, B, C, R(27));
 +    P(C, D, E, A, B, R(28));
 +    P(B, C, D, E, A, R(29));
 +    P(A, B, C, D, E, R(30));
 +    P(E, A, B, C, D, R(31));
 +    P(D, E, A, B, C, R(32));
 +    P(C, D, E, A, B, R(33));
 +    P(B, C, D, E, A, R(34));
 +    P(A, B, C, D, E, R(35));
 +    P(E, A, B, C, D, R(36));
 +    P(D, E, A, B, C, R(37));
 +    P(C, D, E, A, B, R(38));
 +    P(B, C, D, E, A, R(39));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) ((x & y) | (z & (x | y)))
 +#define K 0x8F1BBCDC
 +
 +    P(A, B, C, D, E, R(40));
 +    P(E, A, B, C, D, R(41));
 +    P(D, E, A, B, C, R(42));
 +    P(C, D, E, A, B, R(43));
 +    P(B, C, D, E, A, R(44));
 +    P(A, B, C, D, E, R(45));
 +    P(E, A, B, C, D, R(46));
 +    P(D, E, A, B, C, R(47));
 +    P(C, D, E, A, B, R(48));
 +    P(B, C, D, E, A, R(49));
 +    P(A, B, C, D, E, R(50));
 +    P(E, A, B, C, D, R(51));
 +    P(D, E, A, B, C, R(52));
 +    P(C, D, E, A, B, R(53));
 +    P(B, C, D, E, A, R(54));
 +    P(A, B, C, D, E, R(55));
 +    P(E, A, B, C, D, R(56));
 +    P(D, E, A, B, C, R(57));
 +    P(C, D, E, A, B, R(58));
 +    P(B, C, D, E, A, R(59));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) (x ^ y ^ z)
 +#define K 0xCA62C1D6
 +
 +    P(A, B, C, D, E, R(60));
 +    P(E, A, B, C, D, R(61));
 +    P(D, E, A, B, C, R(62));
 +    P(C, D, E, A, B, R(63));
 +    P(B, C, D, E, A, R(64));
 +    P(A, B, C, D, E, R(65));
 +    P(E, A, B, C, D, R(66));
 +    P(D, E, A, B, C, R(67));
 +    P(C, D, E, A, B, R(68));
 +    P(B, C, D, E, A, R(69));
 +    P(A, B, C, D, E, R(70));
 +    P(E, A, B, C, D, R(71));
 +    P(D, E, A, B, C, R(72));
 +    P(C, D, E, A, B, R(73));
 +    P(B, C, D, E, A, R(74));
 +    P(A, B, C, D, E, R(75));
 +    P(E, A, B, C, D, R(76));
 +    P(D, E, A, B, C, R(77));
 +    P(C, D, E, A, B, R(78));
 +    P(B, C, D, E, A, R(79));
 +
 +#undef K
 +#undef F
 +
 +    A += state[0];
 +    B += state[1];
 +    C += state[2];
 +    D += state[3];
 +    E += state[4];
 +
 +    PUT_WORD_32_BE(A,​ buf,  0);
 +    PUT_WORD_32_BE(B,​ buf,  4);
 +    PUT_WORD_32_BE(C,​ buf,  8);
 +    PUT_WORD_32_BE(D,​ buf, 12);
 +    PUT_WORD_32_BE(E,​ buf, 16);
 +
 +    buf[20] = 0x80;
 +    PUT_WORD_32_BE(0x2A0,​ buf, 60);
 +
 +    // step 6: append the stream of data '​text'​ to the B byte sting resulting from step 2
 +    // first part of stream (64 bytes) is opad, second part of stream (64 bytes) is the H result from step 4
 +
 +    // step 7: apply H to the stream (opad & buf) generated in step 6 and output the result
 +    GET_WORD_32_BE(W[ 0], opad,  0);
 +    GET_WORD_32_BE(W[ 1], opad,  4);
 +    GET_WORD_32_BE(W[ 2], opad,  8);
 +    GET_WORD_32_BE(W[ 3], opad, 12);
 +    GET_WORD_32_BE(W[ 4], opad, 16);
 +    GET_WORD_32_BE(W[ 5], opad, 20);
 +    GET_WORD_32_BE(W[ 6], opad, 24);
 +    GET_WORD_32_BE(W[ 7], opad, 28);
 +    GET_WORD_32_BE(W[ 8], opad, 32);
 +    GET_WORD_32_BE(W[ 9], opad, 36);
 +    GET_WORD_32_BE(W[10],​ opad, 40);
 +    GET_WORD_32_BE(W[11],​ opad, 44);
 +    GET_WORD_32_BE(W[12],​ opad, 48);
 +    GET_WORD_32_BE(W[13],​ opad, 52);
 +    GET_WORD_32_BE(W[14],​ opad, 56);
 +    GET_WORD_32_BE(W[15],​ opad, 60);
 +
 +    A = INIT_SHA1_A;​
 +    B = INIT_SHA1_B;​
 +    C = INIT_SHA1_C;​
 +    D = INIT_SHA1_D;​
 +    E = INIT_SHA1_E;​
 +
 +#define F(x,y,z) (z ^ (x & (y ^ z)))
 +#define K 0x5A827999
 +
 +    P(A, B, C, D, E, W[0] );
 +    P(E, A, B, C, D, W[1] );
 +    P(D, E, A, B, C, W[2] );
 +    P(C, D, E, A, B, W[3] );
 +    P(B, C, D, E, A, W[4] );
 +    P(A, B, C, D, E, W[5] );
 +    P(E, A, B, C, D, W[6] );
 +    P(D, E, A, B, C, W[7] );
 +    P(C, D, E, A, B, W[8] );
 +    P(B, C, D, E, A, W[9] );
 +    P(A, B, C, D, E, W[10]);
 +    P(E, A, B, C, D, W[11]);
 +    P(D, E, A, B, C, W[12]);
 +    P(C, D, E, A, B, W[13]);
 +    P(B, C, D, E, A, W[14]);
 +    P(A, B, C, D, E, W[15]);
 +    P(E, A, B, C, D, R(16));
 +    P(D, E, A, B, C, R(17));
 +    P(C, D, E, A, B, R(18));
 +    P(B, C, D, E, A, R(19));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) (x ^ y ^ z)
 +#define K 0x6ED9EBA1
 +
 +    P(A, B, C, D, E, R(20));
 +    P(E, A, B, C, D, R(21));
 +    P(D, E, A, B, C, R(22));
 +    P(C, D, E, A, B, R(23));
 +    P(B, C, D, E, A, R(24));
 +    P(A, B, C, D, E, R(25));
 +    P(E, A, B, C, D, R(26));
 +    P(D, E, A, B, C, R(27));
 +    P(C, D, E, A, B, R(28));
 +    P(B, C, D, E, A, R(29));
 +    P(A, B, C, D, E, R(30));
 +    P(E, A, B, C, D, R(31));
 +    P(D, E, A, B, C, R(32));
 +    P(C, D, E, A, B, R(33));
 +    P(B, C, D, E, A, R(34));
 +    P(A, B, C, D, E, R(35));
 +    P(E, A, B, C, D, R(36));
 +    P(D, E, A, B, C, R(37));
 +    P(C, D, E, A, B, R(38));
 +    P(B, C, D, E, A, R(39));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) ((x & y) | (z & (x | y)))
 +#define K 0x8F1BBCDC
 +
 +    P(A, B, C, D, E, R(40));
 +    P(E, A, B, C, D, R(41));
 +    P(D, E, A, B, C, R(42));
 +    P(C, D, E, A, B, R(43));
 +    P(B, C, D, E, A, R(44));
 +    P(A, B, C, D, E, R(45));
 +    P(E, A, B, C, D, R(46));
 +    P(D, E, A, B, C, R(47));
 +    P(C, D, E, A, B, R(48));
 +    P(B, C, D, E, A, R(49));
 +    P(A, B, C, D, E, R(50));
 +    P(E, A, B, C, D, R(51));
 +    P(D, E, A, B, C, R(52));
 +    P(C, D, E, A, B, R(53));
 +    P(B, C, D, E, A, R(54));
 +    P(A, B, C, D, E, R(55));
 +    P(E, A, B, C, D, R(56));
 +    P(D, E, A, B, C, R(57));
 +    P(C, D, E, A, B, R(58));
 +    P(B, C, D, E, A, R(59));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) (x ^ y ^ z)
 +#define K 0xCA62C1D6
 +
 +    P(A, B, C, D, E, R(60));
 +    P(E, A, B, C, D, R(61));
 +    P(D, E, A, B, C, R(62));
 +    P(C, D, E, A, B, R(63));
 +    P(B, C, D, E, A, R(64));
 +    P(A, B, C, D, E, R(65));
 +    P(E, A, B, C, D, R(66));
 +    P(D, E, A, B, C, R(67));
 +    P(C, D, E, A, B, R(68));
 +    P(B, C, D, E, A, R(69));
 +    P(A, B, C, D, E, R(70));
 +    P(E, A, B, C, D, R(71));
 +    P(D, E, A, B, C, R(72));
 +    P(C, D, E, A, B, R(73));
 +    P(B, C, D, E, A, R(74));
 +    P(A, B, C, D, E, R(75));
 +    P(E, A, B, C, D, R(76));
 +    P(D, E, A, B, C, R(77));
 +    P(C, D, E, A, B, R(78));
 +    P(B, C, D, E, A, R(79));
 +
 +#undef K
 +#undef F
 +
 +    A += INIT_SHA1_A;​
 +    B += INIT_SHA1_B;​
 +    C += INIT_SHA1_C;​
 +    D += INIT_SHA1_D;​
 +    E += INIT_SHA1_E;​
 +
 +    // store state for 2nd part
 +    state[0] = A;
 +    state[1] = B;
 +    state[2] = C;
 +    state[3] = D;
 +    state[4] = E;
 +
 +    GET_WORD_32_BE(W[ 0], buf,  0);
 +    GET_WORD_32_BE(W[ 1], buf,  4);
 +    GET_WORD_32_BE(W[ 2], buf,  8);
 +    GET_WORD_32_BE(W[ 3], buf, 12);
 +    GET_WORD_32_BE(W[ 4], buf, 16);
 +    GET_WORD_32_BE(W[ 5], buf, 20);
 +    GET_WORD_32_BE(W[ 6], buf, 24);
 +    GET_WORD_32_BE(W[ 7], buf, 28);
 +    GET_WORD_32_BE(W[ 8], buf, 32);
 +    GET_WORD_32_BE(W[ 9], buf, 36);
 +    GET_WORD_32_BE(W[10],​ buf, 40);
 +    GET_WORD_32_BE(W[11],​ buf, 44);
 +    GET_WORD_32_BE(W[12],​ buf, 48);
 +    GET_WORD_32_BE(W[13],​ buf, 52);
 +    GET_WORD_32_BE(W[14],​ buf, 56);
 +    GET_WORD_32_BE(W[15],​ buf, 60);
 +
 +#define F(x,y,z) (z ^ (x & (y ^ z)))
 +#define K 0x5A827999
 +
 +    P(A, B, C, D, E, W[0] );
 +    P(E, A, B, C, D, W[1] );
 +    P(D, E, A, B, C, W[2] );
 +    P(C, D, E, A, B, W[3] );
 +    P(B, C, D, E, A, W[4] );
 +    P(A, B, C, D, E, W[5] );
 +    P(E, A, B, C, D, W[6] );
 +    P(D, E, A, B, C, W[7] );
 +    P(C, D, E, A, B, W[8] );
 +    P(B, C, D, E, A, W[9] );
 +    P(A, B, C, D, E, W[10]);
 +    P(E, A, B, C, D, W[11]);
 +    P(D, E, A, B, C, W[12]);
 +    P(C, D, E, A, B, W[13]);
 +    P(B, C, D, E, A, W[14]);
 +    P(A, B, C, D, E, W[15]);
 +    P(E, A, B, C, D, R(16));
 +    P(D, E, A, B, C, R(17));
 +    P(C, D, E, A, B, R(18));
 +    P(B, C, D, E, A, R(19));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) (x ^ y ^ z)
 +#define K 0x6ED9EBA1
 +
 +    P(A, B, C, D, E, R(20));
 +    P(E, A, B, C, D, R(21));
 +    P(D, E, A, B, C, R(22));
 +    P(C, D, E, A, B, R(23));
 +    P(B, C, D, E, A, R(24));
 +    P(A, B, C, D, E, R(25));
 +    P(E, A, B, C, D, R(26));
 +    P(D, E, A, B, C, R(27));
 +    P(C, D, E, A, B, R(28));
 +    P(B, C, D, E, A, R(29));
 +    P(A, B, C, D, E, R(30));
 +    P(E, A, B, C, D, R(31));
 +    P(D, E, A, B, C, R(32));
 +    P(C, D, E, A, B, R(33));
 +    P(B, C, D, E, A, R(34));
 +    P(A, B, C, D, E, R(35));
 +    P(E, A, B, C, D, R(36));
 +    P(D, E, A, B, C, R(37));
 +    P(C, D, E, A, B, R(38));
 +    P(B, C, D, E, A, R(39));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) ((x & y) | (z & (x | y)))
 +#define K 0x8F1BBCDC
 +
 +    P(A, B, C, D, E, R(40));
 +    P(E, A, B, C, D, R(41));
 +    P(D, E, A, B, C, R(42));
 +    P(C, D, E, A, B, R(43));
 +    P(B, C, D, E, A, R(44));
 +    P(A, B, C, D, E, R(45));
 +    P(E, A, B, C, D, R(46));
 +    P(D, E, A, B, C, R(47));
 +    P(C, D, E, A, B, R(48));
 +    P(B, C, D, E, A, R(49));
 +    P(A, B, C, D, E, R(50));
 +    P(E, A, B, C, D, R(51));
 +    P(D, E, A, B, C, R(52));
 +    P(C, D, E, A, B, R(53));
 +    P(B, C, D, E, A, R(54));
 +    P(A, B, C, D, E, R(55));
 +    P(E, A, B, C, D, R(56));
 +    P(D, E, A, B, C, R(57));
 +    P(C, D, E, A, B, R(58));
 +    P(B, C, D, E, A, R(59));
 +
 +#undef K
 +#undef F
 +
 +#define F(x,y,z) (x ^ y ^ z)
 +#define K 0xCA62C1D6
 +
 +    P(A, B, C, D, E, R(60));
 +    P(E, A, B, C, D, R(61));
 +    P(D, E, A, B, C, R(62));
 +    P(C, D, E, A, B, R(63));
 +    P(B, C, D, E, A, R(64));
 +    P(A, B, C, D, E, R(65));
 +    P(E, A, B, C, D, R(66));
 +    P(D, E, A, B, C, R(67));
 +    P(C, D, E, A, B, R(68));
 +    P(B, C, D, E, A, R(69));
 +    P(A, B, C, D, E, R(70));
 +    P(E, A, B, C, D, R(71));
 +    P(D, E, A, B, C, R(72));
 +    P(C, D, E, A, B, R(73));
 +    P(B, C, D, E, A, R(74));
 +    P(A, B, C, D, E, R(75));
 +    P(E, A, B, C, D, R(76));
 +    P(D, E, A, B, C, R(77));
 +    P(C, D, E, A, B, R(78));
 +    P(B, C, D, E, A, R(79));
 +
 +#undef K
 +#undef F
 +
 +    A += state[0];
 +    B += state[1];
 +    C += state[2];
 +    D += state[3];
 +    E += state[4];
 +
 +    PUT_WORD_32_BE(A,​ output, ​ 0);
 +    PUT_WORD_32_BE(B,​ output, ​ 4);
 +    PUT_WORD_32_BE(C,​ output, ​ 8);
 +    PUT_WORD_32_BE(D,​ output, 12);
 +    PUT_WORD_32_BE(E,​ output, 16);
 +}
 +
 +
 +/* PBKDF2
 + * stripped-down implementation
 + * based on the source code written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL Project 1999
 + */
 +static void PBKDF2_DCC2(const unsigned char *pass, const unsigned char *salt, int saltlen, unsigned char *out)
 +{
 +    unsigned char temp[SHA1_DIGEST_LENGTH];​
 +    unsigned char buf[48];
 +    unsigned int i;
 +
 +    memset(buf, 0, 48);
 +    memcpy(buf, salt, saltlen);
 +    buf[saltlen + 3] = 0x01;
 +
 +    hmac_sha1(pass,​ 16, buf, saltlen + 4, temp);
 +
 +    memcpy(out, temp, 16);
 +
 +    for (i = 1; i < ITERATIONS; i++)
 +    {
 +        hmac_sha1(pass,​ 16, temp, SHA1_DIGEST_LENGTH,​ temp);
 +
 +        out[ 0] ^= temp[0];
 +        out[ 1] ^= temp[1];
 +        out[ 2] ^= temp[2];
 +        out[ 3] ^= temp[3];
 +        out[ 4] ^= temp[4];
 +        out[ 5] ^= temp[5];
 +        out[ 6] ^= temp[6];
 +        out[ 7] ^= temp[7];
 +        out[ 8] ^= temp[8];
 +        out[ 9] ^= temp[9];
 +        out[10] ^= temp[10];
 +        out[11] ^= temp[11];
 +        out[12] ^= temp[12];
 +        out[13] ^= temp[13];
 +        out[14] ^= temp[14];
 +        out[15] ^= temp[15];
 +        out[16] ^= temp[16];
 +    }
 +}
 +
 +
 +
 +// MD4 compression function
 +void md4_crypt(unsigned int *buffer, unsigned int *hash)
 +{
 +    unsigned int a;
 +    unsigned int b;
 +    unsigned int c;
 +    unsigned int d;
 +
 +    // round 1
 +    a = 0xFFFFFFFF ​ +  buffer[0]; a = (a << 3 ) | (a >> 29);
 +    d = INIT_MD4_D + (INIT_MD4_C ^ (a & 0x77777777)) + buffer[1]; d = (d << 7 ) | (d >> 25);
 +    c = INIT_MD4_C + (INIT_MD4_B ^ (d & (a ^ INIT_MD4_B))) + buffer[2]; c = (c << 11) | (c >> 21);
 +    b = INIT_MD4_B + (a ^ (c & (d ^ a))) + buffer[3]; b = (b << 19) | (b >> 13); 
 +
 +    a += (d ^ (b & (c ^ d)))  +  buffer[4]; ​ a = (a << 3 ) | (a >> 29);
 +    d += (c ^ (a & (b ^ c)))  +  buffer[5]; ​ d = (d << 7 ) | (d >> 25);
 +    c += (b ^ (d & (a ^ b)))  +  buffer[6]; ​ c = (c << 11) | (c >> 21);
 +    b += (a ^ (c & (d ^ a)))  +  buffer[7]; ​ b = (b << 19) | (b >> 13);
 +
 +    a += (d ^ (b & (c ^ d)))  + buffer[8] ;  a = (a << 3 ) | (a >> 29);
 +    d += (c ^ (a & (b ^ c)))  + buffer[9] ;  d = (d << 7 ) | (d >> 25);
 +    c += (b ^ (d & (a ^ b)))  + buffer[10]; ​ c = (c << 11) | (c >> 21);
 +    b += (a ^ (c & (d ^ a)))  + buffer[11]; ​ b = (b << 19) | (b >> 13);
 +
 +    a += (d ^ (b & (c ^ d)))  + buffer[12]; a = (a << 3 ) | (a >> 29);
 +    d += (c ^ (a & (b ^ c)))  + buffer[13]; d = (d << 7 ) | (d >> 25);
 +    c += (b ^ (d & (a ^ b)))  + buffer[14]; c = (c << 11) | (c >> 21);
 +    b += (a ^ (c & (d ^ a)))  + buffer[15]; b = (b << 19) | (b >> 13);
 +
 +    // round 2
 +    a += ((b & (c | d)) | (c & d)) + buffer[0] ​ + SQRT_2; a = (a<<3 ) | (a>>​29);​
 +    d += ((a & (b | c)) | (b & c)) + buffer[4] ​ + SQRT_2; d = (d<<5 ) | (d>>​27);​
 +    c += ((d & (a | b)) | (a & b)) + buffer[8] ​ + SQRT_2; c = (c<<9 ) | (c>>​23);​
 +    b += ((c & (d | a)) | (d & a)) + buffer[12] + SQRT_2; b = (b<<​13) | (b>>​19);​
 +
 +    a += ((b & (c | d)) | (c & d)) + buffer[1] ​ + SQRT_2; a = (a<<3 ) | (a>>​29);​
 +    d += ((a & (b | c)) | (b & c)) + buffer[5] ​ + SQRT_2; d = (d<<5 ) | (d>>​27);​
 +    c += ((d & (a | b)) | (a & b)) + buffer[9] ​ + SQRT_2; c = (c<<9 ) | (c>>​23);​
 +    b += ((c & (d | a)) | (d & a)) + buffer[13] + SQRT_2; b = (b<<​13) | (b>>​19);​
 +
 +    a += ((b & (c | d)) | (c & d)) + buffer[2] ​ + SQRT_2; a = (a<<3 ) | (a>>​29);​
 +    d += ((a & (b | c)) | (b & c)) + buffer[6] ​ + SQRT_2; d = (d<<5 ) | (d>>​27);​
 +    c += ((d & (a | b)) | (a & b)) + buffer[10] + SQRT_2; c = (c<<9 ) | (c>>​23);​
 +    b += ((c & (d | a)) | (d & a)) + buffer[14] + SQRT_2; b = (b<<​13) | (b>>​19);​
 +
 +    a += ((b & (c | d)) | (c & d)) + buffer[3] ​ + SQRT_2; a = (a<<3 ) | (a>>​29);​
 +    d += ((a & (b | c)) | (b & c)) + buffer[7] ​ + SQRT_2; d = (d<<5 ) | (d>>​27);​
 +    c += ((d & (a | b)) | (a & b)) + buffer[11] + SQRT_2; c = (c<<9 ) | (c>>​23);​
 +    b += ((c & (d | a)) | (d & a)) + buffer[15] + SQRT_2; b = (b<<​13) | (b>>​19); ​        
 +
 +    // round 3
 +    a += (d ^ c ^ b) + buffer[0] ​ +  SQRT_3; a = (a << 3 ) | (a >> 29);
 +    d += (c ^ b ^ a) + buffer[8] ​ +  SQRT_3; d = (d << 9 ) | (d >> 23);
 +    c += (b ^ a ^ d) + buffer[4] ​ +  SQRT_3; c = (c << 11) | (c >> 21);
 +    b += (a ^ d ^ c) + buffer[12] +  SQRT_3; b = (b << 15) | (b >> 17);
 +
 +    a += (d ^ c ^ b) + buffer[2] ​ +  SQRT_3; a = (a << 3 ) | (a >> 29);
 +    d += (c ^ b ^ a) + buffer[10] +  SQRT_3; d = (d << 9 ) | (d >> 23);
 +    c += (b ^ a ^ d) + buffer[6] ​ +  SQRT_3; c = (c << 11) | (c >> 21);
 +    b += (a ^ d ^ c) + buffer[14] +  SQRT_3; b = (b << 15) | (b >> 17);
 +
 +    a += (d ^ c ^ b) + buffer[1] ​ +  SQRT_3; a = (a << 3 ) | (a >> 29);
 +    d += (c ^ b ^ a) + buffer[9] ​ +  SQRT_3; d = (d << 9 ) | (d >> 23);
 +    c += (b ^ a ^ d) + buffer[5] ​ +  SQRT_3; c = (c << 11) | (c >> 21);
 +    b += (a ^ d ^ c) + buffer[13] +  SQRT_3; b = (b << 15) | (b >> 17);
 +
 +    a += (d ^ c ^ b) + buffer[3] ​ +  SQRT_3; a = (a << 3 ) | (a >> 29);
 +
 +    d += (c ^ b ^ a) + buffer[11] +  SQRT_3; d = (d << 9 ) | (d >> 23);
 +    c += (b ^ a ^ d) + buffer[7] ​ +  SQRT_3; c = (c << 11) | (c >> 21);
 +    b += (a ^ d ^ c) + buffer[15] +  SQRT_3; b = (b << 15) | (b >> 17);
 +
 +    hash[0] = a + INIT_MD4_A;
 +    hash[1] = b + INIT_MD4_B;
 +    hash[2] = c + INIT_MD4_C;
 +    hash[3] = d + INIT_MD4_D;
 +}
 +
 +// main
 +int main(int argc, char *argv[])
 +{
 +    unsigned int i;
 +    unsigned int buffer[16];
 +    unsigned int nt_hash[16];​
 +    unsigned int dcc_hash[16];​
 +    unsigned int dcc2_hash[16];​
 +    unsigned char salt[44];
 +    unsigned char username[] = "​test";​
 +    unsigned char password[] = "​password";​
 +    unsigned int username_len = strlen(username);​
 +    unsigned int password_len = strlen(password);​
 +
 +    memset(nt_hash,​ 0, 64);
 +    memset(buffer,​ 0, 64);
 +    memset(salt,​ 0, 44);
 +        ​
 +    // convert ASCII username to Unicode (WideChar)
 +    for(i = 0; i < (username_len >> 1) + 1; i++)
 +        ((unsigned int *)salt)[i] = username[2 * i] | (username[2 * i + 1] << 16);
 +    ​
 +    // convert ASCII password to Unicode
 +
 +    for(i = 0; i < password_len >> 1; i++)  ​
 +        buffer[i] = password[2 * i] | (password[2 * i + 1] << 16);
 + 
 +    // MD4 padding
 +    if(password_len % 2 == 1)
 +        buffer[i] = password[password_len - 1] | 0x800000;
 +    else
 +        buffer[i]=0x80;​
 +    ​
 +    // put password length at end of buffer
 +    buffer[14] = password_len << 4;
 +        ​
 +    // generate MD4 hash of the password (NT hash)
 +    md4_crypt(buffer,​ nt_hash);
 +    ​
 +    // concatenate NT hash and the username (salt)
 +    memcpy((unsigned char *)nt_hash + 16, salt, username_len << 1); 
 +    ​
 +    i = username_len + 8;
 +      ​
 +    // MD4 padding
 +    if(username_len % 2 == 1)
 +        nt_hash[i >> 1] = username[username_len - 1] | 0x800000;
 +    else
 +        nt_hash[i >> 1] = 0x80;
 +
 +    // put length at end of buffer
 +    nt_hash[14] = i << 4; 
 +        ​
 +    md4_crypt(nt_hash,​ dcc_hash);
 +    ​
 +
 +    // stripped-down PBKDF2 for DCC2
 +    PBKDF2_DCC2((unsigned char*)dcc_hash,​ salt, username_len << 1, (unsigned char*)dcc2_hash);​
 +
 +    // the even slower OpenSSL PBKDF2 implementation (compile with -lssl) ​  
 +//  PKCS5_PBKDF2_HMAC_SHA1((unsigned char*)dcc_hash,​ 16, salt, username_len << 1, ITERATIONS, 16, (unsigned char*)dcc2_hash);​
 +
 +    // user credentials and DCC and DCC2 hash values
 +    printf("​username ​          : %s\n", username);
 +    printf("​password ​          : %s\n", password);
 +    printf("​DCC ​ aka M$ Cache  : %s\n", byte2hexstring((unsigned char *)dcc_hash, 16));
 +    printf("​DCC2 aka M$ Cache 2: %s\n", byte2hexstring((unsigned char *)dcc2_hash,​ 16));
 +
 +    return 0;
 +}
 +</​code>​
MSCash2.txt ยท Last modified: 2010/12/26 12:03 by The_S3nf
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate to DokuWiki Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki Powered by OpenVZ Powered by Openwall GNU/*/Linux Bookmark and Share