From 81dcf8a648303ae7965fb76389280d224c5a291c Mon Sep 17 00:00:00 2001 From: magnum Date: Fri, 23 May 2025 13:52:03 +0200 Subject: [PATCH 1/2] Several formats' prepare(): Fix a bug when trying to reject unknown login fields[0] is never NULL, and the string it points to is only a nullstring if there is an explicit field saying so (i.e. line starts with a ":") For a missing login field (no ":", bare hash) field[0] is set to "?" in loader. This bug made the formats make up uncrackable hashes instead of rejecting when salt is unknown - leading to false negatives. --- src/leet_cc_fmt_plug.c | 2 +- src/mscash_common_plug.c | 4 ++-- src/oracle_fmt_plug.c | 2 +- src/sl3_common_plug.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/leet_cc_fmt_plug.c b/src/leet_cc_fmt_plug.c index 4f9079e3767..5b0c9f5167a 100644 --- a/src/leet_cc_fmt_plug.c +++ b/src/leet_cc_fmt_plug.c @@ -157,7 +157,7 @@ static char *prepare(char *split_fields[10], struct fmt_main *self) { char* cp; - if (!split_fields[0]) + if (!split_fields[0][0] || !strcmp(split_fields[0], "?")) return split_fields[1]; if (strnlen(split_fields[1], BINARY_SIZE * 2 + 1) != BINARY_SIZE * 2) return split_fields[1]; diff --git a/src/mscash_common_plug.c b/src/mscash_common_plug.c index ed37154976b..a2b2dbd8ae0 100644 --- a/src/mscash_common_plug.c +++ b/src/mscash_common_plug.c @@ -143,7 +143,7 @@ char *mscash1_common_prepare(char *split_fields[10], struct fmt_main *self) if (!strncmp(split_fields[1], FORMAT_TAG, FORMAT_TAG_LEN)) return split_fields[1]; - if (!split_fields[0]) + if (!split_fields[0][0] || !strcmp(split_fields[0], "?")) return split_fields[1]; // ONLY check, if this string split_fields[1], is ONLY a 32 byte hex string. @@ -391,7 +391,7 @@ char *mscash2_common_prepare(char *split_fields[10], struct fmt_main *self) MEM_FREE(cp); return split_fields[1]; } - if (!split_fields[0]) + if (!split_fields[0][0] || !strcmp(split_fields[0], "?")) return split_fields[1]; // ONLY check, if this string split_fields[1], is ONLY a 32 byte hex string. diff --git a/src/oracle_fmt_plug.c b/src/oracle_fmt_plug.c index 947c8e0cc22..746d10b569c 100644 --- a/src/oracle_fmt_plug.c +++ b/src/oracle_fmt_plug.c @@ -168,7 +168,7 @@ static char *prepare(char *split_fields[10], struct fmt_main *self) { char *cp; - if (!split_fields[0]) + if (!split_fields[0][0] || !strcmp(split_fields[0], "?")) return split_fields[1]; if (!strncmp(split_fields[1], FORMAT_TAG, FORMAT_TAG_LEN)) return split_fields[1]; diff --git a/src/sl3_common_plug.c b/src/sl3_common_plug.c index 6fc3e4b3fe7..7e1ee4231cd 100644 --- a/src/sl3_common_plug.c +++ b/src/sl3_common_plug.c @@ -28,7 +28,7 @@ char *sl3_prepare(char *split_fields[10], struct fmt_main *self) if (strlen(split_fields[1]) != 2 * BINARY_SIZE) return split_fields[1]; - if (!split_fields[0]) + if (!split_fields[0][0] || !strcmp(split_fields[0], "?")) return split_fields[1]; len = strlen(split_fields[0]); From fbd5fec2150ae1d0dae5c806ee4c9bc3c7bbea0f Mon Sep 17 00:00:00 2001 From: magnum Date: Fri, 23 May 2025 15:30:44 +0200 Subject: [PATCH 2/2] Several formats' prepare(): Fix bugs when checking fields fields[n] is never NULL so no test for that needed. The intended checks were otherwise typically to check that a field wasn't an empty string. --- src/MSCHAPv2_bs_fmt_plug.c | 6 ++---- src/NETLMv2_fmt_plug.c | 4 +++- src/NETNTLMv2_fmt_plug.c | 4 +++- src/asaMD5_fmt_plug.c | 2 +- src/dynamic_fmt.c | 4 ++-- src/oldoffice_common_plug.c | 6 ++---- src/opencl_ntlmv2_fmt_plug.c | 4 +++- src/wow_srp_fmt_plug.c | 4 ++++ 8 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/MSCHAPv2_bs_fmt_plug.c b/src/MSCHAPv2_bs_fmt_plug.c index 7a289f211e3..3494b16f8e7 100644 --- a/src/MSCHAPv2_bs_fmt_plug.c +++ b/src/MSCHAPv2_bs_fmt_plug.c @@ -281,13 +281,11 @@ static char *prepare(char *split_fields[10], struct fmt_main *pFmt) } } } - else if (split_fields[0] && split_fields[3] && split_fields[4] && split_fields[5] && - strlen(split_fields[3]) == CHALLENGE_LENGTH/2 && + else if (strlen(split_fields[3]) == CHALLENGE_LENGTH/2 && strlen(split_fields[4]) == CIPHERTEXT_LENGTH && strlen(split_fields[5]) == CHALLENGE_LENGTH/2) ret = prepare_long(split_fields); - else if (split_fields[0] && split_fields[3] && split_fields[4] && - strlen(split_fields[3]) == CHALLENGE_LENGTH/4 && + else if (strlen(split_fields[3]) == CHALLENGE_LENGTH/4 && strlen(split_fields[4]) == CIPHERTEXT_LENGTH) ret = prepare_short(split_fields); else diff --git a/src/NETLMv2_fmt_plug.c b/src/NETLMv2_fmt_plug.c index a0fd44f8751..e04981d0045 100644 --- a/src/NETLMv2_fmt_plug.c +++ b/src/NETLMv2_fmt_plug.c @@ -183,7 +183,9 @@ static char *prepare(char *split_fields[10], struct fmt_main *self) if (!strncmp(split_fields[1], FORMAT_TAG, FORMAT_TAG_LEN)) return split_fields[1]; - if (!login || !uid || !srv_challenge || !nethashv2 || !cli_challenge) + if (!login[0] || !strcmp(login, "?")) + return split_fields[1]; + if (!srv_challenge[0] || !nethashv2[0] || !cli_challenge[0]) return split_fields[1]; /* DOMAIN\USER: -or- USER::DOMAIN: */ diff --git a/src/NETNTLMv2_fmt_plug.c b/src/NETNTLMv2_fmt_plug.c index 43da16da8cb..ba0753cde24 100644 --- a/src/NETNTLMv2_fmt_plug.c +++ b/src/NETNTLMv2_fmt_plug.c @@ -197,7 +197,9 @@ static char *prepare(char *split_fields[10], struct fmt_main *self) if (!strncmp(split_fields[1], FORMAT_TAG, FORMAT_TAG_LEN)) return split_fields[1]; - if (!login || !uid || !srv_challenge || !nethashv2 || !cli_challenge) + if (!login[0] || !strcmp(login, "?")) + return split_fields[1]; + if (!srv_challenge[0] || !nethashv2[0] || !cli_challenge[0]) return split_fields[1]; /* DOMAIN\USER: -or- USER::DOMAIN: */ diff --git a/src/asaMD5_fmt_plug.c b/src/asaMD5_fmt_plug.c index 8294ee9c59f..b35948fff81 100644 --- a/src/asaMD5_fmt_plug.c +++ b/src/asaMD5_fmt_plug.c @@ -103,7 +103,7 @@ static char *prepare(char *split_fields[10], struct fmt_main *self) return split_fields[1]; if (!valid(split_fields[1], self)) { - if (split_fields[1] && strlen(split_fields[1]) == 16) { + if (strlen(split_fields[1]) == 16) { char username[4+1] = ""; strncat(username, split_fields[0], 4); diff --git a/src/dynamic_fmt.c b/src/dynamic_fmt.c index 87a65f0ad51..be1303b53d5 100644 --- a/src/dynamic_fmt.c +++ b/src/dynamic_fmt.c @@ -1138,7 +1138,7 @@ static char *prepare(char *split_fields[10], struct fmt_main *pFmt) // at this point max length is still < 512. 491 + strlen($dynamic_xxxxx$) is 506 if (pPriv->nUserName && !strstr(cpBuilding, "$$U")) { - if (split_fields[0] && split_fields[0][0] && strcmp(split_fields[0], "?")) { + if (split_fields[0][0] && strcmp(split_fields[0], "?")) { char *userName=split_fields[0], *cp; static char ct[1024]; // assume field[0] is in format: username OR DOMAIN\\username If we find a \\, then use the username 'following' it. @@ -1154,7 +1154,7 @@ static char *prepare(char *split_fields[10], struct fmt_main *pFmt) for (i = 0; i < 10; ++i) { if (pPriv->FldMask&(MGF_FLDx_BIT<