int dictstat_init (hashcat_ctx_t *hashcat_ctx) { dictstat_ctx_t *dictstat_ctx = hashcat_ctx->dictstat_ctx; folder_config_t *folder_config = hashcat_ctx->folder_config; user_options_t *user_options = hashcat_ctx->user_options; dictstat_ctx->enabled = false; if (user_options->benchmark == true) return 0; if (user_options->example_hashes == true) return 0; if (user_options->keyspace == true) return 0; if (user_options->left == true) return 0; if (user_options->opencl_info == true) return 0; if (user_options->show == true) return 0; if (user_options->usage == true) return 0; if (user_options->version == true) return 0; if (user_options->attack_mode == ATTACK_MODE_BF) return 0; dictstat_ctx->enabled = true; dictstat_ctx->base = (dictstat_t *) hccalloc (MAX_DICTSTAT, sizeof (dictstat_t)); dictstat_ctx->cnt = 0; hc_asprintf (&dictstat_ctx->filename, "%s/%s", folder_config->profile_dir, DICTSTAT_FILENAME); return 0; }
char *module_jit_build_options (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra, MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const hc_device_param_t *device_param) { const u32 scrypt_N = 16384; const u32 scrypt_r = 1; const u32 scrypt_p = 1; const u64 extra_buffer_size = device_param->extra_buffer_size; const u64 kernel_power_max = device_param->device_processors * hashconfig->kernel_threads_max * hashconfig->kernel_accel_max; const u64 size_scrypt = (128 * scrypt_r) * scrypt_N; const u64 scrypt_tmto_final = (kernel_power_max * size_scrypt) / extra_buffer_size; const u64 tmp_size = (128 * scrypt_r) * scrypt_p; char *jit_build_options = NULL; hc_asprintf (&jit_build_options, "-DSCRYPT_N=%u -DSCRYPT_R=%u -DSCRYPT_P=%u -DSCRYPT_TMTO=%" PRIu64 " -DSCRYPT_TMP_ELEM=%" PRIu64, hashes->salts_buf[0].scrypt_N, hashes->salts_buf[0].scrypt_r, hashes->salts_buf[0].scrypt_p, scrypt_tmto_final, tmp_size / 16); return jit_build_options; }
char *module_jit_build_options (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra, MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const hc_device_param_t *device_param) { char *jit_build_options = NULL; if (device_param->device_vendor_id == VENDOR_ID_NV) { hc_asprintf (&jit_build_options, "-D NO_UNROLL"); } if (device_param->device_vendor_id == VENDOR_ID_AMD) { hc_asprintf (&jit_build_options, "-D NO_UNROLL"); } return jit_build_options; }
char *module_jit_build_options (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra, MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const hc_device_param_t *device_param) { char *jit_build_options = NULL; u32 fixed_local_size = 0; if (device_param->device_type & CL_DEVICE_TYPE_CPU) { fixed_local_size = 1; } else { if (user_options->kernel_threads_chgd == true) { fixed_local_size = user_options->kernel_threads; } else { u32 overhead = 0; if (device_param->device_vendor_id == VENDOR_ID_NV) { overhead = 4; } fixed_local_size = (device_param->device_local_mem_size - overhead) / 4096; } } hc_asprintf (&jit_build_options, "-D FIXED_LOCAL_SIZE=%u", fixed_local_size); return jit_build_options; }
int outcheck_ctx_init (hashcat_ctx_t *hashcat_ctx) { folder_config_t *folder_config = hashcat_ctx->folder_config; outcheck_ctx_t *outcheck_ctx = hashcat_ctx->outcheck_ctx; user_options_t *user_options = hashcat_ctx->user_options; outcheck_ctx->enabled = false; if (user_options->keyspace == true) return 0; if (user_options->benchmark == true) return 0; if (user_options->speed_only == true) return 0; if (user_options->progress_only == true) return 0; if (user_options->opencl_info == true) return 0; if (user_options->outfile_check_timer == 0) return 0; if ((user_options->hash_mode == 5200) || ((user_options->hash_mode >= 6200) && (user_options->hash_mode <= 6299)) || ((user_options->hash_mode >= 13700) && (user_options->hash_mode <= 13799)) || (user_options->hash_mode == 9000)) return 0; if (user_options->outfile_check_dir == NULL) { hc_asprintf (&outcheck_ctx->root_directory, "%s/%s.%s", folder_config->session_dir, user_options->session, OUTFILES_DIR); } else { outcheck_ctx->root_directory = user_options->outfile_check_dir; } hc_stat_t outfile_check_stat; if (hc_stat (outcheck_ctx->root_directory, &outfile_check_stat) == 0) { const u32 is_dir = S_ISDIR (outfile_check_stat.st_mode); if (is_dir == 0) { event_log_error (hashcat_ctx, "Directory specified in outfile-check '%s' is not a valid directory", outcheck_ctx->root_directory); return -1; } } else { if (hc_mkdir (outcheck_ctx->root_directory, 0700) == -1) { event_log_error (hashcat_ctx, "%s: %m", outcheck_ctx->root_directory); return -1; } } outcheck_ctx->enabled = true; return 0; }
static int get_exec_path (char *exec_path, const size_t exec_path_sz) { #if defined (__linux__) || defined (__CYGWIN__) char *tmp; hc_asprintf (&tmp, "/proc/%d/exe", getpid ()); const ssize_t len = readlink (tmp, exec_path, exec_path_sz - 1); hcfree (tmp); if (len == -1) return -1; #elif defined (_WIN) const DWORD len = GetModuleFileName (NULL, exec_path, exec_path_sz - 1); if (len == 0) return -1; #elif defined (__APPLE__) u32 size = (u32) exec_path_sz; if (_NSGetExecutablePath (exec_path, &size) != 0) return -1; const size_t len = strlen (exec_path); #elif defined (__FreeBSD__) #include <sys/sysctl.h> int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; size_t size = exec_path_sz; sysctl (mib, 4, exec_path, &size, NULL, 0); const size_t len = strlen (exec_path); #else #error Your Operating System is not supported or detected #endif exec_path[len] = 0; return 0; }
void hashes_init_filename (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; user_options_extra_t *user_options_extra = hashcat_ctx->user_options_extra; char *hash_or_file = user_options_extra->hc_hash; /** * load hashes, part I: find input mode, count hashes */ if ((user_options->benchmark == false) && (user_options->stdout_flag == false) && (user_options->keyspace == false)) { if (hashconfig->opts_type & OPTS_TYPE_BINARY_HASHFILE) { hashes->hashlist_mode = HL_MODE_ARG; hashes->hashfile = hash_or_file; hc_asprintf (&hashes->hashfile_hcdmp, "%s.hcdmp", hashes->hashfile); } else { hashes->hashlist_mode = (hc_path_exist (hash_or_file) == true) ? HL_MODE_FILE : HL_MODE_ARG; if (hashes->hashlist_mode == HL_MODE_FILE) { hashes->hashfile = hash_or_file; hc_asprintf (&hashes->hashfile_hcdmp, "%s.hcdmp", hashes->hashfile); } } } else { hashes->hashlist_mode = HL_MODE_ARG; } }
int logfile_init (hashcat_ctx_t *hashcat_ctx) { folder_config_t *folder_config = hashcat_ctx->folder_config; logfile_ctx_t *logfile_ctx = hashcat_ctx->logfile_ctx; user_options_t *user_options = hashcat_ctx->user_options; if (user_options->logfile_disable == true) return 0; hc_asprintf (&logfile_ctx->logfile, "%s/%s.log", folder_config->session_dir, user_options->session); logfile_ctx->subid = (char *) hcmalloc (HCBUFSIZ_TINY); logfile_ctx->topid = (char *) hcmalloc (HCBUFSIZ_TINY); logfile_ctx->enabled = true; return 0; }
int outcheck_ctx_init (hashcat_ctx_t *hashcat_ctx) { folder_config_t *folder_config = hashcat_ctx->folder_config; outcheck_ctx_t *outcheck_ctx = hashcat_ctx->outcheck_ctx; user_options_t *user_options = hashcat_ctx->user_options; outcheck_ctx->enabled = false; if (user_options->keyspace == true) return 0; if (user_options->benchmark == true) return 0; if (user_options->example_hashes == true) return 0; if (user_options->speed_only == true) return 0; if (user_options->progress_only == true) return 0; if (user_options->opencl_info == true) return 0; if (user_options->outfile_check_timer == 0) return 0; if ((user_options->hash_mode == 5200) || ((user_options->hash_mode >= 6200) && (user_options->hash_mode <= 6299)) || ((user_options->hash_mode >= 13700) && (user_options->hash_mode <= 13799)) || (user_options->hash_mode == 9000)) return 0; if (user_options->outfile_check_dir == NULL) { hc_asprintf (&outcheck_ctx->root_directory, "%s/%s.%s", folder_config->session_dir, user_options->session, OUTFILES_DIR); } else { outcheck_ctx->root_directory = user_options->outfile_check_dir; } outcheck_ctx->enabled = true; if (hc_path_exist (outcheck_ctx->root_directory) == false) { if (hc_mkdir (outcheck_ctx->root_directory, 0700) == -1) { event_log_error (hashcat_ctx, "%s: %s", outcheck_ctx->root_directory, strerror (errno)); return -1; } } return 0; }
static int mask_append (hashcat_ctx_t *hashcat_ctx, const char *mask, const char *prepend) { hashconfig_t *hashconfig = hashcat_ctx->hashconfig; user_options_t *user_options = hashcat_ctx->user_options; if (user_options->increment == true) { const u32 mask_length = mp_get_length (mask); u32 increment_min = user_options->increment_min; u32 increment_max = user_options->increment_max; increment_max = MIN (increment_max, mask_length); if (user_options->attack_mode == ATTACK_MODE_BF) { const u32 pw_min = hashconfig->pw_min; const u32 pw_max = hashconfig->pw_max; increment_min = MAX (increment_min, pw_min); increment_max = MIN (increment_max, pw_max); } for (u32 increment_len = increment_min; increment_len <= increment_max; increment_len++) { char *mask_truncated = (char *) hcmalloc (256); char *mask_truncated_next = mask_truncated; if (prepend) { // this happens with maskfiles only mask_truncated_next += snprintf (mask_truncated, 256, "%s,", prepend); } const int rc_truncated_mask = mp_get_truncated_mask (hashcat_ctx, mask, strlen (mask), increment_len, mask_truncated_next); if (rc_truncated_mask == -1) { hcfree (mask_truncated); break; } const int rc = mask_append_final (hashcat_ctx, mask_truncated); hcfree (mask_truncated); if (rc == -1) return -1; } } else { if (prepend) { // this happens with maskfiles only char *prepend_mask; hc_asprintf (&prepend_mask, "%s,%s", prepend, mask); const int rc = mask_append_final (hashcat_ctx, prepend_mask); hcfree (prepend_mask); if (rc == -1) return -1; } else { const int rc = mask_append_final (hashcat_ctx, mask); if (rc == -1) return -1; } } return 0; }
int potfile_init (hashcat_ctx_t *hashcat_ctx) { folder_config_t *folder_config = hashcat_ctx->folder_config; potfile_ctx_t *potfile_ctx = hashcat_ctx->potfile_ctx; user_options_t *user_options = hashcat_ctx->user_options; potfile_ctx->enabled = false; if (user_options->benchmark == true) return 0; if (user_options->example_hashes == true) return 0; if (user_options->keyspace == true) return 0; if (user_options->opencl_info == true) return 0; if (user_options->stdout_flag == true) return 0; if (user_options->speed_only == true) return 0; if (user_options->progress_only == true) return 0; if (user_options->usage == true) return 0; if (user_options->version == true) return 0; if (user_options->potfile_disable == true) return 0; potfile_ctx->enabled = true; if (user_options->potfile_path == NULL) { potfile_ctx->fp = NULL; hc_asprintf (&potfile_ctx->filename, "%s/hashcat.potfile", folder_config->profile_dir); } else { potfile_ctx->filename = hcstrdup (user_options->potfile_path); potfile_ctx->fp = NULL; } // keep all hashes if --username was combined with --left or --show potfile_ctx->keep_all_hashes = false; if (user_options->username == true) { if ((user_options->show == true) || (user_options->left == 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; } } // starting from here, we should allocate some scratch buffer for later use u8 *out_buf = (u8 *) hcmalloc (HCBUFSIZ_LARGE); potfile_ctx->out_buf = out_buf; // we need two buffers in parallel u8 *tmp_buf = (u8 *) hcmalloc (HCBUFSIZ_LARGE); potfile_ctx->tmp_buf = tmp_buf; // old potfile detection if (user_options->potfile_path == NULL) { char *potfile_old; hc_asprintf (&potfile_old, "%s/hashcat.pot", folder_config->profile_dir); if (hc_path_exist (potfile_old) == true) { event_log_warning (hashcat_ctx, "Old potfile detected: %s", potfile_old); event_log_warning (hashcat_ctx, "New potfile is: %s ", potfile_ctx->filename); event_log_warning (hashcat_ctx, NULL); } hcfree (potfile_old); } return 0; }
int module_hash_binary_save (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos, char **buf) { const salt_t *salts_buf = hashes->salts_buf; const void *esalts_buf = hashes->esalts_buf; const salt_t *salt = &salts_buf[salt_pos]; const u32 digest_cur = salt->digests_offset + digest_pos; const wpa_pmkid_t *wpa_pmkids = (const wpa_pmkid_t *) esalts_buf; const wpa_pmkid_t *wpa_pmkid = &wpa_pmkids[digest_cur]; int len = 0; if (wpa_pmkid->essid_len) { char tmp_buf[128]; const int tmp_len = hex_encode ((const u8 *) wpa_pmkid->essid_buf, wpa_pmkid->essid_len, (u8 *) tmp_buf); tmp_buf[tmp_len] = 0; len = hc_asprintf (buf, "%08x%08x%08x%08x:%02x%02x%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%s" EOL, byte_swap_32 (wpa_pmkid->pmkid[0]), byte_swap_32 (wpa_pmkid->pmkid[1]), byte_swap_32 (wpa_pmkid->pmkid[2]), byte_swap_32 (wpa_pmkid->pmkid[3]), wpa_pmkid->orig_mac_ap[0], wpa_pmkid->orig_mac_ap[1], wpa_pmkid->orig_mac_ap[2], wpa_pmkid->orig_mac_ap[3], wpa_pmkid->orig_mac_ap[4], wpa_pmkid->orig_mac_ap[5], wpa_pmkid->orig_mac_sta[0], wpa_pmkid->orig_mac_sta[1], wpa_pmkid->orig_mac_sta[2], wpa_pmkid->orig_mac_sta[3], wpa_pmkid->orig_mac_sta[4], wpa_pmkid->orig_mac_sta[5], tmp_buf); } else { len = hc_asprintf (buf, "%08x%08x%08x%08x:%02x%02x%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x" EOL, byte_swap_32 (wpa_pmkid->pmkid[0]), byte_swap_32 (wpa_pmkid->pmkid[1]), byte_swap_32 (wpa_pmkid->pmkid[2]), byte_swap_32 (wpa_pmkid->pmkid[3]), wpa_pmkid->orig_mac_ap[0], wpa_pmkid->orig_mac_ap[1], wpa_pmkid->orig_mac_ap[2], wpa_pmkid->orig_mac_ap[3], wpa_pmkid->orig_mac_ap[4], wpa_pmkid->orig_mac_ap[5], wpa_pmkid->orig_mac_sta[0], wpa_pmkid->orig_mac_sta[1], wpa_pmkid->orig_mac_sta[2], wpa_pmkid->orig_mac_sta[3], wpa_pmkid->orig_mac_sta[4], wpa_pmkid->orig_mac_sta[5]); } return len; }
int hashes_init_stage1 (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; user_options_extra_t *user_options_extra = hashcat_ctx->user_options_extra; /** * load hashes, part I: find input mode, count hashes */ const char *hashfile = hashes->hashfile; const u32 hashlist_mode = hashes->hashlist_mode; u32 hashlist_format = HLFMT_HASHCAT; u64 hashes_avail = 0; if ((user_options->benchmark == false) && (user_options->stdout_flag == false) && (user_options->keyspace == false)) { if (hashlist_mode == HL_MODE_ARG) { if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501)) { struct stat st; if (stat (hashes->hashfile, &st) == -1) { event_log_error (hashcat_ctx, "%s: %s", hashes->hashfile, strerror (errno)); return -1; } // 392 = old hccap_t size if ((st.st_size % 392) == 0) { const int rc = check_old_hccap (hashes->hashfile); if (rc == 1) { event_log_error (hashcat_ctx, "%s: Old hccap format detected! You need to update: https://hashcat.net/q/hccapx", hashes->hashfile); return -1; } } hashes_avail = st.st_size / sizeof (hccapx_t); } else if (hashconfig->hash_mode == 14600) { struct stat st; if (stat (hashes->hashfile, &st) == -1) { event_log_error (hashcat_ctx, "%s: %s", hashes->hashfile, strerror (errno)); return -1; } hashes_avail = LUKS_NUMKEYS; } else { hashes_avail = 1; } } else if (hashlist_mode == HL_MODE_FILE) { FILE *fp = NULL; if ((fp = fopen (hashfile, "rb")) == NULL) { event_log_error (hashcat_ctx, "%s: %s", hashfile, strerror (errno)); return -1; } EVENT_DATA (EVENT_HASHLIST_COUNT_LINES_PRE, hashfile, strlen (hashfile)); hashes_avail = count_lines (fp); EVENT_DATA (EVENT_HASHLIST_COUNT_LINES_POST, hashfile, strlen (hashfile)); rewind (fp); if (hashes_avail == 0) { event_log_error (hashcat_ctx, "hashfile is empty or corrupt."); fclose (fp); return -1; } hashlist_format = hlfmt_detect (hashcat_ctx, fp, 100); // 100 = max numbers to "scan". could be hashes_avail, too if ((user_options->remove == true) && (hashlist_format != HLFMT_HASHCAT)) { event_log_error (hashcat_ctx, "Use of --remove is not supported in native hashfile-format mode."); fclose (fp); return -1; } fclose (fp); } } else { hashes_avail = 1; } if (hashconfig->hash_mode == 3000) hashes_avail *= 2; hashes->hashlist_format = hashlist_format; /** * load hashes, part II: allocate required memory, set pointers */ hash_t *hashes_buf = (hash_t *) hccalloc (hashes_avail, sizeof (hash_t)); void *digests_buf = hccalloc (hashes_avail, hashconfig->dgst_size); salt_t *salts_buf = NULL; void *esalts_buf = NULL; void *hook_salts_buf = NULL; if ((user_options->username == true) || (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) || (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)) { u32 hash_pos; for (hash_pos = 0; hash_pos < hashes_avail; hash_pos++) { hashinfo_t *hash_info = (hashinfo_t *) hcmalloc (sizeof (hashinfo_t)); hashes_buf[hash_pos].hash_info = hash_info; if (user_options->username == true) { hash_info->user = (user_t *) hcmalloc (sizeof (user_t)); } if (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) { if (user_options->benchmark == false) { hash_info->orighash = (char *) hcmalloc (256); } } if (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT) { hash_info->split = (split_t *) hcmalloc (sizeof (split_t)); } } } if (hashconfig->is_salted == true) { salts_buf = (salt_t *) hccalloc (hashes_avail, sizeof (salt_t)); if (hashconfig->esalt_size > 0) { esalts_buf = hccalloc (hashes_avail, hashconfig->esalt_size); } if (hashconfig->hook_salt_size > 0) { hook_salts_buf = (seven_zip_hook_salt_t *) hccalloc (hashes_avail, hashconfig->hook_salt_size); } } else { salts_buf = (salt_t *) hccalloc (1, sizeof (salt_t)); } for (u32 hash_pos = 0; hash_pos < hashes_avail; hash_pos++) { hashes_buf[hash_pos].digest = ((char *) digests_buf) + (hash_pos * hashconfig->dgst_size); if (hashconfig->is_salted == true) { hashes_buf[hash_pos].salt = &salts_buf[hash_pos]; if (hashconfig->esalt_size > 0) { hashes_buf[hash_pos].esalt = ((char *) esalts_buf) + (hash_pos * hashconfig->esalt_size); } if (hashconfig->hook_salt_size > 0) { hashes_buf[hash_pos].hook_salt = ((char *) hook_salts_buf) + (hash_pos * hashconfig->hook_salt_size); } } else { hashes_buf[hash_pos].salt = &salts_buf[0]; } } hashes->hashes_buf = hashes_buf; hashes->digests_buf = digests_buf; hashes->salts_buf = salts_buf; hashes->esalts_buf = esalts_buf; hashes->hook_salts_buf = hook_salts_buf; /** * load hashes, part III: parse hashes or generate them if benchmark */ u32 hashes_cnt = 0; if (user_options->benchmark == true) { hashconfig_benchmark_defaults (hashcat_ctx, hashes_buf[0].salt, hashes_buf[0].esalt, hashes_buf[0].hook_salt); hashes->hashfile = "-"; hashes_cnt = 1; } else if (user_options->example_hashes == true) { } else if (user_options->keyspace == true) { } else if (user_options->stdout_flag == true) { } else if (user_options->opencl_info == true) { } else { if (hashes_avail == 0) { // ??? } else if (hashlist_mode == HL_MODE_ARG) { char *input_buf = user_options_extra->hc_hash; size_t input_len = strlen (input_buf); char *hash_buf = NULL; size_t hash_len = 0; hlfmt_hash (hashcat_ctx, hashlist_format, input_buf, input_len, &hash_buf, &hash_len); bool hash_fmt_error = 0; if (hash_len < 1) hash_fmt_error = 1; if (hash_buf == NULL) hash_fmt_error = 1; if (hash_fmt_error) { event_log_warning (hashcat_ctx, "Failed to parse hashes using the '%s' format.", strhlfmt (hashlist_format)); } else { if (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) { hashinfo_t *hash_info_tmp = hashes_buf[hashes_cnt].hash_info; hash_info_tmp->orighash = hcstrdup (hash_buf); } if (hashconfig->is_salted == true) { memset (hashes_buf[0].salt, 0, sizeof (salt_t)); } if (hashconfig->esalt_size > 0) { memset (hashes_buf[0].esalt, 0, hashconfig->esalt_size); } if (hashconfig->hook_salt_size > 0) { memset (hashes_buf[0].hook_salt, 0, hashconfig->hook_salt_size); } int parser_status = PARSER_OK; if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501)) { hashes->hashlist_mode = HL_MODE_FILE; FILE *fp = fopen (hash_buf, "rb"); if (fp == NULL) { event_log_error (hashcat_ctx, "%s: %s", hash_buf, strerror (errno)); return -1; } char *in = (char *) hcmalloc (sizeof (hccapx_t)); while (!feof (fp)) { const size_t nread = hc_fread (in, sizeof (hccapx_t), 1, fp); if (nread == 0) break; if (hashes_avail == hashes_cnt) { event_log_warning (hashcat_ctx, "Hashfile '%s': File changed during runtime. Skipping new data.", hash_buf); break; } if (hashconfig->is_salted == true) { memset (hashes_buf[hashes_cnt].salt, 0, sizeof (salt_t)); } if (hashconfig->esalt_size > 0) { memset (hashes_buf[hashes_cnt].esalt, 0, hashconfig->esalt_size); if ((user_options->hash_mode == 2500) || (user_options->hash_mode == 2501)) { wpa_t *wpa = (wpa_t *) hashes_buf[hashes_cnt].esalt; if (user_options->hccapx_message_pair_chgd == true) { wpa->message_pair_chgd = (int) user_options->hccapx_message_pair_chgd; wpa->message_pair = (u8) user_options->hccapx_message_pair; } wpa->nonce_error_corrections = user_options->nonce_error_corrections; } } if (hashconfig->hook_salt_size > 0) { memset (hashes_buf[hashes_cnt].hook_salt, 0, hashconfig->hook_salt_size); } parser_status = hashconfig->parse_func ((u8 *) in, sizeof (hccapx_t), &hashes_buf[hashes_cnt], hashconfig); if (parser_status != PARSER_OK) { event_log_warning (hashcat_ctx, "Hashfile '%s': %s", hash_buf, strparser (parser_status)); continue; } hashes_cnt++; } hcfree (in); fclose (fp); } else if (hashconfig->hash_mode == 3000) { if (hash_len == 32) { parser_status = hashconfig->parse_func ((u8 *) hash_buf, 16, &hashes_buf[hashes_cnt], hashconfig); 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 { event_log_warning (hashcat_ctx, "Hash '%s': %s", input_buf, strparser (parser_status)); } parser_status = hashconfig->parse_func ((u8 *) hash_buf + 16, 16, &hashes_buf[hashes_cnt], hashconfig); 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 { event_log_warning (hashcat_ctx, "Hash '%s': %s", input_buf, strparser (parser_status)); } } else { parser_status = hashconfig->parse_func ((u8 *) hash_buf, (u32) hash_len, &hashes_buf[hashes_cnt], hashconfig); 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 { event_log_warning (hashcat_ctx, "Hash '%s': %s", input_buf, strparser (parser_status)); } } } else if (hashconfig->hash_mode == 14600) { hashes->hashlist_mode = HL_MODE_FILE; for (int keyslot_idx = 0; keyslot_idx < LUKS_NUMKEYS; keyslot_idx++) { parser_status = luks_parse_hash ((u8 *) hash_buf, (u32) hash_len, &hashes_buf[hashes_cnt], hashconfig, keyslot_idx); if (parser_status != PARSER_OK) { if (parser_status != PARSER_LUKS_KEY_DISABLED) { event_log_warning (hashcat_ctx, "Hashfile '%s': %s", hash_buf, strparser (parser_status)); } continue; } hashes_cnt++; } } else { parser_status = hashconfig->parse_func ((u8 *) hash_buf, (u32) hash_len, &hashes_buf[hashes_cnt], hashconfig); if (parser_status == PARSER_OK) { hashes_cnt++; } else { event_log_warning (hashcat_ctx, "Hash '%s': %s", input_buf, strparser (parser_status)); } } } } else if (hashlist_mode == HL_MODE_FILE) { FILE *fp; if ((fp = fopen (hashfile, "rb")) == NULL) { event_log_error (hashcat_ctx, "%s: %s", hashfile, strerror (errno)); return -1; } u32 line_num = 0; char *line_buf = (char *) hcmalloc (HCBUFSIZ_LARGE); time_t prev = 0; time_t now = 0; while (!feof (fp)) { line_num++; const size_t line_len = fgetl (fp, line_buf); if (line_len == 0) continue; if (hashes_avail == hashes_cnt) { event_log_warning (hashcat_ctx, "Hashfile '%s' on line %u: File changed during runtime. Skipping new data.", hashes->hashfile, line_num); break; } char *hash_buf = NULL; size_t hash_len = 0; hlfmt_hash (hashcat_ctx, hashlist_format, line_buf, line_len, &hash_buf, &hash_len); bool hash_fmt_error = 0; if (hash_len < 1) hash_fmt_error = 1; if (hash_buf == NULL) hash_fmt_error = 1; if (hash_fmt_error) { event_log_warning (hashcat_ctx, "Failed to parse hashes using the '%s' format.", strhlfmt (hashlist_format)); continue; } if (user_options->username == true) { char *user_buf = NULL; size_t user_len = 0; hlfmt_user (hashcat_ctx, hashlist_format, line_buf, line_len, &user_buf, &user_len); // special case: // both hash_t need to have the username info if the pwdump format is used (i.e. we have 2 hashes for 3000, both with same user) u32 hashes_per_user = 1; if (hashconfig->hash_mode == 3000) // the following conditions should be true if (hashlist_format == HLFMT_PWDUMP) { if (hash_len == 32) { hashes_per_user = 2; } } for (u32 i = 0; i < hashes_per_user; i++) { user_t **user = &hashes_buf[hashes_cnt + i].hash_info->user; *user = (user_t *) hcmalloc (sizeof (user_t)); user_t *user_ptr = *user; if (user_buf != NULL) { user_ptr->user_name = hcstrdup (user_buf); } else { user_ptr->user_name = hcstrdup (""); } user_ptr->user_len = (u32) user_len; } } if (hashconfig->opts_type & OPTS_TYPE_HASH_COPY) { hashinfo_t *hash_info_tmp = hashes_buf[hashes_cnt].hash_info; hash_info_tmp->orighash = hcstrdup (hash_buf); } if (hashconfig->is_salted == true) { memset (hashes_buf[hashes_cnt].salt, 0, sizeof (salt_t)); } if (hashconfig->esalt_size > 0) { memset (hashes_buf[hashes_cnt].esalt, 0, hashconfig->esalt_size); } if (hashconfig->hook_salt_size > 0) { memset (hashes_buf[hashes_cnt].hook_salt, 0, hashconfig->hook_salt_size); } if (hashconfig->hash_mode == 3000) { if (hash_len == 32) { int parser_status = hashconfig->parse_func ((u8 *) hash_buf, 16, &hashes_buf[hashes_cnt], hashconfig); if (parser_status < PARSER_GLOBAL_ZERO) { char *tmp_line_buf; hc_asprintf (&tmp_line_buf, "%s", line_buf); compress_terminal_line_length (tmp_line_buf, 38, 32); event_log_warning (hashcat_ctx, "Hashfile '%s' on line %u (%s): %s", hashes->hashfile, line_num, tmp_line_buf, strparser (parser_status)); hcfree (tmp_line_buf); 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); if (parser_status < PARSER_GLOBAL_ZERO) { char *tmp_line_buf; hc_asprintf (&tmp_line_buf, "%s", line_buf); compress_terminal_line_length (tmp_line_buf, 38, 32); event_log_warning (hashcat_ctx, "Hashfile '%s' on line %u (%s): %s", hashes->hashfile, line_num, tmp_line_buf, strparser (parser_status)); hcfree (tmp_line_buf); 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 { int parser_status = hashconfig->parse_func ((u8 *) hash_buf, (u32) hash_len, &hashes_buf[hashes_cnt], hashconfig); if (parser_status < PARSER_GLOBAL_ZERO) { char *tmp_line_buf; hc_asprintf (&tmp_line_buf, "%s", line_buf); compress_terminal_line_length (tmp_line_buf, 38, 32); event_log_warning (hashcat_ctx, "Hashfile '%s' on line %u (%s): %s", hashes->hashfile, line_num, tmp_line_buf, strparser (parser_status)); hcfree (tmp_line_buf); 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++; } } else { int parser_status = hashconfig->parse_func ((u8 *) hash_buf, (u32) hash_len, &hashes_buf[hashes_cnt], hashconfig); if (parser_status < PARSER_GLOBAL_ZERO) { char *tmp_line_buf; hc_asprintf (&tmp_line_buf, "%s", line_buf); compress_terminal_line_length (tmp_line_buf, 38, 32); event_log_warning (hashcat_ctx, "Hashfile '%s' on line %u (%s): %s", hashes->hashfile, line_num, tmp_line_buf, strparser (parser_status)); hcfree (tmp_line_buf); continue; } hashes_cnt++; } time (&now); if ((now - prev) == 0) continue; time (&prev); hashlist_parse_t hashlist_parse; hashlist_parse.hashes_cnt = hashes_cnt; hashlist_parse.hashes_avail = hashes_avail; EVENT_DATA (EVENT_HASHLIST_PARSE_HASH, &hashlist_parse, sizeof (hashlist_parse_t)); } hashlist_parse_t hashlist_parse; hashlist_parse.hashes_cnt = hashes_cnt; hashlist_parse.hashes_avail = hashes_avail; EVENT_DATA (EVENT_HASHLIST_PARSE_HASH, &hashlist_parse, sizeof (hashlist_parse_t)); hcfree (line_buf); fclose (fp); } } hashes->hashes_cnt = hashes_cnt; if (hashes_cnt) { EVENT (EVENT_HASHLIST_SORT_HASH_PRE); if (hashconfig->is_salted == true) { hc_qsort_r (hashes_buf, hashes_cnt, sizeof (hash_t), sort_by_hash, (void *) hashconfig); } else { hc_qsort_r (hashes_buf, hashes_cnt, sizeof (hash_t), sort_by_hash_no_salt, (void *) hashconfig); } 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; }
int hashes_init_selftest (hashcat_ctx_t *hashcat_ctx) { folder_config_t *folder_config = hashcat_ctx->folder_config; hashconfig_t *hashconfig = hashcat_ctx->hashconfig; hashes_t *hashes = hashcat_ctx->hashes; user_options_t *user_options = hashcat_ctx->user_options; if (hashconfig->st_hash == NULL) return 0; void *st_digests_buf = NULL; salt_t *st_salts_buf = NULL; void *st_esalts_buf = NULL; void *st_hook_salts_buf = NULL; st_digests_buf = hccalloc (1, hashconfig->dgst_size); st_salts_buf = (salt_t *) hccalloc (1, sizeof (salt_t)); if (hashconfig->esalt_size > 0) { st_esalts_buf = hccalloc (1, hashconfig->esalt_size); } if (hashconfig->hook_salt_size > 0) { st_hook_salts_buf = hccalloc (1, hashconfig->hook_salt_size); } hash_t hash; hash.digest = st_digests_buf; hash.salt = st_salts_buf; hash.esalt = st_esalts_buf; hash.hook_salt = st_hook_salts_buf; hash.cracked = 0; hash.hash_info = NULL; hash.pw_buf = NULL; hash.pw_len = 0; int parser_status; if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501)) { char *tmpdata = (char *) hcmalloc (sizeof (hccapx_t)); const size_t st_hash_len = strlen (hashconfig->st_hash); for (size_t i = 0, j = 0; j < st_hash_len; i += 1, j += 2) { const u8 c = hex_to_u8 ((const u8 *) hashconfig->st_hash + j); tmpdata[i] = c; } parser_status = hashconfig->parse_func ((u8 *) tmpdata, sizeof (hccapx_t), &hash, hashconfig); hcfree (tmpdata); wpa_t *wpa = (wpa_t *) st_esalts_buf; wpa->nonce_error_corrections = 3; } else if (hashconfig->opts_type & OPTS_TYPE_BINARY_HASHFILE) { char *tmpfile_bin; hc_asprintf (&tmpfile_bin, "%s/selftest.hash", folder_config->session_dir); FILE *fp = fopen (tmpfile_bin, "wb"); const size_t st_hash_len = strlen (hashconfig->st_hash); for (size_t i = 0; i < st_hash_len; i += 2) { const u8 c = hex_to_u8 ((const u8 *) hashconfig->st_hash + i); fputc (c, fp); } fclose (fp); parser_status = hashconfig->parse_func ((u8 *) tmpfile_bin, (u32) strlen (tmpfile_bin), &hash, hashconfig); unlink (tmpfile_bin); hcfree (tmpfile_bin); } else { hashconfig_t *hashconfig_st = (hashconfig_t *) hcmalloc (sizeof (hashconfig_t)); memcpy (hashconfig_st, hashconfig, sizeof (hashconfig_t)); hashconfig_st->separator = SEPARATOR; if (user_options->hex_salt) { if (hashconfig->salt_type == SALT_TYPE_GENERIC) { // this is save as there's no hash mode that has both SALT_TYPE_GENERIC and OPTS_TYPE_ST_HEX by default hashconfig_st->opts_type &= ~OPTS_TYPE_ST_HEX; } } // Make sure that we do not modify constant data. Make a copy of the constant self-test hash // Note: sometimes parse_func () modifies the data internally. We always need to use a copy of the original data char *tmpdata = hcstrdup (hashconfig->st_hash); parser_status = hashconfig->parse_func ((u8 *) tmpdata, (u32) strlen (hashconfig->st_hash), &hash, hashconfig_st); hcfree (tmpdata); hcfree (hashconfig_st); } if (parser_status == PARSER_OK) { // nothing to do } else { event_log_error (hashcat_ctx, "Self-test hash parsing error: %s", strparser (parser_status)); return -1; } hashes->st_digests_buf = st_digests_buf; hashes->st_salts_buf = st_salts_buf; hashes->st_esalts_buf = st_esalts_buf; hashes->st_hook_salts_buf = st_hook_salts_buf; 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; }
int tuning_db_init (hashcat_ctx_t *hashcat_ctx) { folder_config_t *folder_config = hashcat_ctx->folder_config; tuning_db_t *tuning_db = hashcat_ctx->tuning_db; user_options_t *user_options = hashcat_ctx->user_options; user_options_extra_t *user_options_extra = hashcat_ctx->user_options_extra; tuning_db->enabled = false; if (user_options->example_hashes == true) return 0; if (user_options->keyspace == true) return 0; if (user_options->left == true) return 0; if (user_options->opencl_info == true) return 0; if (user_options->show == true) return 0; if (user_options->usage == true) return 0; if (user_options->version == true) return 0; tuning_db->enabled = true; char *tuning_db_file; hc_asprintf (&tuning_db_file, "%s/%s", folder_config->shared_dir, TUNING_DB_FILE); FILE *fp = fopen (tuning_db_file, "rb"); if (fp == NULL) { event_log_error (hashcat_ctx, "%s: %s", tuning_db_file, strerror (errno)); return -1; } hcfree (tuning_db_file); int num_lines = count_lines (fp); // a bit over-allocated tuning_db->alias_buf = (tuning_db_alias_t *) hccalloc (num_lines + 1, sizeof (tuning_db_alias_t)); tuning_db->alias_cnt = 0; tuning_db->entry_buf = (tuning_db_entry_t *) hccalloc (num_lines + 1, sizeof (tuning_db_entry_t)); tuning_db->entry_cnt = 0; rewind (fp); int line_num = 0; char *buf = (char *) hcmalloc (HCBUFSIZ_LARGE); while (!feof (fp)) { char *line_buf = fgets (buf, HCBUFSIZ_LARGE - 1, fp); if (line_buf == NULL) break; line_num++; const int line_len = in_superchop (line_buf); if (line_len == 0) continue; if (line_buf[0] == '#') continue; // start processing char *token_ptr[7] = { NULL }; int token_cnt = 0; char *saveptr = NULL; char *next = strtok_r (line_buf, "\t ", &saveptr); token_ptr[token_cnt] = next; token_cnt++; while ((next = strtok_r ((char *) NULL, "\t ", &saveptr)) != NULL) { token_ptr[token_cnt] = next; token_cnt++; } if (token_cnt == 2) { char *device_name = token_ptr[0]; char *alias_name = token_ptr[1]; tuning_db_alias_t *alias = &tuning_db->alias_buf[tuning_db->alias_cnt]; alias->device_name = hcstrdup (device_name); alias->alias_name = hcstrdup (alias_name); tuning_db->alias_cnt++; } else if (token_cnt == 6) { if ((token_ptr[1][0] != '0') && (token_ptr[1][0] != '1') && (token_ptr[1][0] != '3') && (token_ptr[1][0] != '*')) { event_log_warning (hashcat_ctx, "Tuning-db: Invalid attack_mode '%c' in Line '%d'", token_ptr[1][0], line_num); continue; } if ((token_ptr[3][0] != '1') && (token_ptr[3][0] != '2') && (token_ptr[3][0] != '4') && (token_ptr[3][0] != '8') && (token_ptr[3][0] != 'N')) { event_log_warning (hashcat_ctx, "Tuning-db: Invalid vector_width '%c' in Line '%d'", token_ptr[3][0], line_num); continue; } char *device_name = token_ptr[0]; int attack_mode = -1; int hash_type = -1; int vector_width = -1; int kernel_accel = -1; int kernel_loops = -1; if (token_ptr[1][0] != '*') attack_mode = strtol (token_ptr[1], NULL, 10); if (token_ptr[2][0] != '*') hash_type = strtol (token_ptr[2], NULL, 10); if (token_ptr[3][0] != 'N') vector_width = strtol (token_ptr[3], NULL, 10); if (token_ptr[4][0] == 'A') { kernel_accel = 0; } else if (token_ptr[4][0] == 'M') { kernel_accel = 1024; } else { kernel_accel = strtol (token_ptr[4], NULL, 10); if ((kernel_accel < 1) || (kernel_accel > 1024)) { event_log_warning (hashcat_ctx, "Tuning-db: Invalid kernel_accel '%d' in Line '%d'", kernel_accel, line_num); continue; } } if (token_ptr[5][0] == 'A') { kernel_loops = 0; } else if (token_ptr[5][0] == 'M') { if (user_options_extra->attack_kern == ATTACK_KERN_STRAIGHT) { kernel_loops = KERNEL_RULES; } else if (user_options_extra->attack_kern == ATTACK_KERN_COMBI) { kernel_loops = KERNEL_COMBS; } else if (user_options_extra->attack_kern == ATTACK_KERN_BF) { kernel_loops = KERNEL_BFS; } } else { kernel_loops = strtol (token_ptr[5], NULL, 10); if (kernel_loops < 1) { event_log_warning (hashcat_ctx, "Tuning-db: Invalid kernel_loops '%d' in Line '%d'", kernel_loops, line_num); continue; } if ((user_options_extra->attack_kern == ATTACK_KERN_STRAIGHT) && (kernel_loops > KERNEL_RULES)) { event_log_warning (hashcat_ctx, "Tuning-db: Invalid kernel_loops '%d' in Line '%d'", kernel_loops, line_num); continue; } if ((user_options_extra->attack_kern == ATTACK_KERN_COMBI) && (kernel_loops > KERNEL_COMBS)) { event_log_warning (hashcat_ctx, "Tuning-db: Invalid kernel_loops '%d' in Line '%d'", kernel_loops, line_num); continue; } if ((user_options_extra->attack_kern == ATTACK_KERN_BF) && (kernel_loops > KERNEL_BFS)) { event_log_warning (hashcat_ctx, "Tuning-db: Invalid kernel_loops '%d' in Line '%d'", kernel_loops, line_num); continue; } } tuning_db_entry_t *entry = &tuning_db->entry_buf[tuning_db->entry_cnt]; entry->device_name = hcstrdup (device_name); entry->attack_mode = attack_mode; entry->hash_type = hash_type; entry->vector_width = vector_width; entry->kernel_accel = kernel_accel; entry->kernel_loops = kernel_loops; tuning_db->entry_cnt++; } else { event_log_warning (hashcat_ctx, "Tuning-db: Invalid number of token in Line '%d'", line_num); continue; } } hcfree (buf); fclose (fp); // todo: print loaded 'cnt' message // sort the database qsort (tuning_db->alias_buf, tuning_db->alias_cnt, sizeof (tuning_db_alias_t), sort_by_tuning_db_alias); qsort (tuning_db->entry_buf, tuning_db->entry_cnt, sizeof (tuning_db_entry_t), sort_by_tuning_db_entry); return 0; }