From a5d94c1f0dc0cbb21371e015741ddf5a2a6187cb Mon Sep 17 00:00:00 2001 From: jsteube Date: Wed, 1 Mar 2023 11:35:37 +0000 Subject: [PATCH] Added hash-mode: Veeam VBK --- OpenCL/inc_hash_sha1.cl | 146 ++++++++++++++++ OpenCL/inc_hash_sha1.h | 1 + OpenCL/m31200-pure.cl | 339 +++++++++++++++++++++++++++++++++++++ docs/changes.txt | 1 + docs/readme.txt | 1 + src/modules/module_31200.c | 306 +++++++++++++++++++++++++++++++++ tools/veeamvbk2hashcat.py | 25 +++ 7 files changed, 819 insertions(+) create mode 100644 OpenCL/m31200-pure.cl create mode 100644 src/modules/module_31200.c create mode 100755 tools/veeamvbk2hashcat.py diff --git a/OpenCL/inc_hash_sha1.cl b/OpenCL/inc_hash_sha1.cl index 9d543de19..3f57fb0ff 100644 --- a/OpenCL/inc_hash_sha1.cl +++ b/OpenCL/inc_hash_sha1.cl @@ -1721,6 +1721,152 @@ DECLSPEC void sha1_hmac_init_global_swap (PRIVATE_AS sha1_hmac_ctx_t *ctx, GLOBA sha1_hmac_init_64 (ctx, w0, w1, w2, w3); } +DECLSPEC void sha1_hmac_init_global_utf16le_swap (PRIVATE_AS sha1_hmac_ctx_t *ctx, GLOBAL_AS const u32 *w, const int len) +{ + if (hc_enc_scan_global (w, len)) + { + hc_enc_t hc_enc; + + hc_enc_init (&hc_enc); + + while (hc_enc_has_next (&hc_enc, len)) + { + // forced full decode in one round + + u32 enc_buf[256]; + + const int enc_len = hc_enc_next_global (&hc_enc, w, len, 256, enc_buf, sizeof (enc_buf)); + + if (enc_len == -1) + { + //hmac doesn't have password length + //ctx->len = -1; + + return; + } + + if (enc_len > 64) + { + sha1_ctx_t tmp; + + sha1_init (&tmp); + + sha1_update_utf16le_swap (&tmp, enc_buf, enc_len); + + sha1_final (&tmp); + + enc_buf[ 0] = tmp.h[0]; + enc_buf[ 1] = tmp.h[1]; + enc_buf[ 2] = tmp.h[2]; + enc_buf[ 3] = tmp.h[3]; + enc_buf[ 4] = tmp.h[4]; + enc_buf[ 5] = 0; + enc_buf[ 6] = 0; + enc_buf[ 7] = 0; + enc_buf[ 8] = 0; + enc_buf[ 9] = 0; + enc_buf[10] = 0; + enc_buf[11] = 0; + enc_buf[12] = 0; + enc_buf[13] = 0; + enc_buf[14] = 0; + enc_buf[15] = 0; + } + else + { + enc_buf[ 0] = hc_swap32_S (enc_buf[ 0]); + enc_buf[ 1] = hc_swap32_S (enc_buf[ 1]); + enc_buf[ 2] = hc_swap32_S (enc_buf[ 2]); + enc_buf[ 3] = hc_swap32_S (enc_buf[ 3]); + enc_buf[ 4] = hc_swap32_S (enc_buf[ 4]); + enc_buf[ 5] = hc_swap32_S (enc_buf[ 5]); + enc_buf[ 6] = hc_swap32_S (enc_buf[ 6]); + enc_buf[ 7] = hc_swap32_S (enc_buf[ 7]); + enc_buf[ 8] = hc_swap32_S (enc_buf[ 8]); + enc_buf[ 9] = hc_swap32_S (enc_buf[ 9]); + enc_buf[10] = hc_swap32_S (enc_buf[10]); + enc_buf[11] = hc_swap32_S (enc_buf[11]); + enc_buf[12] = hc_swap32_S (enc_buf[12]); + enc_buf[13] = hc_swap32_S (enc_buf[13]); + enc_buf[14] = hc_swap32_S (enc_buf[14]); + enc_buf[15] = hc_swap32_S (enc_buf[15]); + } + + sha1_hmac_init_64 (ctx, enc_buf + 0, enc_buf + 4, enc_buf + 8, enc_buf + 12); + } + + return; + } + + u32 w0[4]; + u32 w1[4]; + u32 w2[4]; + u32 w3[4]; + + const int len_new = len * 2; + + if (len_new > 64) + { + sha1_ctx_t tmp; + + sha1_init (&tmp); + + sha1_update_global_utf16le_swap (&tmp, w, len); + + sha1_final (&tmp); + + w0[0] = tmp.h[0]; + w0[1] = tmp.h[1]; + w0[2] = tmp.h[2]; + w0[3] = tmp.h[3]; + w1[0] = tmp.h[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; + } + else + { + w0[0] = w[0]; + w0[1] = w[1]; + w0[2] = w[2]; + w0[3] = w[3]; + w1[0] = w[4]; + w1[1] = w[5]; + w1[2] = w[6]; + w1[3] = w[7]; + + make_utf16le_S (w1, w2, w3); + make_utf16le_S (w0, w0, w1); + + w0[0] = hc_swap32_S (w0[0]); + w0[1] = hc_swap32_S (w0[1]); + w0[2] = hc_swap32_S (w0[2]); + w0[3] = hc_swap32_S (w0[3]); + w1[0] = hc_swap32_S (w1[0]); + w1[1] = hc_swap32_S (w1[1]); + w1[2] = hc_swap32_S (w1[2]); + w1[3] = hc_swap32_S (w1[3]); + w2[0] = hc_swap32_S (w2[0]); + w2[1] = hc_swap32_S (w2[1]); + w2[2] = hc_swap32_S (w2[2]); + w2[3] = hc_swap32_S (w2[3]); + w3[0] = hc_swap32_S (w3[0]); + w3[1] = hc_swap32_S (w3[1]); + w3[2] = hc_swap32_S (w3[2]); + w3[3] = hc_swap32_S (w3[3]); + } + + sha1_hmac_init_64 (ctx, w0, w1, w2, w3); +} + DECLSPEC void sha1_hmac_update_64 (PRIVATE_AS sha1_hmac_ctx_t *ctx, PRIVATE_AS u32 *w0, PRIVATE_AS u32 *w1, PRIVATE_AS u32 *w2, PRIVATE_AS u32 *w3, const int len) { sha1_update_64 (&ctx->ipad, w0, w1, w2, w3, len); diff --git a/OpenCL/inc_hash_sha1.h b/OpenCL/inc_hash_sha1.h index c86692b5b..8ad30fb3f 100644 --- a/OpenCL/inc_hash_sha1.h +++ b/OpenCL/inc_hash_sha1.h @@ -112,6 +112,7 @@ DECLSPEC void sha1_hmac_init (PRIVATE_AS sha1_hmac_ctx_t *ctx, PRIVATE_AS const DECLSPEC void sha1_hmac_init_swap (PRIVATE_AS sha1_hmac_ctx_t *ctx, PRIVATE_AS const u32 *w, const int len); DECLSPEC void sha1_hmac_init_global (PRIVATE_AS sha1_hmac_ctx_t *ctx, GLOBAL_AS const u32 *w, const int len); DECLSPEC void sha1_hmac_init_global_swap (PRIVATE_AS sha1_hmac_ctx_t *ctx, GLOBAL_AS const u32 *w, const int len); +DECLSPEC void sha1_hmac_init_global_utf16le_swap (PRIVATE_AS sha1_hmac_ctx_t *ctx, GLOBAL_AS const u32 *w, const int len); DECLSPEC void sha1_hmac_update_64 (PRIVATE_AS sha1_hmac_ctx_t *ctx, PRIVATE_AS u32 *w0, PRIVATE_AS u32 *w1, PRIVATE_AS u32 *w2, PRIVATE_AS u32 *w3, const int len); DECLSPEC void sha1_hmac_update (PRIVATE_AS sha1_hmac_ctx_t *ctx, PRIVATE_AS const u32 *w, const int len); DECLSPEC void sha1_hmac_update_swap (PRIVATE_AS sha1_hmac_ctx_t *ctx, PRIVATE_AS const u32 *w, const int len); diff --git a/OpenCL/m31200-pure.cl b/OpenCL/m31200-pure.cl new file mode 100644 index 000000000..4cbe28053 --- /dev/null +++ b/OpenCL/m31200-pure.cl @@ -0,0 +1,339 @@ +/** + * 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_sha1.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 pbkdf2_sha1_tmp +{ + u32 ipad[5]; + u32 opad[5]; + + u32 dgst[32]; + u32 out[32]; + +} pbkdf2_sha1_tmp_t; + +typedef struct veeam_vbk +{ + u32 ct_buf[4]; + +} veeam_vbk_t; + +DECLSPEC void hmac_sha1_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]; + + 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 m31200_init (KERN_ATTR_TMPS_ESALT (pbkdf2_sha1_tmp_t, veeam_vbk_t)) +{ + /** + * base + */ + + const u64 gid = get_global_id (0); + + if (gid >= GID_CNT) return; + + sha1_hmac_ctx_t sha1_hmac_ctx; + + sha1_hmac_init_global_utf16le_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 (&sha1_hmac_ctx, salt_bufs[DIGESTS_OFFSET_HOST].salt_buf, salt_bufs[DIGESTS_OFFSET_HOST].salt_len); + + for (u32 i = 0, j = 1; i < 12; 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 m31200_loop (KERN_ATTR_TMPS_ESALT (pbkdf2_sha1_tmp_t, veeam_vbk_t)) +{ + const u64 gid = get_global_id (0); + + if ((gid * VECT_SIZE) >= GID_CNT) 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 < 12; 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 m31200_comp (KERN_ATTR_TMPS_ESALT (pbkdf2_sha1_tmp_t, veeam_vbk_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; + + u32 ukey[8]; + + ukey[0] = tmps[gid].out[0]; + ukey[1] = tmps[gid].out[1]; + ukey[2] = tmps[gid].out[2]; + ukey[3] = tmps[gid].out[3]; + ukey[4] = tmps[gid].out[4]; + ukey[5] = tmps[gid].out[5]; + ukey[6] = tmps[gid].out[6]; + ukey[7] = tmps[gid].out[7]; + + #define KEYLEN 60 + + u32 ks[KEYLEN]; + + AES256_set_decrypt_key (ks, ukey, s_te0, s_te1, s_te2, s_te3, s_td0, s_td1, s_td2, s_td3); + + u32 ct[4]; + + ct[0] = esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[0]; + ct[1] = esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[1]; + ct[2] = esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[2]; + ct[3] = esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[3]; + + u32 out[4]; + + AES256_decrypt (ks, ct, out, s_td0, s_td1, s_td2, s_td3, s_td4); + + u32 iv[4]; + + iv[0] = tmps[gid].out[ 8]; + iv[1] = tmps[gid].out[ 9]; + iv[2] = tmps[gid].out[10]; + iv[3] = tmps[gid].out[11]; + + u32 pt[4]; + + pt[0] = out[0] ^ iv[0]; + pt[1] = out[1] ^ iv[1]; + pt[2] = out[2] ^ iv[2]; + pt[3] = out[3] ^ iv[3]; + + if (pt[1] != 0x0c0c0c0c) return; + if (pt[2] != 0x0c0c0c0c) return; + if (pt[3] != 0x0c0c0c0c) return; + + 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, 0, 0, 0); + } +} diff --git a/docs/changes.txt b/docs/changes.txt index 699eaf400..d1eec480f 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -23,6 +23,7 @@ - Added hash-mode: bcrypt(sha256($pass)) - Added hash-mode: md5(md5($salt).md5(md5($pass))) - Added hash-mode: metamask (26610) with plaintext check instead of checking the AES-GCM tag of the data (26600). 26610 no longer needs all data in hash. +- Added hash-mode: Veeam VBK ## ## Performance diff --git a/docs/readme.txt b/docs/readme.txt index d2b57eb6e..5e0b0a52f 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -354,6 +354,7 @@ NVIDIA GPUs require "NVIDIA Driver" (440.64 or later) and "CUDA Toolkit" (9.0 or - SecureZIP AES-128 - SecureZIP AES-192 - SecureZIP AES-256 +- Veeam VBK - WinZip - Android Backup - Stuffit5 diff --git a/src/modules/module_31200.c b/src/modules/module_31200.c new file mode 100644 index 000000000..32c1a181a --- /dev/null +++ b/src/modules/module_31200.c @@ -0,0 +1,306 @@ +/** + * 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_ARCHIVE; +static const char *HASH_NAME = "Veeam VBK"; +static const u64 KERN_TYPE = 31200; +static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE + | 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 = "$vbk$*54731702769149752741495960625996207399688284541933702394775960978730695504382155223405444342855920150089170058956647576461877712*10000*78cf7df8f1ed8bb50bda1129ec8e6810"; + +typedef struct pbkdf2_sha1_tmp +{ + u32 ipad[5]; + u32 opad[5]; + + u32 dgst[32]; + u32 out[32]; + +} pbkdf2_sha1_tmp_t; + +typedef struct veeam_vbk +{ + u32 ct_buf[4]; + +} veeam_vbk_t; + +static const char *SIGNATURE_VEEAM_VBK = "$vbk$"; + +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; } + +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 (pbkdf2_sha1_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 (veeam_vbk_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; + + veeam_vbk_t *veeam_vbk = (veeam_vbk_t *) esalt_buf; + + hc_token_t token; + + token.token_cnt = 4; + + token.signatures_cnt = 1; + token.signatures_buf[0] = SIGNATURE_VEEAM_VBK; + + token.sep[0] = '*'; + token.len_min[0] = 5; + token.len_max[0] = 5; + token.attr[0] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_SIGNATURE; + + token.sep[1] = '*'; + token.len_min[1] = 128; + token.len_max[1] = 128; + token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_HEX; + + token.sep[2] = '*'; + token.len_min[2] = 1; + token.len_max[2] = 10; + token.attr[2] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_DIGIT; + + token.sep[3] = '*'; + token.len_min[3] = 32; + token.len_max[3] = 32; + token.attr[3] = TOKEN_ATTR_VERIFY_HEX + | 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); + + // salt + + const u8 *salt_pos = token.buf[1]; + const int salt_len = token.len[1]; + + if (salt_len != 128) return (PARSER_SALT_LENGTH); + + salt->salt_buf[ 0] = hex_to_u32 (salt_pos + 0); + salt->salt_buf[ 1] = hex_to_u32 (salt_pos + 8); + salt->salt_buf[ 2] = hex_to_u32 (salt_pos + 16); + salt->salt_buf[ 3] = hex_to_u32 (salt_pos + 24); + salt->salt_buf[ 4] = hex_to_u32 (salt_pos + 32); + salt->salt_buf[ 5] = hex_to_u32 (salt_pos + 40); + salt->salt_buf[ 6] = hex_to_u32 (salt_pos + 48); + salt->salt_buf[ 7] = hex_to_u32 (salt_pos + 56); + salt->salt_buf[ 8] = hex_to_u32 (salt_pos + 64); + salt->salt_buf[ 9] = hex_to_u32 (salt_pos + 72); + salt->salt_buf[10] = hex_to_u32 (salt_pos + 80); + salt->salt_buf[11] = hex_to_u32 (salt_pos + 88); + salt->salt_buf[12] = hex_to_u32 (salt_pos + 96); + salt->salt_buf[13] = hex_to_u32 (salt_pos + 104); + salt->salt_buf[14] = hex_to_u32 (salt_pos + 112); + salt->salt_buf[15] = hex_to_u32 (salt_pos + 120); + + salt->salt_buf[ 0] = byte_swap_32 (salt->salt_buf[ 0]); + salt->salt_buf[ 1] = byte_swap_32 (salt->salt_buf[ 1]); + salt->salt_buf[ 2] = byte_swap_32 (salt->salt_buf[ 2]); + salt->salt_buf[ 3] = byte_swap_32 (salt->salt_buf[ 3]); + salt->salt_buf[ 4] = byte_swap_32 (salt->salt_buf[ 4]); + salt->salt_buf[ 5] = byte_swap_32 (salt->salt_buf[ 5]); + salt->salt_buf[ 6] = byte_swap_32 (salt->salt_buf[ 6]); + salt->salt_buf[ 7] = byte_swap_32 (salt->salt_buf[ 7]); + salt->salt_buf[ 8] = byte_swap_32 (salt->salt_buf[ 8]); + salt->salt_buf[ 9] = byte_swap_32 (salt->salt_buf[ 9]); + salt->salt_buf[10] = byte_swap_32 (salt->salt_buf[10]); + salt->salt_buf[11] = byte_swap_32 (salt->salt_buf[11]); + salt->salt_buf[12] = byte_swap_32 (salt->salt_buf[12]); + salt->salt_buf[13] = byte_swap_32 (salt->salt_buf[13]); + salt->salt_buf[14] = byte_swap_32 (salt->salt_buf[14]); + salt->salt_buf[15] = byte_swap_32 (salt->salt_buf[15]); + + salt->salt_len = 64; + + // iter + + const u8 *iter_pos = token.buf[2]; + + const u32 iter = hc_strtoul ((const char *) iter_pos, NULL, 10); + + salt->salt_iter = iter - 1; + + // ct + + const u8 *ct_pos = token.buf[3]; + const int ct_len = token.len[3]; + + if (ct_len != 32) return (PARSER_HASH_LENGTH); + + veeam_vbk->ct_buf[0] = hex_to_u32 (ct_pos + 0); + veeam_vbk->ct_buf[1] = hex_to_u32 (ct_pos + 8); + veeam_vbk->ct_buf[2] = hex_to_u32 (ct_pos + 16); + veeam_vbk->ct_buf[3] = hex_to_u32 (ct_pos + 24); + + veeam_vbk->ct_buf[0] = byte_swap_32 (veeam_vbk->ct_buf[0]); + veeam_vbk->ct_buf[1] = byte_swap_32 (veeam_vbk->ct_buf[1]); + veeam_vbk->ct_buf[2] = byte_swap_32 (veeam_vbk->ct_buf[2]); + veeam_vbk->ct_buf[3] = byte_swap_32 (veeam_vbk->ct_buf[3]); + + // hash + + digest[0] = veeam_vbk->ct_buf[0]; + digest[1] = veeam_vbk->ct_buf[1]; + digest[2] = veeam_vbk->ct_buf[2]; + digest[3] = veeam_vbk->ct_buf[3]; + + 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 u32 *digest = (const u32 *) digest_buf; + + const veeam_vbk_t *veeam_vbk = (const veeam_vbk_t *) esalt_buf; + + const int line_len = snprintf (line_buf, line_size, "%s*%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x*%d*%08x%08x%08x%08x", + SIGNATURE_VEEAM_VBK, + salt->salt_buf[ 0], + salt->salt_buf[ 1], + salt->salt_buf[ 2], + salt->salt_buf[ 3], + salt->salt_buf[ 4], + salt->salt_buf[ 5], + salt->salt_buf[ 6], + salt->salt_buf[ 7], + salt->salt_buf[ 8], + salt->salt_buf[ 9], + salt->salt_buf[10], + salt->salt_buf[11], + salt->salt_buf[12], + salt->salt_buf[13], + salt->salt_buf[14], + salt->salt_buf[15], + salt->salt_iter + 1, + veeam_vbk->ct_buf[0], + veeam_vbk->ct_buf[1], + veeam_vbk->ct_buf[2], + veeam_vbk->ct_buf[3]); + + 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_charset = 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_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_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; +} diff --git a/tools/veeamvbk2hashcat.py b/tools/veeamvbk2hashcat.py new file mode 100755 index 000000000..e8d6ac05c --- /dev/null +++ b/tools/veeamvbk2hashcat.py @@ -0,0 +1,25 @@ +import argparse +import binascii + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--file', required=False, help="VBK file") + parser.add_argument('-s', '--seek', required=False, help="skip N bytes for large files") + options = parser.parse_args() + + if options.file: + with open(options.file, mode="rb") as f: + if options.seek: + f.seek(int(options.seek),0) + while True: + data = f.read(131072) #read data from file per 128 kBytes + if not data: + break + offs = data.find(b'\x60\x00\x00\x00\x10\x00\x00\x00\x40\x00\x00\x00') + if offs != -1: + print("Found !") + part1 = data[offs+12:offs+12+96] + part2 = data[offs+12+96:offs+12+96+16] + part3 = data[offs+12+96+16:offs+12+96+16+64] + print(f'$vbk$*%s*10000*%s' % (binascii.hexlify(part3).decode('utf-8'), binascii.hexlify(part2).decode('utf-8'))) + break