Files
hate_crack/tests/test_permute_attack.py
Justin Bollinger 8ada9b069a feat: add permutation attack using permute.bin (closes #86)
Adds Permutation Attack (menu option 19) that generates all character
permutations of each word in a targeted wordlist and pipes them to
hashcat via permute.bin from hashcat-utils.

- hcatPermute() in main.py: pipes permute.bin < wordlist | hashcat
- permute_crack() in attacks.py: prompts for single wordlist file with
  factorial-growth warning, tab-autocomplete support
- Menu option 19 wired in both main.py and hate_crack.py
- hcatPermuteCount tracking alongside other count globals
- Tests: test_permute_attack.py (handler behavior) and
  test_permute_wrapper.py (subprocess wiring)
- README: added entry in menu listing and attack descriptions
2026-03-19 12:14:05 -04:00

68 lines
2.2 KiB
Python

import os
from unittest.mock import MagicMock, patch
import pytest
from hate_crack.attacks import permute_crack
def _make_ctx(hash_type="1000", hash_file="/tmp/hashes.txt"):
ctx = MagicMock()
ctx.hcatHashType = hash_type
ctx.hcatHashFile = hash_file
ctx.hcatWordlists = "/tmp/wordlists"
return ctx
class TestPermuteCrack:
def test_calls_hcatPermute_with_valid_wordlist(self, tmp_path):
ctx = _make_ctx()
wl = tmp_path / "target.txt"
wl.write_text("abc\ndef\n")
with patch("builtins.input", return_value=str(wl)):
permute_crack(ctx)
ctx.hcatPermute.assert_called_once_with(
ctx.hcatHashType, ctx.hcatHashFile, str(wl)
)
def test_rejects_nonexistent_wordlist_then_accepts_valid(self, tmp_path):
ctx = _make_ctx()
wl = tmp_path / "real.txt"
wl.write_text("test\n")
with patch(
"builtins.input",
side_effect=["/nonexistent/path.txt", str(wl)],
):
permute_crack(ctx)
ctx.hcatPermute.assert_called_once_with(
ctx.hcatHashType, ctx.hcatHashFile, str(wl)
)
def test_rejects_directory_then_accepts_file(self, tmp_path):
ctx = _make_ctx()
wl = tmp_path / "words.txt"
wl.write_text("ab\n")
with patch("builtins.input", side_effect=[str(tmp_path), str(wl)]):
permute_crack(ctx)
ctx.hcatPermute.assert_called_once_with(
ctx.hcatHashType, ctx.hcatHashFile, str(wl)
)
def test_warns_about_factorial_scaling(self, tmp_path, capsys):
ctx = _make_ctx()
wl = tmp_path / "words.txt"
wl.write_text("abc\n")
with patch("builtins.input", return_value=str(wl)):
permute_crack(ctx)
captured = capsys.readouterr()
assert "WARNING" in captured.out or "factorial" in captured.out.lower() or "N!" in captured.out
def test_prints_header(self, tmp_path, capsys):
ctx = _make_ctx()
wl = tmp_path / "words.txt"
wl.write_text("abc\n")
with patch("builtins.input", return_value=str(wl)):
permute_crack(ctx)
captured = capsys.readouterr()
assert "PERMUTATION" in captured.out.upper()