mirror of
https://github.com/trustedsec/hate_crack.git
synced 2026-04-28 12:03:11 -07:00
style: ruff format pass for Notifications submenu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -401,7 +401,9 @@ if hcatOptimizedWordlists:
|
|||||||
if not os.path.isdir(hcatOptimizedWordlists):
|
if not os.path.isdir(hcatOptimizedWordlists):
|
||||||
fallback_optimized = os.path.join(hate_path, "optimized_wordlists")
|
fallback_optimized = os.path.join(hate_path, "optimized_wordlists")
|
||||||
if os.path.isdir(fallback_optimized):
|
if os.path.isdir(fallback_optimized):
|
||||||
print(f"[!] hcatOptimizedWordlists directory not found: {hcatOptimizedWordlists}")
|
print(
|
||||||
|
f"[!] hcatOptimizedWordlists directory not found: {hcatOptimizedWordlists}"
|
||||||
|
)
|
||||||
print(f"[!] Falling back to {fallback_optimized}")
|
print(f"[!] Falling back to {fallback_optimized}")
|
||||||
hcatOptimizedWordlists = fallback_optimized
|
hcatOptimizedWordlists = fallback_optimized
|
||||||
else:
|
else:
|
||||||
@@ -417,8 +419,12 @@ pipalPath = config_parser["pipalPath"]
|
|||||||
hcatDictionaryWordlist = config_parser["hcatDictionaryWordlist"]
|
hcatDictionaryWordlist = config_parser["hcatDictionaryWordlist"]
|
||||||
hcatHybridlist = config_parser["hcatHybridlist"]
|
hcatHybridlist = config_parser["hcatHybridlist"]
|
||||||
hcatCombinationWordlist = config_parser["hcatCombinationWordlist"]
|
hcatCombinationWordlist = config_parser["hcatCombinationWordlist"]
|
||||||
hcatCombinator3Wordlist = config_parser.get("hcatCombinator3Wordlist", ["rockyou.txt", "rockyou.txt", "rockyou.txt"])
|
hcatCombinator3Wordlist = config_parser.get(
|
||||||
hcatCombinatorXWordlist = config_parser.get("hcatCombinatorXWordlist", ["rockyou.txt", "rockyou.txt"])
|
"hcatCombinator3Wordlist", ["rockyou.txt", "rockyou.txt", "rockyou.txt"]
|
||||||
|
)
|
||||||
|
hcatCombinatorXWordlist = config_parser.get(
|
||||||
|
"hcatCombinatorXWordlist", ["rockyou.txt", "rockyou.txt"]
|
||||||
|
)
|
||||||
hcatMiddleCombinatorMasks = config_parser["hcatMiddleCombinatorMasks"]
|
hcatMiddleCombinatorMasks = config_parser["hcatMiddleCombinatorMasks"]
|
||||||
hcatMiddleBaseList = config_parser["hcatMiddleBaseList"]
|
hcatMiddleBaseList = config_parser["hcatMiddleBaseList"]
|
||||||
hcatThoroughCombinatorMasks = config_parser["hcatThoroughCombinatorMasks"]
|
hcatThoroughCombinatorMasks = config_parser["hcatThoroughCombinatorMasks"]
|
||||||
@@ -584,8 +590,12 @@ hcatDictionaryWordlist = _normalize_wordlist_setting(
|
|||||||
hcatCombinationWordlist = _normalize_wordlist_setting(
|
hcatCombinationWordlist = _normalize_wordlist_setting(
|
||||||
hcatCombinationWordlist, wordlists_dir
|
hcatCombinationWordlist, wordlists_dir
|
||||||
)
|
)
|
||||||
hcatCombinator3Wordlist = _normalize_wordlist_setting(hcatCombinator3Wordlist, wordlists_dir)
|
hcatCombinator3Wordlist = _normalize_wordlist_setting(
|
||||||
hcatCombinatorXWordlist = _normalize_wordlist_setting(hcatCombinatorXWordlist, wordlists_dir)
|
hcatCombinator3Wordlist, wordlists_dir
|
||||||
|
)
|
||||||
|
hcatCombinatorXWordlist = _normalize_wordlist_setting(
|
||||||
|
hcatCombinatorXWordlist, wordlists_dir
|
||||||
|
)
|
||||||
hcatHybridlist = _normalize_wordlist_setting(hcatHybridlist, wordlists_dir)
|
hcatHybridlist = _normalize_wordlist_setting(hcatHybridlist, wordlists_dir)
|
||||||
hcatMiddleBaseList = _normalize_wordlist_setting(hcatMiddleBaseList, wordlists_dir)
|
hcatMiddleBaseList = _normalize_wordlist_setting(hcatMiddleBaseList, wordlists_dir)
|
||||||
hcatThoroughBaseList = _normalize_wordlist_setting(hcatThoroughBaseList, wordlists_dir)
|
hcatThoroughBaseList = _normalize_wordlist_setting(hcatThoroughBaseList, wordlists_dir)
|
||||||
@@ -2397,8 +2407,14 @@ def hcatMarkovTrain(source_file, hcatHashFile):
|
|||||||
hcatProcess.wait(timeout=300)
|
hcatProcess.wait(timeout=300)
|
||||||
if hcatProcess.returncode != 0:
|
if hcatProcess.returncode != 0:
|
||||||
_, stderr_data = hcatProcess.communicate()
|
_, stderr_data = hcatProcess.communicate()
|
||||||
err_msg = stderr_data.decode("utf-8", errors="replace") if stderr_data else "Unknown error"
|
err_msg = (
|
||||||
print(f"[!] hcstat2gen.bin failed with code {hcatProcess.returncode}: {err_msg}")
|
stderr_data.decode("utf-8", errors="replace")
|
||||||
|
if stderr_data
|
||||||
|
else "Unknown error"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
f"[!] hcstat2gen.bin failed with code {hcatProcess.returncode}: {err_msg}"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
print("[!] hcstat2gen.bin timed out after 300 seconds")
|
print("[!] hcstat2gen.bin timed out after 300 seconds")
|
||||||
@@ -3011,7 +3027,9 @@ def cleanup():
|
|||||||
if os.path.isfile(out_path):
|
if os.path.isfile(out_path):
|
||||||
print(f"\nCracked passwords combined with original hashes in {out_path}")
|
print(f"\nCracked passwords combined with original hashes in {out_path}")
|
||||||
else:
|
else:
|
||||||
print(f"\nNo cracked hashes to combine. Raw output (if any): {hcatHashFile}.out")
|
print(
|
||||||
|
f"\nNo cracked hashes to combine. Raw output (if any): {hcatHashFile}.out"
|
||||||
|
)
|
||||||
print("\nCleaning up temporary files...")
|
print("\nCleaning up temporary files...")
|
||||||
if os.path.exists(hcatHashFile + ".masks"):
|
if os.path.exists(hcatHashFile + ".masks"):
|
||||||
os.remove(hcatHashFile + ".masks")
|
os.remove(hcatHashFile + ".masks")
|
||||||
@@ -3813,9 +3831,7 @@ def wordlist_filter_req_exclude(infile: str, outfile: str, mask: int) -> bool:
|
|||||||
return result.returncode == 0
|
return result.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
def wordlist_cutb(
|
def wordlist_cutb(infile: str, outfile: str, offset: int, length: int | None) -> bool:
|
||||||
infile: str, outfile: str, offset: int, length: int | None
|
|
||||||
) -> bool:
|
|
||||||
"""Extract a substring from each word starting at offset, optionally limited to length bytes."""
|
"""Extract a substring from each word starting at offset, optionally limited to length bytes."""
|
||||||
cutb_bin = os.path.join(hate_path, "hashcat-utils/bin/cutb.bin")
|
cutb_bin = os.path.join(hate_path, "hashcat-utils/bin/cutb.bin")
|
||||||
cmd = [cutb_bin, str(offset)]
|
cmd = [cutb_bin, str(offset)]
|
||||||
@@ -3853,7 +3869,9 @@ def wordlist_gate(infile: str, outfile: str, mod: int, offset: int) -> bool:
|
|||||||
"""Shard wordlist: keep every mod-th line starting at offset."""
|
"""Shard wordlist: keep every mod-th line starting at offset."""
|
||||||
gate_bin = os.path.join(hate_path, "hashcat-utils/bin/gate.bin")
|
gate_bin = os.path.join(hate_path, "hashcat-utils/bin/gate.bin")
|
||||||
with open(infile, "rb") as fin, open(outfile, "wb") as fout:
|
with open(infile, "rb") as fin, open(outfile, "wb") as fout:
|
||||||
result = subprocess.run([gate_bin, str(mod), str(offset)], stdin=fin, stdout=fout)
|
result = subprocess.run(
|
||||||
|
[gate_bin, str(mod), str(offset)], stdin=fin, stdout=fout
|
||||||
|
)
|
||||||
return result.returncode == 0
|
return result.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
@@ -3871,7 +3889,9 @@ def rules_cleanup(infile: str, outfile: str) -> bool:
|
|||||||
|
|
||||||
def rules_optimize(infile: str, outfile: str) -> bool:
|
def rules_optimize(infile: str, outfile: str) -> bool:
|
||||||
"""Optimize a rule file using rules_optimize.bin. Returns True on success."""
|
"""Optimize a rule file using rules_optimize.bin. Returns True on success."""
|
||||||
optimize_path = os.path.join(hate_path, "hashcat-utils", "bin", "rules_optimize.bin")
|
optimize_path = os.path.join(
|
||||||
|
hate_path, "hashcat-utils", "bin", "rules_optimize.bin"
|
||||||
|
)
|
||||||
with open(infile, "rb") as fin, open(outfile, "wb") as fout:
|
with open(infile, "rb") as fin, open(outfile, "wb") as fout:
|
||||||
result = subprocess.run([optimize_path], stdin=fin, stdout=fout)
|
result = subprocess.run([optimize_path], stdin=fin, stdout=fout)
|
||||||
return result.returncode == 0
|
return result.returncode == 0
|
||||||
|
|||||||
@@ -84,8 +84,12 @@ def load_settings(config_parser: dict | None) -> NotifySettings:
|
|||||||
defaults = NotifySettings()
|
defaults = NotifySettings()
|
||||||
return NotifySettings(
|
return NotifySettings(
|
||||||
enabled=_coerce_bool(cfg.get("notify_enabled"), defaults.enabled),
|
enabled=_coerce_bool(cfg.get("notify_enabled"), defaults.enabled),
|
||||||
pushover_token=_coerce_str(cfg.get("notify_pushover_token"), defaults.pushover_token),
|
pushover_token=_coerce_str(
|
||||||
pushover_user=_coerce_str(cfg.get("notify_pushover_user"), defaults.pushover_user),
|
cfg.get("notify_pushover_token"), defaults.pushover_token
|
||||||
|
),
|
||||||
|
pushover_user=_coerce_str(
|
||||||
|
cfg.get("notify_pushover_user"), defaults.pushover_user
|
||||||
|
),
|
||||||
per_crack_enabled=_coerce_bool(
|
per_crack_enabled=_coerce_bool(
|
||||||
cfg.get("notify_per_crack_enabled"), defaults.per_crack_enabled
|
cfg.get("notify_per_crack_enabled"), defaults.per_crack_enabled
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ and resolves ``toggle_notifications`` / ``toggle_per_crack_notifications`` /
|
|||||||
We therefore patch that module directly — patching the ``hate_crack.py``
|
We therefore patch that module directly — patching the ``hate_crack.py``
|
||||||
proxy would have no effect on the submenu's internal dispatch.
|
proxy would have no effect on the submenu's internal dispatch.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import hate_crack.main as _main_mod
|
import hate_crack.main as _main_mod
|
||||||
import hate_crack.menu as _menu_mod
|
import hate_crack.menu as _menu_mod
|
||||||
from hate_crack.notify.settings import NotifySettings
|
from hate_crack.notify.settings import NotifySettings
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""Unit tests for the toggle_per_crack_enabled runtime toggle."""
|
"""Unit tests for the toggle_per_crack_enabled runtime toggle."""
|
||||||
|
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -80,9 +81,7 @@ class TestTogglePerCrackNotificationsUI:
|
|||||||
from hate_crack.notify.settings import NotifySettings
|
from hate_crack.notify.settings import NotifySettings
|
||||||
|
|
||||||
settings = NotifySettings(enabled=enabled, per_crack_enabled=per_crack)
|
settings = NotifySettings(enabled=enabled, per_crack_enabled=per_crack)
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(CLI_MODULE._notify, "get_settings", lambda: settings)
|
||||||
CLI_MODULE._notify, "get_settings", lambda: settings
|
|
||||||
)
|
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
def test_guard_refuses_on_when_global_off(self, monkeypatch, capsys):
|
def test_guard_refuses_on_when_global_off(self, monkeypatch, capsys):
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""Unit tests for hate_crack.notify.settings."""
|
"""Unit tests for hate_crack.notify.settings."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -40,16 +41,18 @@ class TestLoadSettings:
|
|||||||
assert load_settings(None) == NotifySettings()
|
assert load_settings(None) == NotifySettings()
|
||||||
|
|
||||||
def test_load_full_dict(self) -> None:
|
def test_load_full_dict(self) -> None:
|
||||||
s = load_settings({
|
s = load_settings(
|
||||||
"notify_enabled": True,
|
{
|
||||||
"notify_pushover_token": "tok",
|
"notify_enabled": True,
|
||||||
"notify_pushover_user": "usr",
|
"notify_pushover_token": "tok",
|
||||||
"notify_per_crack_enabled": True,
|
"notify_pushover_user": "usr",
|
||||||
"notify_attack_allowlist": ["Brute Force", "Dictionary"],
|
"notify_per_crack_enabled": True,
|
||||||
"notify_suppress_in_orchestrators": False,
|
"notify_attack_allowlist": ["Brute Force", "Dictionary"],
|
||||||
"notify_max_cracks_per_burst": 20,
|
"notify_suppress_in_orchestrators": False,
|
||||||
"notify_poll_interval_seconds": 2.5,
|
"notify_max_cracks_per_burst": 20,
|
||||||
})
|
"notify_poll_interval_seconds": 2.5,
|
||||||
|
}
|
||||||
|
)
|
||||||
assert s.enabled is True
|
assert s.enabled is True
|
||||||
assert s.pushover_token == "tok"
|
assert s.pushover_token == "tok"
|
||||||
assert s.pushover_user == "usr"
|
assert s.pushover_user == "usr"
|
||||||
@@ -60,12 +63,14 @@ class TestLoadSettings:
|
|||||||
assert s.poll_interval_seconds == 2.5
|
assert s.poll_interval_seconds == 2.5
|
||||||
|
|
||||||
def test_load_tolerates_bad_types(self) -> None:
|
def test_load_tolerates_bad_types(self) -> None:
|
||||||
s = load_settings({
|
s = load_settings(
|
||||||
"notify_enabled": "true",
|
{
|
||||||
"notify_max_cracks_per_burst": "not-a-number",
|
"notify_enabled": "true",
|
||||||
"notify_poll_interval_seconds": "also-bad",
|
"notify_max_cracks_per_burst": "not-a-number",
|
||||||
"notify_attack_allowlist": "not-a-list",
|
"notify_poll_interval_seconds": "also-bad",
|
||||||
})
|
"notify_attack_allowlist": "not-a-list",
|
||||||
|
}
|
||||||
|
)
|
||||||
# string "true" -> True
|
# string "true" -> True
|
||||||
assert s.enabled is True
|
assert s.enabled is True
|
||||||
# bad ints fall back to defaults (5, 5.0)
|
# bad ints fall back to defaults (5, 5.0)
|
||||||
@@ -136,10 +141,14 @@ class TestAddToAllowlist:
|
|||||||
|
|
||||||
def test_preserves_other_entries(self, tmp_path: Path) -> None:
|
def test_preserves_other_entries(self, tmp_path: Path) -> None:
|
||||||
config_path = tmp_path / "config.json"
|
config_path = tmp_path / "config.json"
|
||||||
config_path.write_text(json.dumps({
|
config_path.write_text(
|
||||||
"hcatBin": "hashcat",
|
json.dumps(
|
||||||
"notify_attack_allowlist": ["Existing"],
|
{
|
||||||
}))
|
"hcatBin": "hashcat",
|
||||||
|
"notify_attack_allowlist": ["Existing"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
add_to_allowlist(str(config_path), "Brute Force")
|
add_to_allowlist(str(config_path), "Brute Force")
|
||||||
data = json.loads(config_path.read_text())
|
data = json.loads(config_path.read_text())
|
||||||
assert data["hcatBin"] == "hashcat"
|
assert data["hcatBin"] == "hashcat"
|
||||||
|
|||||||
Reference in New Issue
Block a user