diff --git a/OpenCL/m21500-pure.cl b/OpenCL/m21500-pure.cl index ff81e2b05..f0614c07d 100644 --- a/OpenCL/m21500-pure.cl +++ b/OpenCL/m21500-pure.cl @@ -30,7 +30,7 @@ typedef struct pbkdf2_sha1_tmp typedef struct pbkdf2_sha1 { - u32 salt_buf[64]; + u32 salt_buf[4]; } pbkdf2_sha1_t; diff --git a/docs/changes.txt b/docs/changes.txt index 511a0d95f..8443e93e3 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -37,6 +37,7 @@ - Added hash-mode: Python passlib pbkdf2-sha512 - Added hash-mode: Oracle Transportation Management (SHA256) - Added hash-mode: sha1(md5($pass).$salt) +- Added hash-mode: SolarWinds Orion, SHA512(PBKDF2-HMAC-SHA1) ## ## Bugs diff --git a/docs/credits.txt b/docs/credits.txt index 9eb7b0dac..58360d3de 100644 --- a/docs/credits.txt +++ b/docs/credits.txt @@ -18,6 +18,7 @@ Philipp "philsmd" Schmidt (@philsmd) Gabriele "matrix" Gristina (@gm4tr1x) +* SolarWinds Orion, SHA512(PBKDF2-HMAC-SHA1), kernel module * sha1(md5($pass).$salt) kernel module * gzip wordlists feature * SHA-224 kernel module + optimizations diff --git a/docs/readme.txt b/docs/readme.txt index 7e3e8d468..442dab752 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -279,6 +279,7 @@ NVIDIA GPUs require "NVIDIA Driver" (418.56 or later) and "CUDA Toolkit" (10.1 o - Ethereum Wallet, SCRYPT - Ethereum Pre-Sale Wallet, PBKDF2-HMAC-SHA256 - Ansible Vault +- SolarWinds Orion, SHA512(PBKDF2-HMAC-SHA1) - Plaintext ## diff --git a/src/modules/module_21500.c b/src/modules/module_21500.c index a33949735..cd6bbec6d 100644 --- a/src/modules/module_21500.c +++ b/src/modules/module_21500.c @@ -17,7 +17,7 @@ static const u32 DGST_POS2 = 6; static const u32 DGST_POS3 = 7; static const u32 DGST_SIZE = DGST_SIZE_8_8; static const u32 HASH_CATEGORY = HASH_CATEGORY_GENERIC_KDF; -static const char *HASH_NAME = "SHA512(PBKDF2-HMAC-SHA1)"; +static const char *HASH_NAME = "SolarWinds Orion"; static const u64 KERN_TYPE = 21500; static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE | OPTI_TYPE_USES_BITS_64 @@ -27,7 +27,9 @@ static const u64 OPTS_TYPE = OPTS_TYPE_PT_GENERATE_LE | OPTS_TYPE_HASH_COPY; static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED; static const char *ST_PASS = "hashcat"; -static const char *ST_HASH = "sha1:1000:aGFzaGNhdDE=:Dnz04T9ptYINnj9mckXTuk80w6f1vkZLwv02HiufklgnDw53BU1bgn4gsHia/Q6kxYSqK4PDbxRMwa6HB5KA/w=="; +static const char *ST_HASH = "$solarwinds$0$hashcat1$Dnz04T9ptYINnj9mckXTuk80w6f1vkZLwv02HiufklgnDw53BU1bgn4gsHia/Q6kxYSqK4PDbxRMwa6HB5KA/w=="; + +static const char *SALT_PADDING = "1244352345234"; 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; } @@ -60,7 +62,7 @@ typedef struct pbkdf2_sha1 } pbkdf2_sha1_t; -static const char *SIGNATURE_PBKDF2_SHA1 = "sha1"; +static const char *SIGNATURE_SOLARWINDS_ORION = "$solarwinds$0$"; 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) { @@ -106,63 +108,67 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE token_t token; - token.token_cnt = 4; + token.token_cnt = 3; token.signatures_cnt = 1; - token.signatures_buf[0] = SIGNATURE_PBKDF2_SHA1; + token.signatures_buf[0] = SIGNATURE_SOLARWINDS_ORION; - token.sep[0] = ':'; - token.len_min[0] = 4; - token.len_max[0] = 4; - token.attr[0] = TOKEN_ATTR_VERIFY_LENGTH + token.len[0] = 14; + token.attr[0] = TOKEN_ATTR_FIXED_LENGTH | TOKEN_ATTR_VERIFY_SIGNATURE; - token.sep[1] = ':'; - token.len_min[1] = 1; - token.len_max[1] = 6; - token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH - | TOKEN_ATTR_VERIFY_DIGIT; + token.sep[1] = '$'; + token.len_min[1] = 0; + token.len_max[1] = 16; + token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH; - token.sep[2] = ':'; - token.len_min[2] = 12; - token.len_max[2] = 24; + token.sep[2] = '$'; + token.len_min[2] = 64; + token.len_max[2] = 256; token.attr[2] = TOKEN_ATTR_VERIFY_LENGTH | TOKEN_ATTR_VERIFY_BASE64A; - token.len_min[3] = 64; - token.len_max[3] = 256; - token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH - | TOKEN_ATTR_VERIFY_BASE64A; - const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); if (rc_tokenizer != PARSER_OK) return (rc_tokenizer); - u8 tmp_buf[512]; - int tmp_len; - // iter - const u8 *iter_pos = token.buf[1]; - - const u32 iter = hc_strtoul ((const char *) iter_pos, NULL, 10); + const u32 iter = 1000; salt->salt_iter = iter - 1; // salt - const u8 *salt_pos = token.buf[2]; - const int salt_len = token.len[2]; + char *salt_pos = (char *) token.buf[1]; + int salt_len = token.len[1]; - memset (tmp_buf, 0, sizeof (tmp_buf)); + if (salt_len > 16) return (PARSER_SALT_LENGTH); - tmp_len = base64_decode (base64_to_int, salt_pos, salt_len, tmp_buf); + char custom_salt[17]; - if (tmp_len < 8 || tmp_len > 16) return (PARSER_SALT_LENGTH); + memset (custom_salt, 0, sizeof (custom_salt)); - memcpy (pbkdf2_sha1->salt_buf, tmp_buf, tmp_len); + for (int i = 0; i < salt_len; i++, salt_pos++) + { + if (*salt_pos >= 'A' && *salt_pos <= 'Z') { + custom_salt[i] = *salt_pos + 32; + } else { + custom_salt[i] = *salt_pos; + } + } - salt->salt_len = tmp_len; + if (salt_len < 8) + { + strncat (custom_salt, SALT_PADDING, 8 - salt_len); + salt_len = 8; + } + + salt_pos = custom_salt; + + memcpy (pbkdf2_sha1->salt_buf, salt_pos, salt_len); + + salt->salt_len = salt_len; salt->salt_buf[0] = pbkdf2_sha1->salt_buf[0]; salt->salt_buf[1] = pbkdf2_sha1->salt_buf[1]; @@ -172,12 +178,14 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE // hash - const u8 *hash_pos = token.buf[3]; - const int hash_len = token.len[3]; + const u8 *hash_pos = token.buf[2]; + const int hash_len = token.len[2]; + + u8 tmp_buf[256]; memset (tmp_buf, 0, sizeof (tmp_buf)); - tmp_len = base64_decode (base64_to_int, hash_pos, hash_len, tmp_buf); + int tmp_len = base64_decode (base64_to_int, hash_pos, hash_len, tmp_buf); if (tmp_len < 64) return (PARSER_HASH_LENGTH); @@ -197,7 +205,32 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE 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) { - return snprintf (line_buf, line_size, "%s", hash_info->orighash); + const u64 *digest = (u64 *) digest_buf; + + const pbkdf2_sha1_t *pbkdf2_sha1 = (const pbkdf2_sha1_t *) esalt_buf; + + // hash + + u64 tmp[9]; + + tmp[0] = byte_swap_64 (digest[0]); + tmp[1] = byte_swap_64 (digest[1]); + tmp[2] = byte_swap_64 (digest[2]); + tmp[3] = byte_swap_64 (digest[3]); + tmp[4] = byte_swap_64 (digest[4]); + tmp[5] = byte_swap_64 (digest[5]); + tmp[6] = byte_swap_64 (digest[6]); + tmp[7] = byte_swap_64 (digest[7]); + tmp[8] = 0; + + char hash_enc[256] = { 0 }; + + base64_encode (int_to_base64, (const u8 *) tmp, 64, (u8 *) hash_enc); + + // output + const int line_len = snprintf (line_buf, line_size, "%s%s$%s", SIGNATURE_SOLARWINDS_ORION, (const u8 *) pbkdf2_sha1->salt_buf, hash_enc); + + return line_len; } void module_init (module_ctx_t *module_ctx)