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; hash_t *hashes_buf = hashes->hashes_buf; u32 salts_cnt = hashes->salts_cnt; salt_t *salts_buf = hashes->salts_buf; if (hashconfig->hash_mode == 3000) { for (u32 salt_idx = 0; salt_idx < salts_cnt; salt_idx++) { 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++) { const u32 hashes_idx = salt_buf->digests_offset + digest_idx; 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) { split_neighbor = hash1->hash_info->split->split_neighbor; hash2 = &hashes_buf[split_neighbor]; 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; 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; u32 digests_cnt = salt_buf->digests_cnt; for (u32 digest_idx = 0; digest_idx < digests_cnt; digest_idx++) { const u32 hashes_idx = salt_buf->digests_offset + digest_idx; u32 *digests_shown = hashes->digests_shown; 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); } } } return 0; }
void check_hash (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_param, plain_t *plain) { debugfile_ctx_t *debugfile_ctx = hashcat_ctx->debugfile_ctx; loopback_ctx_t *loopback_ctx = hashcat_ctx->loopback_ctx; hashes_t *hashes = hashcat_ctx->hashes; const u32 salt_pos = plain->salt_pos; const u32 digest_pos = plain->digest_pos; // relative // hash u8 *out_buf = hashes->out_buf; out_buf[0] = 0; ascii_digest (hashcat_ctx, (char *) out_buf, HCBUFSIZ_LARGE, salt_pos, digest_pos); // plain u32 plain_buf[64] = { 0 }; u8 *plain_ptr = (u8 *) plain_buf; int plain_len = 0; build_plain (hashcat_ctx, device_param, plain, plain_buf, &plain_len); // crackpos u64 crackpos = 0; build_crackpos (hashcat_ctx, device_param, plain, &crackpos); // debug u8 debug_rule_buf[RP_PASSWORD_SIZE] = { 0 }; int debug_rule_len = 0; // -1 error u8 debug_plain_ptr[RP_PASSWORD_SIZE] = { 0 }; int debug_plain_len = 0; build_debugdata (hashcat_ctx, device_param, plain, debug_rule_buf, &debug_rule_len, debug_plain_ptr, &debug_plain_len); // no need for locking, we're in a mutex protected function potfile_write_append (hashcat_ctx, (char *) out_buf, plain_ptr, plain_len); // outfile, can be either to file or stdout // if an error occurs opening the file, send to stdout as fallback // the fp gets opened for each cracked hash so that the user can modify (move) the outfile while hashcat runs outfile_write_open (hashcat_ctx); u8 *tmp_buf = hashes->tmp_buf; tmp_buf[0] = 0; const int tmp_len = outfile_write (hashcat_ctx, (char *) out_buf, plain_ptr, plain_len, crackpos, NULL, 0, (char *) tmp_buf); outfile_write_close (hashcat_ctx); EVENT_DATA (EVENT_CRACKER_HASH_CRACKED, tmp_buf, tmp_len); // if enabled, update also the loopback file if (loopback_ctx->fp != NULL) { loopback_write_append (hashcat_ctx, plain_ptr, plain_len); } // if enabled, update also the (rule) debug file if (debugfile_ctx->fp != NULL) { // the next check implies that: // - (user_options->attack_mode == ATTACK_MODE_STRAIGHT) // - debug_mode > 0 if ((debug_plain_len > 0) || (debug_rule_len > 0)) { debugfile_write_append (hashcat_ctx, debug_rule_buf, debug_rule_len, plain_ptr, plain_len, debug_plain_ptr, debug_plain_len); } } }
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; hash_t *hashes_buf = hashes->hashes_buf; u32 salts_cnt = hashes->salts_cnt; salt_t *salts_buf = hashes->salts_buf; if (hashconfig->hash_mode == 3000) { for (u32 salt_idx = 0; salt_idx < salts_cnt; salt_idx++) { 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++) { const u32 hashes_idx = salt_buf->digests_offset + digest_idx; 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) { split_neighbor = hash1->hash_info->split->split_neighbor; hash2 = &hashes_buf[split_neighbor]; 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; 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 (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; u32 digests_cnt = salt_buf->digests_cnt; for (u32 digest_idx = 0; digest_idx < digests_cnt; digest_idx++) { const u32 hashes_idx = salt_buf->digests_offset + digest_idx; u32 *digests_shown = hashes->digests_shown; 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; // special case for collider modes: we do not use the $HEX[] format within the hash itself // therefore we need to convert the $HEX[] password into hexadecimal (without "$HEX[" and "]") bool is_collider_hex_password = false; if ((hashconfig->hash_mode == 9710) || (hashconfig->hash_mode == 9810) || (hashconfig->hash_mode == 10410)) { if (is_hexify ((u8 *) hash->pw_buf, hash->pw_len) == true) { is_collider_hex_password = true; } } int tmp_len = 0; if (is_collider_hex_password == true) { u8 pass_unhexified[HCBUFSIZ_TINY] = { 0 }; u32 pass_unhexified_len = 0; pass_unhexified_len = exec_unhexify ((u8 *) hash->pw_buf, hash->pw_len, pass_unhexified, sizeof (pass_unhexified)); tmp_len = outfile_write (hashcat_ctx, (char *) out_buf, pass_unhexified, pass_unhexified_len, 0, username, user_len, (char *) tmp_buf); } else { 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); } } } return 0; }
int save_hash (hashcat_ctx_t *hashcat_ctx) { hashes_t *hashes = hashcat_ctx->hashes; hashconfig_t *hashconfig = hashcat_ctx->hashconfig; user_options_t *user_options = hashcat_ctx->user_options; const char *hashfile = hashes->hashfile; char *new_hashfile; char *old_hashfile; hc_asprintf (&new_hashfile, "%s.new", hashfile); hc_asprintf (&old_hashfile, "%s.old", hashfile); unlink (new_hashfile); char separator = hashconfig->separator; FILE *fp = fopen (new_hashfile, "wb"); if (fp == NULL) { event_log_error (hashcat_ctx, "%s: %s", new_hashfile, strerror (errno)); free (new_hashfile); free (old_hashfile); return -1; } if (lock_file (fp) == -1) { fclose (fp); event_log_error (hashcat_ctx, "%s: %s", new_hashfile, strerror (errno)); free (new_hashfile); free (old_hashfile); return -1; } u8 *out_buf = (u8 *) hcmalloc (HCBUFSIZ_LARGE); for (u32 salt_pos = 0; salt_pos < hashes->salts_cnt; salt_pos++) { if (hashes->salts_shown[salt_pos] == 1) continue; salt_t *salt_buf = &hashes->salts_buf[salt_pos]; for (u32 digest_pos = 0; digest_pos < salt_buf->digests_cnt; digest_pos++) { u32 idx = salt_buf->digests_offset + digest_pos; if (hashes->digests_shown[idx] == 1) continue; if (hashconfig->opts_type & OPTS_TYPE_BINARY_HASHFILE) { if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501)) { hccapx_t hccapx; to_hccapx_t (hashcat_ctx, &hccapx, salt_pos, digest_pos); hc_fwrite (&hccapx, sizeof (hccapx_t), 1, fp); } else { // TODO } } else { if (user_options->username == true) { user_t *user = hashes->hash_info[idx]->user; u32 i; for (i = 0; i < user->user_len; i++) fputc (user->user_name[i], fp); fputc (separator, fp); } out_buf[0] = 0; ascii_digest (hashcat_ctx, (char *) out_buf, HCBUFSIZ_LARGE, salt_pos, digest_pos); fprintf (fp, "%s" EOL, out_buf); } } } hcfree (out_buf); fflush (fp); fclose (fp); unlink (old_hashfile); if (rename (hashfile, old_hashfile) != 0) { event_log_error (hashcat_ctx, "Rename file '%s' to '%s': %s", hashfile, old_hashfile, strerror (errno)); free (new_hashfile); free (old_hashfile); return -1; } unlink (hashfile); if (rename (new_hashfile, hashfile) != 0) { event_log_error (hashcat_ctx, "Rename file '%s' to '%s': %s", new_hashfile, hashfile, strerror (errno)); free (new_hashfile); free (old_hashfile); return -1; } unlink (old_hashfile); free (new_hashfile); free (old_hashfile); return 0; }