diff --git a/docs/changes.txt b/docs/changes.txt index 2211c79e5..0c6023a1f 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -9,6 +9,7 @@ - Added support for showing all user names with --show and --left if --username was specified - Added support for loading hccapx files - Added support for GPU temperature management on cygwin build +- Added support for automatic merge of LM halfes when --show and --left is used ## ## Algorithms diff --git a/include/types.h b/include/types.h index 69a1f622c..3ed9d4f76 100644 --- a/include/types.h +++ b/include/types.h @@ -338,38 +338,39 @@ typedef enum opti_type typedef enum opts_type { - OPTS_TYPE_PT_UNICODE = (1 << 0), - OPTS_TYPE_PT_UPPER = (1 << 1), - OPTS_TYPE_PT_LOWER = (1 << 2), - OPTS_TYPE_PT_ADD01 = (1 << 3), - OPTS_TYPE_PT_ADD02 = (1 << 4), - OPTS_TYPE_PT_ADD80 = (1 << 5), - OPTS_TYPE_PT_ADDBITS14 = (1 << 6), - OPTS_TYPE_PT_ADDBITS15 = (1 << 7), - OPTS_TYPE_PT_GENERATE_LE = (1 << 8), - OPTS_TYPE_PT_GENERATE_BE = (1 << 9), - OPTS_TYPE_PT_NEVERCRACK = (1 << 10), // if we want all possible results - OPTS_TYPE_PT_BITSLICE = (1 << 11), - OPTS_TYPE_PT_ALWAYS_ASCII = (1 << 12), - OPTS_TYPE_ST_UNICODE = (1 << 13), - OPTS_TYPE_ST_UPPER = (1 << 14), - OPTS_TYPE_ST_LOWER = (1 << 15), - OPTS_TYPE_ST_ADD01 = (1 << 16), - OPTS_TYPE_ST_ADD02 = (1 << 17), - OPTS_TYPE_ST_ADD80 = (1 << 18), - OPTS_TYPE_ST_ADDBITS14 = (1 << 19), - OPTS_TYPE_ST_ADDBITS15 = (1 << 20), - OPTS_TYPE_ST_GENERATE_LE = (1 << 21), - OPTS_TYPE_ST_GENERATE_BE = (1 << 22), - OPTS_TYPE_ST_HEX = (1 << 23), - OPTS_TYPE_ST_BASE64 = (1 << 24), - OPTS_TYPE_ST_HASH_MD5 = (1 << 25), - OPTS_TYPE_HASH_COPY = (1 << 26), - OPTS_TYPE_HOOK12 = (1 << 27), - OPTS_TYPE_HOOK23 = (1 << 28), - OPTS_TYPE_INIT2 = (1 << 29), - OPTS_TYPE_LOOP2 = (1 << 30), - OPTS_TYPE_BINARY_HASHFILE = (1 << 31), + OPTS_TYPE_PT_UNICODE = (1ULL << 0), + OPTS_TYPE_PT_UPPER = (1ULL << 1), + OPTS_TYPE_PT_LOWER = (1ULL << 2), + OPTS_TYPE_PT_ADD01 = (1ULL << 3), + OPTS_TYPE_PT_ADD02 = (1ULL << 4), + OPTS_TYPE_PT_ADD80 = (1ULL << 5), + OPTS_TYPE_PT_ADDBITS14 = (1ULL << 6), + OPTS_TYPE_PT_ADDBITS15 = (1ULL << 7), + OPTS_TYPE_PT_GENERATE_LE = (1ULL << 8), + OPTS_TYPE_PT_GENERATE_BE = (1ULL << 9), + OPTS_TYPE_PT_NEVERCRACK = (1ULL << 10), // if we want all possible results + OPTS_TYPE_PT_BITSLICE = (1ULL << 11), + OPTS_TYPE_PT_ALWAYS_ASCII = (1ULL << 12), + OPTS_TYPE_ST_UNICODE = (1ULL << 13), + OPTS_TYPE_ST_UPPER = (1ULL << 14), + OPTS_TYPE_ST_LOWER = (1ULL << 15), + OPTS_TYPE_ST_ADD01 = (1ULL << 16), + OPTS_TYPE_ST_ADD02 = (1ULL << 17), + OPTS_TYPE_ST_ADD80 = (1ULL << 18), + OPTS_TYPE_ST_ADDBITS14 = (1ULL << 19), + OPTS_TYPE_ST_ADDBITS15 = (1ULL << 20), + OPTS_TYPE_ST_GENERATE_LE = (1ULL << 21), + OPTS_TYPE_ST_GENERATE_BE = (1ULL << 22), + OPTS_TYPE_ST_HEX = (1ULL << 23), + OPTS_TYPE_ST_BASE64 = (1ULL << 24), + OPTS_TYPE_ST_HASH_MD5 = (1ULL << 25), + OPTS_TYPE_HASH_COPY = (1ULL << 26), + OPTS_TYPE_HASH_SPLIT = (1ULL << 27), + OPTS_TYPE_HOOK12 = (1ULL << 28), + OPTS_TYPE_HOOK23 = (1ULL << 29), + OPTS_TYPE_INIT2 = (1ULL << 30), + OPTS_TYPE_LOOP2 = (1ULL << 31), + OPTS_TYPE_BINARY_HASHFILE = (1ULL << 32), } opts_type_t; @@ -677,10 +678,29 @@ typedef struct user } user_t; +typedef enum split_origin +{ + SPLIT_ORIGIN_NONE = 0, + SPLIT_ORIGIN_LEFT = 1, + SPLIT_ORIGIN_RIGHT = 2, + +} split_origin_t; + +typedef struct split +{ + // some hashes, like lm, are split. this id point to the other hash of the group + + int split_group; + int split_neighbor; + int split_origin; + +} split_t; + typedef struct hashinfo { - user_t *user; - char *orighash; + user_t *user; + char *orighash; + split_t *split; } hashinfo_t; @@ -759,7 +779,7 @@ struct hashconfig u32 hash_type; u32 salt_type; u32 attack_exec; - u32 opts_type; + u64 opts_type; u32 kern_type; u32 dgst_size; u32 opti_type; @@ -1247,7 +1267,7 @@ typedef struct potfile_ctx { bool enabled; - bool keep_all_usernames; + bool keep_all_hashes; FILE *fp; char *filename; diff --git a/src/hashes.c b/src/hashes.c index 8b9cc71eb..4789dd96f 100644 --- a/src/hashes.c +++ b/src/hashes.c @@ -579,7 +579,7 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) void *esalts_buf = NULL; void *hook_salts_buf = NULL; - if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY)) + if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) || (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)) { u32 hash_pos; @@ -591,7 +591,7 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) if (user_options->username == true) { - hash_info->user = (user_t*) hcmalloc (sizeof (user_t)); + hash_info->user = (user_t *) hcmalloc (sizeof (user_t)); } if (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) @@ -602,6 +602,10 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) } } + if (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT) + { + hash_info->split = (split_t *) hcmalloc (sizeof (split_t)); + } } } @@ -789,6 +793,9 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) if (parser_status == PARSER_OK) { + hashes_buf[hashes_cnt].hash_info->split->split_group = 0; + hashes_buf[hashes_cnt].hash_info->split->split_origin = SPLIT_ORIGIN_LEFT; + hashes_cnt++; } else @@ -800,6 +807,9 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) if (parser_status == PARSER_OK) { + hashes_buf[hashes_cnt].hash_info->split->split_group = 0; + hashes_buf[hashes_cnt].hash_info->split->split_origin = SPLIT_ORIGIN_RIGHT; + hashes_cnt++; } else @@ -813,6 +823,9 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) if (parser_status == PARSER_OK) { + hashes_buf[hashes_cnt].hash_info->split->split_group = 0; + hashes_buf[hashes_cnt].hash_info->split->split_origin = SPLIT_ORIGIN_NONE; + hashes_cnt++; } else @@ -984,6 +997,9 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) continue; } + hashes_buf[hashes_cnt].hash_info->split->split_group = line_num; + hashes_buf[hashes_cnt].hash_info->split->split_origin = SPLIT_ORIGIN_LEFT; + hashes_cnt++; parser_status = hashconfig->parse_func ((u8 *) hash_buf + 16, 16, &hashes_buf[hashes_cnt], hashconfig); @@ -995,6 +1011,9 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) continue; } + hashes_buf[hashes_cnt].hash_info->split->split_group = line_num; + hashes_buf[hashes_cnt].hash_info->split->split_origin = SPLIT_ORIGIN_RIGHT; + hashes_cnt++; } else @@ -1008,6 +1027,9 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) continue; } + hashes_buf[hashes_cnt].hash_info->split->split_group = line_num; + hashes_buf[hashes_cnt].hash_info->split->split_origin = SPLIT_ORIGIN_NONE; + hashes_cnt++; } } @@ -1070,6 +1092,33 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx) EVENT (EVENT_HASHLIST_SORT_HASH_POST); } + if (hashconfig->hash_mode == 3000) + { + // update split split_neighbor after sorting + // see https://github.com/hashcat/hashcat/issues/1034 for good examples for testing + + for (u32 i = 0; i < hashes_cnt; i++) + { + split_t *split1 = hashes_buf[i].hash_info->split; + + if (split1->split_origin != SPLIT_ORIGIN_LEFT) continue; + + for (u32 j = 0; j < hashes_cnt; j++) + { + split_t *split2 = hashes_buf[j].hash_info->split; + + if (split2->split_origin != SPLIT_ORIGIN_RIGHT) continue; + + if (split1->split_group != split2->split_group) continue; + + split1->split_neighbor = j; + split2->split_neighbor = i; + + break; + } + } + } + return 0; } @@ -1093,7 +1142,7 @@ int hashes_init_stage2 (hashcat_ctx_t *hashcat_ctx) for (u32 hashes_pos = 1; hashes_pos < hashes_cnt; hashes_pos++) { - if (potfile_ctx->keep_all_usernames == true) + if (potfile_ctx->keep_all_hashes == true) { // do not sort, because we need to keep all hashes in this particular case } @@ -1170,7 +1219,7 @@ int hashes_init_stage2 (hashcat_ctx_t *hashcat_ctx) hashinfo_t **hash_info = NULL; - if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY)) + if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) || (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)) { hash_info = (hashinfo_t **) hccalloc (hashes_cnt, sizeof (hashinfo_t *)); } @@ -1221,7 +1270,7 @@ int hashes_init_stage2 (hashcat_ctx_t *hashcat_ctx) hashes_buf[0].digest = digests_buf_new_ptr; - if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY)) + if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) || (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)) { hash_info[0] = hashes_buf[0].hash_info; } @@ -1290,7 +1339,7 @@ int hashes_init_stage2 (hashcat_ctx_t *hashcat_ctx) hashes_buf[hashes_pos].digest = digests_buf_new_ptr; - if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY)) + if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) || (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)) { hash_info[hashes_pos] = hashes_buf[hashes_pos].hash_info; } @@ -1481,6 +1530,11 @@ void hashes_destroy (hashcat_ctx_t *hashcat_ctx) { hcfree (hashes->hash_info[hash_pos]->orighash); } + + if (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT) + { + hcfree (hashes->hash_info[hash_pos]->split); + } } } diff --git a/src/interface.c b/src/interface.c index 052352ddc..7a88d3f4b 100644 --- a/src/interface.c +++ b/src/interface.c @@ -14860,7 +14860,7 @@ int ascii_digest (hashcat_ctx_t *hashcat_ctx, char *out_buf, const size_t out_le const u32 hash_type = hashconfig->hash_type; const u32 hash_mode = hashconfig->hash_mode; const u32 salt_type = hashconfig->salt_type; - const u32 opts_type = hashconfig->opts_type; + const u64 opts_type = hashconfig->opts_type; const u32 opti_type = hashconfig->opti_type; const u32 dgst_size = hashconfig->dgst_size; @@ -19563,7 +19563,8 @@ int hashconfig_init (hashcat_ctx_t *hashcat_ctx) hashconfig->opts_type = OPTS_TYPE_PT_GENERATE_LE | OPTS_TYPE_PT_UPPER | OPTS_TYPE_PT_BITSLICE - | OPTS_TYPE_PT_ALWAYS_ASCII; + | OPTS_TYPE_PT_ALWAYS_ASCII + | OPTS_TYPE_HASH_SPLIT; hashconfig->kern_type = KERN_TYPE_LM; hashconfig->dgst_size = DGST_SIZE_4_4; // originally DGST_SIZE_4_2 hashconfig->parse_func = lm_parse_hash; diff --git a/src/opencl.c b/src/opencl.c index 27104b873..bfc8f0693 100644 --- a/src/opencl.c +++ b/src/opencl.c @@ -134,7 +134,7 @@ static void generate_cached_kernel_filename (const u32 attack_exec, const u32 at } } -static void generate_source_kernel_mp_filename (const u32 opti_type, const u32 opts_type, char *shared_dir, char *source_file) +static void generate_source_kernel_mp_filename (const u32 opti_type, const u64 opts_type, char *shared_dir, char *source_file) { if ((opti_type & OPTI_TYPE_BRUTE_FORCE) && (opts_type & OPTS_TYPE_PT_GENERATE_BE)) { @@ -146,7 +146,7 @@ static void generate_source_kernel_mp_filename (const u32 opti_type, const u32 o } } -static void generate_cached_kernel_mp_filename (const u32 opti_type, const u32 opts_type, char *profile_dir, const char *device_name_chksum, char *cached_file) +static void generate_cached_kernel_mp_filename (const u32 opti_type, const u64 opts_type, char *profile_dir, const char *device_name_chksum, char *cached_file) { if ((opti_type & OPTI_TYPE_BRUTE_FORCE) && (opts_type & OPTS_TYPE_PT_GENERATE_BE)) { diff --git a/src/potfile.c b/src/potfile.c index 6a44aae9a..e3461c991 100644 --- a/src/potfile.c +++ b/src/potfile.c @@ -87,15 +87,25 @@ int potfile_init (hashcat_ctx_t *hashcat_ctx) potfile_ctx->fp = NULL; } - // keep all usernames and hashes if --username was combined with --left or --show + // keep all hashes if --username was combined with --left or --show - potfile_ctx->keep_all_usernames = false; + potfile_ctx->keep_all_hashes = false; if (user_options->username == true) { if ((user_options->show == true) || (user_options->left == true)) { - potfile_ctx->keep_all_usernames = true; + potfile_ctx->keep_all_hashes = true; + } + } + + // keep all hashes if -m 3000 was combined with --left or --show + + if (user_options->hash_mode == 3000) + { + if ((user_options->show == true) || (user_options->left == true)) + { + potfile_ctx->keep_all_hashes = true; } } @@ -363,7 +373,7 @@ int potfile_remove_parse (hashcat_ctx_t *hashcat_ctx) if (parser_status == PARSER_OK) { - if (potfile_ctx->keep_all_usernames == true) + if (potfile_ctx->keep_all_hashes == true) { potfile_update_hashes (hashcat_ctx, &hash_buf, hashes_buf, hashes_cnt, sort_by_hash_no_salt, NULL, 0); } @@ -489,7 +499,7 @@ int potfile_remove_parse (hashcat_ctx_t *hashcat_ctx) { if (hashconfig->is_salted) { - if (potfile_ctx->keep_all_usernames == true) + if (potfile_ctx->keep_all_hashes == true) { potfile_update_hashes (hashcat_ctx, &hash_buf, hashes_buf, hashes_cnt, sort_by_hash, line_pw_buf, line_pw_len); @@ -500,7 +510,7 @@ int potfile_remove_parse (hashcat_ctx_t *hashcat_ctx) } else { - if (potfile_ctx->keep_all_usernames == true) + if (potfile_ctx->keep_all_hashes == true) { potfile_update_hashes (hashcat_ctx, &hash_buf, hashes_buf, hashes_cnt, sort_by_hash_no_salt, line_pw_buf, line_pw_len); @@ -541,6 +551,7 @@ int potfile_remove_parse (hashcat_ctx_t *hashcat_ctx) int potfile_handle_show (hashcat_ctx_t *hashcat_ctx) { + hashconfig_t *hashconfig = hashcat_ctx->hashconfig; hashes_t *hashes = hashcat_ctx->hashes; potfile_ctx_t *potfile_ctx = hashcat_ctx->potfile_ctx; @@ -549,54 +560,173 @@ int potfile_handle_show (hashcat_ctx_t *hashcat_ctx) u32 salts_cnt = hashes->salts_cnt; salt_t *salts_buf = hashes->salts_buf; - for (u32 salt_idx = 0; salt_idx < salts_cnt; salt_idx++) + if (hashconfig->hash_mode == 3000) { - salt_t *salt_buf = salts_buf + salt_idx; - - u32 digests_cnt = salt_buf->digests_cnt; - - for (u32 digest_idx = 0; digest_idx < digests_cnt; digest_idx++) + for (u32 salt_idx = 0; salt_idx < salts_cnt; salt_idx++) { - const u32 hashes_idx = salt_buf->digests_offset + digest_idx; + salt_t *salt_buf = salts_buf + salt_idx; - u32 *digests_shown = hashes->digests_shown; + u32 digests_cnt = salt_buf->digests_cnt; - if (digests_shown[hashes_idx] == 0) continue; - - u8 *out_buf = potfile_ctx->out_buf; - - out_buf[0] = 0; - - ascii_digest (hashcat_ctx, (char *) out_buf, HCBUFSIZ_LARGE, salt_idx, digest_idx); - - hash_t *hash = &hashes_buf[hashes_idx]; - - // user - unsigned char *username = NULL; - - u32 user_len = 0; - - if (hash->hash_info != NULL) + for (u32 digest_idx = 0; digest_idx < digests_cnt; digest_idx++) { - user_t *user = hash->hash_info->user; + const u32 hashes_idx = salt_buf->digests_offset + digest_idx; - if (user) + u32 *digests_shown = hashes->digests_shown; + + hash_t *hash1 = &hashes_buf[hashes_idx]; + hash_t *hash2 = NULL; + + int split_neighbor = -1; + + // find out if at least one of the parts has been cracked + + if (hash1->hash_info->split->split_origin == SPLIT_ORIGIN_LEFT) { - username = (unsigned char *) (user->user_name); + split_neighbor = hash1->hash_info->split->split_neighbor; - user_len = user->user_len; + hash2 = &hashes_buf[split_neighbor]; - username[user_len] = 0; + if ((digests_shown[hashes_idx] == 0) && (digests_shown[split_neighbor] == 0)) continue; } + else if (hash1->hash_info->split->split_origin == SPLIT_ORIGIN_NONE) + { + if (digests_shown[hashes_idx] == 0) continue; + } + else + { + // SPLIT_ORIGIN_RIGHT are not handled this way + + continue; + } + + u8 *out_buf = potfile_ctx->out_buf; + + out_buf[0] = 0; + + ascii_digest (hashcat_ctx, (char *) out_buf + 0, HCBUFSIZ_LARGE - 0, salt_idx, digest_idx); + + if (hash2) + { + ascii_digest (hashcat_ctx, (char *) out_buf + 16, HCBUFSIZ_LARGE - 16, salt_idx, split_neighbor); + } + + // user + unsigned char *username = NULL; + + u32 user_len = 0; + + if (hash1->hash_info != NULL) + { + user_t *user = hash1->hash_info->user; + + if (user) + { + username = (unsigned char *) (user->user_name); + + user_len = user->user_len; + + username[user_len] = 0; + } + } + + u8 *tmp_buf = potfile_ctx->tmp_buf; + + tmp_buf[0] = 0; + + u8 mixed_buf[20] = { 0 }; + + u8 mixed_len = 0; + + if (hash1) + { + if (digests_shown[hashes_idx] == 1) + { + memcpy (mixed_buf + mixed_len, hash1->pw_buf, hash1->pw_len); + + mixed_len += hash1->pw_len; + } + else + { + memcpy (mixed_buf + mixed_len, LM_MASKED_PLAIN, strlen (LM_MASKED_PLAIN)); + + mixed_len += strlen (LM_MASKED_PLAIN); + } + } + + if (hash2) + { + if (digests_shown[split_neighbor] == 1) + { + memcpy (mixed_buf + mixed_len, hash2->pw_buf, hash2->pw_len); + + mixed_len += hash2->pw_len; + } + else + { + memcpy (mixed_buf + mixed_len, LM_MASKED_PLAIN, strlen (LM_MASKED_PLAIN)); + + mixed_len += strlen (LM_MASKED_PLAIN); + } + } + + const int tmp_len = outfile_write (hashcat_ctx, (char *) out_buf, (u8 *) mixed_buf, mixed_len, 0, username, user_len, (char *) tmp_buf); + + EVENT_DATA (EVENT_POTFILE_HASH_SHOW, tmp_buf, tmp_len); } + } + } + else + { + for (u32 salt_idx = 0; salt_idx < salts_cnt; salt_idx++) + { + salt_t *salt_buf = salts_buf + salt_idx; - u8 *tmp_buf = potfile_ctx->tmp_buf; + u32 digests_cnt = salt_buf->digests_cnt; - tmp_buf[0] = 0; + for (u32 digest_idx = 0; digest_idx < digests_cnt; digest_idx++) + { + const u32 hashes_idx = salt_buf->digests_offset + digest_idx; - const int tmp_len = outfile_write (hashcat_ctx, (char *) out_buf, (u8 *) hash->pw_buf, hash->pw_len, 0, username, user_len, (char *) tmp_buf); + u32 *digests_shown = hashes->digests_shown; - EVENT_DATA (EVENT_POTFILE_HASH_SHOW, tmp_buf, tmp_len); + if (digests_shown[hashes_idx] == 0) continue; + + hash_t *hash = &hashes_buf[hashes_idx]; + + u8 *out_buf = potfile_ctx->out_buf; + + out_buf[0] = 0; + + ascii_digest (hashcat_ctx, (char *) out_buf, HCBUFSIZ_LARGE, salt_idx, digest_idx); + + // user + unsigned char *username = NULL; + + u32 user_len = 0; + + if (hash->hash_info != NULL) + { + user_t *user = hash->hash_info->user; + + if (user) + { + username = (unsigned char *) (user->user_name); + + user_len = user->user_len; + + username[user_len] = 0; + } + } + + u8 *tmp_buf = potfile_ctx->tmp_buf; + + tmp_buf[0] = 0; + + const int tmp_len = outfile_write (hashcat_ctx, (char *) out_buf, (u8 *) hash->pw_buf, hash->pw_len, 0, username, user_len, (char *) tmp_buf); + + EVENT_DATA (EVENT_POTFILE_HASH_SHOW, tmp_buf, tmp_len); + } } } @@ -605,6 +735,7 @@ int potfile_handle_show (hashcat_ctx_t *hashcat_ctx) int potfile_handle_left (hashcat_ctx_t *hashcat_ctx) { + hashconfig_t *hashconfig = hashcat_ctx->hashconfig; hashes_t *hashes = hashcat_ctx->hashes; potfile_ctx_t *potfile_ctx = hashcat_ctx->potfile_ctx; @@ -613,54 +744,137 @@ int potfile_handle_left (hashcat_ctx_t *hashcat_ctx) u32 salts_cnt = hashes->salts_cnt; salt_t *salts_buf = hashes->salts_buf; - for (u32 salt_idx = 0; salt_idx < salts_cnt; salt_idx++) + if (hashconfig->hash_mode == 3000) { - salt_t *salt_buf = salts_buf + salt_idx; - - u32 digests_cnt = salt_buf->digests_cnt; - - for (u32 digest_idx = 0; digest_idx < digests_cnt; digest_idx++) + for (u32 salt_idx = 0; salt_idx < salts_cnt; salt_idx++) { - const u32 hashes_idx = salt_buf->digests_offset + digest_idx; + salt_t *salt_buf = salts_buf + salt_idx; - u32 *digests_shown = hashes->digests_shown; + u32 digests_cnt = salt_buf->digests_cnt; - if (digests_shown[hashes_idx] == 1) continue; - - u8 *out_buf = potfile_ctx->out_buf; - - out_buf[0] = 0; - - ascii_digest (hashcat_ctx, (char *) out_buf, HCBUFSIZ_LARGE, salt_idx, digest_idx); - - hash_t *hash = &hashes_buf[hashes_idx]; - - // user - unsigned char *username = NULL; - - u32 user_len = 0; - - if (hash->hash_info != NULL) + for (u32 digest_idx = 0; digest_idx < digests_cnt; digest_idx++) { - user_t *user = hash->hash_info->user; + const u32 hashes_idx = salt_buf->digests_offset + digest_idx; - if (user) + u32 *digests_shown = hashes->digests_shown; + + hash_t *hash1 = &hashes_buf[hashes_idx]; + hash_t *hash2 = NULL; + + int split_neighbor = -1; + + // find out if at least one of the parts has been cracked + + if (hash1->hash_info->split->split_origin == SPLIT_ORIGIN_LEFT) { - username = (unsigned char *) (user->user_name); + split_neighbor = hash1->hash_info->split->split_neighbor; - user_len = user->user_len; + hash2 = &hashes_buf[split_neighbor]; - username[user_len] = 0; + if ((digests_shown[hashes_idx] == 1) && (digests_shown[split_neighbor] == 1)) continue; } + else if (hash1->hash_info->split->split_origin == SPLIT_ORIGIN_NONE) + { + if (digests_shown[hashes_idx] == 1) continue; + } + else + { + // SPLIT_ORIGIN_RIGHT are not handled this way + + continue; + } + + u8 *out_buf = potfile_ctx->out_buf; + + out_buf[0] = 0; + + ascii_digest (hashcat_ctx, (char *) out_buf + 0, HCBUFSIZ_LARGE - 0, salt_idx, digest_idx); + + if (hash2) + { + ascii_digest (hashcat_ctx, (char *) out_buf + 16, HCBUFSIZ_LARGE - 16, salt_idx, split_neighbor); + } + + // user + unsigned char *username = NULL; + + u32 user_len = 0; + + if (hash1->hash_info != NULL) + { + user_t *user = hash1->hash_info->user; + + if (user) + { + username = (unsigned char *) (user->user_name); + + user_len = user->user_len; + + username[user_len] = 0; + } + } + + u8 *tmp_buf = potfile_ctx->tmp_buf; + + tmp_buf[0] = 0; + + const int tmp_len = outfile_write (hashcat_ctx, (char *) out_buf, NULL, 0, 0, username, user_len, (char *) tmp_buf); + + EVENT_DATA (EVENT_POTFILE_HASH_LEFT, tmp_buf, tmp_len); } + } + } + else + { + for (u32 salt_idx = 0; salt_idx < salts_cnt; salt_idx++) + { + salt_t *salt_buf = salts_buf + salt_idx; - u8 *tmp_buf = potfile_ctx->tmp_buf; + u32 digests_cnt = salt_buf->digests_cnt; - tmp_buf[0] = 0; + for (u32 digest_idx = 0; digest_idx < digests_cnt; digest_idx++) + { + const u32 hashes_idx = salt_buf->digests_offset + digest_idx; - const int tmp_len = outfile_write (hashcat_ctx, (char *) out_buf, NULL, 0, 0, username, user_len, (char *) tmp_buf); + u32 *digests_shown = hashes->digests_shown; - EVENT_DATA (EVENT_POTFILE_HASH_LEFT, tmp_buf, tmp_len); + if (digests_shown[hashes_idx] == 1) continue; + + u8 *out_buf = potfile_ctx->out_buf; + + out_buf[0] = 0; + + ascii_digest (hashcat_ctx, (char *) out_buf, HCBUFSIZ_LARGE, salt_idx, digest_idx); + + hash_t *hash = &hashes_buf[hashes_idx]; + + // user + unsigned char *username = NULL; + + u32 user_len = 0; + + if (hash->hash_info != NULL) + { + user_t *user = hash->hash_info->user; + + if (user) + { + username = (unsigned char *) (user->user_name); + + user_len = user->user_len; + + username[user_len] = 0; + } + } + + u8 *tmp_buf = potfile_ctx->tmp_buf; + + tmp_buf[0] = 0; + + const int tmp_len = outfile_write (hashcat_ctx, (char *) out_buf, NULL, 0, 0, username, user_len, (char *) tmp_buf); + + EVENT_DATA (EVENT_POTFILE_HASH_LEFT, tmp_buf, tmp_len); + } } }