Commit Graph
707 Commits
Author SHA1 Message Date
Justin Bollinger 9611565471 feat: add rule file management tools using cleanup-rules.bin and rules_optimize.bin (closes #93)
Adds Rule File Tools submenu (menu option 81) with three operations:
- Clean: removes invalid/duplicate rules via cleanup-rules.bin
- Optimize: consolidates redundant operations via rules_optimize.bin
- Clean and optimize: both in sequence with temp file handling

Wired through the standard three-layer pattern: main.py utility
functions + dispatcher, attacks.py handlers + submenu, root
hate_crack.py menu registration.
2026-03-19 12:12:12 -04:00
Justin Bollinger 53b99d4395 fix: use raw LZMA2 stream instead of XZ container for hcstat2 compression
hashcat's Lzma2Decode() expects a raw LZMA2 stream starting with 0xff chunk
headers, not an XZ container format (0xfd 37 7a...). FORMAT_RAW with
FILTER_LZMA2 produces the correct format.
2026-03-18 20:16:42 -04:00
Justin Bollinger afb4b279fc fix: compress hcstat2 output with LZMA2 format for hashcat compatibility
Hashcat requires hcstat2 files to be LZMA2-compressed. The hcstat2gen.bin utility outputs uncompressed binary data, so we need to compress the output after generation.

Root cause: Hashcat's source code (mpsp.c) uses hc_lzma2_decompress() to read hcstat2 files. The bundled hashcat.hcstat2 file uses LZMA2 compression (XZ format). hcstat2gen.bin outputs plain hcstat format which hashcat cannot decompress, causing "Could not uncompress data" error.

Fix: After hcstat2gen.bin completes, compress the output file using Python's lzma module with XZ format (LZMA2-based).

Also restore proper subprocess invocation: pass output path as argument to hcstat2gen.bin instead of using stdout redirection.

Tests: All 8 markov E2E tests pass, 479 total tests pass
2026-03-18 19:40:18 -04:00
Justin Bollinger c71d2a5321 fix: restore hcstat2gen.bin output path argument - markov training was creating empty file
The previous commit attempted to simplify by passing hcstat2_path as an argument and removing stdout redirection. However, hcstat2gen.bin writes directly to the file specified as its first argument and doesn't use stdout. The code was missing the proper invocation.

Root cause: Removed stdout=PIPE capture but forgot that the binary doesn't write to stdout - it writes directly to the file argument. This left the .hcstat2 file empty/uncreated.

Fix: Restore proper subprocess invocation - pass output path as argument, stdin from wordlist, stderr for error reporting. Remove stdout=PIPE since the binary doesn't use it.

Tests: All 8 markov E2E tests pass, 479 total tests pass
2026-03-18 19:30:23 -04:00
Justin Bollinger 374ac25233 fix: simplify markov training - hcstat2gen.bin supports gzipped input
- Remove unnecessary gzip decompression logic
- hcstat2gen.bin can read both plain text and gzipped files directly
- Simplified code: just pass source file and output path as arguments
- Removed gzip and tempfile imports (no longer needed)
- Add comprehensive end-to-end tests covering all markov attack flows
- Tests verify training with plain text and gzipped wordlists
- Tests verify all handler menu paths (use existing, generate new, cancel, training failure)
- Fixes 'cannot uncompress data' error by not trying to decompress
2026-03-18 19:24:19 -04:00
Justin Bollinger 07f7cad16f fix: pass hcstat2 output path as argument to hcstat2gen.bin
- hcstat2gen.bin expects: hcstat2gen.bin <outfile> < dictionary
- Previously tried to write to stdout which caused 'usage' error
- Now correctly passes output path as command argument
- Markov training now works for both plain text and gzipped wordlists
- Fixes 'Markov table generation failed' error
2026-03-18 19:19:31 -04:00
Justin Bollinger a13cec1792 fix: add detailed error reporting to markov training
- Check hcstat2gen.bin exists before running
- Verify source file is readable
- Capture stdout and stderr from hcstat2gen.bin
- Report hcstat2gen.bin errors with stderr output
- Verify output file created and non-empty
- Add 300 second timeout to prevent hanging
- Write proper output to .hcstat2 file from stdout
- Helps debug training failures with specific error messages
2026-03-18 19:17:54 -04:00
Justin Bollinger 120c251e92 fix: properly decompress gzipped files before markov training
- Add tempfile import for secure temporary file handling
- Detect gzipped files by magic bytes (0x1f 0x8b)
- Decompress gzipped files to temporary file first
- Pass uncompressed data directly to hcstat2gen.bin
- Properly clean up temporary files on success or error
- Fixes 'hcstat2: Could not uncompress data' error
2026-03-18 19:13:10 -04:00
Justin Bollinger 4ff0cff656 fix: handle gzipped training files in markov attack
- Add gzip import to main.py
- Detect gzipped files by magic bytes (0x1f 0x8b)
- Use gzip.open() for compressed files, regular open() for plain text
- Properly close file handles in all cases
- Allows markov training from both .txt and .txt.gz wordlists
2026-03-18 19:09:49 -04:00
Justin Bollinger 02ce2092ec docs: add ad-hoc mask and markov brute force attack documentation
- Update menu listing to show combinator submenu and new attacks (17, 18)
- Remove keys 10/11/12 from main menu (consolidated into submenu)
- Add detailed descriptions for Combinator Attacks submenu, Ad-hoc Mask Attack, and Markov Brute Force Attack
- Document Markov training source selection and table persistence
- Update version history with new feature details
2026-03-18 19:02:35 -04:00
Justin Bollinger 0d83bd03e2 test: fix menu option tests for new attack structure
- Update test cases to reflect combinator_submenu for key 6
- Remove test cases for keys 10/11/12 (moved to sub-menu)
- Add test cases for new keys 17 and 18
- Simplify adhoc_mask tests to avoid global state issues
2026-03-18 19:01:51 -04:00
Justin Bollinger 9a432f8b07 feat: add ad-hoc mask attack, markov brute force, and combinator sub-menu
- Add three hashcat wrapper functions: hcatAdHocMask, hcatMarkovTrain, hcatMarkovBruteForce
- Add corresponding attack handlers in attacks.py with OMEN-style training flow
- Consolidate 4 combinator attacks (keys 10/11/12) into interactive sub-menu (key 6)
- Add key 17 for ad-hoc mask attack and key 18 for markov brute force
- Update both main.py and hate_crack.py menu systems
- Add comprehensive test coverage for new handlers and wrappers
- Training source picker supports cracked passwords or any wordlist
2026-03-18 19:00:40 -04:00
Justin BollingerandGitHub e735c7887e Merge pull request #83 from trustedsec/feat/omen-rules-and-cwd-fix
feat: add rule support to OMEN attack and fix relative path resolution
2026-03-18 18:18:23 -04:00
Justin Bollinger 3bc85d9b8a feat: add rule support to OMEN attack and fix relative path resolution
Extract _select_rules() helper from quick_crack/loopback_attack and wire
it into omen_attack so OMEN can run with rule chains. Extend hcatOmen()
to accept and apply an hcatChains argument including debug mode injection.

Fix resolve_path() to honour HATE_CRACK_ORIG_CWD (set by the install shim)
so relative hash/wordlist paths resolve against the caller's working directory
instead of the repo root. Increase default omenMaxCandidates to 50M.
2026-03-18 18:17:41 -04:00
Justin Bollinger 9423b5a64d feat: restore wordlist_optimizer.py with modernizations
- Resolve binary paths relative to script location with platform-specific extensions
- Replace shell=True with proper subprocess.run argument lists (security fix)
- Convert %-formatting to f-strings throughout
- Replace lineCount() utility with os.path.getsize()
- Add fail-fast error handling with actionable messages
- Verify binaries exist before running
2026-03-17 19:15:20 -04:00
Justin Bollinger fda38d3498 docs: update README with OMEN fix and issues #80, #81, #82 2026-03-17 15:07:02 -04:00
Justin Bollinger 67c462cd41 fix: OMEN attack silent failure - validate model files, capture enumNG errors, add wordlist picker
- Add _omen_model_is_valid() checking all 5 required model files
- Add _omen_model_info() reading model_info.json metadata
- hcatOmenTrain returns bool and writes training metadata
- Capture enumNG stderr and report errors instead of silent failure
- Rewrite omen_attack with train/use/cancel menu and wordlist picker
2026-03-17 15:05:36 -04:00
Justin Bollinger 2852d652bc feat: parallelize hashmob rule downloads and update wordlist filtering in attacks
- Rewrite list_and_download_hashmob_rules with ThreadPoolExecutor
- Update quick_crack to use list_wordlist_files
- Add parallel download tests with stdin TTY mock
2026-03-17 15:05:29 -04:00
Justin Bollinger 36262200a9 feat: filter .7z files from wordlist menus, parallelize rule downloads, dynamic -O flag
- Add list_wordlist_files() helper filtering .7z/.torrent/.out from menus (#80)
- Use ThreadPoolExecutor for parallel rule downloads with summary (#81)
- Add per-attack optimized kernel (-O) via DEFAULT_OPTIMIZED_ATTACKS (#82)
- Add optimizedKernelAttacks config key for user override
2026-03-17 15:05:23 -04:00
Justin Bollinger a1b81ec01d fix: replace uv tool install with bash shim for reliable config resolution
Config and assets were not found when running hate_crack from outside the
repo directory. The shim uses `uv run --directory` to always execute from
the repo root, and _candidate_roots() now includes _repo_root and
_package_path as fallback search locations.
2026-03-17 12:45:19 -04:00
Justin Bollinger d8c009c334 fix: pass configured rules_directory to all rule download and listing callers
api.py's get_rules_dir() independently re-parsed config.json and could
resolve a different rules path than main.py's rulesDirectory global.
Thread the already-resolved rulesDirectory through download_hashmob_rules
and list_and_download_hashmob_rules so all callers (menu option 90,
--rules flag, quick_crack, loopback_attack) use the same path from config.
2026-03-16 14:44:28 -04:00
Justin Bollinger 83491ea17d docs: update README with recent bug fixes in version history 2026-03-16 14:33:43 -04:00
Justin Bollinger 6df74f7969 fix: use os.path.join for rule paths in quick_crack and loopback_attack
Replace 6 instances of f-string slash concatenation with os.path.join()
for building rule file paths, consistent with get_rule_path() in main.py.
2026-03-16 14:32:14 -04:00
Justin Bollinger 79cb290c11 fix: skip leading blank lines in hash format detection
A blank first line caused the format detection regex chain to fall
through to the error exit. Read lines in a loop and skip empty ones
before matching. Add tests for blank lines with LF, CRLF, whitespace,
and BOM variations.
2026-03-16 14:23:09 -04:00
Justin Bollinger f2572d0a80 fix: handle bare NTLM hash detection with BOM, null bytes, and encoding artifacts
Use utf-8-sig encoding to natively strip BOM and remove null bytes from
UTF-16 artifacts so the bare hash regex matches correctly. Replace the
unhelpful "unknown format" error with a diagnostic message showing the
actual first-line content and expected formats.
2026-03-16 14:17:37 -04:00
Justin Bollinger 83f63ddf23 test: add menu test module 2026-03-16 13:08:59 -04:00
Justin Bollinger 22d8858825 feat: default wordlist autocomplete to hcatWordlists dir and add TUI extra 2026-03-16 12:48:45 -04:00
Justin Bollinger ab11985022 fix: ensure potfile exists before passing --potfile-path to hashcat
When running as root, ~/.hashcat/ exists but hashcat.potfile does not.
Hashcat refuses to create the file when given an explicit --potfile-path.
Create the parent directory and touch the file in _append_potfile_arg()
before appending the flag.
2026-03-16 12:37:36 -04:00
Justin Bollinger e0a79d7c7b refactor: remove vendor-assets wheel build flow, use editable install
- Remove vendor-assets and clean-vendor Makefile targets
- Lima VM test and Dockerfile.test now use make install (editable)
- Remove hate_crack/hashcat-utils from submodules-pre expander generation
- Update README to reflect no-vendoring install
2026-03-16 11:50:32 -04:00
Justin Bollinger a3059c1dd2 fix: fall back to cwd for potfile when ~/.hashcat does not exist
When hashcat is not installed via the standard method, ~/.hashcat/
does not exist. Fall back to hashcat.potfile in the current working
directory instead of referencing a path that does not exist.
2026-03-16 11:42:18 -04:00
Justin Bollinger f51d13c29a refactor: make install target truly idempotent
- Skip hashcat-utils build when bin/expander.bin already exists
- Skip princeprocessor build when pp64.bin already exists
- Skip expander source generation when expander8.c already exists
- Skip OS dependency installs when 7z/transmission-cli already present
- Break up submodules-pre one-liner into readable multi-line script
2026-03-16 11:40:41 -04:00
Justin Bollinger b8aebbc65e fix: add missing menu.py module to tracked files
hate_crack/menu.py was imported by main.py but never committed,
causing ModuleNotFoundError on fresh installs.
2026-03-16 11:38:05 -04:00
Justin Bollinger f529667201 fix: resolve uv binary path after fresh install in Makefile
The uv installer adds ~/.local/bin/uv but does not update the current
shell PATH. Use the discovered path or fall back to ~/.local/bin/uv
so the subsequent uv tool install succeeds on first run.
2026-03-16 11:36:17 -04:00
Justin Bollinger 74dd294b38 fix: fall back to ~/.hate_crack for config instead of cwd
When no candidate directory has hate_crack assets, config destination
fell back to cwd which fails on read-only filesystems like /.
2026-03-16 11:33:47 -04:00
Justin Bollinger 5dbd5bfd6f fix: use .get() with defaults for ollama/omen/update config keys
Config keys added after initial release (ollamaModel, ollamaNumCtx,
omenTrainingList, omenMaxCandidates, check_for_updates) raised KeyError
when config.json.example was not found for auto-injection.
2026-03-16 11:33:05 -04:00
Justin Bollinger 2be067df30 docs: add troubleshooting for master-to-main branch rename error 2026-03-16 11:25:51 -04:00
Justin Bollinger 4df759be3b fix: graceful config loading with auto-inject for missing keys
- Add JSON parsing error handling with user-friendly messages for
  malformed config.json (shows line/column and fix instructions)
- Handle corrupt config.json.example with package reinstall guidance
- Consolidate auto-inject messaging to single summary line instead
  of one message per missing key
- Remove ~20 redundant KeyError handlers since auto-inject ensures
  all keys exist before they're read
2026-03-13 21:21:25 -04:00
Justin Bollinger 7f3f33e0bf feat: return to main menu on double Ctrl+C within 2 seconds
Install a custom SIGINT handler that tracks interrupt timing. A single
Ctrl+C raises KeyboardInterrupt as before (kills the current subprocess
and continues). A second Ctrl+C within 2 seconds raises DoubleInterrupt,
which bypasses all existing per-subprocess handlers and is caught at the
main menu loop, printing "[!] Returning to main menu..." and resuming
the menu.

Preprocessing and cleanup sections also catch DoubleInterrupt to ensure
temp file cleanup runs before re-raising.
2026-03-10 14:03:30 -04:00
Justin Bollinger 984bc23f21 test: increase hashcat timeout to 300s for slow GPU init 2026-03-10 12:32:42 -04:00
Justin Bollinger 17f7fb6463 fix: resolve OMEN binary path from repo root as fallback
In dev checkouts where submodules are built in the repo root rather than
vendored into hate_path, OMEN binaries were not found. Introduces _omen_dir
that checks hate_path/omen first and falls back to the repo root omen dir.
Also removes vendor-assets from install/update targets and drops vendored
submodule paths from pyproject.toml package data.
2026-03-10 12:28:14 -04:00
Justin Bollinger c85808e5c3 fix: handle Hashview create_job error response correctly
When the Hashview server returns HTTP 200 with an error message and no
job_id (due to its internal notify_email bug), the CLI and interactive
paths now:
- exit 1 (not 0) in the CLI path
- print "✗ Error" instead of "✓ Success"
- print a hint to check the Hashview UI before retrying, preventing
  duplicate job creation

Adds test for the error response path in test_cli_flags.py.
2026-03-09 13:17:50 -04:00
Justin Bollinger 1244cb1e29 fix: stop sending notify_email in create_job, clarify format override prompt
notify_email is not supported by all Hashview servers and caused job
creation to fail. Changed default to None so it is omitted from the
request unless explicitly passed.

Also reworded the file format override prompt so the detected name does
not appear twice in the output.
2026-03-09 12:39:10 -04:00
Justin Bollinger 0a8cf98869 fix: allow format override in interactive hashview upload hashfile job
Auto-detection still runs but the user can now confirm or change the
detected file format before the upload is sent.
2026-03-09 12:22:11 -04:00
Justin Bollinger d166e9b0ac chore: remove hashcat submodule
hashcat is now a system dependency (installed via apt/brew or PATH) rather
than a compiled submodule. The Lima VM provision script installs it via apt,
and local installs are expected to have hashcat available in PATH.

- Remove hashcat entry from .gitmodules
- Remove hashcat/ submodule checkout
- Remove hashcat submodule skip logic from Makefile submodules target
- Simplify submodules-pre hashcat check to PATH-only
- Update vendor-assets and clean targets to remove submodule references
- Update README: hashcat is now a required prerequisite, not optional
- Document Lima VM E2E prerequisites (lima, rsync) and list all packages
  provisioned automatically by the test VM
2026-03-06 15:51:10 -05:00
Justin Bollinger 9485be4a38 test: harden Lima VM E2E tests
- Add rsync to _require_lima() prerequisite check; missing rsync now
  skips cleanly instead of failing with an opaque command-not-found
- Add _truncate_output() helper and apply to all assertion messages to
  keep failure output readable when make/install emits thousands of lines
- Increase limactl start timeout from 300s to 600s to accommodate slow
  Ubuntu image downloads
- Add limactl stop before delete in cleanup for more reliable teardown
- Add flag verification to test_lima_vm_install_and_run: checks 10 CLI
  flags in --help output, matching the local install test pattern
- Add 3 unit tests: test_truncate_output_trims_long_text,
  test_truncate_output_short_text_unchanged,
  test_require_lima_skips_without_rsync
2026-03-06 15:28:53 -05:00
Justin Bollinger 5a62b40b94 fix: skip hashcat rule tests on OpenCL device build failures
OpenCL/device build errors are environment-specific issues, not code
bugs. Detect clCreateProgramWithBinary and kernel build failures in
stderr and pytest.skip instead of pytest.fail.
2026-03-03 15:00:52 -05:00
Justin Bollinger 39522f5d75 chore: remove GitHub Actions workflows
Quality checks run locally via prek pre-push hooks. CI workflows
(ruff, ty, pytest, lint-infra, version-bump) are no longer needed.
Updated docs to remove all GitHub Actions references.
v2.1.0
2026-03-03 14:42:57 -05:00
Justin Bollinger 102facf42a refactor: remove PassGPT attack (option 17)
Remove the ML-based PassGPT password generation feature entirely:
modules, config keys, [ml] optional dependency group, menu entries,
tests, and documentation.
2026-03-03 14:31:41 -05:00
Justin Bollinger 8222e0a29e test: add 23 unit tests for all CLI flags and argparse errors
Cover --weakpass, --hashmob, --rules, --cleanup, --download-torrent,
--download-all-torrents, --hashview, --download-hashview, --rank,
--potfile-path, --no-potfile-path, --debug, positional hashfile/hashtype
args, hashview download-hashes subcommand, upload-hashfile-job with
--limit-recovered/--no-notify-email, and argparse error cases.
2026-03-02 21:23:28 -05:00
Justin Bollinger fe7b9def34 docs: rewrite TESTING.md and update README git hooks section 2026-03-02 17:41:56 -05:00