From 42c2f0d50be34ce41240ca4af9161271376802d9 Mon Sep 17 00:00:00 2001 From: Justin Bollinger Date: Mon, 16 Mar 2026 14:44:28 -0400 Subject: [PATCH] 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. --- hate_crack/api.py | 9 +++++---- hate_crack/attacks.py | 26 ++++++++++++++------------ hate_crack/main.py | 6 +++--- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/hate_crack/api.py b/hate_crack/api.py index 90b6c65..6c02da5 100644 --- a/hate_crack/api.py +++ b/hate_crack/api.py @@ -1680,7 +1680,7 @@ def list_and_download_official_wordlists(): print(f"Error listing official wordlists: {e}") -def list_and_download_hashmob_rules(): +def list_and_download_hashmob_rules(rules_dir=None): """List rules via the Hashmob API, prompt for selection, and download.""" rules = download_hashmob_rule_list() if not rules: @@ -1703,7 +1703,8 @@ def list_and_download_hashmob_rules(): ) if sel.lower() == "q": return - rules_dir = get_rules_dir() + if not rules_dir: + rules_dir = get_rules_dir() def parse_indices(selection, max_index): indices = set() @@ -1871,9 +1872,9 @@ def download_hashmob_wordlists(print_fn=print) -> None: print_fn("Hashmob wordlist download complete.") -def download_hashmob_rules(print_fn=print) -> None: +def download_hashmob_rules(print_fn=print, rules_dir=None) -> None: """Download Hashmob rules.""" - list_and_download_hashmob_rules() + list_and_download_hashmob_rules(rules_dir=rules_dir) print_fn("Hashmob rules download complete.") diff --git a/hate_crack/attacks.py b/hate_crack/attacks.py index 72fdabf..fa2c92f 100644 --- a/hate_crack/attacks.py +++ b/hate_crack/attacks.py @@ -87,7 +87,8 @@ def quick_crack(ctx: Any) -> None: except ValueError: print("Please enter a valid number.") - rule_files = sorted(f for f in os.listdir(ctx.rulesDirectory) if f != ".DS_Store") + rules_dir = ctx.rulesDirectory + rule_files = sorted(f for f in os.listdir(rules_dir) if f != ".DS_Store") if not rule_files: download_rules = ( input("\nNo rules found. Download rules from Hashmob now? (Y/n): ") @@ -95,8 +96,8 @@ def quick_crack(ctx: Any) -> None: .lower() ) if download_rules in ("", "y", "yes"): - download_hashmob_rules(print_fn=print) - rule_files = sorted(os.listdir(ctx.rulesDirectory)) + download_hashmob_rules(print_fn=print, rules_dir=rules_dir) + rule_files = sorted(os.listdir(rules_dir)) if not rule_files: print("No rules available. Proceeding without rules.") @@ -138,7 +139,7 @@ def quick_crack(ctx: Any) -> None: return if "98" in rule_choice: for rule in rule_files: - selected_hcatRules.append(f"-r {os.path.join(ctx.rulesDirectory, rule)}") + selected_hcatRules.append(f"-r {os.path.join(rules_dir, rule)}") elif "0" in rule_choice: selected_hcatRules = [""] else: @@ -148,14 +149,14 @@ def quick_crack(ctx: Any) -> None: choices = choice.split("+") for rule in choices: try: - rule_path = os.path.join(ctx.rulesDirectory, rule_files[int(rule) - 1]) + rule_path = os.path.join(rules_dir, rule_files[int(rule) - 1]) combined_choice = f"{combined_choice} -r {rule_path}" except Exception: continue selected_hcatRules.append(combined_choice) else: try: - rule_path = os.path.join(ctx.rulesDirectory, rule_files[int(choice) - 1]) + rule_path = os.path.join(rules_dir, rule_files[int(choice) - 1]) selected_hcatRules.append(f"-r {rule_path}") except IndexError: continue @@ -178,7 +179,8 @@ def loopback_attack(ctx: Any) -> None: rule_choice = None selected_hcatRules = [] - rule_files = sorted(f for f in os.listdir(ctx.rulesDirectory) if f != ".DS_Store") + rules_dir = ctx.rulesDirectory + rule_files = sorted(f for f in os.listdir(rules_dir) if f != ".DS_Store") if not rule_files: download_rules = ( input("\nNo rules found. Download rules from Hashmob now? (Y/n): ") @@ -186,8 +188,8 @@ def loopback_attack(ctx: Any) -> None: .lower() ) if download_rules in ("", "y", "yes"): - download_hashmob_rules(print_fn=print) - rule_files = sorted(os.listdir(ctx.rulesDirectory)) + download_hashmob_rules(print_fn=print, rules_dir=rules_dir) + rule_files = sorted(os.listdir(rules_dir)) if not rule_files: print("No rules available. Proceeding without rules.") @@ -229,7 +231,7 @@ def loopback_attack(ctx: Any) -> None: return if "98" in rule_choice: for rule in rule_files: - selected_hcatRules.append(f"-r {os.path.join(ctx.rulesDirectory, rule)}") + selected_hcatRules.append(f"-r {os.path.join(rules_dir, rule)}") elif "0" in rule_choice: selected_hcatRules = [""] else: @@ -239,14 +241,14 @@ def loopback_attack(ctx: Any) -> None: choices = choice.split("+") for rule in choices: try: - rule_path = os.path.join(ctx.rulesDirectory, rule_files[int(rule) - 1]) + rule_path = os.path.join(rules_dir, rule_files[int(rule) - 1]) combined_choice = f"{combined_choice} -r {rule_path}" except Exception: continue selected_hcatRules.append(combined_choice) else: try: - rule_path = os.path.join(ctx.rulesDirectory, rule_files[int(choice) - 1]) + rule_path = os.path.join(rules_dir, rule_files[int(choice) - 1]) selected_hcatRules.append(f"-r {rule_path}") except IndexError: continue diff --git a/hate_crack/main.py b/hate_crack/main.py index 8ac8a5b..c02c091 100755 --- a/hate_crack/main.py +++ b/hate_crack/main.py @@ -3329,7 +3329,7 @@ def get_main_menu_options(): "14": loopback_attack, "15": ollama_attack, "16": omen_attack, - "90": download_hashmob_rules, + "90": lambda: download_hashmob_rules(rules_dir=rulesDirectory), "91": analyze_rules, "92": download_hashmob_wordlists, "93": weakpass_wordlist_menu, @@ -3725,7 +3725,7 @@ def main(): download_hashmob_wordlists(print_fn=print) sys.exit(0) if args.rules: - download_hashmob_rules(print_fn=print) + download_hashmob_rules(print_fn=print, rules_dir=rulesDirectory) sys.exit(0) if args.hashfile and args.hashtype: @@ -3781,7 +3781,7 @@ def main(): sys.exit(0) # Otherwise continue the menu loop elif choice == "4" or args.rules: - download_hashmob_rules(print_fn=print) + download_hashmob_rules(print_fn=print, rules_dir=rulesDirectory) if args.rules: sys.exit(0) # Otherwise continue the menu loop