diff --git a/docs/changes.txt b/docs/changes.txt index 8436120af..14b1f8fc3 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -9,6 +9,7 @@ - Added CUDA as a new compute API to hashcat backend (enables hashcat to run on NVIDIA Jetson, IBM POWER9 w/ Nvidia V100, etc.) - Added new options --backend-ignore-cuda and --backend-ingore-opencl to ignore CUDA and/or OpenCL interface from being load on startup - Added new parameter --brain-server-timer to specify the seconds for the next scheduled backup +- Added new way to specify the outfile format, the new --outfile-format now also supports timestamps - Support use of all available GPU memory using CUDA backend - Support use of all available CPU cores for hash-mode specific hooks - Support on-the-fly loading of compressed wordlists in zip and gzip format diff --git a/extra/tab_completion/hashcat.sh b/extra/tab_completion/hashcat.sh index d420faf23..ad32a61f4 100644 --- a/extra/tab_completion/hashcat.sh +++ b/extra/tab_completion/hashcat.sh @@ -302,7 +302,7 @@ _hashcat () local ATTACK_MODES="0 1 3 6 7" local HCCAPX_MESSAGE_PAIRS="0 1 2 3 4 5" - local OUTFILE_FORMATS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" + local OUTFILE_FORMATS="1 2 3 4 5 6" local OPENCL_DEVICE_TYPES="1 2 3" local BACKEND_VECTOR_WIDTH="1 2 4 8 16" local DEBUG_MODE="1 2 3 4" @@ -348,7 +348,29 @@ _hashcat () ;; --outfile-format) - COMPREPLY=($(compgen -W "${OUTFILE_FORMATS}" -- ${cur})) + local outfile_format_list="" + + local filter_list=$(echo -n "${OUTFILE_FORMATS}" | sed 's/ //g') + + if echo "${cur}" | grep -q "^[,${filter_list}]*$"; then + outfile_format_list="${cur}" + + # remove formats already used in the command line: + local formats_used=$(echo -n "${cur}" | sed 's/,/\n/g') + local allowed_formats=$(echo -n "${OUTFILE_FORMATS}" | sed 's/ /\n/g') + + local i + for i in $formats_used; do + allowed_formats=$(echo -n "${allowed_formats}" | grep -v "${formats_used}") + done + + outfile_format_list="${cur}" + for i in $allowed_formats; do + outfile_format_list="${outfile_format_list} ${cur},${i}" + done + fi + + COMPREPLY=($(compgen -W "${outfile_format_list}" -- ${cur})) return 0 ;; diff --git a/include/outfile.h b/include/outfile.h index 79790cf61..e54c09a35 100644 --- a/include/outfile.h +++ b/include/outfile.h @@ -14,6 +14,8 @@ int build_plain (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_para int build_crackpos (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_param, plain_t *plain, u64 *out_pos); int build_debugdata (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_param, plain_t *plain, u8 *debug_rule_buf, int *debug_rule_len, u8 *debug_plain_ptr, int *debug_plain_len); +u32 outfile_format_parse (const char *format_string); + int outfile_init (hashcat_ctx_t *hashcat_ctx); void outfile_destroy (hashcat_ctx_t *hashcat_ctx); int outfile_write_open (hashcat_ctx_t *hashcat_ctx); diff --git a/include/types.h b/include/types.h index 099cdb19c..057085768 100644 --- a/include/types.h +++ b/include/types.h @@ -485,7 +485,9 @@ typedef enum outfile_fmt OUTFILE_FMT_HASH = (1 << 0), OUTFILE_FMT_PLAIN = (1 << 1), OUTFILE_FMT_HEXPLAIN = (1 << 2), - OUTFILE_FMT_CRACKPOS = (1 << 3) + OUTFILE_FMT_CRACKPOS = (1 << 3), + OUTFILE_FMT_TIME_ABS = (1 << 4), + OUTFILE_FMT_TIME_REL = (1 << 5) } outfile_fmt_t; @@ -1923,6 +1925,7 @@ typedef struct user_options char *opencl_device_types; char *outfile; char *outfile_check_dir; + char *outfile_format; char *potfile_path; char *restore_file_path; char **rp_files; @@ -1962,7 +1965,6 @@ typedef struct user_options u32 spin_damp; u32 backend_vector_width; u32 outfile_check_timer; - u32 outfile_format; u32 remove_timer; u32 restore_timer; u32 rp_files_cnt; diff --git a/src/interface.c b/src/interface.c index 68be9f796..76ef8b330 100644 --- a/src/interface.c +++ b/src/interface.c @@ -12,6 +12,7 @@ #include "modules.h" #include "dynloader.h" #include "interface.h" +#include "outfile.h" /** * parsing @@ -515,7 +516,7 @@ u32 default_kernel_threads_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAY u32 default_forced_outfile_format (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { - const u32 forced_outfile_format = user_options->outfile_format; + const u32 forced_outfile_format = outfile_format_parse (user_options->outfile_format); return forced_outfile_format; } diff --git a/src/outfile.c b/src/outfile.c index 8dc949b50..f1d2b4989 100644 --- a/src/outfile.c +++ b/src/outfile.c @@ -5,6 +5,7 @@ #include "common.h" #include "types.h" +#include "memory.h" #include "event.h" #include "convert.h" #include "mpsp.h" @@ -16,6 +17,94 @@ #include "locking.h" #include "outfile.h" +u32 outfile_format_parse (const char *format_string) +{ + if (format_string == NULL) return OUTFILE_FORMAT; // default outfile format + + char *format = hcstrdup (format_string); + + if (format == NULL) return 0; + + char *saveptr = NULL; + + char *next = strtok_r (format, ",", &saveptr); + + u32 outfile_format = 0; + + do + { + const int tok_len = strlen (next); + + // reject non-numbers: + + if (is_valid_digit_string ((const u8 *) next, tok_len) == false) + { + outfile_format = 0; + break; + } + + // string to number conversion: + + const u32 num = hc_strtoul (next, NULL, 10); + + if (num == 0) + { + outfile_format = 0; + break; + } + + if (num > 31) + { + outfile_format = 0; + break; + } + + // to bitmask: + + const u32 bit = 1 << (num - 1); + + bool accepted = false; + + switch (bit) + { + // allowed formats: + case OUTFILE_FMT_HASH: + case OUTFILE_FMT_PLAIN: + case OUTFILE_FMT_HEXPLAIN: + case OUTFILE_FMT_CRACKPOS: + case OUTFILE_FMT_TIME_ABS: + case OUTFILE_FMT_TIME_REL: + accepted = true; + break; + // NOT acceptable formats: + default: + accepted = false; + break; + } + + if (accepted == false) + { + outfile_format = 0; + break; + } + + // the user should specify any format at most once: + + if (outfile_format & bit) + { + outfile_format = 0; + break; + } + + outfile_format |= bit; + + } while ((next = strtok_r ((char *) NULL, ",", &saveptr)) != NULL); + + hcfree (format); + + return outfile_format; +} + int build_plain (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_param, plain_t *plain, u32 *plain_buf, int *out_len) { const combinator_ctx_t *combinator_ctx = hashcat_ctx->combinator_ctx; @@ -391,10 +480,10 @@ int outfile_init (hashcat_ctx_t *hashcat_ctx) outfile_ctx_t *outfile_ctx = hashcat_ctx->outfile_ctx; user_options_t *user_options = hashcat_ctx->user_options; - outfile_ctx->fp.pfp = NULL; - outfile_ctx->filename = user_options->outfile; - outfile_ctx->outfile_format = user_options->outfile_format; - outfile_ctx->outfile_autohex = user_options->outfile_autohex; + outfile_ctx->fp.pfp = NULL; + outfile_ctx->filename = user_options->outfile; + outfile_ctx->outfile_format = outfile_format_parse (user_options->outfile_format); + outfile_ctx->outfile_autohex = user_options->outfile_autohex; return 0; } @@ -445,6 +534,7 @@ int outfile_write (hashcat_ctx_t *hashcat_ctx, const char *out_buf, const int ou const hashconfig_t *hashconfig = hashcat_ctx->hashconfig; const user_options_t *user_options = hashcat_ctx->user_options; outfile_ctx_t *outfile_ctx = hashcat_ctx->outfile_ctx; + status_ctx_t *status_ctx = hashcat_ctx->status_ctx; const u32 outfile_format = (hashconfig->opts_type & OPTS_TYPE_PT_ALWAYS_HEXIFY) ? 5 : outfile_ctx->outfile_format; @@ -458,7 +548,7 @@ int outfile_write (hashcat_ctx_t *hashcat_ctx, const char *out_buf, const int ou tmp_len += user_len; - if (outfile_format & (OUTFILE_FMT_HASH | OUTFILE_FMT_PLAIN | OUTFILE_FMT_HEXPLAIN | OUTFILE_FMT_CRACKPOS)) + if (outfile_format & (OUTFILE_FMT_TIME_ABS | OUTFILE_FMT_TIME_REL | OUTFILE_FMT_HASH | OUTFILE_FMT_PLAIN | OUTFILE_FMT_HEXPLAIN | OUTFILE_FMT_CRACKPOS)) { tmp_buf[tmp_len] = hashconfig->separator; @@ -467,6 +557,47 @@ int outfile_write (hashcat_ctx_t *hashcat_ctx, const char *out_buf, const int ou } } + if (outfile_format & OUTFILE_FMT_TIME_ABS) + { + time_t now; + + time (&now); + + tmp_len += snprintf (tmp_buf + tmp_len, HCBUFSIZ_LARGE - tmp_len, "%" PRIu64, (u64) now); + + if (outfile_format & (OUTFILE_FMT_TIME_REL | OUTFILE_FMT_HASH | OUTFILE_FMT_PLAIN | OUTFILE_FMT_HEXPLAIN | OUTFILE_FMT_CRACKPOS)) + { + tmp_buf[tmp_len] = hashconfig->separator; + + tmp_len += 1; + } + } + + if (outfile_format & OUTFILE_FMT_TIME_REL) + { + time_t time_now; + + time (&time_now); + + time_t time_started = status_ctx->runtime_start; + + u64 diff = 0; + + if (time_now > time_started) // should always be true, but you never know + { + diff = (u64) time_now - (u64) time_started; + } + + tmp_len += snprintf (tmp_buf + tmp_len, HCBUFSIZ_LARGE - tmp_len, "%" PRIu64, diff); + + if (outfile_format & (OUTFILE_FMT_HASH | OUTFILE_FMT_PLAIN | OUTFILE_FMT_HEXPLAIN | OUTFILE_FMT_CRACKPOS)) + { + tmp_buf[tmp_len] = hashconfig->separator; + + tmp_len += 1; + } + } + if (outfile_format & OUTFILE_FMT_HASH) { memcpy (tmp_buf + tmp_len, out_buf, out_len); diff --git a/src/usage.c b/src/usage.c index c7af49a18..6f5df8c74 100644 --- a/src/usage.c +++ b/src/usage.c @@ -53,7 +53,7 @@ static const char *const USAGE_BIG_PRE_HASHMODES[] = " --restore-disable | | Do not write restore file |", " --restore-file-path | File | Specific path to restore file | --restore-file-path=x.restore", " -o, --outfile | File | Define outfile for recovered hash | -o outfile.txt", - " --outfile-format | Num | Define outfile-format X for recovered hash | --outfile-format=7", + " --outfile-format | Str | Outfile format to use, separated with commas | --outfile-format=1,3", " --outfile-autohex-disable | | Disable the use of $HEX[] in output plains |", " --outfile-check-timer | Num | Sets seconds between outfile checks to X | --outfile-check=30", " --wordlist-autohex-disable | | Disable the conversion of $HEX[] from the wordlist |", @@ -160,19 +160,10 @@ static const char *const USAGE_BIG_POST_HASHMODES[] = " ===+========", " 1 | hash[:salt]", " 2 | plain", - " 3 | hash[:salt]:plain", - " 4 | hex_plain", - " 5 | hash[:salt]:hex_plain", - " 6 | plain:hex_plain", - " 7 | hash[:salt]:plain:hex_plain", - " 8 | crack_pos", - " 9 | hash[:salt]:crack_pos", - " 10 | plain:crack_pos", - " 11 | hash[:salt]:plain:crack_pos", - " 12 | hex_plain:crack_pos", - " 13 | hash[:salt]:hex_plain:crack_pos", - " 14 | plain:hex_plain:crack_pos", - " 15 | hash[:salt]:plain:hex_plain:crack_pos", + " 3 | hex_plain", + " 4 | crack_pos", + " 5 | timestamp absolute", + " 6 | timestamp relative", "", "- [ Rule Debugging Modes ] -", "", diff --git a/src/user_options.c b/src/user_options.c index e6811f87e..9d7fa473e 100644 --- a/src/user_options.c +++ b/src/user_options.c @@ -13,6 +13,7 @@ #include "usage.h" #include "backend.h" #include "user_options.h" +#include "outfile.h" #ifdef WITH_BRAIN #include "brain.h" @@ -218,7 +219,7 @@ int user_options_init (hashcat_ctx_t *hashcat_ctx) user_options->outfile_autohex = OUTFILE_AUTOHEX; user_options->outfile_check_dir = NULL; user_options->outfile_check_timer = OUTFILE_CHECK_TIMER; - user_options->outfile_format = OUTFILE_FORMAT; + user_options->outfile_format = NULL; user_options->outfile = NULL; user_options->potfile_disable = POTFILE_DISABLE; user_options->potfile_path = NULL; @@ -310,7 +311,6 @@ int user_options_getopt (hashcat_ctx_t *hashcat_ctx, int argc, char **argv) case IDX_RP_GEN_FUNC_MAX: case IDX_RP_GEN_SEED: case IDX_MARKOV_THRESHOLD: - case IDX_OUTFILE_FORMAT: case IDX_OUTFILE_CHECK_TIMER: case IDX_BACKEND_VECTOR_WIDTH: case IDX_WORKLOAD_PROFILE: @@ -423,7 +423,7 @@ int user_options_getopt (hashcat_ctx_t *hashcat_ctx, int argc, char **argv) case IDX_MARKOV_THRESHOLD: user_options->markov_threshold = hc_strtoul (optarg, NULL, 10); break; case IDX_MARKOV_HCSTAT2: user_options->markov_hcstat2 = optarg; break; case IDX_OUTFILE: user_options->outfile = optarg; break; - case IDX_OUTFILE_FORMAT: user_options->outfile_format = hc_strtoul (optarg, NULL, 10); + case IDX_OUTFILE_FORMAT: user_options->outfile_format = optarg; user_options->outfile_format_chgd = true; break; case IDX_OUTFILE_AUTOHEX_DISABLE: user_options->outfile_autohex = false; break; case IDX_OUTFILE_CHECK_TIMER: user_options->outfile_check_timer = hc_strtoul (optarg, NULL, 10); break; @@ -659,7 +659,9 @@ int user_options_sanity (hashcat_ctx_t *hashcat_ctx) return -1; } - if (user_options->outfile_format > 16) + const u32 outfile_format = outfile_format_parse (user_options->outfile_format); + + if (outfile_format == 0) { event_log_error (hashcat_ctx, "Invalid --outfile-format value specified."); @@ -670,7 +672,7 @@ int user_options_sanity (hashcat_ctx_t *hashcat_ctx) { if (user_options->outfile_format_chgd == true) { - if (user_options->outfile_format > 1) + if (outfile_format > 1) { event_log_error (hashcat_ctx, "Combining --outfile-format > 1 with --left is not allowed."); @@ -683,9 +685,23 @@ int user_options_sanity (hashcat_ctx_t *hashcat_ctx) { if (user_options->outfile_format_chgd == true) { - if (user_options->outfile_format > 7) + if (outfile_format & OUTFILE_FMT_CRACKPOS) + { + event_log_error (hashcat_ctx, "Using crack_pos in --outfile-format for --show is not allowed."); + + return -1; + } + + if (outfile_format & OUTFILE_FMT_TIME_ABS) + { + event_log_error (hashcat_ctx, "Using the absolute timestamp in --outfile-format for --show is not allowed."); + + return -1; + } + + if (outfile_format & OUTFILE_FMT_TIME_REL) { - event_log_error (hashcat_ctx, "Combining --outfile-format > 7 with --show is not allowed."); + event_log_error (hashcat_ctx, "Using the relative timestamp in --outfile-format for --show is not allowed."); return -1; } @@ -1688,7 +1704,7 @@ void user_options_preprocess (hashcat_ctx_t *hashcat_ctx) user_options->hash_mode = 2000; user_options->kernel_accel = 1024; user_options->backend_vector_width = 1; - user_options->outfile_format = OUTFILE_FMT_PLAIN; + user_options->outfile_format = hcstrdup ("2"); user_options->quiet = true; if (user_options->attack_mode == ATTACK_MODE_STRAIGHT) @@ -1722,7 +1738,7 @@ void user_options_preprocess (hashcat_ctx_t *hashcat_ctx) if (user_options->left == true) { - user_options->outfile_format = OUTFILE_FMT_HASH; + user_options->outfile_format = hcstrdup ("1"); } if (user_options->show == true || user_options->left == true) @@ -2829,6 +2845,7 @@ void user_options_logger (hashcat_ctx_t *hashcat_ctx) logfile_top_string (user_options->opencl_device_types); logfile_top_string (user_options->outfile); logfile_top_string (user_options->outfile_check_dir); + logfile_top_string (user_options->outfile_format); logfile_top_string (user_options->potfile_path); logfile_top_string (user_options->restore_file_path); logfile_top_string (user_options->rp_files[0]); @@ -2877,7 +2894,6 @@ void user_options_logger (hashcat_ctx_t *hashcat_ctx) logfile_top_uint (user_options->optimized_kernel_enable); logfile_top_uint (user_options->outfile_autohex); logfile_top_uint (user_options->outfile_check_timer); - logfile_top_uint (user_options->outfile_format); logfile_top_uint (user_options->wordlist_autohex_disable); logfile_top_uint (user_options->potfile_disable); logfile_top_uint (user_options->progress_only);