Simple Bash wrapper around hashcat for running a curated set of cracking workflows from an interactive menu. Background and usage philosophy are covered in this blog post.
Useful wordlist sources:
If hashcat outputs values as $HEX[...], see hex-to-readable or use CyberChef.
git clone https://github.com/crypt0rr/hash-cracker
cd hash-cracker
chmod +x hash-cracker.shhashcatmust be installed and executablehash-cracker.confmust exist in the repository root
At startup, hash-cracker checks that:
HASHCATpoints to an executablehashcatbinaryPOTFILEis an existing regular file with read/write access- the required config keys are set in
hash-cracker.conf
Normal runs fail before Hashcat starts if the potfile is missing, a directory, or cannot be read and written. Dry-run mode reports a missing potfile without creating or modifying it.
These are only needed for specific menu options.
python3- Needed for option
12(PACK rulegen) and option13(PACK mask) - Option
12requirespyenchant: python3 -m pip install pyenchant==3.3.0
- Needed for option
cewl- Needed for option
18
- Needed for option
scripts/extensions/common-substr-linux- Needed for options
10and11
- Needed for options
scripts/extensions/mkpass-linux- Needed for option
17(Markov password generation)
- Needed for option
- Bundled native helpers support Apple Silicon (
arm64) only; Intel macOS is not supported for those workflows. python3- Needed for option
12(PACK rulegen) and option13(PACK mask) - Option
12requirespyenchant: python3 -m pip install pyenchant==3.3.0
- Needed for option
cewlcommand in PATH, orscripts/extensions/cewl/cewl.rb- Needed for option
18
- Needed for option
scripts/extensions/common-substr-mac- Needed for options
10and11
- Needed for options
scripts/extensions/mkpass-mac- Needed for option
17(Markov password generation)
- Needed for option
The default smoke suite simulates Darwin on Linux and verifies the portable
shell filesystem paths without invoking native helpers. Before closing a
macOS release validation, run options 10, 11, and 17 on an Apple Silicon
host with the bundled helpers available; Intel macOS is not a supported target.
Notes:
- Option
13uses the bundled PACK scripts and generates masks from the existing potfile.
hash-cracker.conf is required and is loaded automatically on every start.
The configuration is sourced as trusted Bash code. Only use a configuration file you created or reviewed locally; do not point HASH_CRACKER_CONFIG at untrusted input.
The file must live in the repository root and define these settings:
HASHCAT- path to thehashcatbinary, preferably as a quoted Bash array assignment such asHASHCAT=("/path with spaces/hashcat")DEVICE- value passed tohashcat -dHASHTYPE- hash mode, for example1000for NTLMHASHLIST- file containing target hashesPOTFILE- path to an existing readable/writable potfileWORDLIST- primary wordlist pathWORDLIST2- secondary wordlist path used by combinator-style workflows
Current example:
# Hashcat path
HASHCAT=("/usr/local/bin/hashcat")
# Device to Use (hashcat -d $DEVICE)
DEVICE=1
# Hashtype
HASHTYPE=1000
# File containing target hashes
HASHLIST="input"
# Potfile you want to use
POTFILE="hash-cracker.pot"
# Wordlist(s)
WORDLIST="wordlists/ignis-1M.txt"
WORDLIST2="wordlists/ignis-1K.txt"Run from the repository root:
./hash-cracker.shWith flags:
./hash-cracker.sh [FLAG]Help:
./hash-cracker.sh --helpShow module descriptions:
./hash-cracker.sh --module-infoSearch the local hash type list:
./hash-cracker.sh --search ntlmRun in dry-run mode:
./hash-cracker.sh --dry-runList available jobs and exit:
./hash-cracker.sh --list-jobsRun one job non-interactively:
./hash-cracker.sh --job 8List built-in presets:
./hash-cracker.sh --list-presetsRun a built-in preset:
./hash-cracker.sh --preset quickPreset runs print a compact execution summary with each executed job, result, exit code, and duration.
Run with session logging disabled:
./hash-cracker.sh --no-session-logExport stats JSON to a file:
./hash-cracker.sh --stats-export /tmp/hash-cracker-stats.jsonExport stats JSON with full log history:
./hash-cracker.sh --stats-export /tmp/hash-cracker-stats.json --stats-export-scope allRun non-interactive health checks:
./hash-cracker.sh --self-testCreate and run a reproducible campaign plan (requires python3):
./hash-cracker.sh --plan deep-plus --output campaign.json
./hash-cracker.sh --execute campaign.json
./hash-cracker.sh --resume campaign.jsonCampaign manifests record the ordered jobs, resolved Hashcat commands, immutable input fingerprints, optional execution-artifact fingerprints, per-step exit codes, and command-level execution state. Plans never execute Hashcat. During execution, every Hashcat command receives a deterministic session name and restore-file path. If a run is interrupted, --resume skips completed commands and re-enters the interrupted command with the same session and --restore; failed commands are retried with a new session. Generated processor inputs used by the interrupted command are retained until that command completes. New manifests include a private artifact workspace under <manifest>.state/workspace; generated processor inputs and interrupted-command state are kept there with restrictive permissions. Manifest-controlled workspace, restore-file, session, and preserved-input paths are rejected if they escape that private state. Older manifests without a workspace retain compatibility only for user-owned generated temporary inputs whose names begin with hash-cracker-campaign-; other external preserved-input paths are rejected. Campaign sidecar state is stored beside the manifest under <manifest>.state. A manifest is single-writer state: concurrent executions against the same campaign are unsupported. New manifests reject changed configuration, runtime flags, hashlist, wordlist, Hashcat, processor, selector, rule, or referenced helper artifacts when those fingerprints are present; older manifests continue to use their recorded input and runtime checks. These content fingerprints do not record native-binary source commits or toolchain provenance. The potfile is mutable campaign state and is expected to grow append-only during normal Hashcat execution; reductions trigger a safe statistics recount. Campaign sources are built-in presets or non-interactive job IDs: 1, 9, 10, 11, 12, 13, 14, 16, and 19.
Run the smoke suite with Bash coverage (requires python3):
make coverageThe report is written to coverage/ and includes HTML and JSON output, including executable-line and function coverage. Coverage uses Bash’s execution trace so nested bash -lc test cases and sourced processor scripts are attributed to the application files. The measured application scope excludes bundled wordlists, rules, and third-party helper binaries; it also excludes shell-only syntax, here-document data, and embedded awk source that Bash cannot execute or trace as Bash lines. The committed coverage-baseline.txt and function-coverage-baseline.txt files establish the measured line and function baselines. If either baseline is missing, the run writes a candidate under coverage/; otherwise, subsequent coverage runs fail if either metric decreases.
Python campaign coverage is measured separately with:
make coverage-pythonThe Python report covers only first-party scripts/campaign.py logic and is written to coverage/python/. Its independent baseline is stored in python-coverage-baseline.txt; this keeps Bash and Python coverage metrics from being combined into a misleading single percentage.
The default CI suite never starts Hashcat and does not require GPU hardware. An opt-in integration check is available for a Linux runner with a real Hashcat installation and OpenCL/CUDA backend:
HASHCAT_INTEGRATION_DEVICE=1 \
HASHCAT_INTEGRATION_REQUIRE_GPU=1 \
make test-integrationThe check creates isolated temporary inputs, runs real Hashcat-backed mask,
wordlist/rules, hybrid, and combinator paths against known MD5 test values,
and verifies the cracked results in a temporary potfile. It does not use the
developer configuration or modify repository data. HASHCAT_INTEGRATION_REQUIRE_GPU=0
permits a CPU OpenCL backend for local validation.
The manual Hashcat Integration workflow
targets a trusted self-hosted Linux runner with the labels self-hosted,
linux, x64, and hashcat. It is intentionally manual-only because real
Hashcat execution and self-hosted runners are outside the deterministic default
CI contract. The dispatch form defaults to GPU validation; selecting 0 for
require_gpu validates the same cases on a CPU OpenCL backend when the runner
provides one.
By default, hash-cracker enables optimized kernels, enables loopback, disables hardware monitoring, and shows cracked hashes on stdout.
-l,--no-loopback- disable loopback functionality-n,--no-limit- disable optimized kernels--hwmon-enable- enable hardware monitoring-m,--module-info- print descriptions of the available modules and exit-s [hash-name],--search [hash-name]- search the local hash type database and exit-d,--disable-cracked- suppress cracked hashes on stdout by writing them to/dev/null--dry-run- print the resolved hashcat commands without executing them; preprocessor file/tool actions are reported and skipped--no-session-log- disable session stats logging to file--session-log-keep [N],--session-log-keep=N- keep lastNauto-created session logs inlogs/(default:0, no pruning)--stats-debug- print whether stats refresh used incremental update or full recount--stats-export [PATH],--stats-export=PATH- export machine-readable session stats JSON toPATH--stats-export-scope [latest|all],--stats-export-scope=...- export latest snapshot only (latest, default) or include all parsed entries fromlogs/session-*.log(all)--job [ID],--job=ID- run one menu option non-interactively and exit (supports1-22and99)--list-jobs- print available job IDs and exit--preset [NAME],--preset=NAME- run a built-in non-interactive job preset and exit--list-presets- print available built-in presets and exit--plan [PRESET|JOB] --output PATH- create a versioned campaign manifest without executing Hashcat--execute PATH- execute a campaign manifest from its first incomplete step--resume PATH- resume an interrupted or failed campaign manifest--self-test,--doctor- run non-interactive configuration and dependency checks, then exit with status code
Presets run safe non-interactive jobs in sequence, stop on the first failed job, and print a run summary with timings.
quick- baseline and iteration coverage (1,9)quick-plus- quick coverage plus common substring pass (1,9,11)deep- baseline, iteration, prefix/suffix, substring, and digit-remover coverage (1,9,10,11,19)deep-plus- extended potfile-driven coverage with prefix/suffix and substring passes (1,9,10,11,14,19,9)
When the tool starts successfully, it opens an interactive menu with these options:
- Brute force
- Light rules
- Heavy rules
- Enter specific word/name/company
- Enter specific word/name/company (brute force)
- Hybrid
- Toggle-case
- Combinator
- Iterate results
- Prefix suffix
- Common substring
- PACK rulegen
- PACK mask
- Fingerprint attack
- Directory of word lists plain and then with
OneRuleToRuleThemAll - Username iteration (only complete NTDS)
- Markov-chain passwords generator
- CeWL wordlist generator
- Digit remover
- Stacker
- Custom brute force
- Directory of word lists plain and then with
buka_400k - Session stats dashboard
- Options
2,3,6,7, and20ask whether to use a single wordlist or multiple wordlists. - Option
8usesWORDLISTandWORDLIST2from the config file. - Options
15and22accept either a directory of wordlists or a single wordlist file. - Options
4and5prompt for a custom word or company name. - Option
16expects an NTDS-style input file and extracts usernames fromHASHLIST. - Option
17can generate candidates from either the potfile or a selected wordlist. - Option
18prompts for a URL, output wordlist name, spider depth, and minimum word length. - Option
21prompts for brute-force length and whether increment mode should be enabled. - Option
14generates fingerprint fragments internally from the potfile. SetFINGERPRINT_SEGMENT_MAXto tune the fragment length limit; default is8, producing combinator candidates up to16characters. --jobmode runs selected options directly without entering the interactive menu.- In non-interactive contexts, prompt-dependent jobs (for example
4,5,8,15,17,18,21,22) fail fast with a clear message.
- At startup, before initial counters are built, the tool prints:
Preparing session stats (counting potfile and input hashes)...
- After a job, if the potfile changed and unique plaintext recount is needed, the tool prints:
Refreshing session stats (recounting unique potfile plaintexts, this may take a moment)...
- Option
99prints a dedicated ASCII dashboard with:- session delta (
new ... lines,... unique,... bytes) - total cracked passwords in potfile (
... lines) - unique input hashes from the active
HASHLIST - log status/retention/current log file
- session delta (
- Session stats are written to a timestamped log file:
- Default per-session file:
logs/session-YYYYmmdd-HHMMSS-PID.log - Convenience pointer:
logs/latest.logpoints to the current session file - Retention for auto-created logs defaults to
0(no pruning) - Set
--session-log-keep [N]to tune retention - Override path with
SESSION_STATS_LOGFILE - Set
--no-session-logto disable file logging
- Default per-session file:
- With
--stats-debug, the tool prints which refresh path was used (incrementalorfull recount). - With
--stats-export, current stats are written as JSON on each refresh cycle. - Session logs and requested JSON exports are local audit artifacts. JSON export write failures are fatal; default session-log failures are reported as warnings so a cracking run is not mistaken for a missing audit record.
- Exported JSON includes a top-level
"schema_version"for stable downstream parsing. - With
--stats-export-scope latest(default), JSON contains the latest snapshot only. - With
--stats-export-scope all, JSON also includes parsed history fromsession-*.logfiles in the configured session-log directory. - See Audit artifacts for integrity limitations, retention behavior, and preservation guidance.
Sample hashes are provided in example-hashes/:
- MD5 (
-m 0) - SHA1 (
-m 100) - NTLM (
-m 1000)
For large public datasets, see Have I Been Pwned Passwords.
See VERSION.md.
These checks are maintainer-only and are not required for end users running hash-cracker.
make lint
make format-check
make format
make qa
make test-smokemake lintrunsshellcheckon project shell scripts.make format-checkverifies formatting withshfmt.make formatappliesshfmtformatting changes.make verify-toolschecks ShellCheck0.10.0and shfmt3.8.0.make test-smokeruns non-interactive menu and dry-run smoke checks.make coverage-pythonmeasures first-party campaign coverage separately from Bash coverage.- CI installs the pinned lint and format tool releases with checksum verification.
- CI runs the maintainer checks, campaign tests, and separate Bash/Python coverage jobs automatically on push and pull request;
workflow_dispatchis available for a manual rerun.
GNU GPLv3