diff --git a/docs/changes.txt b/docs/changes.txt index 8df8cadeb..7bb460341 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 448b94699..f2590cb15 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; diff --git a/src/modules/module_09710.c b/src/modules/module_09710.c index f2f8b662a..2f7a5957a 100644 --- a/src/modules/module_09710.c +++ b/src/modules/module_09710.c @@ -99,7 +99,7 @@ const char *module_benchmark_mask (MAYBE_UNUSED const hashconfig_t *hashconfig, u32 module_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 = 5; + const u32 forced_outfile_format = OUTFILE_FMT_HASH | OUTFILE_FMT_HEXPLAIN; return forced_outfile_format; } diff --git a/src/modules/module_09810.c b/src/modules/module_09810.c index ecbba7c64..fd80151fa 100644 --- a/src/modules/module_09810.c +++ b/src/modules/module_09810.c @@ -98,7 +98,7 @@ const char *module_benchmark_mask (MAYBE_UNUSED const hashconfig_t *hashconfig, u32 module_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 = 5; + const u32 forced_outfile_format = OUTFILE_FMT_HASH | OUTFILE_FMT_HEXPLAIN; return forced_outfile_format; } diff --git a/src/modules/module_10410.c b/src/modules/module_10410.c index 96624d904..d641ae03c 100644 --- a/src/modules/module_10410.c +++ b/src/modules/module_10410.c @@ -107,7 +107,7 @@ const char *module_benchmark_mask (MAYBE_UNUSED const hashconfig_t *hashconfig, u32 module_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 = 5; + const u32 forced_outfile_format = OUTFILE_FMT_HASH | OUTFILE_FMT_HEXPLAIN; return forced_outfile_format; } diff --git a/src/outfile.c b/src/outfile.c index 8dc949b50..2e49a4597 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,101 @@ #include "locking.h" #include "outfile.h" +u32 outfile_format_parse (const char *format_string) +{ + if (format_string == NULL) return 0; + + char *format = hcstrdup (format_string); + + if (format == NULL) return 0; + + char *saveptr = NULL; + + char *next = strtok_r (format, ",", &saveptr); + + if (next == NULL) + { + hcfree (format); + + return 0; + } + + 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 +487,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 = user_options->outfile_format; + outfile_ctx->outfile_autohex = user_options->outfile_autohex; return 0; } @@ -445,6 +541,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 +555,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 +564,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..57e09a7ce 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" @@ -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 = outfile_format_parse (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,7 @@ int user_options_sanity (hashcat_ctx_t *hashcat_ctx) return -1; } - if (user_options->outfile_format > 16) + if (user_options->outfile_format == 0) { event_log_error (hashcat_ctx, "Invalid --outfile-format value specified."); @@ -683,9 +683,23 @@ int user_options_sanity (hashcat_ctx_t *hashcat_ctx) { if (user_options->outfile_format_chgd == true) { - if (user_options->outfile_format > 7) + if (user_options->outfile_format & OUTFILE_FMT_CRACKPOS) { - event_log_error (hashcat_ctx, "Combining --outfile-format > 7 with --show is not allowed."); + event_log_error (hashcat_ctx, "Using crack_pos in --outfile-format for --show is not allowed."); + + return -1; + } + + if (user_options->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 (user_options->outfile_format & OUTFILE_FMT_TIME_REL) + { + event_log_error (hashcat_ctx, "Using the relative timestamp in --outfile-format for --show is not allowed."); return -1; }