int sort_by_hash_no_salt (const void *v1, const void *v2, void *v3) { const hash_t *h1 = (const hash_t *) v1; const hash_t *h2 = (const hash_t *) v2; const void *d1 = h1->digest; const void *d2 = h2->digest; return sort_by_digest_p0p1 (d1, d2, v3); }
int sort_by_hash (const void *v1, const void *v2, void *v3) { const hash_t *h1 = (const hash_t *) v1; const hash_t *h2 = (const hash_t *) v2; hashconfig_t *hashconfig = (hashconfig_t *) v3; if (hashconfig->is_salted == true) { const salt_t *s1 = h1->salt; const salt_t *s2 = h2->salt; int res = sort_by_salt (s1, s2); if (res != 0) return (res); } const void *d1 = h1->digest; const void *d2 = h2->digest; return sort_by_digest_p0p1 (d1, d2, v3); }
int hashes_init_stage2 (hashcat_ctx_t *hashcat_ctx) { hashconfig_t *hashconfig = hashcat_ctx->hashconfig; hashes_t *hashes = hashcat_ctx->hashes; user_options_t *user_options = hashcat_ctx->user_options; potfile_ctx_t *potfile_ctx = hashcat_ctx->potfile_ctx; hash_t *hashes_buf = hashes->hashes_buf; u32 hashes_cnt = hashes->hashes_cnt; /** * Remove duplicates */ EVENT (EVENT_HASHLIST_UNIQUE_HASH_PRE); u32 hashes_cnt_new = 1; for (u32 hashes_pos = 1; hashes_pos < hashes_cnt; hashes_pos++) { if (potfile_ctx->keep_all_hashes == true) { // do not sort, because we need to keep all hashes in this particular case } else if (hashconfig->is_salted == true) { if (sort_by_salt (hashes_buf[hashes_pos].salt, hashes_buf[hashes_pos - 1].salt) == 0) { if (sort_by_digest_p0p1 (hashes_buf[hashes_pos].digest, hashes_buf[hashes_pos - 1].digest, (void *) hashconfig) == 0) continue; } } else { if (sort_by_digest_p0p1 (hashes_buf[hashes_pos].digest, hashes_buf[hashes_pos - 1].digest, (void *) hashconfig) == 0) continue; } hash_t tmp; memcpy (&tmp, &hashes_buf[hashes_pos], sizeof (hash_t)); memcpy (&hashes_buf[hashes_cnt_new], &tmp, sizeof (hash_t)); hashes_cnt_new++; } for (u32 i = hashes_cnt_new; i < hashes->hashes_cnt; i++) { memset (&hashes_buf[i], 0, sizeof (hash_t)); } hashes_cnt = hashes_cnt_new; hashes->hashes_cnt = hashes_cnt; EVENT (EVENT_HASHLIST_UNIQUE_HASH_POST); /** * Now generate all the buffers required for later */ void *digests_buf_new = hccalloc (hashes_cnt, hashconfig->dgst_size); salt_t *salts_buf_new = NULL; void *esalts_buf_new = NULL; void *hook_salts_buf_new = NULL; if (hashconfig->is_salted == true) { salts_buf_new = (salt_t *) hccalloc (hashes_cnt, sizeof (salt_t)); } else { salts_buf_new = (salt_t *) hccalloc (1, sizeof (salt_t)); } if (hashconfig->esalt_size > 0) { esalts_buf_new = hccalloc (hashes_cnt, hashconfig->esalt_size); } if (hashconfig->hook_salt_size > 0) { hook_salts_buf_new = hccalloc (hashes_cnt, hashconfig->hook_salt_size); } EVENT (EVENT_HASHLIST_SORT_SALT_PRE); u32 digests_cnt = hashes_cnt; u32 digests_done = 0; u32 *digests_shown = (u32 *) hccalloc (digests_cnt, sizeof (u32)); u32 *digests_shown_tmp = (u32 *) hccalloc (digests_cnt, sizeof (u32)); u32 salts_cnt = 0; u32 salts_done = 0; hashinfo_t **hash_info = NULL; 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 *)); } u32 *salts_shown = (u32 *) hccalloc (digests_cnt, sizeof (u32)); salt_t *salt_buf; { // copied from inner loop salt_buf = &salts_buf_new[salts_cnt]; memcpy (salt_buf, hashes_buf[0].salt, sizeof (salt_t)); hashes_buf[0].salt = salt_buf; if (hashconfig->hook_salt_size > 0) { char *hook_salts_buf_new_ptr = ((char *) hook_salts_buf_new) + (salts_cnt * hashconfig->hook_salt_size); memcpy (hook_salts_buf_new_ptr, hashes_buf[0].hook_salt, hashconfig->hook_salt_size); hashes_buf[0].hook_salt = hook_salts_buf_new_ptr; } salt_buf->digests_cnt = 0; salt_buf->digests_done = 0; salt_buf->digests_offset = 0; salts_cnt++; } salt_buf->digests_cnt++; char *digests_buf_new_ptr = ((char *) digests_buf_new) + (0 * hashconfig->dgst_size); memcpy (digests_buf_new_ptr, hashes_buf[0].digest, hashconfig->dgst_size); hashes_buf[0].digest = digests_buf_new_ptr; if (hashconfig->esalt_size > 0) { char *esalts_buf_new_ptr = ((char *) esalts_buf_new) + (0 * hashconfig->esalt_size); memcpy (esalts_buf_new_ptr, hashes_buf[0].esalt, hashconfig->esalt_size); hashes_buf[0].esalt = esalts_buf_new_ptr; } 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; } // copy from inner loop for (u32 hashes_pos = 1; hashes_pos < hashes_cnt; hashes_pos++) { if (hashconfig->is_salted == true) { if (sort_by_salt (hashes_buf[hashes_pos].salt, hashes_buf[hashes_pos - 1].salt) != 0) { salt_buf = &salts_buf_new[salts_cnt]; memcpy (salt_buf, hashes_buf[hashes_pos].salt, sizeof (salt_t)); hashes_buf[hashes_pos].salt = salt_buf; if (hashconfig->hook_salt_size > 0) { char *hook_salts_buf_new_ptr = ((char *) hook_salts_buf_new) + (salts_cnt * hashconfig->hook_salt_size); memcpy (hook_salts_buf_new_ptr, hashes_buf[hashes_pos].hook_salt, hashconfig->hook_salt_size); hashes_buf[hashes_pos].hook_salt = hook_salts_buf_new_ptr; } salt_buf->digests_cnt = 0; salt_buf->digests_done = 0; salt_buf->digests_offset = hashes_pos; salts_cnt++; } hashes_buf[hashes_pos].salt = salt_buf; if (hashconfig->hook_salt_size > 0) { char *hook_salts_buf_new_ptr = ((char *) hook_salts_buf_new) + (salts_cnt * hashconfig->hook_salt_size); hashes_buf[hashes_pos].hook_salt = hook_salts_buf_new_ptr; } } salt_buf->digests_cnt++; digests_buf_new_ptr = ((char *) digests_buf_new) + (hashes_pos * hashconfig->dgst_size); memcpy (digests_buf_new_ptr, hashes_buf[hashes_pos].digest, hashconfig->dgst_size); hashes_buf[hashes_pos].digest = digests_buf_new_ptr; if (hashconfig->esalt_size > 0) { char *esalts_buf_new_ptr = ((char *) esalts_buf_new) + (hashes_pos * hashconfig->esalt_size); memcpy (esalts_buf_new_ptr, hashes_buf[hashes_pos].esalt, hashconfig->esalt_size); hashes_buf[hashes_pos].esalt = esalts_buf_new_ptr; } 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; } } EVENT (EVENT_HASHLIST_SORT_SALT_POST); hcfree (hashes->digests_buf); hcfree (hashes->salts_buf); hcfree (hashes->esalts_buf); hcfree (hashes->hook_salts_buf); hashes->digests_cnt = digests_cnt; hashes->digests_done = digests_done; hashes->digests_buf = digests_buf_new; hashes->digests_shown = digests_shown; hashes->digests_shown_tmp = digests_shown_tmp; hashes->salts_cnt = salts_cnt; hashes->salts_done = salts_done; hashes->salts_buf = salts_buf_new; hashes->salts_shown = salts_shown; hashes->esalts_buf = esalts_buf_new; hashes->hook_salts_buf = hook_salts_buf_new; hashes->hash_info = hash_info; return 0; }
static int outfile_remove (hashcat_ctx_t *hashcat_ctx) { // some hash-dependent constants hashconfig_t *hashconfig = hashcat_ctx->hashconfig; hashes_t *hashes = hashcat_ctx->hashes; outcheck_ctx_t *outcheck_ctx = hashcat_ctx->outcheck_ctx; status_ctx_t *status_ctx = hashcat_ctx->status_ctx; user_options_t *user_options = hashcat_ctx->user_options; u32 dgst_size = hashconfig->dgst_size; u32 is_salted = hashconfig->is_salted; u32 esalt_size = hashconfig->esalt_size; u32 hash_mode = hashconfig->hash_mode; char separator = hashconfig->separator; char *root_directory = outcheck_ctx->root_directory; u32 outfile_check_timer = user_options->outfile_check_timer; // buffers hash_t hash_buf = { 0, 0, 0, 0, 0, NULL, 0 }; hash_buf.digest = hcmalloc (dgst_size); if (is_salted) hash_buf.salt = (salt_t *) hcmalloc (sizeof (salt_t)); if (esalt_size) hash_buf.esalt = (void *) hcmalloc (esalt_size); u32 digest_buf[64] = { 0 }; outfile_data_t *out_info = NULL; char **out_files = NULL; time_t folder_mtime = 0; int out_cnt = 0; u32 check_left = outfile_check_timer; // or 1 if we want to check it at startup while (status_ctx->shutdown_inner == false) { hc_sleep (1); if (status_ctx->devices_status != STATUS_RUNNING) continue; check_left--; if (check_left == 0) { hc_stat_t outfile_check_stat; if (hc_stat (root_directory, &outfile_check_stat) == 0) { u32 is_dir = S_ISDIR (outfile_check_stat.st_mode); if (is_dir == 1) { if (outfile_check_stat.st_mtime > folder_mtime) { char **out_files_new = scan_directory (root_directory); int out_cnt_new = count_dictionaries (out_files_new); outfile_data_t *out_info_new = NULL; if (out_cnt_new > 0) { out_info_new = (outfile_data_t *) hccalloc (out_cnt_new, sizeof (outfile_data_t)); for (int i = 0; i < out_cnt_new; i++) { out_info_new[i].file_name = out_files_new[i]; // check if there are files that we have seen/checked before (and not changed) for (int j = 0; j < out_cnt; j++) { if (strcmp (out_info[j].file_name, out_info_new[i].file_name) == 0) { hc_stat_t outfile_stat; if (hc_stat (out_info_new[i].file_name, &outfile_stat) == 0) { if (outfile_stat.st_ctime == out_info[j].ctime) { out_info_new[i].ctime = out_info[j].ctime; out_info_new[i].seek = out_info[j].seek; } } } } } } hcfree (out_info); hcfree (out_files); out_files = out_files_new; out_cnt = out_cnt_new; out_info = out_info_new; folder_mtime = outfile_check_stat.st_mtime; } for (int j = 0; j < out_cnt; j++) { FILE *fp = fopen (out_info[j].file_name, "rb"); if (fp != NULL) { //hc_thread_mutex_lock (status_ctx->mux_display); hc_stat_t outfile_stat; hc_fstat (fileno (fp), &outfile_stat); if (outfile_stat.st_ctime > out_info[j].ctime) { out_info[j].ctime = outfile_stat.st_ctime; out_info[j].seek = 0; } fseeko (fp, out_info[j].seek, SEEK_SET); char *line_buf = (char *) hcmalloc (HCBUFSIZ_LARGE); while (!feof (fp)) { char *ptr = fgets (line_buf, HCBUFSIZ_LARGE - 1, fp); if (ptr == NULL) break; size_t line_len = strlen (line_buf); if (line_len == 0) continue; size_t iter = MAX_CUT_TRIES; for (size_t i = line_len - 1; i && iter; i--, line_len--) { if (line_buf[i] != separator) continue; iter--; int parser_status = PARSER_OK; if ((hash_mode != 2500) && (hash_mode != 6800)) { parser_status = hashconfig->parse_func ((u8 *) line_buf, line_len - 1, &hash_buf, hashconfig); } u32 found = 0; if (parser_status == PARSER_OK) { for (u32 salt_pos = 0; (found == 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; (found == 0) && (digest_pos < salt_buf->digests_cnt); digest_pos++) { u32 idx = salt_buf->digests_offset + digest_pos; if (hashes->digests_shown[idx] == 1) continue; u32 cracked = 0; if (hash_mode == 6800) { if (i == salt_buf->salt_len) { cracked = (memcmp (line_buf, salt_buf->salt_buf, salt_buf->salt_len) == 0); } } else if (hash_mode == 2500) { // BSSID : MAC1 : MAC2 (:plain) if (i == (salt_buf->salt_len + 1 + 12 + 1 + 12)) { cracked = (memcmp (line_buf, salt_buf->salt_buf, salt_buf->salt_len) == 0); if (!cracked) continue; // now compare MAC1 and MAC2 too, since we have this additional info char *mac1_pos = line_buf + salt_buf->salt_len + 1; char *mac2_pos = mac1_pos + 12 + 1; wpa_t *wpas = (wpa_t *) hashes->esalts_buf; wpa_t *wpa = &wpas[salt_pos]; // compare hex string(s) vs binary MAC address(es) for (u32 mac_idx = 0, orig_mac_idx = 0; mac_idx < 6; mac_idx++, orig_mac_idx += 2) { if (wpa->orig_mac1[mac_idx] != hex_to_u8 ((const u8 *) &mac1_pos[orig_mac_idx])) { cracked = 0; break; } } // early skip ;) if (!cracked) continue; for (u32 mac_idx = 0, orig_mac_idx = 0; mac_idx < 6; mac_idx++, orig_mac_idx += 2) { if (wpa->orig_mac2[mac_idx] != hex_to_u8 ((const u8 *) &mac2_pos[orig_mac_idx])) { cracked = 0; break; } } } } else { char *digests_buf_ptr = (char *) hashes->digests_buf; memcpy (digest_buf, digests_buf_ptr + (hashes->salts_buf[salt_pos].digests_offset * dgst_size) + (digest_pos * dgst_size), dgst_size); cracked = (sort_by_digest_p0p1 (digest_buf, hash_buf.digest, hashconfig) == 0); } if (cracked == 1) { found = 1; hashes->digests_shown[idx] = 1; hashes->digests_done++; salt_buf->digests_done++; if (salt_buf->digests_done == salt_buf->digests_cnt) { hashes->salts_shown[salt_pos] = 1; hashes->salts_done++; if (hashes->salts_done == hashes->salts_cnt) mycracked (hashcat_ctx); } } } if (status_ctx->devices_status == STATUS_CRACKED) break; } } if (found) break; if (status_ctx->devices_status == STATUS_CRACKED) break; } if (status_ctx->devices_status == STATUS_CRACKED) break; } hcfree (line_buf); out_info[j].seek = ftello (fp); //hc_thread_mutex_unlock (status_ctx->mux_display); fclose (fp); } } } } check_left = outfile_check_timer; } } hcfree (hash_buf.esalt); hcfree (hash_buf.salt); hcfree (hash_buf.digest); hcfree (out_info); hcfree (out_files); return 0; }
static int outfile_remove (hashcat_ctx_t *hashcat_ctx) { // some hash-dependent constants hashconfig_t *hashconfig = hashcat_ctx->hashconfig; hashes_t *hashes = hashcat_ctx->hashes; outcheck_ctx_t *outcheck_ctx = hashcat_ctx->outcheck_ctx; status_ctx_t *status_ctx = hashcat_ctx->status_ctx; user_options_t *user_options = hashcat_ctx->user_options; u32 dgst_size = hashconfig->dgst_size; bool is_salted = hashconfig->is_salted; u32 esalt_size = hashconfig->esalt_size; u32 hook_salt_size = hashconfig->hook_salt_size; u32 hash_mode = hashconfig->hash_mode; char separator = hashconfig->separator; char *root_directory = outcheck_ctx->root_directory; u32 outfile_check_timer = user_options->outfile_check_timer; // buffers hash_t hash_buf = { 0, 0, 0, 0, 0, 0, NULL, 0 }; hash_buf.digest = hcmalloc (dgst_size); if (is_salted == true) hash_buf.salt = (salt_t *) hcmalloc (sizeof (salt_t)); if (esalt_size > 0) hash_buf.esalt = hcmalloc (esalt_size); if (hook_salt_size > 0) hash_buf.hook_salt = hcmalloc (hook_salt_size); u32 digest_buf[64] = { 0 }; outfile_data_t *out_info = NULL; char **out_files = NULL; time_t folder_mtime = 0; int out_cnt = 0; u32 check_left = outfile_check_timer; // or 1 if we want to check it at startup while (status_ctx->shutdown_inner == false) { sleep (1); if (status_ctx->devices_status != STATUS_RUNNING) continue; check_left--; if (check_left == 0) { if (hc_path_exist (root_directory) == true) { const bool is_dir = hc_path_is_directory (root_directory); if (is_dir == true) { struct stat outfile_check_stat; if (stat (root_directory, &outfile_check_stat) == -1) { event_log_error (hashcat_ctx, "%s: %s", root_directory, strerror (errno)); hcfree (out_files); hcfree (out_info); return -1; } if (outfile_check_stat.st_mtime > folder_mtime) { char **out_files_new = scan_directory (root_directory); int out_cnt_new = count_dictionaries (out_files_new); outfile_data_t *out_info_new = NULL; if (out_cnt_new > 0) { out_info_new = (outfile_data_t *) hccalloc (out_cnt_new, sizeof (outfile_data_t)); for (int i = 0; i < out_cnt_new; i++) { out_info_new[i].file_name = out_files_new[i]; // check if there are files that we have seen/checked before (and not changed) for (int j = 0; j < out_cnt; j++) { if (strcmp (out_info[j].file_name, out_info_new[i].file_name) == 0) { struct stat outfile_stat; if (stat (out_info_new[i].file_name, &outfile_stat) == 0) { if (outfile_stat.st_ctime == out_info[j].ctime) { out_info_new[i].ctime = out_info[j].ctime; out_info_new[i].seek = out_info[j].seek; } } } } } } hcfree (out_info); hcfree (out_files); out_files = out_files_new; out_cnt = out_cnt_new; out_info = out_info_new; folder_mtime = outfile_check_stat.st_mtime; } for (int j = 0; j < out_cnt; j++) { FILE *fp = fopen (out_info[j].file_name, "rb"); if (fp != NULL) { //hc_thread_mutex_lock (status_ctx->mux_display); struct stat outfile_stat; if (fstat (fileno (fp), &outfile_stat)) { fclose (fp); continue; } if (outfile_stat.st_ctime > out_info[j].ctime) { out_info[j].ctime = outfile_stat.st_ctime; out_info[j].seek = 0; } fseeko (fp, out_info[j].seek, SEEK_SET); char *line_buf = (char *) hcmalloc (HCBUFSIZ_LARGE); while (!feof (fp)) { char *ptr = fgets (line_buf, HCBUFSIZ_LARGE - 1, fp); if (ptr == NULL) break; size_t line_len = strlen (line_buf); if (line_len == 0) continue; size_t iter = 1; for (size_t i = line_len - 1; i && iter; i--, line_len--) { if (line_buf[i] != separator) continue; iter--; int parser_status = PARSER_OK; if ((hash_mode != 2500) && (hash_mode != 2501) && (hash_mode != 6800)) { parser_status = hashconfig->parse_func ((u8 *) line_buf, line_len - 1, &hash_buf, hashconfig); } u32 found = 0; if (parser_status == PARSER_OK) { for (u32 salt_pos = 0; (found == 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; (found == 0) && (digest_pos < salt_buf->digests_cnt); digest_pos++) { u32 idx = salt_buf->digests_offset + digest_pos; if (hashes->digests_shown[idx] == 1) continue; u32 cracked = 0; if (hash_mode == 6800) { if (i == salt_buf->salt_len) { cracked = (memcmp (line_buf, salt_buf->salt_buf, salt_buf->salt_len) == 0); } } else if ((hash_mode == 2500) || (hash_mode == 2501)) { // this comparison is a bit inaccurate as we compare only ESSID // call it a bug, but it's good enough for a special case used in a special case // in this case all essid will be marked as cracked that match the essid if (i == salt_buf->salt_len) { cracked = (memcmp (line_buf, salt_buf->salt_buf, salt_buf->salt_len) == 0); } } else { char *digests_buf_ptr = (char *) hashes->digests_buf; memcpy (digest_buf, digests_buf_ptr + (hashes->salts_buf[salt_pos].digests_offset * dgst_size) + (digest_pos * dgst_size), dgst_size); cracked = (sort_by_digest_p0p1 (digest_buf, hash_buf.digest, hashconfig) == 0); } if (cracked == 1) { found = 1; hashes->digests_shown[idx] = 1; hashes->digests_done++; salt_buf->digests_done++; if (salt_buf->digests_done == salt_buf->digests_cnt) { hashes->salts_shown[salt_pos] = 1; hashes->salts_done++; if (hashes->salts_done == hashes->salts_cnt) mycracked (hashcat_ctx); } } } if (status_ctx->devices_status == STATUS_CRACKED) break; } } if (found) break; if (status_ctx->devices_status == STATUS_CRACKED) break; } if (status_ctx->devices_status == STATUS_CRACKED) break; } hcfree (line_buf); out_info[j].seek = ftello (fp); //hc_thread_mutex_unlock (status_ctx->mux_display); fclose (fp); } } } } check_left = outfile_check_timer; } } hcfree (hash_buf.esalt); hcfree (hash_buf.hook_salt); hcfree (hash_buf.salt); hcfree (hash_buf.digest); hcfree (out_info); hcfree (out_files); return 0; }