diff --git a/README.md b/README.md index a7d51c3..6f83a7b 100644 --- a/README.md +++ b/README.md @@ -912,6 +912,9 @@ Interactive menu for downloading and managing wordlists from Weakpass.com via Bi ------------------------------------------------------------------- ### Version History +Version 2.10.5 + - Pipal analysis no longer corrupts its input when cracked passwords contain `$HEX[...]` rows. `binascii.unhexlify().decode()` returned the bytes without the trailing newline that normal rows inherit from `password[-1]`, so every HEX-encoded password got concatenated with the next one in the `.passwords` file fed to pipal (e.g. three cracks → two lines, one of them a bogus mashup). Pipal then under-counted entries and reported wrong top base words. The HEX branch now re-appends `\n` so each cracked password lands on its own line + Version 2.10.4 - Pushover notifications fire correctly for Quick Crack, Loopback, Combinator, PRINCE-LING, and N-gram attacks (#110). The handlers prompted the user under one name (e.g. "Quick Crack") while the underlying hashcat wrapper passed a different `attack_name` to `_should_fire` ("Quick Dictionary"), so the per-run consent lookup always missed. The prompt name now flows down to `_run_hcat_cmd` for both the job-done summary and the per-crack tailer diff --git a/hate_crack/main.py b/hate_crack/main.py index 7e4c0fd..93dde4a 100755 --- a/hate_crack/main.py +++ b/hate_crack/main.py @@ -4220,6 +4220,8 @@ def pipal(): clearTextPass = binascii.unhexlify(match.group(1)).decode( "iso-8859-9" ) + if not clearTextPass.endswith("\n"): + clearTextPass += "\n" pipalFile.write(clearTextPass) pipalFile.close() diff --git a/tests/test_pipal.py b/tests/test_pipal.py index 407c95a..e740c25 100644 --- a/tests/test_pipal.py +++ b/tests/test_pipal.py @@ -46,6 +46,44 @@ def test_pipal_runs_and_parses_basewords(hc_module, tmp_path, capsys): assert "pass123" in content +def test_pipal_passwords_file_is_newline_separated_with_hex(hc_module, tmp_path): + """HEX-encoded cracked passwords must not be glued to the next line. + + Regression: binascii.unhexlify().decode() drops the trailing newline that + normal lines retain from password[-1], so HEX rows concatenated with the + next password in the .passwords file fed to pipal. + """ + hc = hc_module + hc.hcatHashType = "0" + hc.pipal_count = 3 + hc.hcatHashFile = str(tmp_path / "hashes") + + out_path = tmp_path / "hashes.out" + out_path.write_text( + "hash1:password123\n" + "hash2:$HEX[70617373313233]\n" # "pass123" + "hash3:letmein\n" + ) + + pipal_stub = tmp_path / "pipal_stub.py" + _write_executable( + pipal_stub, + "#!/usr/bin/env python3\n" + "import sys\n" + "out = sys.argv[sys.argv.index('--output') + 1]\n" + "open(out, 'w').write('Top 3 base words\\n'\n" + " 'pass123 1\\n'\n" + " 'letmein 1\\n'\n" + " 'welcome 1\\n')\n", + ) + hc.pipalPath = str(pipal_stub) + + hc.pipal() + + passwords = (tmp_path / "hashes.passwords").read_text().splitlines() + assert passwords == ["password123", "pass123", "letmein"] + + def test_pipal_missing_out_returns_empty(hc_module, tmp_path, capsys): hc = hc_module hc.hcatHashType = "0"