From 6f45285919cad2e6ea908268ac7dd084f132abc9 Mon Sep 17 00:00:00 2001 From: Gabriele Gristina Date: Sun, 6 Mar 2022 00:55:47 +0100 Subject: [PATCH] DPAPI masterkey file v2 (context 3) --- OpenCL/m15910-pure.cl | 1189 ++++++++++++++++++++++++++++++++++ src/modules/module_15910.c | 473 ++++++++++++++ tools/test_modules/m15910.pm | 434 +++++++++++++ 3 files changed, 2096 insertions(+) create mode 100644 OpenCL/m15910-pure.cl create mode 100644 src/modules/module_15910.c create mode 100644 tools/test_modules/m15910.pm diff --git a/OpenCL/m15910-pure.cl b/OpenCL/m15910-pure.cl new file mode 100644 index 000000000..d73d748ea --- /dev/null +++ b/OpenCL/m15910-pure.cl @@ -0,0 +1,1189 @@ +/** + * Author......: See docs/credits.txt + * License.....: MIT + */ + +#define NEW_SIMD_CODE + +#ifdef KERNEL_STATIC +#include M2S(INCLUDE_PATH/inc_vendor.h) +#include M2S(INCLUDE_PATH/inc_types.h) +#include M2S(INCLUDE_PATH/inc_platform.cl) +#include M2S(INCLUDE_PATH/inc_common.cl) +#include M2S(INCLUDE_PATH/inc_simd.cl) +#include M2S(INCLUDE_PATH/inc_hash_md4.cl) +#include M2S(INCLUDE_PATH/inc_hash_sha1.cl) +#include M2S(INCLUDE_PATH/inc_hash_sha256.cl) +#include M2S(INCLUDE_PATH/inc_hash_sha512.cl) +#include M2S(INCLUDE_PATH/inc_cipher_aes.cl) +#endif + +#define COMPARE_S M2S(INCLUDE_PATH/inc_comp_single.cl) +#define COMPARE_M M2S(INCLUDE_PATH/inc_comp_multi.cl) + +typedef struct dpapimk_tmp_v2 +{ + // sha256 + u32 ipad[8]; + u32 opad[8]; + u32 dgst[32]; + u32 out[32]; + + // sha512 + u64 ipad64[8]; + u64 opad64[8]; + u64 dgst64[16]; + u64 out64[16]; + + u32 userKey[8]; + +} dpapimk_tmp_v2_t; + +typedef struct dpapimk +{ + u32 context; + + u32 SID[32]; + u32 SID_len; + u32 SID_offset; + + /* here only for possible + forward compatibiliy + */ + // u8 cipher_algo[16]; + // u8 hash_algo[16]; + + u32 iv[4]; + u32 contents_len; + u32 contents[128]; + +} dpapimk_t; + +DECLSPEC void hmac_sha256_run_V (PRIVATE_AS u32x *w0, PRIVATE_AS u32x *w1, PRIVATE_AS u32x *w2, PRIVATE_AS u32x *w3, PRIVATE_AS u32x *ipad, PRIVATE_AS u32x *opad, PRIVATE_AS u32x *digest) +{ + digest[0] = ipad[0]; + digest[1] = ipad[1]; + digest[2] = ipad[2]; + digest[3] = ipad[3]; + digest[4] = ipad[4]; + digest[5] = ipad[5]; + digest[6] = ipad[6]; + digest[7] = ipad[7]; + + sha256_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] = digest[5]; + w1[2] = digest[6]; + w1[3] = digest[7]; + w2[0] = 0x80000000; + w2[1] = 0; + w2[2] = 0; + w2[3] = 0; + w3[0] = 0; + w3[1] = 0; + w3[2] = 0; + w3[3] = (64 + 32) * 8; + + digest[0] = opad[0]; + digest[1] = opad[1]; + digest[2] = opad[2]; + digest[3] = opad[3]; + digest[4] = opad[4]; + digest[5] = opad[5]; + digest[6] = opad[6]; + digest[7] = opad[7]; + + sha256_transform_vector (w0, w1, w2, w3, digest); +} + +DECLSPEC void hmac_sha512_run_V (PRIVATE_AS u32x *w0, PRIVATE_AS u32x *w1, PRIVATE_AS u32x *w2, PRIVATE_AS u32x *w3, PRIVATE_AS u32x *w4, PRIVATE_AS u32x *w5, PRIVATE_AS u32x *w6, PRIVATE_AS u32x *w7, PRIVATE_AS u64x *ipad, PRIVATE_AS u64x *opad, PRIVATE_AS u64x *digest) +{ + digest[0] = ipad[0]; + digest[1] = ipad[1]; + digest[2] = ipad[2]; + digest[3] = ipad[3]; + digest[4] = ipad[4]; + digest[5] = ipad[5]; + digest[6] = ipad[6]; + digest[7] = ipad[7]; + + sha512_transform_vector (w0, w1, w2, w3, w4, w5, w6, w7, digest); + + w0[0] = h32_from_64 (digest[0]); + w0[1] = l32_from_64 (digest[0]); + w0[2] = h32_from_64 (digest[1]); + w0[3] = l32_from_64 (digest[1]); + w1[0] = h32_from_64 (digest[2]); + w1[1] = l32_from_64 (digest[2]); + w1[2] = h32_from_64 (digest[3]); + w1[3] = l32_from_64 (digest[3]); + w2[0] = h32_from_64 (digest[4]); + w2[1] = l32_from_64 (digest[4]); + w2[2] = h32_from_64 (digest[5]); + w2[3] = l32_from_64 (digest[5]); + w3[0] = h32_from_64 (digest[6]); + w3[1] = l32_from_64 (digest[6]); + w3[2] = h32_from_64 (digest[7]); + w3[3] = l32_from_64 (digest[7]); + w4[0] = 0x80000000; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = (128 + 64) * 8; + + digest[0] = opad[0]; + digest[1] = opad[1]; + digest[2] = opad[2]; + digest[3] = opad[3]; + digest[4] = opad[4]; + digest[5] = opad[5]; + digest[6] = opad[6]; + digest[7] = opad[7]; + + sha512_transform_vector (w0, w1, w2, w3, w4, w5, w6, w7, digest); +} + +KERNEL_FQ void m15910_init (KERN_ATTR_TMPS_ESALT (dpapimk_tmp_v2_t, dpapimk_t)) +{ + /** + * base + */ + + const u64 gid = get_global_id (0); + + if (gid >= GID_CNT) return; + + /** + * main + */ + + // context 3 + + md4_ctx_t ctx; + + md4_init (&ctx); + + md4_update_global_utf16le (&ctx, pws[gid].i, pws[gid].pw_len); + + md4_final (&ctx); + + // derived = pbkdf2-hmac-sha256 (pass=md4_hash, salt=utf16le(SID), iter=10000, outlen=32) + + u32 w0[4]; + u32 w1[4]; + u32 w2[4]; + u32 w3[4]; + + w0[0] = hc_swap32_S (ctx.h[0]); + w0[1] = hc_swap32_S (ctx.h[1]); + w0[2] = hc_swap32_S (ctx.h[2]); + w0[3] = hc_swap32_S (ctx.h[3]); + 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; + + sha256_hmac_ctx_t sha256_hmac_ctx; + + sha256_hmac_init_64 (&sha256_hmac_ctx, w0, w1, w2, w3); + + tmps[gid].ipad[0] = sha256_hmac_ctx.ipad.h[0]; + tmps[gid].ipad[1] = sha256_hmac_ctx.ipad.h[1]; + tmps[gid].ipad[2] = sha256_hmac_ctx.ipad.h[2]; + tmps[gid].ipad[3] = sha256_hmac_ctx.ipad.h[3]; + tmps[gid].ipad[4] = sha256_hmac_ctx.ipad.h[4]; + tmps[gid].ipad[5] = sha256_hmac_ctx.ipad.h[5]; + tmps[gid].ipad[6] = sha256_hmac_ctx.ipad.h[6]; + tmps[gid].ipad[7] = sha256_hmac_ctx.ipad.h[7]; + + tmps[gid].opad[0] = sha256_hmac_ctx.opad.h[0]; + tmps[gid].opad[1] = sha256_hmac_ctx.opad.h[1]; + tmps[gid].opad[2] = sha256_hmac_ctx.opad.h[2]; + tmps[gid].opad[3] = sha256_hmac_ctx.opad.h[3]; + tmps[gid].opad[4] = sha256_hmac_ctx.opad.h[4]; + tmps[gid].opad[5] = sha256_hmac_ctx.opad.h[5]; + tmps[gid].opad[6] = sha256_hmac_ctx.opad.h[6]; + tmps[gid].opad[7] = sha256_hmac_ctx.opad.h[7]; + + sha256_hmac_update_global (&sha256_hmac_ctx, esalt_bufs[DIGESTS_OFFSET_HOST].SID, esalt_bufs[DIGESTS_OFFSET_HOST].SID_len); + + for (u32 i = 0, j = 1; i < 8; i += 8, j += 1) + { + sha256_hmac_ctx_t sha256_hmac_ctx2 = sha256_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; + + sha256_hmac_update_64 (&sha256_hmac_ctx2, w0, w1, w2, w3, 4); + + sha256_hmac_final (&sha256_hmac_ctx2); + + tmps[gid].dgst[i + 0] = sha256_hmac_ctx2.opad.h[0]; + tmps[gid].dgst[i + 1] = sha256_hmac_ctx2.opad.h[1]; + tmps[gid].dgst[i + 2] = sha256_hmac_ctx2.opad.h[2]; + tmps[gid].dgst[i + 3] = sha256_hmac_ctx2.opad.h[3]; + tmps[gid].dgst[i + 4] = sha256_hmac_ctx2.opad.h[4]; + tmps[gid].dgst[i + 5] = sha256_hmac_ctx2.opad.h[5]; + tmps[gid].dgst[i + 6] = sha256_hmac_ctx2.opad.h[6]; + tmps[gid].dgst[i + 7] = sha256_hmac_ctx2.opad.h[7]; + + 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]; + tmps[gid].out[i + 5] = tmps[gid].dgst[i + 5]; + tmps[gid].out[i + 6] = tmps[gid].dgst[i + 6]; + tmps[gid].out[i + 7] = tmps[gid].dgst[i + 7]; + } +} + +KERNEL_FQ void m15910_loop (KERN_ATTR_TMPS_ESALT (dpapimk_tmp_v2_t, dpapimk_t)) +{ + const u64 gid = get_global_id (0); + + if ((gid * VECT_SIZE) >= GID_CNT) return; + + u32x ipad[8]; + u32x opad[8]; + + 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); + ipad[5] = packv (tmps, ipad, gid, 5); + ipad[6] = packv (tmps, ipad, gid, 6); + ipad[7] = packv (tmps, ipad, gid, 7); + + 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); + opad[5] = packv (tmps, opad, gid, 5); + opad[6] = packv (tmps, opad, gid, 6); + opad[7] = packv (tmps, opad, gid, 7); + + for (u32 i = 0; i < 8; i += 8) + { + u32x dgst[8]; + u32x out[8]; + + 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); + dgst[5] = packv (tmps, dgst, gid, i + 5); + dgst[6] = packv (tmps, dgst, gid, i + 6); + dgst[7] = packv (tmps, dgst, gid, i + 7); + + 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); + out[5] = packv (tmps, out, gid, i + 5); + out[6] = packv (tmps, out, gid, i + 6); + out[7] = packv (tmps, out, gid, i + 7); + + 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] = dgst[5]; + w1[2] = dgst[6]; + w1[3] = dgst[7]; + w2[0] = 0x80000000; + w2[1] = 0; + w2[2] = 0; + w2[3] = 0; + w3[0] = 0; + w3[1] = 0; + w3[2] = 0; + w3[3] = (64 + 32) * 8; + + hmac_sha256_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]; + out[5] ^= dgst[5]; + out[6] ^= dgst[6]; + out[7] ^= dgst[7]; + } + + 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, dgst, gid, i + 5, dgst[5]); + unpackv (tmps, dgst, gid, i + 6, dgst[6]); + unpackv (tmps, dgst, gid, i + 7, dgst[7]); + + 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]); + unpackv (tmps, out, gid, i + 5, out[5]); + unpackv (tmps, out, gid, i + 6, out[6]); + unpackv (tmps, out, gid, i + 7, out[7]); + } +} + +KERNEL_FQ void m15910_init2 (KERN_ATTR_TMPS_ESALT (dpapimk_tmp_v2_t, dpapimk_t)) +{ + /** + * base + */ + + const u64 gid = get_global_id (0); + + if (gid >= GID_CNT) return; + + // pbkdf2-hmac-sha256 (pass=derived, salt=utf16le(SID), iter=1, outlen=16) + + u32 w0[4]; + u32 w1[4]; + u32 w2[4]; + u32 w3[4]; + + w0[0] = tmps[gid].out[0]; + w0[1] = tmps[gid].out[1]; + w0[2] = tmps[gid].out[2]; + w0[3] = tmps[gid].out[3]; + w1[0] = tmps[gid].out[4]; + w1[1] = tmps[gid].out[5]; + w1[2] = tmps[gid].out[6]; + w1[3] = tmps[gid].out[7]; + w2[0] = 0; + w2[1] = 0; + w2[2] = 0; + w2[3] = 0; + w3[0] = 0; + w3[1] = 0; + w3[2] = 0; + w3[3] = 0; + + sha256_hmac_ctx_t sha256_hmac_ctx; + + sha256_hmac_init_64 (&sha256_hmac_ctx, w0, w1, w2, w3); + + tmps[gid].ipad[0] = sha256_hmac_ctx.ipad.h[0]; + tmps[gid].ipad[1] = sha256_hmac_ctx.ipad.h[1]; + tmps[gid].ipad[2] = sha256_hmac_ctx.ipad.h[2]; + tmps[gid].ipad[3] = sha256_hmac_ctx.ipad.h[3]; + tmps[gid].ipad[4] = sha256_hmac_ctx.ipad.h[4]; + tmps[gid].ipad[5] = sha256_hmac_ctx.ipad.h[5]; + tmps[gid].ipad[6] = sha256_hmac_ctx.ipad.h[6]; + tmps[gid].ipad[7] = sha256_hmac_ctx.ipad.h[7]; + + tmps[gid].opad[0] = sha256_hmac_ctx.opad.h[0]; + tmps[gid].opad[1] = sha256_hmac_ctx.opad.h[1]; + tmps[gid].opad[2] = sha256_hmac_ctx.opad.h[2]; + tmps[gid].opad[3] = sha256_hmac_ctx.opad.h[3]; + tmps[gid].opad[4] = sha256_hmac_ctx.opad.h[4]; + tmps[gid].opad[5] = sha256_hmac_ctx.opad.h[5]; + tmps[gid].opad[6] = sha256_hmac_ctx.opad.h[6]; + tmps[gid].opad[7] = sha256_hmac_ctx.opad.h[7]; + + sha256_hmac_update_global (&sha256_hmac_ctx, esalt_bufs[DIGESTS_OFFSET_HOST].SID, esalt_bufs[DIGESTS_OFFSET_HOST].SID_len); + + for (u32 i = 0, j = 1; i < 8; i += 8, j += 1) + { + sha256_hmac_ctx_t sha256_hmac_ctx2 = sha256_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; + + sha256_hmac_update_64 (&sha256_hmac_ctx2, w0, w1, w2, w3, 4); + + sha256_hmac_final (&sha256_hmac_ctx2); + + tmps[gid].dgst[i + 0] = sha256_hmac_ctx2.opad.h[0]; + tmps[gid].dgst[i + 1] = sha256_hmac_ctx2.opad.h[1]; + tmps[gid].dgst[i + 2] = sha256_hmac_ctx2.opad.h[2]; + tmps[gid].dgst[i + 3] = sha256_hmac_ctx2.opad.h[3]; + tmps[gid].dgst[i + 4] = sha256_hmac_ctx2.opad.h[3]; + tmps[gid].dgst[i + 5] = sha256_hmac_ctx2.opad.h[3]; + tmps[gid].dgst[i + 6] = sha256_hmac_ctx2.opad.h[6]; + tmps[gid].dgst[i + 7] = sha256_hmac_ctx2.opad.h[7]; + + 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]; + tmps[gid].out[i + 5] = tmps[gid].dgst[i + 5]; + tmps[gid].out[i + 6] = tmps[gid].dgst[i + 6]; + tmps[gid].out[i + 7] = tmps[gid].dgst[i + 7]; + } + + /* initialize hmac-sha1 */ + + w0[0] = tmps[gid].out[0]; + w0[1] = tmps[gid].out[1]; + w0[2] = tmps[gid].out[2]; + w0[3] = tmps[gid].out[3]; + 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_ctx_t ctx; + + sha1_hmac_init_64 (&ctx, w0, w1, w2, w3); + + sha1_hmac_update_global (&ctx, esalt_bufs[DIGESTS_OFFSET_HOST].SID, esalt_bufs[DIGESTS_OFFSET_HOST].SID_len + 2); + + sha1_hmac_final (&ctx); + + u32 key[5]; + + key[0] = ctx.opad.h[0]; + key[1] = ctx.opad.h[1]; + key[2] = ctx.opad.h[2]; + key[3] = ctx.opad.h[3]; + key[4] = ctx.opad.h[4]; + + /* this key is used as password for pbkdf2-hmac-sha512 */ + + tmps[gid].userKey[0] = key[0]; + tmps[gid].userKey[1] = key[1]; + tmps[gid].userKey[2] = key[2]; + tmps[gid].userKey[3] = key[3]; + tmps[gid].userKey[4] = key[4]; + + u32 w4[4]; + u32 w5[4]; + u32 w6[4]; + u32 w7[4]; + + w0[0] = key[0]; + w0[1] = key[1]; + w0[2] = key[2]; + w0[3] = key[3]; + w1[0] = key[4]; + 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; + w4[0] = 0; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = 0; + + sha512_hmac_ctx_t sha512_hmac_ctx; + + sha512_hmac_init_128 (&sha512_hmac_ctx, w0, w1, w2, w3, w4, w5, w6, w7); + + tmps[gid].ipad64[0] = sha512_hmac_ctx.ipad.h[0]; + tmps[gid].ipad64[1] = sha512_hmac_ctx.ipad.h[1]; + tmps[gid].ipad64[2] = sha512_hmac_ctx.ipad.h[2]; + tmps[gid].ipad64[3] = sha512_hmac_ctx.ipad.h[3]; + tmps[gid].ipad64[4] = sha512_hmac_ctx.ipad.h[4]; + tmps[gid].ipad64[5] = sha512_hmac_ctx.ipad.h[5]; + tmps[gid].ipad64[6] = sha512_hmac_ctx.ipad.h[6]; + tmps[gid].ipad64[7] = sha512_hmac_ctx.ipad.h[7]; + + tmps[gid].opad64[0] = sha512_hmac_ctx.opad.h[0]; + tmps[gid].opad64[1] = sha512_hmac_ctx.opad.h[1]; + tmps[gid].opad64[2] = sha512_hmac_ctx.opad.h[2]; + tmps[gid].opad64[3] = sha512_hmac_ctx.opad.h[3]; + tmps[gid].opad64[4] = sha512_hmac_ctx.opad.h[4]; + tmps[gid].opad64[5] = sha512_hmac_ctx.opad.h[5]; + tmps[gid].opad64[6] = sha512_hmac_ctx.opad.h[6]; + tmps[gid].opad64[7] = sha512_hmac_ctx.opad.h[7]; + + w0[0] = esalt_bufs[DIGESTS_OFFSET_HOST].iv[0]; + w0[1] = esalt_bufs[DIGESTS_OFFSET_HOST].iv[1]; + w0[2] = esalt_bufs[DIGESTS_OFFSET_HOST].iv[2]; + w0[3] = esalt_bufs[DIGESTS_OFFSET_HOST].iv[3]; + 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; + w4[0] = 0; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = 0; + + sha512_hmac_update_128 (&sha512_hmac_ctx, w0, w1, w2, w3, w4, w5, w6, w7, 16); + + for (u32 i = 0, j = 1; i < 8; i += 8, j += 1) + { + sha512_hmac_ctx_t sha512_hmac_ctx2 = sha512_hmac_ctx; + + 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; + w4[0] = 0; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = 0; + + sha512_hmac_update_128 (&sha512_hmac_ctx2, w0, w1, w2, w3, w4, w5, w6, w7, 4); + + sha512_hmac_final (&sha512_hmac_ctx2); + + tmps[gid].dgst64[i + 0] = sha512_hmac_ctx2.opad.h[0]; + tmps[gid].dgst64[i + 1] = sha512_hmac_ctx2.opad.h[1]; + tmps[gid].dgst64[i + 2] = sha512_hmac_ctx2.opad.h[2]; + tmps[gid].dgst64[i + 3] = sha512_hmac_ctx2.opad.h[3]; + tmps[gid].dgst64[i + 4] = sha512_hmac_ctx2.opad.h[4]; + tmps[gid].dgst64[i + 5] = sha512_hmac_ctx2.opad.h[5]; + tmps[gid].dgst64[i + 6] = sha512_hmac_ctx2.opad.h[6]; + tmps[gid].dgst64[i + 7] = sha512_hmac_ctx2.opad.h[7]; + + tmps[gid].out64[i + 0] = tmps[gid].dgst64[i + 0]; + tmps[gid].out64[i + 1] = tmps[gid].dgst64[i + 1]; + tmps[gid].out64[i + 2] = tmps[gid].dgst64[i + 2]; + tmps[gid].out64[i + 3] = tmps[gid].dgst64[i + 3]; + tmps[gid].out64[i + 4] = tmps[gid].dgst64[i + 4]; + tmps[gid].out64[i + 5] = tmps[gid].dgst64[i + 5]; + tmps[gid].out64[i + 6] = tmps[gid].dgst64[i + 6]; + tmps[gid].out64[i + 7] = tmps[gid].dgst64[i + 7]; + } +} + +KERNEL_FQ void m15910_loop2 (KERN_ATTR_TMPS_ESALT (dpapimk_tmp_v2_t, dpapimk_t)) +{ + /** + * base + */ + + const u64 gid = get_global_id (0); + + if ((gid * VECT_SIZE) >= GID_CNT) return; + + u64x ipad[8]; + u64x opad[8]; + + ipad[0] = pack64v (tmps, ipad64, gid, 0); + ipad[1] = pack64v (tmps, ipad64, gid, 1); + ipad[2] = pack64v (tmps, ipad64, gid, 2); + ipad[3] = pack64v (tmps, ipad64, gid, 3); + ipad[4] = pack64v (tmps, ipad64, gid, 4); + ipad[5] = pack64v (tmps, ipad64, gid, 5); + ipad[6] = pack64v (tmps, ipad64, gid, 6); + ipad[7] = pack64v (tmps, ipad64, gid, 7); + + opad[0] = pack64v (tmps, opad64, gid, 0); + opad[1] = pack64v (tmps, opad64, gid, 1); + opad[2] = pack64v (tmps, opad64, gid, 2); + opad[3] = pack64v (tmps, opad64, gid, 3); + opad[4] = pack64v (tmps, opad64, gid, 4); + opad[5] = pack64v (tmps, opad64, gid, 5); + opad[6] = pack64v (tmps, opad64, gid, 6); + opad[7] = pack64v (tmps, opad64, gid, 7); + + for (u32 i = 0; i < 8; i += 8) + { + u64x dgst[8]; + u64x out[8]; + + dgst[0] = pack64v (tmps, dgst64, gid, i + 0); + dgst[1] = pack64v (tmps, dgst64, gid, i + 1); + dgst[2] = pack64v (tmps, dgst64, gid, i + 2); + dgst[3] = pack64v (tmps, dgst64, gid, i + 3); + dgst[4] = pack64v (tmps, dgst64, gid, i + 4); + dgst[5] = pack64v (tmps, dgst64, gid, i + 5); + dgst[6] = pack64v (tmps, dgst64, gid, i + 6); + dgst[7] = pack64v (tmps, dgst64, gid, i + 7); + + out[0] = pack64v (tmps, out64, gid, i + 0); + out[1] = pack64v (tmps, out64, gid, i + 1); + out[2] = pack64v (tmps, out64, gid, i + 2); + out[3] = pack64v (tmps, out64, gid, i + 3); + out[4] = pack64v (tmps, out64, gid, i + 4); + out[5] = pack64v (tmps, out64, gid, i + 5); + out[6] = pack64v (tmps, out64, gid, i + 6); + out[7] = pack64v (tmps, out64, gid, i + 7); + + for (u32 j = 0; j < LOOP_CNT; j++) + { + u32x w0[4]; + u32x w1[4]; + u32x w2[4]; + u32x w3[4]; + u32x w4[4]; + u32x w5[4]; + u32x w6[4]; + u32x w7[4]; + + w0[0] = h32_from_64 (out[0]); + w0[1] = l32_from_64 (out[0]); + w0[2] = h32_from_64 (out[1]); + w0[3] = l32_from_64 (out[1]); + w1[0] = h32_from_64 (out[2]); + w1[1] = l32_from_64 (out[2]); + w1[2] = h32_from_64 (out[3]); + w1[3] = l32_from_64 (out[3]); + w2[0] = h32_from_64 (out[4]); + w2[1] = l32_from_64 (out[4]); + w2[2] = h32_from_64 (out[5]); + w2[3] = l32_from_64 (out[5]); + w3[0] = h32_from_64 (out[6]); + w3[1] = l32_from_64 (out[6]); + w3[2] = h32_from_64 (out[7]); + w3[3] = l32_from_64 (out[7]); + w4[0] = 0x80000000; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = (128 + 64) * 8; + + hmac_sha512_run_V (w0, w1, w2, w3, w4, w5, w6, w7, ipad, opad, dgst); + + out[0] ^= dgst[0]; + out[1] ^= dgst[1]; + out[2] ^= dgst[2]; + out[3] ^= dgst[3]; + out[4] ^= dgst[4]; + out[5] ^= dgst[5]; + out[6] ^= dgst[6]; + out[7] ^= dgst[7]; + } + + unpack64v (tmps, dgst64, gid, i + 0, dgst[0]); + unpack64v (tmps, dgst64, gid, i + 1, dgst[1]); + unpack64v (tmps, dgst64, gid, i + 2, dgst[2]); + unpack64v (tmps, dgst64, gid, i + 3, dgst[3]); + unpack64v (tmps, dgst64, gid, i + 4, dgst[4]); + unpack64v (tmps, dgst64, gid, i + 5, dgst[5]); + unpack64v (tmps, dgst64, gid, i + 6, dgst[6]); + unpack64v (tmps, dgst64, gid, i + 7, dgst[7]); + + unpack64v (tmps, out64, gid, i + 0, out[0]); + unpack64v (tmps, out64, gid, i + 1, out[1]); + unpack64v (tmps, out64, gid, i + 2, out[2]); + unpack64v (tmps, out64, gid, i + 3, out[3]); + unpack64v (tmps, out64, gid, i + 4, out[4]); + unpack64v (tmps, out64, gid, i + 5, out[5]); + unpack64v (tmps, out64, gid, i + 6, out[6]); + unpack64v (tmps, out64, gid, i + 7, out[7]); + } +} + +KERNEL_FQ void m15910_comp (KERN_ATTR_TMPS_ESALT (dpapimk_tmp_v2_t, dpapimk_t)) +{ + 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_VK u32 s_td0[256]; + LOCAL_VK u32 s_td1[256]; + LOCAL_VK u32 s_td2[256]; + LOCAL_VK u32 s_td3[256]; + LOCAL_VK u32 s_td4[256]; + + LOCAL_VK u32 s_te0[256]; + LOCAL_VK u32 s_te1[256]; + LOCAL_VK u32 s_te2[256]; + LOCAL_VK u32 s_te3[256]; + LOCAL_VK 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]; + } + + SYNC_THREADS (); + + #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_CNT) return; + + /** + * main + */ + + u32 w0[4]; + u32 w1[4]; + u32 w2[4]; + u32 w3[4]; + u32 w4[4]; + u32 w5[4]; + u32 w6[4]; + u32 w7[4]; + + /* Construct AES key */ + + u32 key[8]; + + key[0] = h32_from_64_S (tmps[gid].out64[0]); + key[1] = l32_from_64_S (tmps[gid].out64[0]); + key[2] = h32_from_64_S (tmps[gid].out64[1]); + key[3] = l32_from_64_S (tmps[gid].out64[1]); + key[4] = h32_from_64_S (tmps[gid].out64[2]); + key[5] = l32_from_64_S (tmps[gid].out64[2]); + key[6] = h32_from_64_S (tmps[gid].out64[3]); + key[7] = l32_from_64_S (tmps[gid].out64[3]); + + u32 iv[4]; + + iv[0] = h32_from_64_S (tmps[gid].out64[4]); + iv[1] = l32_from_64_S (tmps[gid].out64[4]); + iv[2] = h32_from_64_S (tmps[gid].out64[5]); + iv[3] = l32_from_64_S (tmps[gid].out64[5]); + + #define KEYLEN 60 + + u32 ks[KEYLEN]; + + AES256_set_decrypt_key (ks, key, s_te0, s_te1, s_te2, s_te3, s_td0, s_td1, s_td2, s_td3); + + u32 out[4]; + + u32 hmac_data[4]; + + hmac_data[0] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[0]; + hmac_data[1] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[1]; + hmac_data[2] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[2]; + hmac_data[3] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[3]; + + u32 expected_key[4]; + + expected_key[0] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[4]; + expected_key[1] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[5]; + expected_key[2] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[6]; + expected_key[3] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[7]; + + u32 last_iv[4]; + + last_iv[0] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[16]; + last_iv[1] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[17]; + last_iv[2] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[18]; + last_iv[3] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[19]; + + u32 last_key[16]; + + last_key[ 0] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[20]; + last_key[ 1] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[21]; + last_key[ 2] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[22]; + last_key[ 3] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[23]; + last_key[ 4] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[24]; + last_key[ 5] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[25]; + last_key[ 6] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[26]; + last_key[ 7] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[27]; + last_key[ 8] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[28]; + last_key[ 9] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[29]; + last_key[10] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[30]; + last_key[11] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[31]; + last_key[12] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[32]; + last_key[13] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[33]; + last_key[14] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[34]; + last_key[15] = esalt_bufs[DIGESTS_OFFSET_HOST].contents[35]; + + // hmac_data + + AES256_decrypt (ks, hmac_data, out, s_td0, s_td1, s_td2, s_td3, s_td4); + + out[0] ^= iv[0]; + out[1] ^= iv[1]; + out[2] ^= iv[2]; + out[3] ^= iv[3]; + + iv[0] = hmac_data[0]; + iv[1] = hmac_data[1]; + iv[2] = hmac_data[2]; + iv[3] = hmac_data[3]; + + hmac_data[0] = out[0]; + hmac_data[1] = out[1]; + hmac_data[2] = out[2]; + hmac_data[3] = out[3]; + + // expected_key + + AES256_decrypt (ks, expected_key, out, s_td0, s_td1, s_td2, s_td3, s_td4); + + out[0] ^= iv[0]; + out[1] ^= iv[1]; + out[2] ^= iv[2]; + out[3] ^= iv[3]; + + iv[0] = expected_key[0]; + iv[1] = expected_key[1]; + iv[2] = expected_key[2]; + iv[3] = expected_key[3]; + + expected_key[0] = out[0]; + expected_key[1] = out[1]; + expected_key[2] = out[2]; + expected_key[3] = out[3]; + + // last_key + + iv[0] = last_iv[0]; + iv[1] = last_iv[1]; + iv[2] = last_iv[2]; + iv[3] = last_iv[3]; + + for (int off = 0; off < 16; off += 4) + { + AES256_decrypt (ks, last_key + off, out, s_td0, s_td1, s_td2, s_td3, s_td4); + + out[0] ^= iv[0]; + out[1] ^= iv[1]; + out[2] ^= iv[2]; + out[3] ^= iv[3]; + + iv[0] = last_key[off + 0]; + iv[1] = last_key[off + 1]; + iv[2] = last_key[off + 2]; + iv[3] = last_key[off + 3]; + + last_key[off + 0] = out[0]; + last_key[off + 1] = out[1]; + last_key[off + 2] = out[2]; + last_key[off + 3] = out[3]; + } + + w0[0] = tmps[gid].userKey[0]; + w0[1] = tmps[gid].userKey[1]; + w0[2] = tmps[gid].userKey[2]; + w0[3] = tmps[gid].userKey[3]; + w1[0] = tmps[gid].userKey[4]; + 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; + w4[0] = 0; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = 0; + + sha512_hmac_ctx_t ctx; + + sha512_hmac_init_128 (&ctx, w0, w1, w2, w3, w4, w5, w6, w7); + + w0[0] = hmac_data[0]; + w0[1] = hmac_data[1]; + w0[2] = hmac_data[2]; + w0[3] = hmac_data[3]; + 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; + w4[0] = 0; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = 0; + + sha512_hmac_update_128 (&ctx, w0, w1, w2, w3, w4, w5, w6, w7, 16); + + sha512_hmac_final (&ctx); + + w0[0] = h32_from_64_S (ctx.opad.h[0]); + w0[1] = l32_from_64_S (ctx.opad.h[0]); + w0[2] = h32_from_64_S (ctx.opad.h[1]); + w0[3] = l32_from_64_S (ctx.opad.h[1]); + w1[0] = h32_from_64_S (ctx.opad.h[2]); + w1[1] = l32_from_64_S (ctx.opad.h[2]); + w1[2] = h32_from_64_S (ctx.opad.h[3]); + w1[3] = l32_from_64_S (ctx.opad.h[3]); + w2[0] = h32_from_64_S (ctx.opad.h[4]); + w2[1] = l32_from_64_S (ctx.opad.h[4]); + w2[2] = h32_from_64_S (ctx.opad.h[5]); + w2[3] = l32_from_64_S (ctx.opad.h[5]); + w3[0] = h32_from_64_S (ctx.opad.h[6]); + w3[1] = l32_from_64_S (ctx.opad.h[6]); + w3[2] = h32_from_64_S (ctx.opad.h[7]); + w3[3] = l32_from_64_S (ctx.opad.h[7]); + w4[0] = 0; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = 0; + + sha512_hmac_init_128 (&ctx, w0, w1, w2, w3, w4, w5, w6, w7); + + w0[0] = last_key[ 0]; + w0[1] = last_key[ 1]; + w0[2] = last_key[ 2]; + w0[3] = last_key[ 3]; + w1[0] = last_key[ 4]; + w1[1] = last_key[ 5]; + w1[2] = last_key[ 6]; + w1[3] = last_key[ 7]; + w2[0] = last_key[ 8]; + w2[1] = last_key[ 9]; + w2[2] = last_key[10]; + w2[3] = last_key[11]; + w3[0] = last_key[12]; + w3[1] = last_key[13]; + w3[2] = last_key[14]; + w3[3] = last_key[15]; + w4[0] = 0; + w4[1] = 0; + w4[2] = 0; + w4[3] = 0; + w5[0] = 0; + w5[1] = 0; + w5[2] = 0; + w5[3] = 0; + w6[0] = 0; + w6[1] = 0; + w6[2] = 0; + w6[3] = 0; + w7[0] = 0; + w7[1] = 0; + w7[2] = 0; + w7[3] = 0; + + sha512_hmac_update_128 (&ctx, w0, w1, w2, w3, w4, w5, w6, w7, 64); + + sha512_hmac_final (&ctx); + + #define il_pos 0 + + if ((expected_key[0] == h32_from_64_S (ctx.opad.h[0])) + && (expected_key[1] == l32_from_64_S (ctx.opad.h[0])) + && (expected_key[2] == h32_from_64_S (ctx.opad.h[1])) + && (expected_key[3] == l32_from_64_S (ctx.opad.h[1]))) + { + if (hc_atomic_inc (&hashes_shown[DIGESTS_OFFSET_HOST]) == 0) + { + mark_hash (plains_buf, d_return_buf, SALT_POS_HOST, DIGESTS_CNT, 0, DIGESTS_OFFSET_HOST + 0, gid, il_pos, 0, 0); + } + } +} diff --git a/src/modules/module_15910.c b/src/modules/module_15910.c new file mode 100644 index 000000000..dd02b1bf4 --- /dev/null +++ b/src/modules/module_15910.c @@ -0,0 +1,473 @@ +/** + * 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" +#include "memory.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_OS; +static const char *HASH_NAME = "DPAPI masterkey file v2 (context 3)"; +static const u64 KERN_TYPE = 15910; +static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE + | OPTI_TYPE_USES_BITS_64 + | OPTI_TYPE_SLOW_HASH_SIMD_LOOP + | OPTI_TYPE_SLOW_HASH_SIMD_LOOP2; +static const u64 OPTS_TYPE = OPTS_TYPE_PT_GENERATE_LE + | OPTS_TYPE_INIT2 + | OPTS_TYPE_LOOP2; +static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED; +static const char *ST_PASS = "hashcat"; +static const char *ST_HASH = "$DPAPImk$2*3*S-15-21-464497560-472124119-475628788-1088*aes256*sha512*13450*685165fdb6d0627a15100215ec331ed8*288*7e1ea6f7ec3c2111f2a3903c73aefe66e524d8b241dc1482d0bd07cc1f3ccdadd8cebd4263b3b7c2496da48f40d2eb4890513e6624aeefbe6bbc6ea73f2f71fecf9cc5fef3891a2e697a4415ba7a069642069c142335d53cc750d42a4f4d2b0592956b4a0e57a5d5b1bfd27f0a8eac9d0d5fc5c5e5e23af18ce1a8eff442ed335e5db3bad6e89146f71aa9351e132fd9"; + +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 dpapimk +{ + u32 context; + + u32 SID[32]; + u32 SID_len; + u32 SID_offset; + + /* here only for possible + forward compatibiliy + */ + // u8 cipher_algo[16]; + // u8 hash_algo[16]; + + u32 iv[4]; + u32 contents_len; + u32 contents[128]; + +} dpapimk_t; + +typedef struct dpapimk_tmp_v2 +{ + u32 ipad[8]; + u32 opad[8]; + u32 dgst[32]; + u32 out[32]; + + u64 ipad64[8]; + u64 opad64[8]; + u64 dgst64[16]; + u64 out64[16]; + + u32 userKey[8]; + +} dpapimk_tmp_v2_t; + +static const char *SIGNATURE_DPAPIMK = "$DPAPImk$"; + +salt_t *module_benchmark_salt (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) +{ + salt_t *salt = (salt_t *) hcmalloc (sizeof (salt_t)); + + salt->salt_iter = 10000 - 1; + salt->salt_iter2 = 13450 - 1; + salt->salt_len = 16; + + return salt; +} + +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 (dpapimk_tmp_v2_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 (dpapimk_t); + + return esalt_size; +} + +u32 module_pw_max (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 u32 pw_max = PW_MAX; + + return pw_max; +} + +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; + + dpapimk_t *dpapimk = (dpapimk_t *) esalt_buf; + + memset (dpapimk, 0, sizeof (dpapimk_t)); + + hc_token_t token; + + token.token_cnt = 10; + + token.signatures_cnt = 1; + token.signatures_buf[0] = SIGNATURE_DPAPIMK; + + // signature + token.len[0] = 9; + token.attr[0] = TOKEN_ATTR_FIXED_LENGTH + | TOKEN_ATTR_VERIFY_SIGNATURE; + + // version + token.len_min[1] = 1; + token.len_max[1] = 1; + token.sep[1] = '*'; + token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_DIGIT; + + // context + token.len_min[2] = 1; + token.len_max[2] = 1; + token.sep[2] = '*'; + token.attr[2] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_DIGIT; + + // sid + token.len_min[3] = 10; + token.len_max[3] = 60; + token.sep[3] = '*'; + token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH; + + // cipher + token.len_min[4] = 4; + token.len_max[4] = 6; + token.sep[4] = '*'; + token.attr[4] = TOKEN_ATTR_VERIFY_LENGTH; + + // hash + token.len_min[5] = 4; + token.len_max[5] = 6; + token.sep[5] = '*'; + token.attr[5] = TOKEN_ATTR_VERIFY_LENGTH; + + // iterations + token.len_min[6] = 1; + token.len_max[6] = 6; + token.sep[6] = '*'; + token.attr[6] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_DIGIT; + + // iv + token.len_min[7] = 32; + token.len_max[7] = 32; + token.sep[7] = '*'; + token.attr[7] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_HEX; + + // content len + token.len_min[8] = 1; + token.len_max[8] = 6; + token.sep[8] = '*'; + token.attr[8] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_DIGIT; + + // content + token.len_min[9] = 0; + token.len_max[9] = 1024; + token.attr[9] = 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 *version_pos = token.buf[1]; + const u8 *context_pos = token.buf[2]; + const u8 *SID_pos = token.buf[3]; + const u8 *rounds_pos = token.buf[6]; + const u8 *iv_pos = token.buf[7]; + const u8 *contents_len_pos = token.buf[8]; + const u8 *contents_pos = token.buf[9]; + + /** + * content verification + */ + + const int version = hc_strtoul ((const char *) version_pos, NULL, 10); + const int contents_len = hc_strtoul ((const char *) contents_len_pos, NULL, 10); + + if (version == 1) + { + if (contents_len != 208) return (PARSER_SALT_LENGTH); + } + else if (version == 2) + { + if (contents_len != 288) return (PARSER_SALT_LENGTH); + } + else + { + return (PARSER_SALT_VALUE); + } + + if (contents_len != token.len[9]) return (PARSER_SALT_LENGTH); + + dpapimk->contents_len = contents_len; + + dpapimk->context = hc_strtoul ((const char *) context_pos, NULL, 10); + + if (dpapimk->context != 3) return (PARSER_SALT_LENGTH); + + for (u32 i = 0; i < dpapimk->contents_len / 8; i++) + { + dpapimk->contents[i] = hex_to_u32 ((const u8 *) &contents_pos[i * 8]); + + dpapimk->contents[i] = byte_swap_32 (dpapimk->contents[i]); + } + + // SID + + const int SID_len = token.len[3]; + + u8 SID_utf16le[128] = { 0 }; + + for (int i = 0; i < SID_len; i++) + { + SID_utf16le[i * 2] = SID_pos[i]; + } + + dpapimk->SID_len = SID_len * 2; + + memcpy ((u8 *) dpapimk->SID, SID_utf16le, sizeof (SID_utf16le)); + + for (u32 i = 0; i < 32; i++) + { + dpapimk->SID[i] = byte_swap_32 (dpapimk->SID[i]); + } + + // iv + + dpapimk->iv[0] = hex_to_u32 ((const u8 *) &iv_pos[ 0]); + dpapimk->iv[1] = hex_to_u32 ((const u8 *) &iv_pos[ 8]); + dpapimk->iv[2] = hex_to_u32 ((const u8 *) &iv_pos[16]); + dpapimk->iv[3] = hex_to_u32 ((const u8 *) &iv_pos[24]); + + dpapimk->iv[0] = byte_swap_32 (dpapimk->iv[0]); + dpapimk->iv[1] = byte_swap_32 (dpapimk->iv[1]); + dpapimk->iv[2] = byte_swap_32 (dpapimk->iv[2]); + dpapimk->iv[3] = byte_swap_32 (dpapimk->iv[3]); + + digest[0] = dpapimk->iv[0]; + digest[1] = dpapimk->iv[1]; + digest[2] = dpapimk->iv[2]; + digest[3] = dpapimk->iv[3]; + + salt->salt_buf[0] = dpapimk->iv[0]; + salt->salt_buf[1] = dpapimk->iv[1]; + salt->salt_buf[2] = dpapimk->iv[2]; + salt->salt_buf[3] = dpapimk->iv[3]; + + salt->salt_len = 16; + + // iter + + salt->salt_iter = 10000 - 1; + salt->salt_iter2 = hc_strtoul ((const char *) rounds_pos, NULL, 10) - 1; + + 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 dpapimk_t *dpapimk = (const dpapimk_t *) esalt_buf; + + u32 version = 2; + u32 context = dpapimk->context; + u32 rounds = salt->salt_iter2 + 1; + u32 contents_len = dpapimk->contents_len; + u32 SID_len = dpapimk->SID_len; + u32 iv_len = 32; + + u8 cipher_algorithm[8] = { 0 }; + u8 hash_algorithm[8] = { 0 }; + u8 SID[512] = { 0 }; + u8 *SID_tmp = NULL; + + u32 *ptr_SID = (u32 *) dpapimk->SID; + u32 *ptr_iv = (u32 *) dpapimk->iv; + u32 *ptr_contents = (u32 *) dpapimk->contents; + + u32 u32_iv[4]; + u8 iv[32 + 1]; + + u32 u32_contents[36]; + u8 contents[288 + 1]; + + memset (u32_iv, 0, sizeof (u32_iv)); + memset (iv, 0, sizeof (iv)); + + memset (u32_contents, 0, sizeof (u32_contents)); + memset (contents, 0, sizeof (contents)); + + // convert back SID + + SID_tmp = (u8 *) hcmalloc ((SID_len + 1) * sizeof (u8)); + + for (u32 i = 0; i < (SID_len / 4); i++) + { + u8 hex[8] = { 0 }; + + u32_to_hex (byte_swap_32 (ptr_SID[i]), hex); + + for (u32 j = 0, k = 0; j < 8; j += 2, k++) + { + SID_tmp[i * 4 + k] = hex_to_u8 (&hex[j]); + } + } + + // overwrite trailing 0x80 + + SID_tmp[SID_len] = 0; + + for (u32 i = 0, j = 0 ; j < SID_len ; i++, j += 2) + { + SID[i] = SID_tmp[j]; + } + + hcfree (SID_tmp); + + for (u32 i = 0; i < iv_len / 8; i++) + { + u32_iv[i] = byte_swap_32 (ptr_iv[i]); + + u32_to_hex (u32_iv[i], iv + i * 8); + } + + iv[32] = 0; + + for (u32 i = 0; i < contents_len / 8; i++) + { + u32_contents[i] = byte_swap_32 (ptr_contents[i]); + + u32_to_hex (u32_contents[i], contents + i * 8); + } + + contents[288] = 0; + + if (contents_len == 288) + { + memcpy (cipher_algorithm, "aes256", strlen ("aes256")); + + memcpy (hash_algorithm, "sha512", strlen ("sha512")); + } + + const int line_len = snprintf (line_buf, line_size, "%s%u*%u*%s*%s*%s*%u*%s*%u*%s", + SIGNATURE_DPAPIMK, + version, + context, + SID, + cipher_algorithm, + hash_algorithm, + rounds, + iv, + contents_len, + contents); + + 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_benchmark_salt; + module_ctx->module_build_plain_postprocess = MODULE_DEFAULT; + module_ctx->module_deep_comp_kernel = MODULE_DEFAULT; + module_ctx->module_deprecated_notice = 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_extra_tuningdb_block = 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_postprocess = 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_hashes_count_min = MODULE_DEFAULT; + module_ctx->module_hashes_count_max = MODULE_DEFAULT; + module_ctx->module_hlfmt_disable = MODULE_DEFAULT; + module_ctx->module_hook_extra_param_size = MODULE_DEFAULT; + module_ctx->module_hook_extra_param_init = MODULE_DEFAULT; + module_ctx->module_hook_extra_param_term = 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_pw_max; + 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; +} diff --git a/tools/test_modules/m15910.pm b/tools/test_modules/m15910.pm new file mode 100644 index 000000000..736a639ec --- /dev/null +++ b/tools/test_modules/m15910.pm @@ -0,0 +1,434 @@ +#!/usr/bin/env perl + +## +## Author......: See docs/credits.txt +## License.....: MIT +## + +use strict; +use warnings; + +use Digest::MD4 qw (md4); +use Digest::SHA qw (sha1 hmac_sha1 hmac_sha512); +use Crypt::PBKDF2; +use Crypt::CBC; +use Crypt::ECB; +use Encode; + +sub module_constraints { [[0, 256], [-1, -1], [-1, -1], [-1, -1], [-1, -1]] } + +sub get_random_dpapimk_salt +{ + my $version = shift; + + my $salt_buf = ""; + + my $context = 3; + + my $cipher_algo = ""; + + my $hash_algo = ""; + + my $iterations; + + my $SID = sprintf ('S-15-21-%d-%d-%d-%d', + random_number (400000000,490000000), + random_number (400000000,490000000), + random_number (400000000,490000000), + random_number (1000,1999)); + + my $cipher_len = 0; + + if ($version == 1) + { + $iterations = random_number (4000, 24000); + + $cipher_algo = "des3"; + + $hash_algo = "sha1"; + + $cipher_len = 208; + } + elsif ($version == 2) + { + $iterations = random_number (8000, 17000); + + $cipher_algo = "aes256"; + + $hash_algo = "sha512"; + + $cipher_len = 288; + } + + my $iv = random_bytes (16); + $iv = unpack ("H*", $iv); + + $salt_buf = $version . '*' . + $context . '*' . + $SID . '*' . + $cipher_algo . '*' . + $hash_algo . '*' . + $iterations . '*' . + $iv . '*' . + $cipher_len . '*'; + + return $salt_buf; +} + +# Thanks to Jochen Hoenicke +# (one of the authors of Palm Keyring) +# for these next two subs. + +sub dpapi_pbkdf2 +{ + my ($password, $salt, $iter, $keylen, $prf) = @_; + my ($k, $t, $u, $ui, $i); + + $t = ""; + + for ($k = 1; length ($t) < $keylen; $k++) + { + $u = $ui = &$prf ($salt . pack ('N', $k), $password); + + for ($i = 1; $i < $iter; $i++) + { + # modification to fit Microsoft + # weird pbkdf2 implementation... + + $ui = &$prf ($u, $password); + $u ^= $ui; + } + + $t .= $u; + } + + return substr ($t, 0, $keylen); +} + +sub module_generate_hash +{ + my $word_buf = shift; + my $salt_buf = shift; + my $dpapimk_salt = shift // get_random_dpapimk_salt (2); + my $cipher = shift; + + my @salt_arr = split ('\*', $dpapimk_salt); + + my $version = $salt_arr[0]; + my $context = $salt_arr[1]; + my $SID = $salt_arr[2]; + my $cipher_algorithm = $salt_arr[3]; + my $hash_algorithm = $salt_arr[4]; + my $iterations = $salt_arr[5]; + my $salt = pack ("H*", $salt_arr[6]); + my $cipher_len = $salt_arr[7]; + + # intermediate values + + my $user_hash; + my $user_derivationKey; + my $encKey; + my $expected_hmac; + my $cleartext; + + my $SIDenc = encode ("UTF-16LE", $SID); + + my $NTLMhash = md4 (encode ("UTF-16LE", $word_buf)); + + my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256); + + my $pbkdf2_1 = Crypt::PBKDF2->new ( + hasher => $hasher, + iterations => 10000, + output_len => 32 + ); + + my $pbkdf2_2 = Crypt::PBKDF2->new ( + hasher => $hasher, + iterations => 1, + output_len => 16 + ); + + $user_hash = $pbkdf2_1->PBKDF2 ($SIDenc, $NTLMhash); + + $user_hash = $pbkdf2_2->PBKDF2 ($SIDenc, $user_hash); + + $user_derivationKey = hmac_sha1 (encode ("UTF-16LE", $SID . "\x00"), $user_hash); + + my $hmacSalt = random_bytes (16); + my $last_key = random_bytes (64); + + if ($version == 1) + { + $encKey = hmac_sha1 ($hmacSalt, $user_derivationKey); + $expected_hmac = hmac_sha1 ($last_key, $encKey); + + # need padding because keyLen is 24 and hashLen 20 + $expected_hmac = $expected_hmac . random_bytes (4); + } + elsif ($version == 2) + { + $encKey = hmac_sha512 ($hmacSalt, $user_derivationKey); + $expected_hmac = hmac_sha512 ($last_key, $encKey); + } + + $cleartext = $hmacSalt . $expected_hmac . $last_key; + + my $derived_key; + my $key; + my $iv; + + my $pbkdf2; + + if ($version == 1) + { + $derived_key = dpapi_pbkdf2 ($user_derivationKey, $salt, $iterations, 32, \&hmac_sha1); + } + elsif ($version == 2) + { + $derived_key = dpapi_pbkdf2 ($user_derivationKey, $salt, $iterations, 48, \&hmac_sha512); + } + + if (defined $cipher) + { + $cipher = pack ("H*", $cipher); + + my $computed_hmac = ""; + + if ($version == 1) + { + $key = substr ($derived_key, 0, 24); + $iv = substr ($derived_key, 24, 8); + + my $p1 = Crypt::ECB->new ({ + key => substr ($key, 0, 8), + cipher => "DES", + literal_key => 1, + header => "none", + keysize => 8, + padding => "none", + }); + + my $p2 = Crypt::ECB->new ({ + key => substr ($key, 8, 8), + cipher => "DES", + literal_key => 1, + header => "none", + keysize => 8, + padding => "none", + }); + + my $p3 = Crypt::ECB->new ({ + key => substr ($key, 16, 8), + cipher => "DES", + literal_key => 1, + header => "none", + keysize => 8, + padding => "none", + }); + + # let's compute a 3DES-EDE-CBC decryption + + my $out1; + my $out2; + my $out3; + my $expected_cleartext = ""; + + # size of cipherlen is 104 bytes + for (my $k = 0; $k < 13; $k++) + { + $out1 = $p3->decrypt (substr ($cipher, $k * 8, 8)); + $out2 = $p2->encrypt ($out1); + $out3 = $p1->decrypt ($out2); + + $expected_cleartext .= substr ($out3, 0, 8) ^ $iv; + + $iv = substr ($cipher, $k * 8, 8); + } + + $last_key = substr ($expected_cleartext, length ($expected_cleartext) - 64, 64); + $hmacSalt = substr ($expected_cleartext, 0, 16); + $expected_hmac = substr ($expected_cleartext, 16, 20); + + $encKey = hmac_sha1 ($hmacSalt, $user_derivationKey); + $computed_hmac = hmac_sha1 ($last_key, $encKey); + + $cleartext = $expected_cleartext; + + if (unpack ("H*", $expected_hmac) ne unpack ("H*", $computed_hmac)) + { + $cleartext = "0" x 104; + } + } + elsif ($version == 2) + { + $key = substr ($derived_key, 0, 32); + $iv = substr ($derived_key, 32, 16); + + my $aes = Crypt::CBC->new ({ + key => $key, + cipher => "Crypt::Rijndael", + iv => $iv, + literal_key => 1, + header => "none", + keysize => 32, + padding => "none", + }); + + my $expected_cleartext = $aes->decrypt ($cipher); + + $last_key = substr ($expected_cleartext, length ($expected_cleartext) - 64, 64); + $hmacSalt = substr ($expected_cleartext, 0, 16); + $expected_hmac = substr ($expected_cleartext, 16, 64); + + $encKey = hmac_sha512 ($hmacSalt, $user_derivationKey); + $computed_hmac = hmac_sha512 ($last_key, $encKey); + + $cleartext = $expected_cleartext; + + if (unpack ("H*", $expected_hmac) ne unpack ("H*", $computed_hmac)) + { + $cleartext = "0" x 144; + } + } + } + + if ($version == 1) + { + $key = substr ($derived_key, 0, 24); + $iv = substr ($derived_key, 24, 8); + + my $p1 = Crypt::ECB->new ({ + key => substr ($key, 0, 8), + cipher => "DES", + literal_key => 1, + header => "none", + keysize => 8, + padding => "none", + }); + + my $p2 = Crypt::ECB->new ({ + key => substr ($key, 8, 8), + cipher => "DES", + literal_key => 1, + header => "none", + keysize => 8, + padding => "none", + }); + + my $p3 = Crypt::ECB->new ({ + key => substr ($key, 16, 8), + cipher => "DES", + literal_key => 1, + header => "none", + keysize => 8, + padding => "none", + }); + + # let's compute a 3DES-EDE-CBC encryption + + # compute first block + my $out1 = $p1->encrypt (substr ($cleartext, 0, 8) ^ $iv); + my $out2 = $p2->decrypt ($out1); + my $out3 = $p3->encrypt ($out2); + + $cipher = substr ($out3, 0, 8); + + # size of cipherlen is 104 bytes + for (my $k = 1; $k < 13; $k++) + { + $iv = $out3; + + $out1 = $p1->encrypt (substr ($cleartext, $k * 8, 8) ^ $iv); + $out2 = $p2->decrypt ($out1); + $out3 = $p3->encrypt ($out2); + + $cipher .= substr ($out3, 0, 8); + } + } + else + { + $key = substr ($derived_key, 0, 32); + $iv = substr ($derived_key, 32, 16); + + my $aes = Crypt::CBC->new ({ + key => $key, + cipher => "Crypt::Rijndael", + iv => $iv, + literal_key => 1, + header => "none", + keysize => 32, + padding => "none", + }); + + $cipher = $aes->encrypt ($cleartext); + } + + my $tmp_hash = sprintf ('$DPAPImk$%d*%d*%s*%s*%s*%d*%s*%d*%s', + $version, + $context, + $SID, + $cipher_algorithm, + $hash_algorithm, + $iterations, + unpack ("H*", $salt), + $cipher_len, + unpack ("H*", $cipher)); + + return $tmp_hash; +} + +sub module_verify_hash +{ + my $line = shift; + + my ($hash, $word) = split (':', $line); + + return unless defined $hash; + return unless defined $word; + + my @tmp_data = split ('\$', $hash); + + my $signature = $tmp_data[1]; + + return unless ($signature eq 'DPAPImk'); + + my @data = split ('\*', $tmp_data[2]); + + return unless (scalar @data == 9); + + my $version = shift @data; + + return unless ($version == 1 || $version == 2); + + my $context = shift @data; + my $SID = shift @data; + my $cipher_algorithm = shift @data; + my $hash_algorithm = shift @data; + my $iteration = shift @data; + my $iv = shift @data; + my $cipher_len = shift @data; + my $cipher = shift @data; + + return unless ($context == 3); + return unless (length ($cipher) == $cipher_len); + + if ($version == 1) + { + return unless ($cipher_len == 208); + } + elsif ($version == 2) + { + return unless ($cipher_len == 288); + } + + my $dpapimk_salt = substr ($hash, length ('$DPAPImk$')); + + my $word_packed = pack_if_HEX_notation ($word); + + my $new_hash = module_generate_hash ($word_packed, undef, $dpapimk_salt, $cipher); + + return ($new_hash, $word); +} + +1;