1
0
mirror of https://github.com/hashcat/hashcat.git synced 2025-07-29 09:59:06 +00:00
hashcat/src/hashcat.c
Jens Steube 07395626fa Introduce hashes_init_stage5() and call module_extra_tmp_size() there. At this stage, the self-test hash is initialized and its values can be used.
Remove hard-coded SCRYPT N, R, and P values in modules, except where they are intentionally hardcoded.
Fix a bug that always caused a TMTO value of 1, even when it was not needed.
Respect device_available_mem and device_maxmem_alloc values even if a reliable low-level free memory API is present, and always select the lowest of all available limits.
Fix benchmark_deep.pl mask to avoid UTF-8 rejects.
Improve error messages when the check verifying that all SCRYPT configuration settings across all hashes are identical is triggered.
Also improve the error message shown when the SCRYPT configuration of the self-test hash does not match that of the target hash.
Fix a bug where a low-tuned SCRYPT hash combined with a TMTO could result in fewer than 1024 iterations, which breaks the hard-coded minimum of 1024 iterations in the SCRYPT kernel.
2025-06-15 14:13:48 +02:00

2112 lines
62 KiB
C

/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#include "common.h"
// basic tools
#include "types.h"
#include "folder.h"
#include "memory.h"
#include "shared.h"
#include "thread.h"
#include "timer.h"
// features
#include "affinity.h"
#include "autotune.h"
#include "benchmark.h"
#include "bitmap.h"
#include "bridges.h"
#include "combinator.h"
#include "cpt.h"
#include "debugfile.h"
#include "dictstat.h"
#include "dispatch.h"
#include "event.h"
#include "hashes.h"
#include "hwmon.h"
#include "hlfmt.h"
#include "induct.h"
#include "interface.h"
#include "logfile.h"
#include "loopback.h"
#include "monitor.h"
#include "mpsp.h"
#include "backend.h"
#include "outfile_check.h"
#include "outfile.h"
#include "pidfile.h"
#include "potfile.h"
#include "restore.h"
#include "selftest.h"
#include "status.h"
#include "straight.h"
#include "tuningdb.h"
#include "user_options.h"
#include "wordlist.h"
#include "hashcat.h"
#include "usage.h"
#ifdef WITH_BRAIN
#include "brain.h"
#endif
// inner2_loop iterates through wordlists, then calls kernel execution
static int inner2_loop (hashcat_ctx_t *hashcat_ctx)
{
hashes_t *hashes = hashcat_ctx->hashes;
induct_ctx_t *induct_ctx = hashcat_ctx->induct_ctx;
logfile_ctx_t *logfile_ctx = hashcat_ctx->logfile_ctx;
backend_ctx_t *backend_ctx = hashcat_ctx->backend_ctx;
restore_ctx_t *restore_ctx = hashcat_ctx->restore_ctx;
status_ctx_t *status_ctx = hashcat_ctx->status_ctx;
user_options_extra_t *user_options_extra = hashcat_ctx->user_options_extra;
user_options_t *user_options = hashcat_ctx->user_options;
//status_ctx->run_main_level1 = true;
//status_ctx->run_main_level2 = true;
//status_ctx->run_main_level3 = true;
status_ctx->run_thread_level1 = true;
status_ctx->run_thread_level2 = true;
status_ctx->devices_status = STATUS_INIT;
logfile_generate_subid (hashcat_ctx);
logfile_sub_msg ("START");
status_progress_reset (hashcat_ctx);
status_ctx->msec_paused = 0;
status_ctx->words_off = 0;
status_ctx->words_cur = 0;
if (restore_ctx->restore_execute == true)
{
restore_ctx->restore_execute = false;
restore_data_t *rd = restore_ctx->rd;
status_ctx->words_off = rd->words_cur;
status_ctx->words_cur = status_ctx->words_off;
// --restore always overrides --skip
user_options->skip = 0;
}
if (user_options->skip > 0)
{
status_ctx->words_off = user_options->skip;
status_ctx->words_cur = status_ctx->words_off;
user_options->skip = 0;
}
backend_session_reset (hashcat_ctx);
cpt_ctx_reset (hashcat_ctx);
/**
* Update attack-mode specific stuff based on mask
*/
if (mask_ctx_update_loop (hashcat_ctx) == -1) return 0;
/**
* Update attack-mode specific stuff based on wordlist
*/
if (straight_ctx_update_loop (hashcat_ctx) == -1) return 0;
// words base
const u64 amplifier_cnt = user_options_extra_amplifier (hashcat_ctx);
status_ctx->words_base = status_ctx->words_cnt / amplifier_cnt;
EVENT (EVENT_CALCULATED_WORDS_BASE);
if (user_options->keyspace == true)
{
status_ctx->devices_status = STATUS_RUNNING;
return 0;
}
// restore stuff
if (status_ctx->words_off > status_ctx->words_base)
{
event_log_error (hashcat_ctx, "Restore value is greater than keyspace.");
return -1;
}
if (user_options->attack_mode == ATTACK_MODE_ASSOCIATION)
{
const u64 progress_restored = 1 * amplifier_cnt;
for (u32 i = 0; i < status_ctx->words_off; i++)
{
status_ctx->words_progress_restored[i] = progress_restored;
}
}
else
{
const u64 progress_restored = status_ctx->words_off * amplifier_cnt;
for (u32 i = 0; i < hashes->salts_cnt; i++)
{
status_ctx->words_progress_restored[i] = progress_restored;
}
}
#ifdef WITH_BRAIN
if (user_options->brain_client == true)
{
user_options->brain_attack = brain_compute_attack (hashcat_ctx);
}
#endif
/**
* limit kernel loops by the amplification count we have from:
* - straight_ctx, combinator_ctx or mask_ctx for fast hashes
* - hash iteration count for slow hashes
* this is required for autotune
*/
backend_ctx_devices_kernel_loops (hashcat_ctx);
/**
* prepare thread buffers
*/
thread_param_t *threads_param = (thread_param_t *) hccalloc (backend_ctx->backend_devices_cnt, sizeof (thread_param_t));
hc_thread_t *c_threads = (hc_thread_t *) hccalloc (backend_ctx->backend_devices_cnt, sizeof (hc_thread_t));
/**
* create autotune threads
*/
EVENT (EVENT_AUTOTUNE_STARTING);
status_ctx->devices_status = STATUS_AUTOTUNE;
for (int backend_devices_idx = 0; backend_devices_idx < backend_ctx->backend_devices_cnt; backend_devices_idx++)
{
thread_param_t *thread_param = threads_param + backend_devices_idx;
thread_param->hashcat_ctx = hashcat_ctx;
thread_param->tid = backend_devices_idx;
hc_thread_create (c_threads[backend_devices_idx], thread_autotune, thread_param);
}
hc_thread_wait (backend_ctx->backend_devices_cnt, c_threads);
// check for any autotune failures
// by default, skipping device on error
// using --force, accel/loops/threads min values are used instead of skipping
int at_err = 0;
for (int backend_devices_idx = 0; backend_devices_idx < backend_ctx->backend_devices_cnt; backend_devices_idx++)
{
if (backend_ctx->enabled == false) continue;
hc_device_param_t *device_param = backend_ctx->devices_param + backend_devices_idx;
if (device_param->skipped == true) continue;
if (device_param->skipped_warning == true) continue;
if (device_param->at_status == AT_STATUS_FAILED)
{
at_err++;
if (user_options->force == false)
{
event_log_warning (hashcat_ctx, "* Device #%u: skipped, due to kernel autotune failure (%d).", device_param->device_id + 1, device_param->at_rc);
device_param->skipped = true;
// update counters
if (device_param->is_hip == true) backend_ctx->hip_devices_active--;
if (device_param->is_cuda == true) backend_ctx->cuda_devices_active--;
if (device_param->is_opencl == true) backend_ctx->opencl_devices_active--;
backend_ctx->backend_devices_active--;
}
else
{
event_log_warning (hashcat_ctx, "* Device #%u: detected kernel autotune failure (%d), min values will be used", device_param->device_id + 1, device_param->at_rc);
}
}
}
if (at_err > 0)
{
event_log_warning (hashcat_ctx, NULL);
if (user_options->force == false)
{
// if all enabled devices fail, abort session
if (backend_ctx->backend_devices_active <= 0)
{
event_log_error (hashcat_ctx, "Aborting session due to kernel autotune failures, for all active devices.");
event_log_warning (hashcat_ctx, "You can use --force to override this, but do not report related errors.");
event_log_warning (hashcat_ctx, NULL);
return -10;
}
}
}
EVENT (EVENT_AUTOTUNE_FINISHED);
/**
* find same backend devices and equal results
*/
backend_ctx_devices_sync_tuning (hashcat_ctx);
/**
* autotune modified kernel_accel, which modifies backend_ctx->kernel_power_all
*/
backend_ctx_devices_update_power (hashcat_ctx);
/**
* Begin loopback recording
*/
if (user_options->loopback == true)
{
loopback_write_open (hashcat_ctx);
}
/**
* Prepare cracking stats
*/
hc_timer_set (&status_ctx->timer_running);
time_t runtime_start;
time (&runtime_start);
status_ctx->runtime_start = runtime_start;
/**
* create cracker threads
*/
EVENT (EVENT_CRACKER_STARTING);
status_ctx->devices_status = STATUS_RUNNING;
status_ctx->accessible = true;
for (int backend_devices_idx = 0; backend_devices_idx < backend_ctx->backend_devices_cnt; backend_devices_idx++)
{
thread_param_t *thread_param = threads_param + backend_devices_idx;
thread_param->hashcat_ctx = hashcat_ctx;
thread_param->tid = backend_devices_idx;
if (user_options_extra->wordlist_mode == WL_MODE_STDIN)
{
hc_thread_create (c_threads[backend_devices_idx], thread_calc_stdin, thread_param);
}
else
{
hc_thread_create (c_threads[backend_devices_idx], thread_calc, thread_param);
}
}
hc_thread_wait (backend_ctx->backend_devices_cnt, c_threads);
hcfree (c_threads);
hcfree (threads_param);
if ((status_ctx->devices_status == STATUS_RUNNING) && (status_ctx->checkpoint_shutdown == true))
{
myabort_checkpoint (hashcat_ctx);
}
if ((status_ctx->devices_status == STATUS_RUNNING) && (status_ctx->finish_shutdown == true))
{
myabort_finish (hashcat_ctx);
}
if ((status_ctx->devices_status != STATUS_CRACKED)
&& (status_ctx->devices_status != STATUS_ERROR)
&& (status_ctx->devices_status != STATUS_ABORTED)
&& (status_ctx->devices_status != STATUS_ABORTED_CHECKPOINT)
&& (status_ctx->devices_status != STATUS_ABORTED_FINISH)
&& (status_ctx->devices_status != STATUS_ABORTED_RUNTIME)
&& (status_ctx->devices_status != STATUS_QUIT)
&& (status_ctx->devices_status != STATUS_BYPASS))
{
status_ctx->devices_status = STATUS_EXHAUSTED;
}
if (status_ctx->devices_status == STATUS_EXHAUSTED)
{
// the options speed-only and progress-only cause hashcat to abort quickly.
// therefore, they will end up (if no other error occurred) as STATUS_EXHAUSTED.
// however, that can create confusion in hashcats RC, because exhausted translates to RC = 1.
// but then having RC = 1 does not match our exception if we use for speed-only and progress-only.
// to get hashcat to return RC = 0 we have to set it to CRACKED or BYPASS
// note: other options like --show, --left, --benchmark, --keyspace, --backend-info, etc.
// do not reach this section of the code, they've returned already with rc 0.
if ((user_options->speed_only == true) || (user_options->progress_only == true))
{
status_ctx->devices_status = STATUS_BYPASS;
}
}
// update some timer
time_t runtime_stop;
time (&runtime_stop);
status_ctx->runtime_stop = runtime_stop;
logfile_sub_uint (runtime_start);
logfile_sub_uint (runtime_stop);
if (hashcat_get_status (hashcat_ctx, status_ctx->hashcat_status_final) == -1)
{
fprintf (stderr, "Initialization problem: the hashcat status monitoring function returned an unexpected value\n");
}
status_ctx->accessible = false;
// update newly cracked hashes per session
logfile_sub_uint (hashes->digests_done_new);
EVENT (EVENT_CRACKER_FINISHED);
// mark sub logfile
logfile_sub_var_uint ("status-after-work", status_ctx->devices_status);
logfile_sub_msg ("STOP");
// stop loopback recording
if (user_options->loopback == true)
{
loopback_write_close (hashcat_ctx);
}
// New induction folder check, which is a controlled recursion
if (induct_ctx->induction_dictionaries_cnt == 0)
{
induct_ctx_scan (hashcat_ctx);
while (induct_ctx->induction_dictionaries_cnt)
{
for (induct_ctx->induction_dictionaries_pos = 0; induct_ctx->induction_dictionaries_pos < induct_ctx->induction_dictionaries_cnt; induct_ctx->induction_dictionaries_pos++)
{
if (status_ctx->devices_status == STATUS_EXHAUSTED)
{
if (inner2_loop (hashcat_ctx) == -1) myabort (hashcat_ctx);
if (status_ctx->run_main_level3 == false) break;
}
unlink (induct_ctx->induction_dictionaries[induct_ctx->induction_dictionaries_pos]);
}
hcfree (induct_ctx->induction_dictionaries);
induct_ctx_scan (hashcat_ctx);
}
}
return 0;
}
// inner1_loop iterates through masks, then calls inner2_loop
static int inner1_loop (hashcat_ctx_t *hashcat_ctx)
{
restore_ctx_t *restore_ctx = hashcat_ctx->restore_ctx;
status_ctx_t *status_ctx = hashcat_ctx->status_ctx;
straight_ctx_t *straight_ctx = hashcat_ctx->straight_ctx;
//status_ctx->run_main_level1 = true;
//status_ctx->run_main_level2 = true;
status_ctx->run_main_level3 = true;
status_ctx->run_thread_level1 = true;
status_ctx->run_thread_level2 = true;
/**
* loop through wordlists
*/
EVENT (EVENT_INNERLOOP2_STARTING);
if (restore_ctx->rd)
{
restore_data_t *rd = restore_ctx->rd;
if (rd->dicts_pos > 0)
{
straight_ctx->dicts_pos = rd->dicts_pos;
rd->dicts_pos = 0;
}
}
if (straight_ctx->dicts_cnt)
{
for (u32 dicts_pos = straight_ctx->dicts_pos; dicts_pos < straight_ctx->dicts_cnt; dicts_pos++)
{
straight_ctx->dicts_pos = dicts_pos;
if (inner2_loop (hashcat_ctx) == -1) myabort (hashcat_ctx);
if (status_ctx->run_main_level3 == false) break;
}
if (status_ctx->run_main_level3 == true)
{
if (straight_ctx->dicts_pos + 1 == straight_ctx->dicts_cnt) straight_ctx->dicts_pos = 0;
}
}
else
{
if (inner2_loop (hashcat_ctx) == -1) myabort (hashcat_ctx);
}
EVENT (EVENT_INNERLOOP2_FINISHED);
return 0;
}
// outer_loop iterates through hash_modes (in benchmark mode)
// also initializes stuff that depend on hash mode
static int outer_loop (hashcat_ctx_t *hashcat_ctx)
{
hashconfig_t *hashconfig = hashcat_ctx->hashconfig;
hashes_t *hashes = hashcat_ctx->hashes;
mask_ctx_t *mask_ctx = hashcat_ctx->mask_ctx;
module_ctx_t *module_ctx = hashcat_ctx->module_ctx;
backend_ctx_t *backend_ctx = hashcat_ctx->backend_ctx;
outcheck_ctx_t *outcheck_ctx = hashcat_ctx->outcheck_ctx;
restore_ctx_t *restore_ctx = hashcat_ctx->restore_ctx;
status_ctx_t *status_ctx = hashcat_ctx->status_ctx;
straight_ctx_t *straight_ctx = hashcat_ctx->straight_ctx;
user_options_t *user_options = hashcat_ctx->user_options;
user_options_extra_t *user_options_extra = hashcat_ctx->user_options_extra;
status_ctx->devices_status = STATUS_INIT;
//status_ctx->run_main_level1 = true;
status_ctx->run_main_level2 = true;
status_ctx->run_main_level3 = true;
status_ctx->run_thread_level1 = true;
status_ctx->run_thread_level2 = true;
/**
* setup variables and buffers depending on hash_mode
*/
EVENT (EVENT_HASHCONFIG_PRE);
if (hashconfig_init (hashcat_ctx) == -1)
{
event_log_error (hashcat_ctx, "Invalid hash-mode '%u' selected.", user_options->hash_mode);
return -1;
}
EVENT (EVENT_HASHCONFIG_POST);
/**
* deprecated notice
*/
if (module_ctx->module_deprecated_notice != MODULE_DEFAULT)
{
if (user_options->deprecated_check == true)
{
if ((user_options->show == true) || (user_options->left == true))
{
const char *module_deprecated_notice = module_ctx->module_deprecated_notice (hashconfig, user_options, user_options_extra);
event_log_warning (hashcat_ctx, "%s", module_deprecated_notice);
event_log_warning (hashcat_ctx, NULL);
}
else if (user_options->benchmark == true)
{
if (user_options->hash_mode_chgd == true)
{
const char *module_deprecated_notice = module_ctx->module_deprecated_notice (hashconfig, user_options, user_options_extra);
event_log_warning (hashcat_ctx, "%s", module_deprecated_notice);
event_log_warning (hashcat_ctx, NULL);
}
else
{
return 0;
}
}
else
{
const char *module_deprecated_notice = module_ctx->module_deprecated_notice (hashconfig, user_options, user_options_extra);
event_log_error (hashcat_ctx, "%s", module_deprecated_notice);
return 0;
}
}
}
/**
* generate hashlist filename for later use
*/
if (hashes_init_filename (hashcat_ctx) == -1) return -1;
/**
* load hashes, stage 1
*/
if (hashes_init_stage1 (hashcat_ctx) == -1) return -1;
if ((user_options->keyspace == false) && (user_options->stdout_flag == false))
{
if (hashes->hashes_cnt == 0)
{
event_log_error (hashcat_ctx, "No hashes loaded.");
return -1;
}
}
/**
* load hashes, stage 2, remove duplicates, build base structure
*/
hashes->hashes_cnt_orig = hashes->hashes_cnt;
if (hashes_init_stage2 (hashcat_ctx) == -1) return -1;
/**
* potfile removes
*/
if (user_options->potfile == true)
{
EVENT (EVENT_POTFILE_REMOVE_PARSE_PRE);
if (user_options->loopback == true)
{
loopback_write_open (hashcat_ctx);
}
potfile_remove_parse (hashcat_ctx);
if (user_options->loopback == true)
{
loopback_write_close (hashcat_ctx);
}
EVENT (EVENT_POTFILE_REMOVE_PARSE_POST);
}
/**
* zero hash removes
*/
if (hashes_init_zerohash (hashcat_ctx) == -1) return -1;
/**
* load hashes, stage 3, update cracked results from potfile
*/
if (hashes_init_stage3 (hashcat_ctx) == -1) return -1;
/**
* potfile show/left handling
*/
if (user_options->show == true)
{
status_ctx->devices_status = STATUS_RUNNING;
outfile_write_open (hashcat_ctx);
if (potfile_handle_show (hashcat_ctx) == -1) return -1;
outfile_write_close (hashcat_ctx);
return 0;
}
if (user_options->left == true)
{
status_ctx->devices_status = STATUS_RUNNING;
outfile_write_open (hashcat_ctx);
if (potfile_handle_left (hashcat_ctx) == -1) return -1;
outfile_write_close (hashcat_ctx);
return 0;
}
/**
* check global hash count in case module developer sets a them to a specific limit
*/
if (hashes->digests_cnt < hashconfig->hashes_count_min)
{
event_log_error (hashcat_ctx, "Not enough hashes loaded - minimum is %u for this hash-mode.", hashconfig->hashes_count_min);
return -1;
}
if (hashes->digests_cnt > hashconfig->hashes_count_max)
{
event_log_error (hashcat_ctx, "Too many hashes loaded - maximum is %u for this hash-mode.", hashconfig->hashes_count_max);
return -1;
}
/**
* maybe all hashes were cracked, we can exit here
*/
if (status_ctx->devices_status == STATUS_CRACKED)
{
if ((user_options->remove == true) && ((hashes->hashlist_mode == HL_MODE_FILE_PLAIN) || (hashes->hashlist_mode == HL_MODE_FILE_BINARY)))
{
if (hashes->digests_saved != hashes->digests_done)
{
const int rc = save_hash (hashcat_ctx);
if (rc == -1) return -1;
}
}
EVENT (EVENT_POTFILE_ALL_CRACKED);
return 0;
}
/**
* load hashes, stage 4, automatic Optimizers
*/
if (hashes_init_stage4 (hashcat_ctx) == -1) return -1;
/**
* load hashes, selftest
*/
if (hashes_init_selftest (hashcat_ctx) == -1) return -1;
/**
* load hashes, post automatisation
*/
if (hashes_init_stage5 (hashcat_ctx) == -1) return -1;
/**
* load hashes, benchmark
*/
if (hashes_init_benchmark (hashcat_ctx) == -1) return -1;
/**
* Done loading hashes, log results
*/
hashes_logger (hashcat_ctx);
/**
* bitmaps
*/
EVENT (EVENT_BITMAP_INIT_PRE);
if (bitmap_ctx_init (hashcat_ctx) == -1) return -1;
EVENT (EVENT_BITMAP_INIT_POST);
/**
* cracks-per-time allocate buffer
*/
cpt_ctx_init (hashcat_ctx);
/**
* Wordlist allocate buffer
*/
if (wl_data_init (hashcat_ctx) == -1) return -1;
/**
* straight mode init
*/
if (straight_ctx_init (hashcat_ctx) == -1) return -1;
/**
* combinator mode init
*/
if (combinator_ctx_init (hashcat_ctx) == -1) return -1;
/**
* charsets : keep them together for more easy maintenance
*/
if (mask_ctx_init (hashcat_ctx) == -1) return -1;
/**
* prevent the user from using --skip/--limit together with maskfile and/or multiple word lists
*/
if (user_options->skip != 0 || user_options->limit != 0)
{
if ((mask_ctx->masks_cnt > 1) || (straight_ctx->dicts_cnt > 1))
{
event_log_error (hashcat_ctx, "Use of --skip/--limit is not supported with --increment, mask files, or --stdout.");
return -1;
}
}
/**
* prevent the user from using --keyspace together with maskfile and/or multiple word lists
*/
if (user_options->keyspace == true)
{
if ((mask_ctx->masks_cnt > 1) || (straight_ctx->dicts_cnt > 1))
{
event_log_error (hashcat_ctx, "Use of --keyspace is not supported with --increment or mask files.");
return -1;
}
}
/**
* prevent the user from using -m/--hash-type together with --stdout
*/
if (user_options->hash_mode_chgd == true && user_options->stdout_flag == true)
{
event_log_error (hashcat_ctx, "Use of -m/--hash-type is not supported with --stdout.");
return -1;
}
/**
* status progress init; needs hashes that's why we have to do it here and separate from status_ctx_init
*/
if (status_progress_init (hashcat_ctx) == -1) return -1;
/**
* main screen
*/
EVENT (EVENT_OUTERLOOP_MAINSCREEN);
/**
* Tell user about cracked hashes by potfile
*/
EVENT (EVENT_POTFILE_NUM_CRACKED);
/**
* setup salts for bridges, needs to be after bridge init, but before session start
*/
EVENT (EVENT_BRIDGES_SALT_PRE);
if (bridges_salt_prepare (hashcat_ctx) == false)
{
event_log_error (hashcat_ctx, "Bridge salt preparation for hash-mode '%u' failed.", user_options->hash_mode);
return -1;
}
EVENT (EVENT_BRIDGES_SALT_POST);
/**
* inform the user
*/
EVENT (EVENT_BACKEND_SESSION_PRE);
if (backend_session_begin (hashcat_ctx) == -1)
{
if (user_options->benchmark == true)
{
if (user_options->hash_mode_chgd == false)
{
// finalize backend session
backend_session_destroy (hashcat_ctx);
// clean up
#ifdef WITH_BRAIN
brain_ctx_destroy (hashcat_ctx);
#endif
bridges_salt_destroy (hashcat_ctx);
bridges_destroy (hashcat_ctx);
bitmap_ctx_destroy (hashcat_ctx);
combinator_ctx_destroy (hashcat_ctx);
cpt_ctx_destroy (hashcat_ctx);
hashconfig_destroy (hashcat_ctx);
hashes_destroy (hashcat_ctx);
mask_ctx_destroy (hashcat_ctx);
status_progress_destroy (hashcat_ctx);
straight_ctx_destroy (hashcat_ctx);
wl_data_destroy (hashcat_ctx);
return 0;
}
}
return -1;
}
EVENT (EVENT_BACKEND_SESSION_POST);
/**
* create self-test threads
*/
if ((hashconfig->opts_type & OPTS_TYPE_SELF_TEST_DISABLE) == 0)
{
EVENT (EVENT_SELFTEST_STARTING);
thread_param_t *threads_param = (thread_param_t *) hccalloc (backend_ctx->backend_devices_cnt, sizeof (thread_param_t));
hc_thread_t *selftest_threads = (hc_thread_t *) hccalloc (backend_ctx->backend_devices_cnt, sizeof (hc_thread_t));
status_ctx->devices_status = STATUS_SELFTEST;
for (int backend_devices_idx = 0; backend_devices_idx < backend_ctx->backend_devices_cnt; backend_devices_idx++)
{
thread_param_t *thread_param = threads_param + backend_devices_idx;
thread_param->hashcat_ctx = hashcat_ctx;
thread_param->tid = backend_devices_idx;
hc_thread_create (selftest_threads[backend_devices_idx], thread_selftest, thread_param);
}
hc_thread_wait (backend_ctx->backend_devices_cnt, selftest_threads);
hcfree (threads_param);
hcfree (selftest_threads);
// check for any selftest failures
for (int backend_devices_idx = 0; backend_devices_idx < backend_ctx->backend_devices_cnt; backend_devices_idx++)
{
if (backend_ctx->enabled == false) continue;
hc_device_param_t *device_param = backend_ctx->devices_param + backend_devices_idx;
if (device_param->skipped == true) continue;
if (device_param->st_status == ST_STATUS_FAILED)
{
event_log_error (hashcat_ctx, "Aborting session due to kernel self-test failure.");
event_log_warning (hashcat_ctx, "You can use --self-test-disable to override, but do not report related errors.");
event_log_warning (hashcat_ctx, NULL);
backend_ctx->self_test_warnings = true;
return -1;
}
}
status_ctx->devices_status = STATUS_INIT;
EVENT (EVENT_SELFTEST_FINISHED);
}
/**
* (old) weak hash check is the first to write to potfile, so open it for writing from here
* the weak hash check was removed maybe we can move this more to the bottom now
*/
if (potfile_write_open (hashcat_ctx) == -1) return -1;
/**
* status and monitor threads
*/
int inner_threads_cnt = 0;
hc_thread_t *inner_threads = (hc_thread_t *) hccalloc (10, sizeof (hc_thread_t));
status_ctx->shutdown_inner = false;
/**
* Outfile remove
*/
if (user_options->keyspace == false && user_options->stdout_flag == false && user_options->speed_only == false)
{
hc_thread_create (inner_threads[inner_threads_cnt], thread_monitor, hashcat_ctx);
inner_threads_cnt++;
if (outcheck_ctx->enabled == true)
{
hc_thread_create (inner_threads[inner_threads_cnt], thread_outfile_remove, hashcat_ctx);
inner_threads_cnt++;
}
}
// main call
if (restore_ctx->rd)
{
restore_data_t *rd = restore_ctx->rd;
if (rd->masks_pos > 0)
{
mask_ctx->masks_pos = rd->masks_pos;
rd->masks_pos = 0;
}
}
EVENT (EVENT_INNERLOOP1_STARTING);
if (mask_ctx->masks_cnt)
{
for (u32 masks_pos = mask_ctx->masks_pos; masks_pos < mask_ctx->masks_cnt; masks_pos++)
{
mask_ctx->masks_pos = masks_pos;
if (inner1_loop (hashcat_ctx) == -1) myabort (hashcat_ctx);
if (status_ctx->run_main_level2 == false) break;
}
if (status_ctx->run_main_level2 == true)
{
if (mask_ctx->masks_pos + 1 == mask_ctx->masks_cnt) mask_ctx->masks_pos = 0;
}
}
else
{
if (inner1_loop (hashcat_ctx) == -1) myabort (hashcat_ctx);
}
// wait for inner threads
status_ctx->shutdown_inner = true;
for (int thread_idx = 0; thread_idx < inner_threads_cnt; thread_idx++)
{
hc_thread_wait (1, &inner_threads[thread_idx]);
}
hcfree (inner_threads);
EVENT (EVENT_INNERLOOP1_FINISHED);
// finalize potfile
potfile_write_close (hashcat_ctx);
// finalize backend session
backend_session_destroy (hashcat_ctx);
// clean up
#ifdef WITH_BRAIN
brain_ctx_destroy (hashcat_ctx);
#endif
bridges_salt_destroy (hashcat_ctx);
bridges_destroy (hashcat_ctx);
bitmap_ctx_destroy (hashcat_ctx);
combinator_ctx_destroy (hashcat_ctx);
cpt_ctx_destroy (hashcat_ctx);
hashconfig_destroy (hashcat_ctx);
hashes_destroy (hashcat_ctx);
mask_ctx_destroy (hashcat_ctx);
status_progress_destroy (hashcat_ctx);
straight_ctx_destroy (hashcat_ctx);
wl_data_destroy (hashcat_ctx);
return 0;
}
static void event_stub (MAYBE_UNUSED const u32 id, MAYBE_UNUSED hashcat_ctx_t *hashcat_ctx, MAYBE_UNUSED const void *buf, MAYBE_UNUSED const size_t len)
{
}
int hashcat_init (hashcat_ctx_t *hashcat_ctx, void (*event) (const u32, struct hashcat_ctx *, const void *, const size_t))
{
if (event == NULL)
{
hashcat_ctx->event = event_stub;
}
else
{
hashcat_ctx->event = event;
}
hashcat_ctx->bitmap_ctx = (bitmap_ctx_t *) hcmalloc (sizeof (bitmap_ctx_t));
hashcat_ctx->brain_ctx = (brain_ctx_t *) hcmalloc (sizeof (brain_ctx_t));
hashcat_ctx->bridge_ctx = (bridge_ctx_t *) hcmalloc (sizeof (bridge_ctx_t));
hashcat_ctx->combinator_ctx = (combinator_ctx_t *) hcmalloc (sizeof (combinator_ctx_t));
hashcat_ctx->cpt_ctx = (cpt_ctx_t *) hcmalloc (sizeof (cpt_ctx_t));
hashcat_ctx->debugfile_ctx = (debugfile_ctx_t *) hcmalloc (sizeof (debugfile_ctx_t));
hashcat_ctx->dictstat_ctx = (dictstat_ctx_t *) hcmalloc (sizeof (dictstat_ctx_t));
hashcat_ctx->event_ctx = (event_ctx_t *) hcmalloc (sizeof (event_ctx_t));
hashcat_ctx->folder_config = (folder_config_t *) hcmalloc (sizeof (folder_config_t));
hashcat_ctx->hashcat_user = (hashcat_user_t *) hcmalloc (sizeof (hashcat_user_t));
hashcat_ctx->hashconfig = (hashconfig_t *) hcmalloc (sizeof (hashconfig_t));
hashcat_ctx->hashes = (hashes_t *) hcmalloc (sizeof (hashes_t));
hashcat_ctx->hwmon_ctx = (hwmon_ctx_t *) hcmalloc (sizeof (hwmon_ctx_t));
hashcat_ctx->induct_ctx = (induct_ctx_t *) hcmalloc (sizeof (induct_ctx_t));
hashcat_ctx->logfile_ctx = (logfile_ctx_t *) hcmalloc (sizeof (logfile_ctx_t));
hashcat_ctx->loopback_ctx = (loopback_ctx_t *) hcmalloc (sizeof (loopback_ctx_t));
hashcat_ctx->mask_ctx = (mask_ctx_t *) hcmalloc (sizeof (mask_ctx_t));
hashcat_ctx->module_ctx = (module_ctx_t *) hcmalloc (sizeof (module_ctx_t));
hashcat_ctx->backend_ctx = (backend_ctx_t *) hcmalloc (sizeof (backend_ctx_t));
hashcat_ctx->outcheck_ctx = (outcheck_ctx_t *) hcmalloc (sizeof (outcheck_ctx_t));
hashcat_ctx->outfile_ctx = (outfile_ctx_t *) hcmalloc (sizeof (outfile_ctx_t));
hashcat_ctx->pidfile_ctx = (pidfile_ctx_t *) hcmalloc (sizeof (pidfile_ctx_t));
hashcat_ctx->potfile_ctx = (potfile_ctx_t *) hcmalloc (sizeof (potfile_ctx_t));
hashcat_ctx->restore_ctx = (restore_ctx_t *) hcmalloc (sizeof (restore_ctx_t));
hashcat_ctx->status_ctx = (status_ctx_t *) hcmalloc (sizeof (status_ctx_t));
hashcat_ctx->straight_ctx = (straight_ctx_t *) hcmalloc (sizeof (straight_ctx_t));
hashcat_ctx->tuning_db = (tuning_db_t *) hcmalloc (sizeof (tuning_db_t));
hashcat_ctx->user_options_extra = (user_options_extra_t *) hcmalloc (sizeof (user_options_extra_t));
hashcat_ctx->user_options = (user_options_t *) hcmalloc (sizeof (user_options_t));
hashcat_ctx->wl_data = (wl_data_t *) hcmalloc (sizeof (wl_data_t));
return 0;
}
void hashcat_destroy (hashcat_ctx_t *hashcat_ctx)
{
hcfree (hashcat_ctx->bitmap_ctx);
hcfree (hashcat_ctx->brain_ctx);
hcfree (hashcat_ctx->bridge_ctx);
hcfree (hashcat_ctx->combinator_ctx);
hcfree (hashcat_ctx->cpt_ctx);
hcfree (hashcat_ctx->debugfile_ctx);
hcfree (hashcat_ctx->dictstat_ctx);
hcfree (hashcat_ctx->event_ctx);
hcfree (hashcat_ctx->folder_config);
hcfree (hashcat_ctx->hashcat_user);
hcfree (hashcat_ctx->hashconfig);
hcfree (hashcat_ctx->hashes);
hcfree (hashcat_ctx->hwmon_ctx);
hcfree (hashcat_ctx->induct_ctx);
hcfree (hashcat_ctx->logfile_ctx);
hcfree (hashcat_ctx->loopback_ctx);
hcfree (hashcat_ctx->mask_ctx);
hcfree (hashcat_ctx->module_ctx);
hcfree (hashcat_ctx->backend_ctx);
hcfree (hashcat_ctx->outcheck_ctx);
hcfree (hashcat_ctx->outfile_ctx);
hcfree (hashcat_ctx->pidfile_ctx);
hcfree (hashcat_ctx->potfile_ctx);
hcfree (hashcat_ctx->restore_ctx);
hcfree (hashcat_ctx->status_ctx);
hcfree (hashcat_ctx->straight_ctx);
hcfree (hashcat_ctx->tuning_db);
hcfree (hashcat_ctx->user_options_extra);
hcfree (hashcat_ctx->user_options);
hcfree (hashcat_ctx->wl_data);
memset (hashcat_ctx, 0, sizeof (hashcat_ctx_t));
}
int hashcat_session_init (hashcat_ctx_t *hashcat_ctx, const char *install_folder, const char *shared_folder, int argc, char **argv, const int comptime)
{
user_options_t *user_options = hashcat_ctx->user_options;
/**
* make it a bit more comfortable to use some of the special modes in hashcat
*/
user_options_session_auto (hashcat_ctx);
/**
* event init (needed for logging so should be first)
*/
if (event_ctx_init (hashcat_ctx) == -1) return -1;
/**
* status init
*/
if (status_ctx_init (hashcat_ctx) == -1) return -1;
/**
* folder
*/
if (folder_config_init (hashcat_ctx, install_folder, shared_folder) == -1) return -1;
/**
* pidfile
*/
if (pidfile_ctx_init (hashcat_ctx) == -1) return -1;
/**
* restore
*/
if (restore_ctx_init (hashcat_ctx, argc, argv) == -1) return -1;
/**
* process user input
*/
user_options_preprocess (hashcat_ctx);
user_options_extra_init (hashcat_ctx);
user_options_postprocess (hashcat_ctx);
/**
* windows and sockets...
*/
#ifdef WITH_BRAIN
#if defined (_WIN)
if (user_options->brain_client == true)
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD (2,2);
if (WSAStartup (wVersionRequested, &wsaData) != NO_ERROR)
{
fprintf (stderr, "WSAStartup: %s\n", strerror (errno));
return -1;
}
}
#endif
/**
* brain
*/
if (brain_ctx_init (hashcat_ctx) == -1) return -1;
#endif
/**
* logfile
*/
if (logfile_init (hashcat_ctx) == -1) return -1;
/**
* cpu affinity
*/
if (set_cpu_affinity (hashcat_ctx) == -1) return -1;
/**
* prepare seeding for random number generator, required by logfile and rules generator
*/
setup_seeding (user_options->rp_gen_seed_chgd, user_options->rp_gen_seed);
/**
* To help users a bit
*/
setup_environment_variables (hashcat_ctx->folder_config, hashcat_ctx->user_options);
setup_umask ();
/**
* tuning db
*/
if (tuning_db_init (hashcat_ctx) == -1) return -1;
/**
* induction directory
*/
if (induct_ctx_init (hashcat_ctx) == -1) return -1;
/**
* outfile-check directory
*/
if (outcheck_ctx_init (hashcat_ctx) == -1) return -1;
/**
* outfile itself
*/
if (outfile_init (hashcat_ctx) == -1) return -1;
/**
* potfile init
* this is only setting path because potfile can be used in read and write mode depending on user options
* plus it depends on hash_mode, so we continue using it in outer_loop
*/
if (potfile_init (hashcat_ctx) == -1) return -1;
/**
* dictstat init
*/
if (dictstat_init (hashcat_ctx) == -1) return -1;
/**
* loopback init
*/
if (loopback_init (hashcat_ctx) == -1) return -1;
/**
* debugfile init
*/
if (debugfile_init (hashcat_ctx) == -1) return -1;
/**
* Try to detect if all the files we're going to use are accessible in the mode we want them
*/
if (user_options_check_files (hashcat_ctx) == -1) return -1;
/**
* Load bridge a bit too early actually, but we need to know the unit count so we can automatically configure virtualization for the user
*/
EVENT (EVENT_BRIDGES_INIT_PRE);
if (bridges_init (hashcat_ctx) == false)
{
event_log_error (hashcat_ctx, "Bridge initialization for hash-mode '%u' failed.", user_options->hash_mode);
return -1;
}
EVENT (EVENT_BRIDGES_INIT_POST);
/**
* Init backend library loader
*/
if (backend_ctx_init (hashcat_ctx) == -1) return -1;
/**
* Init backend devices
*/
if (backend_ctx_devices_init (hashcat_ctx, comptime) == -1) return -1;
/**
* HM devices: init
*/
if (hwmon_ctx_init (hashcat_ctx) == -1) return -1;
// done
return 0;
}
bool autodetect_hashmode_test (hashcat_ctx_t *hashcat_ctx)
{
hashconfig_t *hashconfig = hashcat_ctx->hashconfig;
hashes_t *hashes = hashcat_ctx->hashes;
module_ctx_t *module_ctx = hashcat_ctx->module_ctx;
user_options_t *user_options = hashcat_ctx->user_options;
user_options_extra_t *user_options_extra = hashcat_ctx->user_options_extra;
// check for file or hash on command line
// if file, find out if binary file
if (hashconfig->opts_type & OPTS_TYPE_AUTODETECT_DISABLE) return false;
if (hashconfig->opts_type & OPTS_TYPE_BINARY_HASHFILE)
{
if (hashconfig->opts_type & OPTS_TYPE_BINARY_HASHFILE_OPTIONAL)
{
hashes->hashlist_mode = (hc_path_exist (user_options_extra->hc_hash) == true) ? HL_MODE_FILE_PLAIN : HL_MODE_ARG;
if (hashes->hashlist_mode == HL_MODE_FILE_PLAIN)
{
hashes->hashfile = user_options_extra->hc_hash;
}
}
else
{
hashes->hashlist_mode = HL_MODE_FILE_BINARY;
if (hc_path_read (user_options_extra->hc_hash) == false) return false;
hashes->hashfile = user_options_extra->hc_hash;
}
}
else
{
hashes->hashlist_mode = (hc_path_exist (user_options_extra->hc_hash) == true) ? HL_MODE_FILE_PLAIN : HL_MODE_ARG;
if (hashes->hashlist_mode == HL_MODE_FILE_PLAIN)
{
hashes->hashfile = user_options_extra->hc_hash;
}
}
/**
* load hashes, part I: find input mode
*/
const char *hashfile = hashes->hashfile;
const u32 hashlist_mode = hashes->hashlist_mode;
u32 hashlist_format = HLFMT_HASHCAT;
if (hashlist_mode == HL_MODE_FILE_PLAIN)
{
HCFILE fp;
if (hc_fopen (&fp, hashfile, "rb") == false) return false;
hashlist_format = hlfmt_detect (hashcat_ctx, &fp, 100);
hc_fclose (&fp);
}
hashes->hashlist_format = hashlist_format;
/**
* load hashes, part II: allocate required memory, set pointers
*/
void *digest = hccalloc (1, hashconfig->dgst_size);
salt_t *salt = (salt_t *) hccalloc (1, sizeof (salt_t));
void *esalt = NULL;
void *hook_salt = NULL;
if (hashconfig->esalt_size > 0)
{
esalt = hccalloc (1, hashconfig->esalt_size);
}
if (hashconfig->hook_salt_size > 0)
{
hook_salt = hccalloc (1, hashconfig->hook_salt_size);
}
hashinfo_t *hash_info = (hashinfo_t *) hcmalloc (sizeof (hashinfo_t));
hash_info->dynamicx = (dynamicx_t *) hcmalloc (sizeof (dynamicx_t));
hash_info->user = (user_t *) hcmalloc (sizeof (user_t));
hash_info->orighash = (char *) hcmalloc (256);
hash_info->split = (split_t *) hcmalloc (sizeof (split_t));
// this is required for multi hash iterations in binary files, for instance used in -m 14600
#define HASHES_IN_BINARY 10
hash_t *hashes_buf = (hash_t *) hccalloc (HASHES_IN_BINARY, sizeof (hash_t));
for (int i = 0; i < HASHES_IN_BINARY; i++)
{
hashes_buf[i].digest = digest;
hashes_buf[i].salt = salt;
hashes_buf[i].esalt = esalt;
hashes_buf[i].hook_salt = hook_salt;
}
hashes->hashes_buf = hashes_buf;
hashes->digests_buf = digest;
hashes->salts_buf = salt;
hashes->esalts_buf = esalt;
hashes->hook_salts_buf = hook_salt;
bool success = false;
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;
int hash_len = 0;
hlfmt_hash (hashcat_ctx, hashlist_format, input_buf, input_len, &hash_buf, &hash_len);
bool hash_fmt_error = false;
if (hash_len < 1) hash_fmt_error = true;
if (hash_buf == NULL) hash_fmt_error = true;
if (hash_fmt_error) return false;
const int parser_status = module_ctx->module_hash_decode (hashconfig, digest, salt, esalt, hook_salt, hash_info, hash_buf, hash_len);
if (parser_status == PARSER_OK) success = true;
}
else if (hashlist_mode == HL_MODE_FILE_PLAIN)
{
HCFILE fp;
int error_count = 0;
if (hc_fopen (&fp, hashfile, "rb") == false) return false;
char *line_buf = (char *) hcmalloc (HCBUFSIZ_LARGE);
while (!hc_feof (&fp))
{
const size_t line_len = fgetl (&fp, line_buf, HCBUFSIZ_LARGE);
if (line_len == 0) continue;
char *hash_buf = NULL;
int hash_len = 0;
hlfmt_hash (hashcat_ctx, hashlist_format, line_buf, line_len, &hash_buf, &hash_len);
bool hash_fmt_error = false;
if (hash_len < 1) hash_fmt_error = true;
if (hash_buf == NULL) hash_fmt_error = true;
if (hash_fmt_error) continue;
int parser_status = module_ctx->module_hash_decode (hashconfig, digest, salt, esalt, hook_salt, hash_info, hash_buf, hash_len);
if (parser_status == PARSER_OK)
{
success = true;
break;
}
// abort this list after 100 errors
if (error_count == 100)
{
break;
}
else
{
error_count++;
}
}
hcfree (line_buf);
hc_fclose (&fp);
}
else if (hashlist_mode == HL_MODE_FILE_BINARY)
{
char *input_buf = user_options_extra->hc_hash;
size_t input_len = strlen (input_buf);
if (module_ctx->module_hash_binary_parse != MODULE_DEFAULT)
{
const int hashes_parsed = module_ctx->module_hash_binary_parse (hashconfig, user_options, user_options_extra, hashes);
if (hashes_parsed > 0) success = true;
}
else
{
const int parser_status = module_ctx->module_hash_decode (hashconfig, digest, salt, esalt, hook_salt, hash_info, input_buf, input_len);
if (parser_status == PARSER_OK) success = true;
}
}
hcfree (digest);
hcfree (salt);
hcfree (hash_info);
hcfree (hashes_buf);
if (hashconfig->esalt_size > 0)
{
hcfree (esalt);
}
if (hashconfig->hook_salt_size > 0)
{
hcfree (hook_salt);
}
hashes->digests_buf = NULL;
hashes->salts_buf = NULL;
hashes->esalts_buf = NULL;
hashes->hook_salts_buf = NULL;
return success;
}
int autodetect_hashmodes (hashcat_ctx_t *hashcat_ctx, usage_sort_t *usage_sort_buf)
{
folder_config_t *folder_config = hashcat_ctx->folder_config;
user_options_t *user_options = hashcat_ctx->user_options;
int usage_sort_cnt = 0;
// save quiet state so we can restore later
EVENT (EVENT_AUTODETECT_STARTING);
const bool quiet_sav = user_options->quiet;
user_options->quiet = true;
char *modulefile = (char *) hcmalloc (HCBUFSIZ_TINY);
if (modulefile == NULL) return -1;
// brute force all the modes
for (int i = 0; i < MODULE_HASH_MODES_MAXIMUM; i++)
{
user_options->hash_mode = i;
// this is just to find out of that hash-mode exists or not
module_filename (folder_config, i, modulefile, HCBUFSIZ_TINY);
if (hc_path_exist (modulefile) == false) continue;
// we know it exists, so load the plugin
const int hashconfig_init_rc = hashconfig_init (hashcat_ctx);
if (hashconfig_init_rc == 0)
{
const bool test_rc = autodetect_hashmode_test (hashcat_ctx);
if (test_rc == true)
{
usage_sort_buf[usage_sort_cnt].hash_mode = hashcat_ctx->hashconfig->hash_mode;
usage_sort_buf[usage_sort_cnt].hash_name = hcstrdup (hashcat_ctx->hashconfig->hash_name);
usage_sort_buf[usage_sort_cnt].hash_category = hashcat_ctx->hashconfig->hash_category;
usage_sort_cnt++;
}
}
// clean up
hashconfig_destroy (hashcat_ctx);
}
hcfree (modulefile);
qsort (usage_sort_buf, usage_sort_cnt, sizeof (usage_sort_t), sort_by_usage);
user_options->quiet = quiet_sav;
EVENT (EVENT_AUTODETECT_FINISHED);
return usage_sort_cnt;
}
int hashcat_session_execute (hashcat_ctx_t *hashcat_ctx)
{
folder_config_t *folder_config = hashcat_ctx->folder_config;
logfile_ctx_t *logfile_ctx = hashcat_ctx->logfile_ctx;
status_ctx_t *status_ctx = hashcat_ctx->status_ctx;
user_options_t *user_options = hashcat_ctx->user_options;
backend_ctx_t *backend_ctx = hashcat_ctx->backend_ctx;
// start logfile entry
const time_t proc_start = time (NULL);
logfile_generate_topid (hashcat_ctx);
logfile_top_msg ("START");
// capture current working directory in session log
// https://github.com/hashcat/hashcat/issues/2453
logfile_top_string (folder_config->cwd);
logfile_top_string (folder_config->install_dir);
logfile_top_string (folder_config->profile_dir);
logfile_top_string (folder_config->session_dir);
logfile_top_string (folder_config->shared_dir);
// add all user options to logfile in case we want to debug some user session
user_options_logger (hashcat_ctx);
// read dictionary cache
dictstat_read (hashcat_ctx);
// autodetect
if (user_options->autodetect == true)
{
status_ctx->devices_status = STATUS_AUTODETECT;
usage_sort_t *usage_sort_buf = (usage_sort_t *) hccalloc (MODULE_HASH_MODES_MAXIMUM, sizeof (usage_sort_t));
if (usage_sort_buf == NULL) return -1;
const int modes_cnt = autodetect_hashmodes (hashcat_ctx, usage_sort_buf);
if (modes_cnt <= 0)
{
if (user_options->show == false) event_log_error (hashcat_ctx, "No hash-mode matches the structure of the input hash.");
return -1;
}
if (modes_cnt > 1)
{
if (user_options->machine_readable == false)
{
event_log_info (hashcat_ctx, "The following %d hash-modes match the structure of your input hash:", modes_cnt);
event_log_info (hashcat_ctx, NULL);
event_log_info (hashcat_ctx, " # | Name | Category");
event_log_info (hashcat_ctx, " ======+============================================================+======================================");
}
for (int i = 0; i < modes_cnt; i++)
{
if (user_options->machine_readable == false)
{
event_log_info (hashcat_ctx, "%7u | %-58s | %s", usage_sort_buf[i].hash_mode, usage_sort_buf[i].hash_name, strhashcategory (usage_sort_buf[i].hash_category));
}
else
{
event_log_info (hashcat_ctx, "%u", usage_sort_buf[i].hash_mode);
}
hcfree (usage_sort_buf[i].hash_name);
}
hcfree (usage_sort_buf);
if (user_options->machine_readable == false) event_log_info (hashcat_ctx, NULL);
if (user_options->identify == false)
{
event_log_error (hashcat_ctx, "Please specify the hash-mode with -m [hash-mode].");
return -1;
}
return 0;
}
// modes_cnt == 1
if (user_options->identify == false)
{
event_log_warning (hashcat_ctx, "Hash-mode was not specified with -m. Attempting to auto-detect hash mode.");
event_log_warning (hashcat_ctx, "The following mode was auto-detected as the only one matching your input hash:");
}
if (user_options->identify == true)
{
if (user_options->machine_readable == true)
{
event_log_info (hashcat_ctx, "%u", usage_sort_buf[0].hash_mode);
}
else
{
event_log_info (hashcat_ctx, "The following hash-mode match the structure of your input hash:");
event_log_info (hashcat_ctx, NULL);
event_log_info (hashcat_ctx, " # | Name | Category");
event_log_info (hashcat_ctx, " ======+============================================================+======================================");
event_log_info (hashcat_ctx, "%7u | %-58s | %s", usage_sort_buf[0].hash_mode, usage_sort_buf[0].hash_name, strhashcategory (usage_sort_buf[0].hash_category));
event_log_info (hashcat_ctx, NULL);
}
}
else
{
event_log_info (hashcat_ctx, "\n%u | %s | %s\n", usage_sort_buf[0].hash_mode, usage_sort_buf[0].hash_name, strhashcategory (usage_sort_buf[0].hash_category));
}
if (user_options->identify == false)
{
event_log_warning (hashcat_ctx, "NOTE: Auto-detect is best effort. The correct hash-mode is NOT guaranteed!");
event_log_warning (hashcat_ctx, "Do NOT report auto-detect issues unless you are certain of the hash type.");
event_log_warning (hashcat_ctx, NULL);
}
user_options->hash_mode = usage_sort_buf[0].hash_mode;
hcfree (usage_sort_buf[0].hash_name);
hcfree (usage_sort_buf);
if (user_options->identify == true) return 0;
user_options->autodetect = false;
}
/**
* outer loop
*/
EVENT (EVENT_OUTERLOOP_STARTING);
int rc_final = -1;
if (user_options->benchmark == true)
{
const bool quiet_sav = user_options->quiet;
user_options->quiet = true;
if (user_options->hash_mode_chgd == true)
{
rc_final = outer_loop (hashcat_ctx);
if (rc_final == -1) myabort (hashcat_ctx);
}
else
{
int hash_mode = 0;
while ((hash_mode = benchmark_next (hashcat_ctx)) != -1)
{
if ((u32) hash_mode < user_options->benchmark_min) continue;
if ((u32) hash_mode > user_options->benchmark_max) continue;
user_options->hash_mode = hash_mode;
rc_final = outer_loop (hashcat_ctx);
if (rc_final == -1) myabort (hashcat_ctx);
if (status_ctx->run_main_level1 == false) break;
}
}
user_options->quiet = quiet_sav;
}
else
{
const bool quiet_sav = user_options->quiet;
if (user_options->speed_only == true) user_options->quiet = true;
rc_final = outer_loop (hashcat_ctx);
if (rc_final == -1) myabort (hashcat_ctx);
if (user_options->speed_only == true) user_options->quiet = quiet_sav;
}
EVENT (EVENT_OUTERLOOP_FINISHED);
// if exhausted or cracked, unlink the restore file
unlink_restore (hashcat_ctx);
// final update dictionary cache
dictstat_write (hashcat_ctx);
// final logfile entry
const time_t proc_stop = time (NULL);
logfile_top_uint (proc_start);
logfile_top_uint (proc_stop);
logfile_top_msg ("STOP");
// set final status code
if (rc_final == 0)
{
if (status_ctx->devices_status == STATUS_ABORTED_FINISH) rc_final = RC_FINAL_ABORT_FINISH;
if (status_ctx->devices_status == STATUS_ABORTED_RUNTIME) rc_final = RC_FINAL_ABORT_RUNTIME;
if (status_ctx->devices_status == STATUS_ABORTED_CHECKPOINT) rc_final = RC_FINAL_ABORT_CHECKPOINT;
if (status_ctx->devices_status == STATUS_ABORTED) rc_final = RC_FINAL_ABORT;
if (status_ctx->devices_status == STATUS_QUIT) rc_final = RC_FINAL_ABORT;
if (status_ctx->devices_status == STATUS_EXHAUSTED) rc_final = RC_FINAL_EXHAUSTED;
if (status_ctx->devices_status == STATUS_CRACKED) rc_final = RC_FINAL_OK;
if (status_ctx->devices_status == STATUS_ERROR) rc_final = RC_FINAL_ERROR;
}
else if (rc_final == -1)
{
// set up the new negative status code, useful in test.sh
// -2 is marked as used in status_codes.txt
if (backend_ctx->runtime_skip_warning == true) rc_final = -3;
if (backend_ctx->memory_hit_warning == true) rc_final = -4;
if (backend_ctx->kernel_build_warning == true) rc_final = -5;
if (backend_ctx->kernel_create_warning == true) rc_final = -6;
if (backend_ctx->kernel_accel_warnings == true) rc_final = -7;
if (backend_ctx->extra_size_warning == true) rc_final = -8;
if (backend_ctx->mixed_warnings == true) rc_final = -9;
if (backend_ctx->self_test_warnings == true) rc_final = -11;
}
// special case for --stdout
if (user_options->stdout_flag == true)
{
if (status_ctx->devices_status == STATUS_EXHAUSTED)
{
rc_final = 0;
}
}
// done
return rc_final;
}
int hashcat_session_pause (hashcat_ctx_t *hashcat_ctx)
{
return SuspendThreads (hashcat_ctx);
}
int hashcat_session_resume (hashcat_ctx_t *hashcat_ctx)
{
return ResumeThreads (hashcat_ctx);
}
int hashcat_session_bypass (hashcat_ctx_t *hashcat_ctx)
{
return bypass (hashcat_ctx);
}
int hashcat_session_checkpoint (hashcat_ctx_t *hashcat_ctx)
{
return stop_at_checkpoint (hashcat_ctx);
}
int hashcat_session_finish (hashcat_ctx_t *hashcat_ctx)
{
return finish_after_attack (hashcat_ctx);
}
int hashcat_session_quit (hashcat_ctx_t *hashcat_ctx)
{
return myabort (hashcat_ctx);
}
int hashcat_session_destroy (hashcat_ctx_t *hashcat_ctx)
{
#ifdef WITH_BRAIN
#if defined (_WIN)
user_options_t *user_options = hashcat_ctx->user_options;
if (user_options->brain_client == true)
{
WSACleanup ();
}
#endif
#endif
debugfile_destroy (hashcat_ctx);
dictstat_destroy (hashcat_ctx);
folder_config_destroy (hashcat_ctx);
hwmon_ctx_destroy (hashcat_ctx);
induct_ctx_destroy (hashcat_ctx);
logfile_destroy (hashcat_ctx);
loopback_destroy (hashcat_ctx);
backend_ctx_devices_destroy (hashcat_ctx);
backend_ctx_destroy (hashcat_ctx);
outcheck_ctx_destroy (hashcat_ctx);
outfile_destroy (hashcat_ctx);
pidfile_ctx_destroy (hashcat_ctx);
potfile_destroy (hashcat_ctx);
restore_ctx_destroy (hashcat_ctx);
tuning_db_destroy (hashcat_ctx);
user_options_destroy (hashcat_ctx);
user_options_extra_destroy (hashcat_ctx);
status_ctx_destroy (hashcat_ctx);
event_ctx_destroy (hashcat_ctx);
return 0;
}
char *hashcat_get_log (hashcat_ctx_t *hashcat_ctx)
{
event_ctx_t *event_ctx = hashcat_ctx->event_ctx;
return event_ctx->msg_buf;
}
int hashcat_get_status (hashcat_ctx_t *hashcat_ctx, hashcat_status_t *hashcat_status)
{
const status_ctx_t *status_ctx = hashcat_ctx->status_ctx;
memset (hashcat_status, 0, sizeof (hashcat_status_t));
if (status_ctx == NULL) return -1; // way too early
if (status_ctx->accessible == false)
{
if (status_ctx->hashcat_status_final->msec_running > 0)
{
memcpy (hashcat_status, status_ctx->hashcat_status_final, sizeof (hashcat_status_t));
return 0;
}
return -1; // still too early
}
hashcat_status->digests_cnt = status_get_digests_cnt (hashcat_ctx);
hashcat_status->digests_done = status_get_digests_done (hashcat_ctx);
hashcat_status->digests_done_pot = status_get_digests_done_pot (hashcat_ctx);
hashcat_status->digests_done_zero = status_get_digests_done_zero (hashcat_ctx);
hashcat_status->digests_done_new = status_get_digests_done_new (hashcat_ctx);
hashcat_status->digests_percent = status_get_digests_percent (hashcat_ctx);
hashcat_status->digests_percent_new = status_get_digests_percent_new (hashcat_ctx);
hashcat_status->hash_target = status_get_hash_target (hashcat_ctx);
hashcat_status->hash_name = status_get_hash_name (hashcat_ctx);
hashcat_status->guess_base = status_get_guess_base (hashcat_ctx);
hashcat_status->guess_base_offset = status_get_guess_base_offset (hashcat_ctx);
hashcat_status->guess_base_count = status_get_guess_base_count (hashcat_ctx);
hashcat_status->guess_base_percent = status_get_guess_base_percent (hashcat_ctx);
hashcat_status->guess_mod = status_get_guess_mod (hashcat_ctx);
hashcat_status->guess_mod_offset = status_get_guess_mod_offset (hashcat_ctx);
hashcat_status->guess_mod_count = status_get_guess_mod_count (hashcat_ctx);
hashcat_status->guess_mod_percent = status_get_guess_mod_percent (hashcat_ctx);
hashcat_status->guess_charset = status_get_guess_charset (hashcat_ctx);
hashcat_status->guess_mask_length = status_get_guess_mask_length (hashcat_ctx);
hashcat_status->guess_mode = status_get_guess_mode (hashcat_ctx);
hashcat_status->msec_paused = status_get_msec_paused (hashcat_ctx);
hashcat_status->msec_running = status_get_msec_running (hashcat_ctx);
hashcat_status->msec_real = status_get_msec_real (hashcat_ctx);
hashcat_status->progress_mode = status_get_progress_mode (hashcat_ctx);
hashcat_status->progress_finished_percent = status_get_progress_finished_percent (hashcat_ctx);
hashcat_status->progress_cur_relative_skip = status_get_progress_cur_relative_skip (hashcat_ctx);
hashcat_status->progress_cur = status_get_progress_cur (hashcat_ctx);
hashcat_status->progress_done = status_get_progress_done (hashcat_ctx);
hashcat_status->progress_end_relative_skip = status_get_progress_end_relative_skip (hashcat_ctx);
hashcat_status->progress_end = status_get_progress_end (hashcat_ctx);
hashcat_status->progress_ignore = status_get_progress_ignore (hashcat_ctx);
hashcat_status->progress_rejected = status_get_progress_rejected (hashcat_ctx);
hashcat_status->progress_rejected_percent = status_get_progress_rejected_percent (hashcat_ctx);
hashcat_status->progress_restored = status_get_progress_restored (hashcat_ctx);
hashcat_status->progress_skip = status_get_progress_skip (hashcat_ctx);
hashcat_status->restore_point = status_get_restore_point (hashcat_ctx);
hashcat_status->restore_total = status_get_restore_total (hashcat_ctx);
hashcat_status->restore_percent = status_get_restore_percent (hashcat_ctx);
hashcat_status->salts_cnt = status_get_salts_cnt (hashcat_ctx);
hashcat_status->salts_done = status_get_salts_done (hashcat_ctx);
hashcat_status->salts_percent = status_get_salts_percent (hashcat_ctx);
hashcat_status->session = status_get_session (hashcat_ctx);
#ifdef WITH_BRAIN
hashcat_status->brain_session = status_get_brain_session (hashcat_ctx);
hashcat_status->brain_attack = status_get_brain_attack (hashcat_ctx);
hashcat_status->brain_rx_all = status_get_brain_rx_all (hashcat_ctx);
hashcat_status->brain_tx_all = status_get_brain_tx_all (hashcat_ctx);
#endif
hashcat_status->status_string = status_get_status_string (hashcat_ctx);
hashcat_status->status_number = status_get_status_number (hashcat_ctx);
hashcat_status->time_estimated_absolute = status_get_time_estimated_absolute (hashcat_ctx);
hashcat_status->time_estimated_relative = status_get_time_estimated_relative (hashcat_ctx);
hashcat_status->time_started_absolute = status_get_time_started_absolute (hashcat_ctx);
hashcat_status->time_started_relative = status_get_time_started_relative (hashcat_ctx);
hashcat_status->cpt_cur_min = status_get_cpt_cur_min (hashcat_ctx);
hashcat_status->cpt_cur_hour = status_get_cpt_cur_hour (hashcat_ctx);
hashcat_status->cpt_cur_day = status_get_cpt_cur_day (hashcat_ctx);
hashcat_status->cpt_avg_min = status_get_cpt_avg_min (hashcat_ctx);
hashcat_status->cpt_avg_hour = status_get_cpt_avg_hour (hashcat_ctx);
hashcat_status->cpt_avg_day = status_get_cpt_avg_day (hashcat_ctx);
hashcat_status->cpt = status_get_cpt (hashcat_ctx);
// multiple devices
hashcat_status->device_info_cnt = status_get_device_info_cnt (hashcat_ctx);
hashcat_status->device_info_active = status_get_device_info_active (hashcat_ctx);
for (int device_id = 0; device_id < hashcat_status->device_info_cnt; device_id++)
{
device_info_t *device_info = hashcat_status->device_info_buf + device_id;
device_info->skipped_dev = status_get_skipped_dev (hashcat_ctx, device_id);
device_info->skipped_warning_dev = status_get_skipped_warning_dev (hashcat_ctx, device_id);
device_info->hashes_msec_dev = status_get_hashes_msec_dev (hashcat_ctx, device_id);
device_info->hashes_msec_dev_benchmark = status_get_hashes_msec_dev_benchmark (hashcat_ctx, device_id);
device_info->exec_msec_dev = status_get_exec_msec_dev (hashcat_ctx, device_id);
device_info->speed_sec_dev = status_get_speed_sec_dev (hashcat_ctx, device_id);
device_info->guess_candidates_dev = status_get_guess_candidates_dev (hashcat_ctx, device_id);
#if defined(__APPLE__)
device_info->hwmon_fan_dev = status_get_hwmon_fan_dev (hashcat_ctx);
#endif
device_info->hwmon_dev = status_get_hwmon_dev (hashcat_ctx, device_id);
device_info->corespeed_dev = status_get_corespeed_dev (hashcat_ctx, device_id);
device_info->memoryspeed_dev = status_get_memoryspeed_dev (hashcat_ctx, device_id);
device_info->progress_dev = status_get_progress_dev (hashcat_ctx, device_id);
device_info->runtime_msec_dev = status_get_runtime_msec_dev (hashcat_ctx, device_id);
device_info->kernel_accel_dev = status_get_kernel_accel_dev (hashcat_ctx, device_id);
device_info->kernel_loops_dev = status_get_kernel_loops_dev (hashcat_ctx, device_id);
device_info->kernel_threads_dev = status_get_kernel_threads_dev (hashcat_ctx, device_id);
device_info->vector_width_dev = status_get_vector_width_dev (hashcat_ctx, device_id);
device_info->salt_pos_dev = status_get_salt_pos_dev (hashcat_ctx, device_id);
device_info->innerloop_pos_dev = status_get_innerloop_pos_dev (hashcat_ctx, device_id);
device_info->innerloop_left_dev = status_get_innerloop_left_dev (hashcat_ctx, device_id);
device_info->iteration_pos_dev = status_get_iteration_pos_dev (hashcat_ctx, device_id);
device_info->iteration_left_dev = status_get_iteration_left_dev (hashcat_ctx, device_id);
device_info->device_name = status_get_device_name (hashcat_ctx, device_id);
device_info->device_type = status_get_device_type (hashcat_ctx, device_id);
#ifdef WITH_BRAIN
device_info->brain_link_client_id_dev = status_get_brain_link_client_id_dev (hashcat_ctx, device_id);
device_info->brain_link_status_dev = status_get_brain_link_status_dev (hashcat_ctx, device_id);
device_info->brain_link_recv_bytes_dev = status_get_brain_link_recv_bytes_dev (hashcat_ctx, device_id);
device_info->brain_link_send_bytes_dev = status_get_brain_link_send_bytes_dev (hashcat_ctx, device_id);
device_info->brain_link_recv_bytes_sec_dev = status_get_brain_link_recv_bytes_sec_dev (hashcat_ctx, device_id);
device_info->brain_link_send_bytes_sec_dev = status_get_brain_link_send_bytes_sec_dev (hashcat_ctx, device_id);
#endif
}
hashcat_status->hashes_msec_all = status_get_hashes_msec_all (hashcat_ctx);
hashcat_status->exec_msec_all = status_get_exec_msec_all (hashcat_ctx);
hashcat_status->speed_sec_all = status_get_speed_sec_all (hashcat_ctx);
return 0;
}