1
0
mirror of https://github.com/hashcat/hashcat.git synced 2024-12-23 07:08:19 +00:00

Merge pull request #1991 from brandoncasaba/master

Add hash modes 19800 (krb5pa etype 17) and 19900 (krb5pa etype 18)
This commit is contained in:
Jens Steube 2019-04-20 19:10:33 +02:00 committed by GitHub
commit 17ab30b29f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 2281 additions and 0 deletions

616
OpenCL/m19800-pure.cl Normal file
View File

@ -0,0 +1,616 @@
/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#define NEW_SIMD_CODE
#ifdef KERNEL_STATIC
#include "inc_vendor.h"
#include "inc_types.h"
#include "inc_common.cl"
#include "inc_simd.cl"
#include "inc_hash_sha1.cl"
#include "inc_cipher_aes.cl"
#endif
typedef struct krb5pa_17
{
u32 user[128];
u32 domain[128];
u32 account_info[512];
u32 account_info_len;
u32 checksum[3];
u32 enc_timestamp[32];
u32 enc_timestamp_len;
} krb5pa_17_t;
typedef struct krb5pa_17_tmp
{
u32 ipad[5];
u32 opad[5];
u32 dgst[10];
u32 out[10];
} krb5pa_17_tmp_t;
DECLSPEC static void aes128_encrypt_cbc (const u32 *aes_ks, u32 *aes_iv, const u32 *in, u32 *out, SHM_TYPE u32 *s_te0, SHM_TYPE u32 *s_te1, SHM_TYPE u32 *s_te2, SHM_TYPE u32 *s_te3, SHM_TYPE u32 *s_te4)
{
u32 data[4];
data[0] = hc_swap32_S (in[0]);
data[1] = hc_swap32_S (in[1]);
data[2] = hc_swap32_S (in[2]);
data[3] = hc_swap32_S (in[3]);
data[0] ^= aes_iv[0];
data[1] ^= aes_iv[1];
data[2] ^= aes_iv[2];
data[3] ^= aes_iv[3];
aes128_encrypt (aes_ks, data, out, s_te0, s_te1, s_te2, s_te3, s_te4);
aes_iv[0] = out[0];
aes_iv[1] = out[1];
aes_iv[2] = out[2];
aes_iv[3] = out[3];
out[0] = hc_swap32_S (out[0]);
out[1] = hc_swap32_S (out[1]);
out[2] = hc_swap32_S (out[2]);
out[3] = hc_swap32_S (out[3]);
}
DECLSPEC static void aes128_decrypt_cbc (const u32 *ks1, const u32 *in, u32 *out, u32 *essiv, SHM_TYPE u32 *s_td0, SHM_TYPE u32 *s_td1, SHM_TYPE u32 *s_td2, SHM_TYPE u32 *s_td3, SHM_TYPE u32 *s_td4)
{
aes128_decrypt (ks1, in, out, s_td0, s_td1, s_td2, s_td3, s_td4);
out[0] ^= essiv[0];
out[1] ^= essiv[1];
out[2] ^= essiv[2];
out[3] ^= essiv[3];
essiv[0] = in[0];
essiv[1] = in[1];
essiv[2] = in[2];
essiv[3] = in[3];
}
DECLSPEC static void hmac_sha1_run_V (u32x *w0, u32x *w1, u32x *w2, u32x *w3, u32x *ipad, u32x *opad, u32x *digest)
{
digest[0] = ipad[0];
digest[1] = ipad[1];
digest[2] = ipad[2];
digest[3] = ipad[3];
digest[4] = ipad[4];
sha1_transform_vector (w0, w1, w2, w3, digest);
w0[0] = digest[0];
w0[1] = digest[1];
w0[2] = digest[2];
w0[3] = digest[3];
w1[0] = digest[4];
w1[1] = 0x80000000;
w1[2] = 0;
w1[3] = 0;
w2[0] = 0;
w2[1] = 0;
w2[2] = 0;
w2[3] = 0;
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = (64 + 20) * 8;
digest[0] = opad[0];
digest[1] = opad[1];
digest[2] = opad[2];
digest[3] = opad[3];
digest[4] = opad[4];
sha1_transform_vector (w0, w1, w2, w3, digest);
}
KERNEL_FQ void m19800_init (KERN_ATTR_TMPS_ESALT (krb5pa_17_tmp_t, krb5pa_17_t))
{
/**
* base
*/
const u64 gid = get_global_id (0);
if (gid >= gid_max) return;
/**
* main
*/
/* initialize hmac-sha1 for pbkdf2(password, account, 4096, account_len) */
sha1_hmac_ctx_t sha1_hmac_ctx;
sha1_hmac_init_global_swap (&sha1_hmac_ctx, pws[gid].i, pws[gid].pw_len);
tmps[gid].ipad[0] = sha1_hmac_ctx.ipad.h[0];
tmps[gid].ipad[1] = sha1_hmac_ctx.ipad.h[1];
tmps[gid].ipad[2] = sha1_hmac_ctx.ipad.h[2];
tmps[gid].ipad[3] = sha1_hmac_ctx.ipad.h[3];
tmps[gid].ipad[4] = sha1_hmac_ctx.ipad.h[4];
tmps[gid].opad[0] = sha1_hmac_ctx.opad.h[0];
tmps[gid].opad[1] = sha1_hmac_ctx.opad.h[1];
tmps[gid].opad[2] = sha1_hmac_ctx.opad.h[2];
tmps[gid].opad[3] = sha1_hmac_ctx.opad.h[3];
tmps[gid].opad[4] = sha1_hmac_ctx.opad.h[4];
sha1_hmac_update_global_swap (&sha1_hmac_ctx, esalt_bufs[digests_offset].account_info, esalt_bufs[digests_offset].account_info_len);
for (u32 i = 0, j = 1; i < 4; i += 5, j += 1)
{
sha1_hmac_ctx_t sha1_hmac_ctx2 = sha1_hmac_ctx;
u32 w0[4];
u32 w1[4];
u32 w2[4];
u32 w3[4];
w0[0] = j;
w0[1] = 0;
w0[2] = 0;
w0[3] = 0;
w1[0] = 0;
w1[1] = 0;
w1[2] = 0;
w1[3] = 0;
w2[0] = 0;
w2[1] = 0;
w2[2] = 0;
w2[3] = 0;
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = 0;
sha1_hmac_update_64 (&sha1_hmac_ctx2, w0, w1, w2, w3, 4);
sha1_hmac_final (&sha1_hmac_ctx2);
tmps[gid].dgst[i + 0] = sha1_hmac_ctx2.opad.h[0];
tmps[gid].dgst[i + 1] = sha1_hmac_ctx2.opad.h[1];
tmps[gid].dgst[i + 2] = sha1_hmac_ctx2.opad.h[2];
tmps[gid].dgst[i + 3] = sha1_hmac_ctx2.opad.h[3];
tmps[gid].dgst[i + 4] = sha1_hmac_ctx2.opad.h[4];
tmps[gid].out[i + 0] = tmps[gid].dgst[i + 0];
tmps[gid].out[i + 1] = tmps[gid].dgst[i + 1];
tmps[gid].out[i + 2] = tmps[gid].dgst[i + 2];
tmps[gid].out[i + 3] = tmps[gid].dgst[i + 3];
tmps[gid].out[i + 4] = tmps[gid].dgst[i + 4];
}
}
KERNEL_FQ void m19800_loop (KERN_ATTR_TMPS_ESALT (krb5pa_17_tmp_t, krb5pa_17_t))
{
/**
* base
*/
const u64 gid = get_global_id (0);
if ((gid * VECT_SIZE) >= gid_max) return;
u32x ipad[5];
u32x opad[5];
ipad[0] = packv (tmps, ipad, gid, 0);
ipad[1] = packv (tmps, ipad, gid, 1);
ipad[2] = packv (tmps, ipad, gid, 2);
ipad[3] = packv (tmps, ipad, gid, 3);
ipad[4] = packv (tmps, ipad, gid, 4);
opad[0] = packv (tmps, opad, gid, 0);
opad[1] = packv (tmps, opad, gid, 1);
opad[2] = packv (tmps, opad, gid, 2);
opad[3] = packv (tmps, opad, gid, 3);
opad[4] = packv (tmps, opad, gid, 4);
for (u32 i = 0; i < 4; i += 5)
{
u32x dgst[5];
u32x out[5];
dgst[0] = packv (tmps, dgst, gid, i + 0);
dgst[1] = packv (tmps, dgst, gid, i + 1);
dgst[2] = packv (tmps, dgst, gid, i + 2);
dgst[3] = packv (tmps, dgst, gid, i + 3);
dgst[4] = packv (tmps, dgst, gid, i + 4);
out[0] = packv (tmps, out, gid, i + 0);
out[1] = packv (tmps, out, gid, i + 1);
out[2] = packv (tmps, out, gid, i + 2);
out[3] = packv (tmps, out, gid, i + 3);
out[4] = packv (tmps, out, gid, i + 4);
for (u32 j = 0; j < loop_cnt; j++)
{
u32x w0[4];
u32x w1[4];
u32x w2[4];
u32x w3[4];
w0[0] = dgst[0];
w0[1] = dgst[1];
w0[2] = dgst[2];
w0[3] = dgst[3];
w1[0] = dgst[4];
w1[1] = 0x80000000;
w1[2] = 0;
w1[3] = 0;
w2[0] = 0;
w2[1] = 0;
w2[2] = 0;
w2[3] = 0;
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = (64 + 20) * 8;
hmac_sha1_run_V (w0, w1, w2, w3, ipad, opad, dgst);
out[0] ^= dgst[0];
out[1] ^= dgst[1];
out[2] ^= dgst[2];
out[3] ^= dgst[3];
out[4] ^= dgst[4];
}
unpackv (tmps, dgst, gid, i + 0, dgst[0]);
unpackv (tmps, dgst, gid, i + 1, dgst[1]);
unpackv (tmps, dgst, gid, i + 2, dgst[2]);
unpackv (tmps, dgst, gid, i + 3, dgst[3]);
unpackv (tmps, dgst, gid, i + 4, dgst[4]);
unpackv (tmps, out, gid, i + 0, out[0]);
unpackv (tmps, out, gid, i + 1, out[1]);
unpackv (tmps, out, gid, i + 2, out[2]);
unpackv (tmps, out, gid, i + 3, out[3]);
unpackv (tmps, out, gid, i + 4, out[4]);
}
}
KERNEL_FQ void m19800_comp (KERN_ATTR_TMPS_ESALT (krb5pa_17_tmp_t, krb5pa_17_t))
{
/**
* base
*/
const u64 gid = get_global_id (0);
const u64 lid = get_local_id (0);
const u64 lsz = get_local_size (0);
/**
* aes shared
*/
#ifdef REAL_SHM
LOCAL_AS u32 s_td0[256];
LOCAL_AS u32 s_td1[256];
LOCAL_AS u32 s_td2[256];
LOCAL_AS u32 s_td3[256];
LOCAL_AS u32 s_td4[256];
LOCAL_AS u32 s_te0[256];
LOCAL_AS u32 s_te1[256];
LOCAL_AS u32 s_te2[256];
LOCAL_AS u32 s_te3[256];
LOCAL_AS u32 s_te4[256];
for (u32 i = lid; i < 256; i += lsz)
{
s_td0[i] = td0[i];
s_td1[i] = td1[i];
s_td2[i] = td2[i];
s_td3[i] = td3[i];
s_td4[i] = td4[i];
s_te0[i] = te0[i];
s_te1[i] = te1[i];
s_te2[i] = te2[i];
s_te3[i] = te3[i];
s_te4[i] = te4[i];
}
barrier (CLK_LOCAL_MEM_FENCE);
#else
CONSTANT_AS u32a *s_td0 = td0;
CONSTANT_AS u32a *s_td1 = td1;
CONSTANT_AS u32a *s_td2 = td2;
CONSTANT_AS u32a *s_td3 = td3;
CONSTANT_AS u32a *s_td4 = td4;
CONSTANT_AS u32a *s_te0 = te0;
CONSTANT_AS u32a *s_te1 = te1;
CONSTANT_AS u32a *s_te2 = te2;
CONSTANT_AS u32a *s_te3 = te3;
CONSTANT_AS u32a *s_te4 = te4;
#endif
if (gid >= gid_max) return;
/*
at this point, the output ('seed') will be used to generate AES keys:
key_bytes = derive(seed, 'kerberos'.encode(), seedsize)
'key_bytes' will be the AES key used to generate 'ke' and 'ki'
'ke' will be the AES key to decrypt the ticket
'ki' will be the key to compute the final HMAC
*/
u32 nfolded[4];
// we can precompute _nfold('kerberos', 16)
nfolded[0] = 0x6b657262;
nfolded[1] = 0x65726f73;
nfolded[2] = 0x7b9b5b2b;
nfolded[3] = 0x93132b93;
// then aes_cbc encrypt this nfolded value with 'seed' as key along with a null IV
u32 aes_key[4];
aes_key[0] = hc_swap32_S (tmps[gid].out[0]);
aes_key[1] = hc_swap32_S (tmps[gid].out[1]);
aes_key[2] = hc_swap32_S (tmps[gid].out[2]);
aes_key[3] = hc_swap32_S (tmps[gid].out[3]);
u32 aes_iv[4];
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
u32 aes_ks[44];
aes128_set_encrypt_key (aes_ks, aes_key, s_te0, s_te1, s_te2, s_te3);
u32 key_bytes[4];
u32 out[4];
aes128_encrypt_cbc (aes_ks, aes_iv, nfolded, out, s_te0, s_te1, s_te2, s_te3, s_te4);
key_bytes[0] = hc_swap32_S (out[0]);
key_bytes[1] = hc_swap32_S (out[1]);
key_bytes[2] = hc_swap32_S (out[2]);
key_bytes[3] = hc_swap32_S (out[3]);
// then aes_cbc encrypt this nfolded value with 'key_bytes' as key along with a null IV
aes128_set_encrypt_key (aes_ks, key_bytes, s_te0, s_te1, s_te2, s_te3);
/* we will now compute 'ke' */
u32 ke[4];
// we can precompute _nfold(pack('>IB', 1, 0xAA), 16)
nfolded[0] = 0xae2c160b;
nfolded[1] = 0x04ad5006;
nfolded[2] = 0xab55aad5;
nfolded[3] = 0x6a80355a;
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
// then aes_cbc encrypt this nfolded value with 'key_bytes' as key along with a null IV
aes128_encrypt_cbc (aes_ks, aes_iv, nfolded, out, s_te0, s_te1, s_te2, s_te3, s_te4);
ke[0] = out[0];
ke[1] = out[1];
ke[2] = out[2];
ke[3] = out[3];
// Decode the CTS mode encryption by decrypting c_n-1 and swapping it with c_n
u32 enc_blocks[12];
u32 decrypted_block[4];
// c_0
enc_blocks[0] = esalt_bufs[digests_offset].enc_timestamp[0];
enc_blocks[1] = esalt_bufs[digests_offset].enc_timestamp[1];
enc_blocks[2] = esalt_bufs[digests_offset].enc_timestamp[2];
enc_blocks[3] = esalt_bufs[digests_offset].enc_timestamp[3];
// c_1 aka c_n-1 since there are guaranteed to be exactly 3 blocks
enc_blocks[4] = esalt_bufs[digests_offset].enc_timestamp[4];
enc_blocks[5] = esalt_bufs[digests_offset].enc_timestamp[5];
enc_blocks[6] = esalt_bufs[digests_offset].enc_timestamp[6];
enc_blocks[7] = esalt_bufs[digests_offset].enc_timestamp[7];
u32 w0[4];
u32 w1[4];
u32 w2[4];
u32 w3[4];
u32 aes_cts_decrypt_ks[44];
AES128_set_decrypt_key (aes_cts_decrypt_ks, ke, s_te0, s_te1, s_te2, s_te3, s_td0, s_td1, s_td2, s_td3);
// Our first decryption is the last block (currently in c_n-1) using the first portion of (c_n) as our IV, this allows us to get plaintext in one crypto operation
aes_iv[0] = esalt_bufs[digests_offset].enc_timestamp[8];
aes_iv[1] = esalt_bufs[digests_offset].enc_timestamp[9];
aes_iv[2] = esalt_bufs[digests_offset].enc_timestamp[10];
aes_iv[3] = esalt_bufs[digests_offset].enc_timestamp[11];
aes128_decrypt_cbc (aes_cts_decrypt_ks, enc_blocks + 4, decrypted_block, aes_iv, s_td0, s_td1, s_td2, s_td3, s_td4);
w0[0] = hc_swap32_S (decrypted_block[0]);
w0[1] = hc_swap32_S (decrypted_block[1]);
w0[2] = hc_swap32_S (decrypted_block[2]);
w0[3] = hc_swap32_S (decrypted_block[3]);
// Move as much code as possible after this branch to avoid unnecessary computation on misses
if (((w0[0] & 0xf0f0f0f0) == 0x30303030) && ((w0[1] & 0xffff0000) == 0x5aa10000))
{
// Decrypt c_n-1 without an IV for the padding blocks on c_n
aes128_decrypt (aes_cts_decrypt_ks, enc_blocks + 4, decrypted_block, s_td0, s_td1, s_td2, s_td3, s_td4);
w0[0] = decrypted_block[0];
w0[1] = decrypted_block[1];
w0[2] = decrypted_block[2];
w0[3] = decrypted_block[3];
int enc_timestamp_len = esalt_bufs[digests_offset].enc_timestamp_len;
int last_word_position = enc_timestamp_len / 4;
// New c_1, join c_n with result of the decrypted c_n-1
int last_block_iter;
for (last_block_iter = 4; last_block_iter < 8; last_block_iter++)
{
if (last_word_position > last_block_iter + 4)
{
enc_blocks[last_block_iter] = esalt_bufs[digests_offset].enc_timestamp[last_block_iter + 4];
}
else if (last_word_position == last_block_iter + 4)
{
// Handle case when the split lands in the middle of a WORD
switch (enc_timestamp_len % 4)
{
case 1:
enc_blocks[last_block_iter] = (esalt_bufs[digests_offset].enc_timestamp[last_block_iter + 4] & 0x000000ff) | (w0[last_block_iter - 4] & 0xffffff00);
break;
case 2:
enc_blocks[last_block_iter] = (esalt_bufs[digests_offset].enc_timestamp[last_block_iter + 4] & 0x0000ffff) | (w0[last_block_iter - 4] & 0xffff0000);
break;
case 3:
enc_blocks[last_block_iter] = (esalt_bufs[digests_offset].enc_timestamp[last_block_iter + 4] & 0x00ffffff) | (w0[last_block_iter - 4] & 0xff000000);
break;
default:
enc_blocks[last_block_iter] = w0[last_block_iter - 4];
}
}
else
{
enc_blocks[last_block_iter] = w0[last_block_iter - 4];
}
}
// c_2 aka c_n which is now equal to the old c_n-1
enc_blocks[8] = esalt_bufs[digests_offset].enc_timestamp[4];
enc_blocks[9] = esalt_bufs[digests_offset].enc_timestamp[5];
enc_blocks[10] = esalt_bufs[digests_offset].enc_timestamp[6];
enc_blocks[11] = esalt_bufs[digests_offset].enc_timestamp[7];
// Go ahead and decrypt all blocks now as a normal AES CBC operation
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
aes128_decrypt_cbc (aes_cts_decrypt_ks, enc_blocks, decrypted_block, aes_iv, s_td0, s_td1, s_td2, s_td3, s_td4);
w0[0] = hc_swap32_S (decrypted_block[0]);
w0[1] = hc_swap32_S (decrypted_block[1]);
w0[2] = hc_swap32_S (decrypted_block[2]);
w0[3] = hc_swap32_S (decrypted_block[3]);
aes128_decrypt_cbc (aes_cts_decrypt_ks, enc_blocks + 4, decrypted_block, aes_iv, s_td0, s_td1, s_td2, s_td3, s_td4);
w1[0] = hc_swap32_S (decrypted_block[0]);
w1[1] = hc_swap32_S (decrypted_block[1]);
w1[2] = hc_swap32_S (decrypted_block[2]);
w1[3] = hc_swap32_S (decrypted_block[3]);
aes128_decrypt_cbc (aes_cts_decrypt_ks, enc_blocks + 8, decrypted_block, aes_iv, s_td0, s_td1, s_td2, s_td3, s_td4);
w2[0] = hc_swap32_S (decrypted_block[0]);
w2[1] = hc_swap32_S (decrypted_block[1]);
w2[2] = hc_swap32_S (decrypted_block[2]);
w2[3] = hc_swap32_S (decrypted_block[3]);
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = 0;
/* we will now compute 'ki', having 'key_bytes' */
u32 ki[8];
// we can precompute _nfold(pack('>IB', 1, 0x55), 16)
nfolded[0] = 0x5b582c16;
nfolded[1] = 0x0a5aa805;
nfolded[2] = 0x56ab55aa;
nfolded[3] = 0xd5402ab5;
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
// then aes_cbc encrypt this nfolded value with 'key_bytes' as key along with a null IV
aes128_set_encrypt_key (aes_ks, key_bytes, s_te0, s_te1, s_te2, s_te3);
aes128_encrypt_cbc (aes_ks, aes_iv, nfolded, out, s_te0, s_te1, s_te2, s_te3, s_te4);
ki[0] = out[0];
ki[1] = out[1];
ki[2] = out[2];
ki[3] = out[3];
sha1_hmac_ctx_t sha1_hmac_ctx;
/*
hmac message = plaintext
hmac key = ki
*/
u32 k0[4];
u32 k1[4];
u32 k2[4];
u32 k3[4];
k0[0] = ki[0];
k0[1] = ki[1];
k0[2] = ki[2];
k0[3] = ki[3];
k1[0] = 0;
k1[1] = 0;
k1[2] = 0;
k1[3] = 0;
k2[0] = 0;
k2[1] = 0;
k2[2] = 0;
k2[3] = 0;
k3[0] = 0;
k3[1] = 0;
k3[2] = 0;
k3[3] = 0;
sha1_hmac_init_64 (&sha1_hmac_ctx, k0, k1, k2, k3);
sha1_hmac_update_64 (&sha1_hmac_ctx, w0, w1, w2, w3, enc_timestamp_len);
sha1_hmac_final(&sha1_hmac_ctx);
// Compare checksum
if(sha1_hmac_ctx.opad.h[0] == esalt_bufs[digests_offset].checksum[0]
&& sha1_hmac_ctx.opad.h[1] == esalt_bufs[digests_offset].checksum[1]
&& sha1_hmac_ctx.opad.h[2] == esalt_bufs[digests_offset].checksum[2])
{
if (atomic_inc (&hashes_shown[digests_offset]) == 0)
{
#define il_pos 0
mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, il_pos, 0, 0);
}
}
}
}

657
OpenCL/m19900-pure.cl Normal file
View File

@ -0,0 +1,657 @@
/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#define NEW_SIMD_CODE
#ifdef KERNEL_STATIC
#include "inc_vendor.h"
#include "inc_types.h"
#include "inc_common.cl"
#include "inc_simd.cl"
#include "inc_hash_sha1.cl"
#include "inc_cipher_aes.cl"
#endif
typedef struct krb5pa_18
{
u32 user[128];
u32 domain[128];
u32 account_info[512];
u32 account_info_len;
u32 checksum[3];
u32 enc_timestamp[32];
u32 enc_timestamp_len;
} krb5pa_18_t;
typedef struct krb5pa_18_tmp
{
u32 ipad[5];
u32 opad[5];
u32 dgst[16];
u32 out[16];
} krb5pa_18_tmp_t;
DECLSPEC static void aes256_encrypt_cbc (const u32 *aes_ks, u32 *aes_iv, const u32 *in, u32 *out, SHM_TYPE u32 *s_te0, SHM_TYPE u32 *s_te1, SHM_TYPE u32 *s_te2, SHM_TYPE u32 *s_te3, SHM_TYPE u32 *s_te4)
{
u32 data[4];
data[0] = hc_swap32_S (in[0]);
data[1] = hc_swap32_S (in[1]);
data[2] = hc_swap32_S (in[2]);
data[3] = hc_swap32_S (in[3]);
data[0] ^= aes_iv[0];
data[1] ^= aes_iv[1];
data[2] ^= aes_iv[2];
data[3] ^= aes_iv[3];
aes256_encrypt (aes_ks, data, out, s_te0, s_te1, s_te2, s_te3, s_te4);
aes_iv[0] = out[0];
aes_iv[1] = out[1];
aes_iv[2] = out[2];
aes_iv[3] = out[3];
out[0] = hc_swap32_S (out[0]);
out[1] = hc_swap32_S (out[1]);
out[2] = hc_swap32_S (out[2]);
out[3] = hc_swap32_S (out[3]);
}
DECLSPEC static void aes256_decrypt_cbc (const u32 *ks1, const u32 *in, u32 *out, u32 *essiv, SHM_TYPE u32 *s_td0, SHM_TYPE u32 *s_td1, SHM_TYPE u32 *s_td2, SHM_TYPE u32 *s_td3, SHM_TYPE u32 *s_td4)
{
aes256_decrypt (ks1, in, out, s_td0, s_td1, s_td2, s_td3, s_td4);
out[0] ^= essiv[0];
out[1] ^= essiv[1];
out[2] ^= essiv[2];
out[3] ^= essiv[3];
essiv[0] = in[0];
essiv[1] = in[1];
essiv[2] = in[2];
essiv[3] = in[3];
}
DECLSPEC static void hmac_sha1_run_V (u32x *w0, u32x *w1, u32x *w2, u32x *w3, u32x *ipad, u32x *opad, u32x *digest)
{
digest[0] = ipad[0];
digest[1] = ipad[1];
digest[2] = ipad[2];
digest[3] = ipad[3];
digest[4] = ipad[4];
sha1_transform_vector (w0, w1, w2, w3, digest);
w0[0] = digest[0];
w0[1] = digest[1];
w0[2] = digest[2];
w0[3] = digest[3];
w1[0] = digest[4];
w1[1] = 0x80000000;
w1[2] = 0;
w1[3] = 0;
w2[0] = 0;
w2[1] = 0;
w2[2] = 0;
w2[3] = 0;
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = (64 + 20) * 8;
digest[0] = opad[0];
digest[1] = opad[1];
digest[2] = opad[2];
digest[3] = opad[3];
digest[4] = opad[4];
sha1_transform_vector (w0, w1, w2, w3, digest);
}
KERNEL_FQ void m19900_init (KERN_ATTR_TMPS_ESALT (krb5pa_18_tmp_t, krb5pa_18_t))
{
/**
* base
*/
const u64 gid = get_global_id (0);
if (gid >= gid_max) return;
/**
* main
*/
/* initialize hmac-sha1 for pbkdf2(password, account, 4096, account_len) */
sha1_hmac_ctx_t sha1_hmac_ctx;
sha1_hmac_init_global_swap (&sha1_hmac_ctx, pws[gid].i, pws[gid].pw_len);
tmps[gid].ipad[0] = sha1_hmac_ctx.ipad.h[0];
tmps[gid].ipad[1] = sha1_hmac_ctx.ipad.h[1];
tmps[gid].ipad[2] = sha1_hmac_ctx.ipad.h[2];
tmps[gid].ipad[3] = sha1_hmac_ctx.ipad.h[3];
tmps[gid].ipad[4] = sha1_hmac_ctx.ipad.h[4];
tmps[gid].opad[0] = sha1_hmac_ctx.opad.h[0];
tmps[gid].opad[1] = sha1_hmac_ctx.opad.h[1];
tmps[gid].opad[2] = sha1_hmac_ctx.opad.h[2];
tmps[gid].opad[3] = sha1_hmac_ctx.opad.h[3];
tmps[gid].opad[4] = sha1_hmac_ctx.opad.h[4];
sha1_hmac_update_global_swap (&sha1_hmac_ctx, esalt_bufs[digests_offset].account_info, esalt_bufs[digests_offset].account_info_len);
for (u32 i = 0, j = 1; i < 8; i += 5, j += 1)
{
sha1_hmac_ctx_t sha1_hmac_ctx2 = sha1_hmac_ctx;
u32 w0[4];
u32 w1[4];
u32 w2[4];
u32 w3[4];
w0[0] = j;
w0[1] = 0;
w0[2] = 0;
w0[3] = 0;
w1[0] = 0;
w1[1] = 0;
w1[2] = 0;
w1[3] = 0;
w2[0] = 0;
w2[1] = 0;
w2[2] = 0;
w2[3] = 0;
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = 0;
sha1_hmac_update_64 (&sha1_hmac_ctx2, w0, w1, w2, w3, 4);
sha1_hmac_final (&sha1_hmac_ctx2);
tmps[gid].dgst[i + 0] = sha1_hmac_ctx2.opad.h[0];
tmps[gid].dgst[i + 1] = sha1_hmac_ctx2.opad.h[1];
tmps[gid].dgst[i + 2] = sha1_hmac_ctx2.opad.h[2];
tmps[gid].dgst[i + 3] = sha1_hmac_ctx2.opad.h[3];
tmps[gid].dgst[i + 4] = sha1_hmac_ctx2.opad.h[4];
tmps[gid].out[i + 0] = tmps[gid].dgst[i + 0];
tmps[gid].out[i + 1] = tmps[gid].dgst[i + 1];
tmps[gid].out[i + 2] = tmps[gid].dgst[i + 2];
tmps[gid].out[i + 3] = tmps[gid].dgst[i + 3];
tmps[gid].out[i + 4] = tmps[gid].dgst[i + 4];
}
}
KERNEL_FQ void m19900_loop (KERN_ATTR_TMPS_ESALT (krb5pa_18_tmp_t, krb5pa_18_t))
{
/**
* base
*/
const u64 gid = get_global_id (0);
if ((gid * VECT_SIZE) >= gid_max) return;
u32x ipad[5];
u32x opad[5];
ipad[0] = packv (tmps, ipad, gid, 0);
ipad[1] = packv (tmps, ipad, gid, 1);
ipad[2] = packv (tmps, ipad, gid, 2);
ipad[3] = packv (tmps, ipad, gid, 3);
ipad[4] = packv (tmps, ipad, gid, 4);
opad[0] = packv (tmps, opad, gid, 0);
opad[1] = packv (tmps, opad, gid, 1);
opad[2] = packv (tmps, opad, gid, 2);
opad[3] = packv (tmps, opad, gid, 3);
opad[4] = packv (tmps, opad, gid, 4);
for (u32 i = 0; i < 8; i += 5)
{
u32x dgst[5];
u32x out[5];
dgst[0] = packv (tmps, dgst, gid, i + 0);
dgst[1] = packv (tmps, dgst, gid, i + 1);
dgst[2] = packv (tmps, dgst, gid, i + 2);
dgst[3] = packv (tmps, dgst, gid, i + 3);
dgst[4] = packv (tmps, dgst, gid, i + 4);
out[0] = packv (tmps, out, gid, i + 0);
out[1] = packv (tmps, out, gid, i + 1);
out[2] = packv (tmps, out, gid, i + 2);
out[3] = packv (tmps, out, gid, i + 3);
out[4] = packv (tmps, out, gid, i + 4);
for (u32 j = 0; j < loop_cnt; j++)
{
u32x w0[4];
u32x w1[4];
u32x w2[4];
u32x w3[4];
w0[0] = dgst[0];
w0[1] = dgst[1];
w0[2] = dgst[2];
w0[3] = dgst[3];
w1[0] = dgst[4];
w1[1] = 0x80000000;
w1[2] = 0;
w1[3] = 0;
w2[0] = 0;
w2[1] = 0;
w2[2] = 0;
w2[3] = 0;
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = (64 + 20) * 8;
hmac_sha1_run_V (w0, w1, w2, w3, ipad, opad, dgst);
out[0] ^= dgst[0];
out[1] ^= dgst[1];
out[2] ^= dgst[2];
out[3] ^= dgst[3];
out[4] ^= dgst[4];
}
unpackv (tmps, dgst, gid, i + 0, dgst[0]);
unpackv (tmps, dgst, gid, i + 1, dgst[1]);
unpackv (tmps, dgst, gid, i + 2, dgst[2]);
unpackv (tmps, dgst, gid, i + 3, dgst[3]);
unpackv (tmps, dgst, gid, i + 4, dgst[4]);
unpackv (tmps, out, gid, i + 0, out[0]);
unpackv (tmps, out, gid, i + 1, out[1]);
unpackv (tmps, out, gid, i + 2, out[2]);
unpackv (tmps, out, gid, i + 3, out[3]);
unpackv (tmps, out, gid, i + 4, out[4]);
}
}
KERNEL_FQ void m19900_comp (KERN_ATTR_TMPS_ESALT (krb5pa_18_tmp_t, krb5pa_18_t))
{
/**
* base
*/
const u64 gid = get_global_id (0);
const u64 lid = get_local_id (0);
const u64 lsz = get_local_size (0);
/**
* aes shared
*/
#ifdef REAL_SHM
LOCAL_AS u32 s_td0[256];
LOCAL_AS u32 s_td1[256];
LOCAL_AS u32 s_td2[256];
LOCAL_AS u32 s_td3[256];
LOCAL_AS u32 s_td4[256];
LOCAL_AS u32 s_te0[256];
LOCAL_AS u32 s_te1[256];
LOCAL_AS u32 s_te2[256];
LOCAL_AS u32 s_te3[256];
LOCAL_AS u32 s_te4[256];
for (u32 i = lid; i < 256; i += lsz)
{
s_td0[i] = td0[i];
s_td1[i] = td1[i];
s_td2[i] = td2[i];
s_td3[i] = td3[i];
s_td4[i] = td4[i];
s_te0[i] = te0[i];
s_te1[i] = te1[i];
s_te2[i] = te2[i];
s_te3[i] = te3[i];
s_te4[i] = te4[i];
}
barrier (CLK_LOCAL_MEM_FENCE);
#else
CONSTANT_AS u32a *s_td0 = td0;
CONSTANT_AS u32a *s_td1 = td1;
CONSTANT_AS u32a *s_td2 = td2;
CONSTANT_AS u32a *s_td3 = td3;
CONSTANT_AS u32a *s_td4 = td4;
CONSTANT_AS u32a *s_te0 = te0;
CONSTANT_AS u32a *s_te1 = te1;
CONSTANT_AS u32a *s_te2 = te2;
CONSTANT_AS u32a *s_te3 = te3;
CONSTANT_AS u32a *s_te4 = te4;
#endif
if (gid >= gid_max) return;
/*
at this point, the output ('seed') will be used to generate AES keys:
key_bytes = derive(seed, 'kerberos'.encode(), seedsize)
'key_bytes' will be the AES key used to generate 'ke' and 'ki'
'ke' will be the AES key to decrypt the ticket
'ki' will be the key to compute the final HMAC
*/
u32 nfolded[4];
// we can precompute _nfold('kerberos', 16)
nfolded[0] = 0x6b657262;
nfolded[1] = 0x65726f73;
nfolded[2] = 0x7b9b5b2b;
nfolded[3] = 0x93132b93;
// then aes_cbc encrypt this nfolded value with 'seed' as key along with a null IV
u32 aes_key[8];
aes_key[0] = hc_swap32_S (tmps[gid].out[0]);
aes_key[1] = hc_swap32_S (tmps[gid].out[1]);
aes_key[2] = hc_swap32_S (tmps[gid].out[2]);
aes_key[3] = hc_swap32_S (tmps[gid].out[3]);
aes_key[4] = hc_swap32_S (tmps[gid].out[4]);
aes_key[5] = hc_swap32_S (tmps[gid].out[5]);
aes_key[6] = hc_swap32_S (tmps[gid].out[6]);
aes_key[7] = hc_swap32_S (tmps[gid].out[7]);
u32 aes_iv[4];
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
u32 aes_ks[60];
aes256_set_encrypt_key (aes_ks, aes_key, s_te0, s_te1, s_te2, s_te3);
u32 key_bytes[8];
u32 out[4];
aes256_encrypt_cbc (aes_ks, aes_iv, nfolded, out, s_te0, s_te1, s_te2, s_te3, s_te4);
key_bytes[0] = hc_swap32_S (out[0]);
key_bytes[1] = hc_swap32_S (out[1]);
key_bytes[2] = hc_swap32_S (out[2]);
key_bytes[3] = hc_swap32_S (out[3]);
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
aes256_encrypt_cbc (aes_ks, aes_iv, out, out, s_te0, s_te1, s_te2, s_te3, s_te4);
key_bytes[4] = hc_swap32_S (out[0]);
key_bytes[5] = hc_swap32_S (out[1]);
key_bytes[6] = hc_swap32_S (out[2]);
key_bytes[7] = hc_swap32_S (out[3]);
// then aes_cbc encrypt this nfolded value with 'key_bytes' as key along with a null IV
aes256_set_encrypt_key (aes_ks, key_bytes, s_te0, s_te1, s_te2, s_te3);
/* we will now compute 'ke' */
u32 ke[8];
// we can precompute _nfold(pack('>IB', 1, 0xAA), 16)
nfolded[0] = 0xae2c160b;
nfolded[1] = 0x04ad5006;
nfolded[2] = 0xab55aad5;
nfolded[3] = 0x6a80355a;
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
// then aes_cbc encrypt this nfolded value with 'key_bytes' as key along with a null IV
aes256_encrypt_cbc (aes_ks, aes_iv, nfolded, out, s_te0, s_te1, s_te2, s_te3, s_te4);
ke[0] = out[0];
ke[1] = out[1];
ke[2] = out[2];
ke[3] = out[3];
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
aes256_encrypt_cbc (aes_ks, aes_iv, out, out, s_te0, s_te1, s_te2, s_te3, s_te4);
ke[4] = out[0];
ke[5] = out[1];
ke[6] = out[2];
ke[7] = out[3];
// Decode the CTS mode encryption by decrypting c_n-1 and swapping it with c_n
u32 enc_blocks[12];
u32 decrypted_block[4];
// c_0
enc_blocks[0] = esalt_bufs[digests_offset].enc_timestamp[0];
enc_blocks[1] = esalt_bufs[digests_offset].enc_timestamp[1];
enc_blocks[2] = esalt_bufs[digests_offset].enc_timestamp[2];
enc_blocks[3] = esalt_bufs[digests_offset].enc_timestamp[3];
// c_1 aka c_n-1 since there are guaranteed to be exactly 3 blocks
enc_blocks[4] = esalt_bufs[digests_offset].enc_timestamp[4];
enc_blocks[5] = esalt_bufs[digests_offset].enc_timestamp[5];
enc_blocks[6] = esalt_bufs[digests_offset].enc_timestamp[6];
enc_blocks[7] = esalt_bufs[digests_offset].enc_timestamp[7];
u32 w0[4];
u32 w1[4];
u32 w2[4];
u32 w3[4];
u32 aes_cts_decrypt_ks[60];
AES256_set_decrypt_key (aes_cts_decrypt_ks, ke, s_te0, s_te1, s_te2, s_te3, s_td0, s_td1, s_td2, s_td3);
// Our first decryption is the last block (currently in c_n-1) using the first portion of (c_n) as our IV, this allows us to get plaintext in one crypto operation
aes_iv[0] = esalt_bufs[digests_offset].enc_timestamp[8];
aes_iv[1] = esalt_bufs[digests_offset].enc_timestamp[9];
aes_iv[2] = esalt_bufs[digests_offset].enc_timestamp[10];
aes_iv[3] = esalt_bufs[digests_offset].enc_timestamp[11];
aes256_decrypt_cbc (aes_cts_decrypt_ks, enc_blocks + 4, decrypted_block, aes_iv, s_td0, s_td1, s_td2, s_td3, s_td4);
w0[0] = hc_swap32_S (decrypted_block[0]);
w0[1] = hc_swap32_S (decrypted_block[1]);
w0[2] = hc_swap32_S (decrypted_block[2]);
w0[3] = hc_swap32_S (decrypted_block[3]);
// Move as much code as possible after this branch to avoid unnecessary computation on misses
if (((w0[0] & 0xf0f0f0f0) == 0x30303030) && ((w0[1] & 0xffff0000) == 0x5aa10000))
{
// Decrypt c_n-1 without an IV for the padding blocks on c_n
aes256_decrypt (aes_cts_decrypt_ks, enc_blocks + 4, decrypted_block, s_td0, s_td1, s_td2, s_td3, s_td4);
w0[0] = decrypted_block[0];
w0[1] = decrypted_block[1];
w0[2] = decrypted_block[2];
w0[3] = decrypted_block[3];
int enc_timestamp_len = esalt_bufs[digests_offset].enc_timestamp_len;
int last_word_position = enc_timestamp_len / 4;
// New c_1, join c_n with result of the decrypted c_n-1
int last_block_iter;
for (last_block_iter = 4; last_block_iter < 8; last_block_iter++)
{
if (last_word_position > last_block_iter + 4)
{
enc_blocks[last_block_iter] = esalt_bufs[digests_offset].enc_timestamp[last_block_iter + 4];
}
else if (last_word_position == last_block_iter + 4)
{
// Handle case when the split lands in the middle of a WORD
switch (enc_timestamp_len % 4)
{
case 1:
enc_blocks[last_block_iter] = (esalt_bufs[digests_offset].enc_timestamp[last_block_iter + 4] & 0x000000ff) | (w0[last_block_iter - 4] & 0xffffff00);
break;
case 2:
enc_blocks[last_block_iter] = (esalt_bufs[digests_offset].enc_timestamp[last_block_iter + 4] & 0x0000ffff) | (w0[last_block_iter - 4] & 0xffff0000);
break;
case 3:
enc_blocks[last_block_iter] = (esalt_bufs[digests_offset].enc_timestamp[last_block_iter + 4] & 0x00ffffff) | (w0[last_block_iter - 4] & 0xff000000);
break;
default:
enc_blocks[last_block_iter] = w0[last_block_iter - 4];
}
}
else
{
enc_blocks[last_block_iter] = w0[last_block_iter - 4];
}
}
// c_2 aka c_n which is now equal to the old c_n-1
enc_blocks[8] = esalt_bufs[digests_offset].enc_timestamp[4];
enc_blocks[9] = esalt_bufs[digests_offset].enc_timestamp[5];
enc_blocks[10] = esalt_bufs[digests_offset].enc_timestamp[6];
enc_blocks[11] = esalt_bufs[digests_offset].enc_timestamp[7];
// Go ahead and decrypt all blocks now as a normal AES CBC operation
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
aes256_decrypt_cbc (aes_cts_decrypt_ks, enc_blocks, decrypted_block, aes_iv, s_td0, s_td1, s_td2, s_td3, s_td4);
w0[0] = hc_swap32_S (decrypted_block[0]);
w0[1] = hc_swap32_S (decrypted_block[1]);
w0[2] = hc_swap32_S (decrypted_block[2]);
w0[3] = hc_swap32_S (decrypted_block[3]);
aes256_decrypt_cbc (aes_cts_decrypt_ks, enc_blocks + 4, decrypted_block, aes_iv, s_td0, s_td1, s_td2, s_td3, s_td4);
w1[0] = hc_swap32_S (decrypted_block[0]);
w1[1] = hc_swap32_S (decrypted_block[1]);
w1[2] = hc_swap32_S (decrypted_block[2]);
w1[3] = hc_swap32_S (decrypted_block[3]);
aes256_decrypt_cbc (aes_cts_decrypt_ks, enc_blocks + 8, decrypted_block, aes_iv, s_td0, s_td1, s_td2, s_td3, s_td4);
w2[0] = hc_swap32_S (decrypted_block[0]);
w2[1] = hc_swap32_S (decrypted_block[1]);
w2[2] = hc_swap32_S (decrypted_block[2]);
w2[3] = hc_swap32_S (decrypted_block[3]);
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = 0;
/* we will now compute 'ki', having 'key_bytes' */
u32 ki[8];
// we can precompute _nfold(pack('>IB', 1, 0x55), 16)
nfolded[0] = 0x5b582c16;
nfolded[1] = 0x0a5aa805;
nfolded[2] = 0x56ab55aa;
nfolded[3] = 0xd5402ab5;
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
// then aes_cbc encrypt this nfolded value with 'key_bytes' as key along with a null IV
aes256_set_encrypt_key (aes_ks, key_bytes, s_te0, s_te1, s_te2, s_te3);
aes256_encrypt_cbc (aes_ks, aes_iv, nfolded, out, s_te0, s_te1, s_te2, s_te3, s_te4);
ki[0] = out[0];
ki[1] = out[1];
ki[2] = out[2];
ki[3] = out[3];
aes_iv[0] = 0;
aes_iv[1] = 0;
aes_iv[2] = 0;
aes_iv[3] = 0;
aes256_encrypt_cbc (aes_ks, aes_iv, out, out, s_te0, s_te1, s_te2, s_te3, s_te4);
ki[4] = out[0];
ki[5] = out[1];
ki[6] = out[2];
ki[7] = out[3];
sha1_hmac_ctx_t sha1_hmac_ctx;
/*
hmac message = plaintext
hmac key = ki
*/
u32 k0[4];
u32 k1[4];
u32 k2[4];
u32 k3[4];
k0[0] = ki[0];
k0[1] = ki[1];
k0[2] = ki[2];
k0[3] = ki[3];
k1[0] = ki[4];
k1[1] = ki[5];
k1[2] = ki[6];
k1[3] = ki[7];
k2[0] = 0;
k2[1] = 0;
k2[2] = 0;
k2[3] = 0;
k3[0] = 0;
k3[1] = 0;
k3[2] = 0;
k3[3] = 0;
sha1_hmac_init_64 (&sha1_hmac_ctx, k0, k1, k2, k3);
sha1_hmac_update_64 (&sha1_hmac_ctx, w0, w1, w2, w3, enc_timestamp_len);
sha1_hmac_final(&sha1_hmac_ctx);
// Compare checksum
if(sha1_hmac_ctx.opad.h[0] == esalt_bufs[digests_offset].checksum[0]
&& sha1_hmac_ctx.opad.h[1] == esalt_bufs[digests_offset].checksum[1]
&& sha1_hmac_ctx.opad.h[2] == esalt_bufs[digests_offset].checksum[2])
{
if (atomic_inc (&hashes_shown[digests_offset]) == 0)
{
#define il_pos 0
mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, il_pos, 0, 0);
}
}
}
}

View File

@ -29,6 +29,7 @@ Gabriele "matrix" Gristina <matrix@hashcat.net> (@gm4tr1x)
Jean-Christophe "Fist0urs" Delaunay <jean-christophe.delaunay@synacktiv.com> (@Fist0urs)
* Kerberos TGS Rep enctype 23 kernel module
* Kerberos TGS Rep enctype 17/18 kernel module
* AxCrypt kernel module
* KeePass kernel module
* DPAPImk v1 and v2 kernel module
@ -61,5 +62,8 @@ Rick "Minga" Redman and KoreLogic <mingakore@gmail.com> (@CrackMeIfYouCan)
* For running the "Crack Me If You Can" password cracking contest, first of its kind
* For pushing password cracking techniques forward
Brandon Chalk <brandon@casaba.com> (@brandoncasaba)
* Kerberos Pre-Auth 17/18 kernel module, ported from @Fist0urs TGS kernel modules
!!! All the package maintainer of hashcat !!!

295
src/modules/module_19800.c Normal file
View File

@ -0,0 +1,295 @@
/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#include "common.h"
#include "types.h"
#include "modules.h"
#include "bitops.h"
#include "convert.h"
#include "shared.h"
static const u32 ATTACK_EXEC = ATTACK_EXEC_OUTSIDE_KERNEL;
static const u32 DGST_POS0 = 0;
static const u32 DGST_POS1 = 1;
static const u32 DGST_POS2 = 2;
static const u32 DGST_POS3 = 3;
static const u32 DGST_SIZE = DGST_SIZE_4_4;
static const u32 HASH_CATEGORY = HASH_CATEGORY_NETWORK_PROTOCOL;
static const char *HASH_NAME = "Kerberos 5 Pre-Auth etype 17 (AES128-CTS-HMAC-SHA1-96)";
static const u64 KERN_TYPE = 19800;
static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE
| OPTI_TYPE_NOT_ITERATED
| OPTI_TYPE_SLOW_HASH_SIMD_LOOP;
static const u64 OPTS_TYPE = OPTS_TYPE_PT_GENERATE_LE;
static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED;
static const char *ST_PASS = "hashcat";
static const char *ST_HASH = "$krb5pa$17$hashcat$HASHCATDOMAIN.COM$a17776abe5383236c58582f515843e029ecbff43706d177651b7b6cdb2713b17597ddb35b1c9c470c281589fd1d51cca125414d19e40e333";
u32 module_attack_exec (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return ATTACK_EXEC; }
u32 module_dgst_pos0 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS0; }
u32 module_dgst_pos1 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS1; }
u32 module_dgst_pos2 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS2; }
u32 module_dgst_pos3 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS3; }
u32 module_dgst_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_SIZE; }
u32 module_hash_category (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return HASH_CATEGORY; }
const char *module_hash_name (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return HASH_NAME; }
u64 module_kern_type (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return KERN_TYPE; }
u32 module_opti_type (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return OPTI_TYPE; }
u64 module_opts_type (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return OPTS_TYPE; }
u32 module_salt_type (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return SALT_TYPE; }
const char *module_st_hash (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return ST_HASH; }
const char *module_st_pass (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return ST_PASS; }
typedef struct krb5pa_17
{
u32 user[128];
u32 domain[128];
u32 account_info[512];
u32 account_info_len;
u32 checksum[3];
u32 enc_timestamp[32];
u32 enc_timestamp_len;
} krb5pa_17_t;
typedef struct krb5pa_17_tmp
{
u32 ipad[5];
u32 opad[5];
u32 dgst[10];
u32 out[10];
} krb5pa_17_tmp_t;
static const char *SIGNATURE_KRB5PA = "$krb5pa$17$";
u64 module_tmp_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
{
const u64 tmp_size = (const u64) sizeof (krb5pa_17_tmp_t);
return tmp_size;
}
u64 module_esalt_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
{
const u64 esalt_size = (const u64) sizeof (krb5pa_17_t);
return esalt_size;
}
int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED void *digest_buf, MAYBE_UNUSED salt_t *salt, MAYBE_UNUSED void *esalt_buf, MAYBE_UNUSED void *hook_salt_buf, MAYBE_UNUSED hashinfo_t *hash_info, const char *line_buf, MAYBE_UNUSED const int line_len)
{
u32 *digest = (u32 *) digest_buf;
krb5pa_17_t *krb5pa = (krb5pa_17_t *) esalt_buf;
token_t token;
token.signatures_cnt = 1;
token.signatures_buf[0] = SIGNATURE_KRB5PA;
token.len[0] = 11;
token.attr[0] = TOKEN_ATTR_FIXED_LENGTH
| TOKEN_ATTR_VERIFY_SIGNATURE;
/**
* $krb5pa$17$*user*realm*$enc_timestamp+checksum
*/
// assume no signature found
if (line_len < 11) return (PARSER_SALT_LENGTH);
// assume $krb5pa$17$user$realm$enc_timestamp+checksum
token.token_cnt = 4;
token.sep[1] = '$';
token.len_min[1] = 1;
token.len_max[1] = 512;
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH;
token.sep[2] = '$';
token.len_min[2] = 1;
token.len_max[2] = 512;
token.attr[2] = TOKEN_ATTR_VERIFY_LENGTH;
token.sep[3] = '$';
token.len_min[3] = 104;
token.len_max[3] = 112;
token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH
| TOKEN_ATTR_VERIFY_HEX;
const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token);
if (rc_tokenizer != PARSER_OK) return (rc_tokenizer);
const u8 *user_pos;
const u8 *domain_pos;
const u8 *data_pos;
const u8 *checksum_pos;
int user_len;
int domain_len;
int data_len;
int account_info_len;
user_pos = token.buf[1];
user_len = token.len[1];
memcpy(krb5pa->user, user_pos, user_len);
domain_pos = token.buf[2];
domain_len = token.len[2];
memcpy(krb5pa->domain, domain_pos, domain_len);
data_pos = token.buf[3];
data_len = token.len[3];
account_info_len = token.len[2] + token.len[1];
u8 *account_info_ptr = (u8 *) krb5pa->account_info;
// domain must be uppercase
u8 domain[128];
memcpy(domain, domain_pos, domain_len);
uppercase(domain, domain_len);
memcpy(account_info_ptr, domain, domain_len);
memcpy(account_info_ptr + domain_len, user_pos, user_len);
krb5pa->account_info_len = account_info_len;
// Split checksum
checksum_pos = data_pos + data_len - 24;
data_len = data_len - 24;
// hmac-sha1 is reduced to 12 bytes
krb5pa->checksum[0] = byte_swap_32 (hex_to_u32 (checksum_pos + 0));
krb5pa->checksum[1] = byte_swap_32 (hex_to_u32 (checksum_pos + 8));
krb5pa->checksum[2] = byte_swap_32 (hex_to_u32 (checksum_pos + 16));
u8 *edata_ptr = (u8 *) krb5pa->enc_timestamp;
for (int i = 0; i < data_len; i += 2)
{
const u8 p0 = data_pos[i + 0];
const u8 p1 = data_pos[i + 1];
*edata_ptr++ = hex_convert (p1) << 0
| hex_convert (p0) << 4;
}
krb5pa->enc_timestamp_len = data_len / 2;
salt->salt_buf[0] = krb5pa->checksum[0];
salt->salt_buf[1] = krb5pa->checksum[1];
salt->salt_buf[2] = krb5pa->checksum[2];
salt->salt_iter = 4096 - 1;
digest[0] = krb5pa->checksum[0];
digest[1] = krb5pa->checksum[1];
digest[2] = krb5pa->checksum[2];
digest[3] = 0;
return (PARSER_OK);
}
int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const void *digest_buf, MAYBE_UNUSED const salt_t *salt, MAYBE_UNUSED const void *esalt_buf, MAYBE_UNUSED const void *hook_salt_buf, MAYBE_UNUSED const hashinfo_t *hash_info, char *line_buf, MAYBE_UNUSED const int line_size)
{
const krb5pa_17_t *krb5pa = (const krb5pa_17_t *) esalt_buf;
char data[32 * 4 * 2] = { 0 };
for (u32 i = 0, j = 0; i < krb5pa->enc_timestamp_len; i += 1, j += 2)
{
u8 *ptr_enc_timestamp = (u8 *) krb5pa->enc_timestamp;
sprintf (data + j, "%02x", ptr_enc_timestamp[i]);
}
const int line_len = snprintf (line_buf, line_size, "%s%s$%s$%s%08x%08x%08x",
SIGNATURE_KRB5PA,
(char *) krb5pa->user,
(char *) krb5pa->domain,
data,
krb5pa->checksum[0],
krb5pa->checksum[1],
krb5pa->checksum[2]);
return line_len;
}
void module_init (module_ctx_t *module_ctx)
{
module_ctx->module_context_size = MODULE_CONTEXT_SIZE_CURRENT;
module_ctx->module_interface_version = MODULE_INTERFACE_VERSION_CURRENT;
module_ctx->module_attack_exec = module_attack_exec;
module_ctx->module_benchmark_esalt = MODULE_DEFAULT;
module_ctx->module_benchmark_hook_salt = MODULE_DEFAULT;
module_ctx->module_benchmark_mask = MODULE_DEFAULT;
module_ctx->module_benchmark_salt = MODULE_DEFAULT;
module_ctx->module_build_plain_postprocess = MODULE_DEFAULT;
module_ctx->module_deep_comp_kernel = MODULE_DEFAULT;
module_ctx->module_dgst_pos0 = module_dgst_pos0;
module_ctx->module_dgst_pos1 = module_dgst_pos1;
module_ctx->module_dgst_pos2 = module_dgst_pos2;
module_ctx->module_dgst_pos3 = module_dgst_pos3;
module_ctx->module_dgst_size = module_dgst_size;
module_ctx->module_dictstat_disable = MODULE_DEFAULT;
module_ctx->module_esalt_size = module_esalt_size;
module_ctx->module_extra_buffer_size = MODULE_DEFAULT;
module_ctx->module_extra_tmp_size = MODULE_DEFAULT;
module_ctx->module_forced_outfile_format = MODULE_DEFAULT;
module_ctx->module_hash_binary_count = MODULE_DEFAULT;
module_ctx->module_hash_binary_parse = MODULE_DEFAULT;
module_ctx->module_hash_binary_save = MODULE_DEFAULT;
module_ctx->module_hash_decode_potfile = MODULE_DEFAULT;
module_ctx->module_hash_decode_zero_hash = MODULE_DEFAULT;
module_ctx->module_hash_decode = module_hash_decode;
module_ctx->module_hash_encode_status = MODULE_DEFAULT;
module_ctx->module_hash_encode_potfile = MODULE_DEFAULT;
module_ctx->module_hash_encode = module_hash_encode;
module_ctx->module_hash_init_selftest = MODULE_DEFAULT;
module_ctx->module_hash_mode = MODULE_DEFAULT;
module_ctx->module_hash_category = module_hash_category;
module_ctx->module_hash_name = module_hash_name;
module_ctx->module_hlfmt_disable = MODULE_DEFAULT;
module_ctx->module_hook12 = MODULE_DEFAULT;
module_ctx->module_hook23 = MODULE_DEFAULT;
module_ctx->module_hook_salt_size = MODULE_DEFAULT;
module_ctx->module_hook_size = MODULE_DEFAULT;
module_ctx->module_jit_build_options = MODULE_DEFAULT;
module_ctx->module_jit_cache_disable = MODULE_DEFAULT;
module_ctx->module_kernel_accel_max = MODULE_DEFAULT;
module_ctx->module_kernel_accel_min = MODULE_DEFAULT;
module_ctx->module_kernel_loops_max = MODULE_DEFAULT;
module_ctx->module_kernel_loops_min = MODULE_DEFAULT;
module_ctx->module_kernel_threads_max = MODULE_DEFAULT;
module_ctx->module_kernel_threads_min = MODULE_DEFAULT;
module_ctx->module_kern_type = module_kern_type;
module_ctx->module_kern_type_dynamic = MODULE_DEFAULT;
module_ctx->module_opti_type = module_opti_type;
module_ctx->module_opts_type = module_opts_type;
module_ctx->module_outfile_check_disable = MODULE_DEFAULT;
module_ctx->module_outfile_check_nocomp = MODULE_DEFAULT;
module_ctx->module_potfile_custom_check = MODULE_DEFAULT;
module_ctx->module_potfile_disable = MODULE_DEFAULT;
module_ctx->module_potfile_keep_all_hashes = MODULE_DEFAULT;
module_ctx->module_pwdump_column = MODULE_DEFAULT;
module_ctx->module_pw_max = MODULE_DEFAULT;
module_ctx->module_pw_min = MODULE_DEFAULT;
module_ctx->module_salt_max = MODULE_DEFAULT;
module_ctx->module_salt_min = MODULE_DEFAULT;
module_ctx->module_salt_type = module_salt_type;
module_ctx->module_separator = MODULE_DEFAULT;
module_ctx->module_st_hash = module_st_hash;
module_ctx->module_st_pass = module_st_pass;
module_ctx->module_tmp_size = module_tmp_size;
module_ctx->module_unstable_warning = MODULE_DEFAULT;
module_ctx->module_warmup_disable = MODULE_DEFAULT;
}

295
src/modules/module_19900.c Normal file
View File

@ -0,0 +1,295 @@
/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#include "common.h"
#include "types.h"
#include "modules.h"
#include "bitops.h"
#include "convert.h"
#include "shared.h"
static const u32 ATTACK_EXEC = ATTACK_EXEC_OUTSIDE_KERNEL;
static const u32 DGST_POS0 = 0;
static const u32 DGST_POS1 = 1;
static const u32 DGST_POS2 = 2;
static const u32 DGST_POS3 = 3;
static const u32 DGST_SIZE = DGST_SIZE_4_4;
static const u32 HASH_CATEGORY = HASH_CATEGORY_NETWORK_PROTOCOL;
static const char *HASH_NAME = "Kerberos 5 Pre-Auth etype 18 (AES256-CTS-HMAC-SHA1-96)";
static const u64 KERN_TYPE = 19900;
static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE
| OPTI_TYPE_NOT_ITERATED
| OPTI_TYPE_SLOW_HASH_SIMD_LOOP;
static const u64 OPTS_TYPE = OPTS_TYPE_PT_GENERATE_LE;
static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED;
static const char *ST_PASS = "hashcat";
static const char *ST_HASH = "$krb5pa$18$hashcat$HASHCATDOMAIN.COM$96c289009b05181bfd32062962740b1b1ce5f74eb12e0266cde74e81094661addab08c0c1a178882c91a0ed89ae4e0e68d2820b9cce69770";
u32 module_attack_exec (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return ATTACK_EXEC; }
u32 module_dgst_pos0 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS0; }
u32 module_dgst_pos1 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS1; }
u32 module_dgst_pos2 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS2; }
u32 module_dgst_pos3 (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_POS3; }
u32 module_dgst_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return DGST_SIZE; }
u32 module_hash_category (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return HASH_CATEGORY; }
const char *module_hash_name (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return HASH_NAME; }
u64 module_kern_type (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return KERN_TYPE; }
u32 module_opti_type (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return OPTI_TYPE; }
u64 module_opts_type (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return OPTS_TYPE; }
u32 module_salt_type (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return SALT_TYPE; }
const char *module_st_hash (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return ST_HASH; }
const char *module_st_pass (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return ST_PASS; }
typedef struct krb5pa_18
{
u32 user[128];
u32 domain[128];
u32 account_info[512];
u32 account_info_len;
u32 checksum[3];
u32 enc_timestamp[32];
u32 enc_timestamp_len;
} krb5pa_18_t;
typedef struct krb5pa_18_tmp
{
u32 ipad[5];
u32 opad[5];
u32 dgst[16];
u32 out[16];
} krb5pa_18_tmp_t;
static const char *SIGNATURE_KRB5PA = "$krb5pa$18$";
u64 module_tmp_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
{
const u64 tmp_size = (const u64) sizeof (krb5pa_18_tmp_t);
return tmp_size;
}
u64 module_esalt_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
{
const u64 esalt_size = (const u64) sizeof (krb5pa_18_t);
return esalt_size;
}
int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED void *digest_buf, MAYBE_UNUSED salt_t *salt, MAYBE_UNUSED void *esalt_buf, MAYBE_UNUSED void *hook_salt_buf, MAYBE_UNUSED hashinfo_t *hash_info, const char *line_buf, MAYBE_UNUSED const int line_len)
{
u32 *digest = (u32 *) digest_buf;
krb5pa_18_t *krb5pa = (krb5pa_18_t *) esalt_buf;
token_t token;
token.signatures_cnt = 1;
token.signatures_buf[0] = SIGNATURE_KRB5PA;
token.len[0] = 11;
token.attr[0] = TOKEN_ATTR_FIXED_LENGTH
| TOKEN_ATTR_VERIFY_SIGNATURE;
/**
* $krb5pa$18$*user*realm*$enc_timestamp+checksum
*/
// assume no signature found
if (line_len < 11) return (PARSER_SALT_LENGTH);
// assume $krb5pa$18$user$realm$enc_timestamp+checksum
token.token_cnt = 4;
token.sep[1] = '$';
token.len_min[1] = 1;
token.len_max[1] = 512;
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH;
token.sep[2] = '$';
token.len_min[2] = 1;
token.len_max[2] = 512;
token.attr[2] = TOKEN_ATTR_VERIFY_LENGTH;
token.sep[3] = '$';
token.len_min[3] = 104;
token.len_max[3] = 112;
token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH
| TOKEN_ATTR_VERIFY_HEX;
const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token);
if (rc_tokenizer != PARSER_OK) return (rc_tokenizer);
const u8 *user_pos;
const u8 *domain_pos;
const u8 *data_pos;
const u8 *checksum_pos;
int user_len;
int domain_len;
int data_len;
int account_info_len;
user_pos = token.buf[1];
user_len = token.len[1];
memcpy(krb5pa->user, user_pos, user_len);
domain_pos = token.buf[2];
domain_len = token.len[2];
memcpy(krb5pa->domain, domain_pos, domain_len);
data_pos = token.buf[3];
data_len = token.len[3];
account_info_len = token.len[2] + token.len[1];
u8 *account_info_ptr = (u8 *) krb5pa->account_info;
// domain must be uppercase
u8 domain[128];
memcpy(domain, domain_pos, domain_len);
uppercase(domain, domain_len);
memcpy(account_info_ptr, domain, domain_len);
memcpy(account_info_ptr + domain_len, user_pos, user_len);
krb5pa->account_info_len = account_info_len;
// Split checksum
checksum_pos = data_pos + data_len - 24;
data_len = data_len - 24;
// hmac-sha1 is reduced to 12 bytes
krb5pa->checksum[0] = byte_swap_32 (hex_to_u32 (checksum_pos + 0));
krb5pa->checksum[1] = byte_swap_32 (hex_to_u32 (checksum_pos + 8));
krb5pa->checksum[2] = byte_swap_32 (hex_to_u32 (checksum_pos + 16));
u8 *edata_ptr = (u8 *) krb5pa->enc_timestamp;
for (int i = 0; i < data_len; i += 2)
{
const u8 p0 = data_pos[i + 0];
const u8 p1 = data_pos[i + 1];
*edata_ptr++ = hex_convert (p1) << 0
| hex_convert (p0) << 4;
}
krb5pa->enc_timestamp_len = data_len / 2;
salt->salt_buf[0] = krb5pa->checksum[0];
salt->salt_buf[1] = krb5pa->checksum[1];
salt->salt_buf[2] = krb5pa->checksum[2];
salt->salt_iter = 4096 - 1;
digest[0] = krb5pa->checksum[0];
digest[1] = krb5pa->checksum[1];
digest[2] = krb5pa->checksum[2];
digest[3] = 0;
return (PARSER_OK);
}
int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const void *digest_buf, MAYBE_UNUSED const salt_t *salt, MAYBE_UNUSED const void *esalt_buf, MAYBE_UNUSED const void *hook_salt_buf, MAYBE_UNUSED const hashinfo_t *hash_info, char *line_buf, MAYBE_UNUSED const int line_size)
{
const krb5pa_18_t *krb5pa = (const krb5pa_18_t *) esalt_buf;
char data[32 * 4 * 2] = { 0 };
for (u32 i = 0, j = 0; i < krb5pa->enc_timestamp_len; i += 1, j += 2)
{
u8 *ptr_enc_timestamp = (u8 *) krb5pa->enc_timestamp;
sprintf (data + j, "%02x", ptr_enc_timestamp[i]);
}
const int line_len = snprintf (line_buf, line_size, "%s%s$%s$%s%08x%08x%08x",
SIGNATURE_KRB5PA,
(char *) krb5pa->user,
(char *) krb5pa->domain,
data,
krb5pa->checksum[0],
krb5pa->checksum[1],
krb5pa->checksum[2]);
return line_len;
}
void module_init (module_ctx_t *module_ctx)
{
module_ctx->module_context_size = MODULE_CONTEXT_SIZE_CURRENT;
module_ctx->module_interface_version = MODULE_INTERFACE_VERSION_CURRENT;
module_ctx->module_attack_exec = module_attack_exec;
module_ctx->module_benchmark_esalt = MODULE_DEFAULT;
module_ctx->module_benchmark_hook_salt = MODULE_DEFAULT;
module_ctx->module_benchmark_mask = MODULE_DEFAULT;
module_ctx->module_benchmark_salt = MODULE_DEFAULT;
module_ctx->module_build_plain_postprocess = MODULE_DEFAULT;
module_ctx->module_deep_comp_kernel = MODULE_DEFAULT;
module_ctx->module_dgst_pos0 = module_dgst_pos0;
module_ctx->module_dgst_pos1 = module_dgst_pos1;
module_ctx->module_dgst_pos2 = module_dgst_pos2;
module_ctx->module_dgst_pos3 = module_dgst_pos3;
module_ctx->module_dgst_size = module_dgst_size;
module_ctx->module_dictstat_disable = MODULE_DEFAULT;
module_ctx->module_esalt_size = module_esalt_size;
module_ctx->module_extra_buffer_size = MODULE_DEFAULT;
module_ctx->module_extra_tmp_size = MODULE_DEFAULT;
module_ctx->module_forced_outfile_format = MODULE_DEFAULT;
module_ctx->module_hash_binary_count = MODULE_DEFAULT;
module_ctx->module_hash_binary_parse = MODULE_DEFAULT;
module_ctx->module_hash_binary_save = MODULE_DEFAULT;
module_ctx->module_hash_decode_potfile = MODULE_DEFAULT;
module_ctx->module_hash_decode_zero_hash = MODULE_DEFAULT;
module_ctx->module_hash_decode = module_hash_decode;
module_ctx->module_hash_encode_status = MODULE_DEFAULT;
module_ctx->module_hash_encode_potfile = MODULE_DEFAULT;
module_ctx->module_hash_encode = module_hash_encode;
module_ctx->module_hash_init_selftest = MODULE_DEFAULT;
module_ctx->module_hash_mode = MODULE_DEFAULT;
module_ctx->module_hash_category = module_hash_category;
module_ctx->module_hash_name = module_hash_name;
module_ctx->module_hlfmt_disable = MODULE_DEFAULT;
module_ctx->module_hook12 = MODULE_DEFAULT;
module_ctx->module_hook23 = MODULE_DEFAULT;
module_ctx->module_hook_salt_size = MODULE_DEFAULT;
module_ctx->module_hook_size = MODULE_DEFAULT;
module_ctx->module_jit_build_options = MODULE_DEFAULT;
module_ctx->module_jit_cache_disable = MODULE_DEFAULT;
module_ctx->module_kernel_accel_max = MODULE_DEFAULT;
module_ctx->module_kernel_accel_min = MODULE_DEFAULT;
module_ctx->module_kernel_loops_max = MODULE_DEFAULT;
module_ctx->module_kernel_loops_min = MODULE_DEFAULT;
module_ctx->module_kernel_threads_max = MODULE_DEFAULT;
module_ctx->module_kernel_threads_min = MODULE_DEFAULT;
module_ctx->module_kern_type = module_kern_type;
module_ctx->module_kern_type_dynamic = MODULE_DEFAULT;
module_ctx->module_opti_type = module_opti_type;
module_ctx->module_opts_type = module_opts_type;
module_ctx->module_outfile_check_disable = MODULE_DEFAULT;
module_ctx->module_outfile_check_nocomp = MODULE_DEFAULT;
module_ctx->module_potfile_custom_check = MODULE_DEFAULT;
module_ctx->module_potfile_disable = MODULE_DEFAULT;
module_ctx->module_potfile_keep_all_hashes = MODULE_DEFAULT;
module_ctx->module_pwdump_column = MODULE_DEFAULT;
module_ctx->module_pw_max = MODULE_DEFAULT;
module_ctx->module_pw_min = MODULE_DEFAULT;
module_ctx->module_salt_max = MODULE_DEFAULT;
module_ctx->module_salt_min = MODULE_DEFAULT;
module_ctx->module_salt_type = module_salt_type;
module_ctx->module_separator = MODULE_DEFAULT;
module_ctx->module_st_hash = module_st_hash;
module_ctx->module_st_pass = module_st_pass;
module_ctx->module_tmp_size = module_tmp_size;
module_ctx->module_unstable_warning = MODULE_DEFAULT;
module_ctx->module_warmup_disable = MODULE_DEFAULT;
}

View File

@ -0,0 +1,205 @@
#!/usr/bin/env perl
##
## Author......: See docs/credits.txt
## License.....: MIT
##
use strict;
use warnings;
use Digest::SHA qw (hmac_sha1);
use Crypt::Mode::CBC;
use Crypt::PBKDF2;
use Encode;
use POSIX qw (strftime);
sub byte2hex
{
my $input = shift;
return unpack ("H*", $input);
}
sub hex2byte
{
my $input = shift;
return pack ("H*", $input);
}
sub pad
{
my $n = shift;
my $size = shift;
return (~$n + 1) & ($size - 1);
}
sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
sub module_generate_hash
{
my $word = shift;
my $salt = shift;
my $user = shift // "user";
my $realm = shift // "realm";
my $checksum = shift;
my $enc_timestamp = shift;
my $mysalt = uc $realm;
$mysalt = $mysalt . $user;
# first we generate the 'seed'
my $iter = 4096;
my $pbkdf2 = Crypt::PBKDF2->new
(
hash_class => 'HMACSHA1',
iterations => $iter,
output_len => 16
);
my $b_seed = $pbkdf2->PBKDF2 ($mysalt, $word);
# we can precompute this
my $b_kerberos_nfolded = hex2byte('6b65726265726f737b9b5b2b93132b93');
my $b_iv = hex2byte('0' x 32);
# 'key_bytes' will be the AES key used to generate 'ki' (for final hmac-sha1)
# and 'ke' (AES key to decrypt/encrypt the ticket)
my $cbc = Crypt::Mode::CBC->new ('AES', 0);
my $b_key_bytes = $cbc->encrypt ($b_kerberos_nfolded, $b_seed, $b_iv);
# precomputed stuff
# nfold 0x0000000155 to 16 bytes
my $b_nfolded1 = hex2byte('5b582c160a5aa80556ab55aad5402ab5');
# nfold 0x00000001aa to 16 bytes
my $b_nfolded2 = hex2byte('ae2c160b04ad5006ab55aad56a80355a');
my $b_ki = $cbc->encrypt ($b_nfolded1, $b_key_bytes, $b_iv);
my $b_ke = $cbc->encrypt ($b_nfolded2, $b_key_bytes, $b_iv);
my $cleartext_ticket = '';
my $check_correct = 0;
if (defined $enc_timestamp)
{
# Do CTS Decryption https://en.wikipedia.org/wiki/Ciphertext_stealing
# Decrypt n-1 block
my $len_last_block = length($enc_timestamp) % 32;
my $len_last_2_blocks = $len_last_block + 32;
my $b_n_1_block = hex2byte (substr($enc_timestamp, -$len_last_2_blocks, 32));
my $b_n_1_decrypted = $cbc->decrypt ($b_n_1_block, $b_ke, $b_iv);
# Pad the last block with last bytes from the decrypted n-1
my $b_padded_enc_ticket = hex2byte($enc_timestamp).(substr $b_n_1_decrypted, -(16 - $len_last_block/2));
# Swap the last two blocks
my $b_cbc_enc_ticket = (substr $b_padded_enc_ticket, 0, -32).(substr $b_padded_enc_ticket, -16, 16).
(substr $b_padded_enc_ticket, -32, 16);
# Decrypt and truncate
my $b_dec_ticket_padded = $cbc->decrypt ($b_cbc_enc_ticket, $b_ke, $b_iv);
my $b_cleartext_ticket = substr $b_dec_ticket_padded, 0, length($enc_timestamp)/2;
$cleartext_ticket = byte2hex($b_cleartext_ticket);
my $check_correct = ((substr ($b_cleartext_ticket, 22, 2) eq "20") &&
(substr ($b_cleartext_ticket, 36, 1) eq "Z"));
if ($check_correct == 1 && defined $checksum)
{
my $b_checksum = hmac_sha1 (hex2byte($cleartext_ticket), $b_ki);
$check_correct = ($checksum eq byte2hex(substr $b_checksum, 0, 12));
}
}
if ($check_correct != 1)
{
# fake/wrong ticket (otherwise if we just decrypt/encrypt we end
#up with false positives all the time)
$cleartext_ticket = '68c8459f3f10c851b8827118bb459c6e301aa011180f323031'.
'32313131363134323835355aa10502030c28a2';
# we have what is required to compute checksum
$checksum = hmac_sha1 (hex2byte($cleartext_ticket), $b_ki);
$checksum = byte2hex(substr $checksum, 0, 12);
}
# CTS Encrypt our new block
my $len_cleartext_last_block = length($cleartext_ticket)%32;
my $cleartext_last_block = substr $cleartext_ticket, -$len_cleartext_last_block;
my $padding = pad(length($cleartext_ticket), 32);
my $b_cleartext_last_block_padded = hex2byte($cleartext_last_block . '0' x $padding);
# we will encrypt until n-1 block (included)
my $truncated_cleartext_ticket = substr $cleartext_ticket, 0, -$len_cleartext_last_block;
my $b_truncated_enc_ticket = $cbc->encrypt (hex2byte($truncated_cleartext_ticket), $b_ke, $b_iv);
my $b_enc_ticket_n_1_block= substr $b_truncated_enc_ticket, -16;
my $b_enc_last_block = substr $b_enc_ticket_n_1_block, 0, $len_cleartext_last_block/2;
# we now craft the new n-1 block
my $tmp = $b_enc_ticket_n_1_block ^ $b_cleartext_last_block_padded;
$b_enc_ticket_n_1_block = $cbc->encrypt ($tmp, $b_ke, $b_iv);
$tmp = substr $b_truncated_enc_ticket, 0, -16;
$enc_timestamp = $tmp . $b_enc_ticket_n_1_block . $b_enc_last_block;
my $tmp_hash = sprintf ('$krb5pa$17$%s$%s$%s%s', $user, $realm, unpack ("H*", $enc_timestamp), $checksum);
return $tmp_hash;
}
sub module_verify_hash
{
my $line = shift;
my ($hash, $word) = split (':', $line);
return unless defined $hash;
return unless defined $word;
my @data = split ('\$', $hash);
return unless scalar @data == 6;
shift @data;
my $signature = shift @data;
my $algorithm = shift @data;
my $user = shift @data;
my $realm = shift @data;
my $edata = shift @data;
return unless ($signature eq "krb5pa");
return unless ($algorithm eq "17");
return unless (length ($edata) >= 88);
return unless (length ($edata) <= 112);
my $checksum = substr $edata, -24;
my $enc_timestamp = substr $edata, 0, -24;
my $word_packed = pack_if_HEX_notation ($word);
my $new_hash = module_generate_hash ($word_packed, undef, $user, $realm, $checksum, $enc_timestamp);
return ($new_hash, $word);
}
1;

View File

@ -0,0 +1,209 @@
#!/usr/bin/env perl
##
## Author......: See docs/credits.txt
## License.....: MIT
##
use strict;
use warnings;
use Digest::SHA qw (hmac_sha1);
use Crypt::Mode::CBC;
use Crypt::PBKDF2;
use Encode;
use POSIX qw (strftime);
sub byte2hex
{
my $input = shift;
return unpack ("H*", $input);
}
sub hex2byte
{
my $input = shift;
return pack ("H*", $input);
}
sub pad
{
my $n = shift;
my $size = shift;
return (~$n + 1) & ($size - 1);
}
sub module_constraints { [[0, 256], [16, 16], [-1, -1], [-1, -1], [-1, -1]] }
sub module_generate_hash
{
my $word = shift;
my $salt = shift;
my $user = shift // "user";
my $realm = shift // "realm";
my $checksum = shift;
my $enc_timestamp = shift;
my $mysalt = uc $realm;
$mysalt = $mysalt . $user;
# first we generate the 'seed'
my $iter = 4096;
my $pbkdf2 = Crypt::PBKDF2->new
(
hash_class => 'HMACSHA1',
iterations => $iter,
output_len => 32
);
my $b_seed = $pbkdf2->PBKDF2 ($mysalt, $word);
# we can precompute this
my $b_kerberos_nfolded = hex2byte('6b65726265726f737b9b5b2b93132b93');
my $b_iv = hex2byte('0' x 32);
# 'key_bytes' will be the AES key used to generate 'ki' (for final hmac-sha1)
# and 'ke' (AES key to decrypt/encrypt the ticket)
my $cbc = Crypt::Mode::CBC->new ('AES', 0);
my $b_key_bytes = $cbc->encrypt ($b_kerberos_nfolded, $b_seed, $b_iv);
$b_key_bytes = $b_key_bytes . $cbc->encrypt ($b_key_bytes, $b_seed, $b_iv);
# precomputed stuff
# nfold 0x0000000155 to 16 bytes
my $b_nfolded1 = hex2byte('5b582c160a5aa80556ab55aad5402ab5');
# nfold 0x00000001aa to 16 bytes
my $b_nfolded2 = hex2byte('ae2c160b04ad5006ab55aad56a80355a');
my $b_ki = $cbc->encrypt ($b_nfolded1, $b_key_bytes, $b_iv);
$b_ki = $b_ki . $cbc->encrypt ($b_ki, $b_key_bytes, $b_iv);
my $b_ke = $cbc->encrypt ($b_nfolded2, $b_key_bytes, $b_iv);
$b_ke = $b_ke . $cbc->encrypt ($b_ke, $b_key_bytes, $b_iv);
my $cleartext_ticket = '';
my $check_correct = 0;
if (defined $enc_timestamp)
{
# Do CTS Decryption https://en.wikipedia.org/wiki/Ciphertext_stealing
# Decrypt n-1 block
my $len_last_block = length($enc_timestamp) % 32;
my $len_last_2_blocks = $len_last_block + 32;
my $b_n_1_block = hex2byte (substr($enc_timestamp, -$len_last_2_blocks, 32));
my $b_n_1_decrypted = $cbc->decrypt ($b_n_1_block, $b_ke, $b_iv);
# Pad the last block with last bytes from the decrypted n-1
my $b_padded_enc_ticket = hex2byte($enc_timestamp).(substr $b_n_1_decrypted, -(16 - $len_last_block/2));
# Swap the last two blocks
my $b_cbc_enc_ticket = (substr $b_padded_enc_ticket, 0, -32).(substr $b_padded_enc_ticket, -16, 16).
(substr $b_padded_enc_ticket, -32, 16);
# Decrypt and truncate
my $b_dec_ticket_padded = $cbc->decrypt ($b_cbc_enc_ticket, $b_ke, $b_iv);
my $b_cleartext_ticket = substr $b_dec_ticket_padded, 0, length($enc_timestamp)/2;
$cleartext_ticket = byte2hex($b_cleartext_ticket);
my $check_correct = ((substr ($b_cleartext_ticket, 22, 2) eq "20") &&
(substr ($b_cleartext_ticket, 36, 1) eq "Z"));
if ($check_correct == 1 && defined $checksum)
{
my $b_checksum = hmac_sha1 (hex2byte($cleartext_ticket), $b_ki);
$check_correct = ($checksum eq byte2hex(substr $b_checksum, 0, 12));
}
}
if ($check_correct != 1)
{
# fake/wrong ticket (otherwise if we just decrypt/encrypt we end
#up with false positives all the time)
$cleartext_ticket = '68c8459f3f10c851b8827118bb459c6e301aa011180f323031'.
'32313131363134323835355aa10502030c28a2';
# we have what is required to compute checksum
$checksum = hmac_sha1 (hex2byte($cleartext_ticket), $b_ki);
$checksum = byte2hex(substr $checksum, 0, 12);
}
# CTS Encrypt our new block
my $len_cleartext_last_block = length($cleartext_ticket)%32;
my $cleartext_last_block = substr $cleartext_ticket, -$len_cleartext_last_block;
my $padding = pad(length($cleartext_ticket), 32);
my $b_cleartext_last_block_padded = hex2byte($cleartext_last_block . '0' x $padding);
# we will encrypt until n-1 block (included)
my $truncated_cleartext_ticket = substr $cleartext_ticket, 0, -$len_cleartext_last_block;
my $b_truncated_enc_ticket = $cbc->encrypt (hex2byte($truncated_cleartext_ticket), $b_ke, $b_iv);
my $b_enc_ticket_n_1_block= substr $b_truncated_enc_ticket, -16;
my $b_enc_last_block = substr $b_enc_ticket_n_1_block, 0, $len_cleartext_last_block/2;
# we now craft the new n-1 block
my $tmp = $b_enc_ticket_n_1_block ^ $b_cleartext_last_block_padded;
$b_enc_ticket_n_1_block = $cbc->encrypt ($tmp, $b_ke, $b_iv);
$tmp = substr $b_truncated_enc_ticket, 0, -16;
$enc_timestamp = $tmp . $b_enc_ticket_n_1_block . $b_enc_last_block;
my $tmp_hash = sprintf ('$krb5pa$18$%s$%s$%s%s', $user, $realm, unpack ("H*", $enc_timestamp), $checksum);
return $tmp_hash;
}
sub module_verify_hash
{
my $line = shift;
my ($hash, $word) = split (':', $line);
return unless defined $hash;
return unless defined $word;
my @data = split ('\$', $hash);
return unless scalar @data == 6;
shift @data;
my $signature = shift @data;
my $algorithm = shift @data;
my $user = shift @data;
my $realm = shift @data;
my $edata = shift @data;
return unless ($signature eq "krb5pa");
return unless ($algorithm eq "18");
return unless (length ($edata) >= 88);
return unless (length ($edata) <= 112);
my $checksum = substr $edata, -24;
my $enc_timestamp = substr $edata, 0, -24;
my $word_packed = pack_if_HEX_notation ($word);
my $new_hash = module_generate_hash ($word_packed, undef, $user, $realm, $checksum, $enc_timestamp);
return ($new_hash, $word);
}
1;