
hate_crack v2.36.1
Uno strumento per automatizzare le metodologie di cracking tramite Hashcat del team TrustedSec.
___ ___ __ _________ __
/ | \_____ _/ |_ ____ \_ ___ \____________ ____ | | __
/ ~ \__ \\ __\/ __ \ / \ \/\_ __ \__ \ _/ ___\| |/ /
\ Y // __ \| | \ ___/ \ \____| | \// __ \\ \___| <
\___|_ /(____ /__| \___ >____\______ /|__| (____ /\___ >__|_ \
\/ \/ \/_____/ \/ \/ \/ \/
Installazione
L'installazione da sorgente è l'unico percorso supportato. hate_crack non è
distribuito su PyPI: pip install hate-crack punta a un placeholder 0.0.0
che fallisce di proposito e rimanda qui. Il nome è riservato solo per evitare che
qualcun altro possa pubblicare un clone sotto di esso — vedi
packaging/pypi-placeholder/.
1. Installare hashcat
Hashcat deve essere installato e disponibile nel tuo PATH:
Ubuntu/Kali:```bash sudo apt-get install -y hashcat
macOS (Homebrew):```bash
brew install hashcat
Oppure scarica un binario precompilato da https://hashcat.net/hashcat/ e imposta hcatPath in config.json alla sua posizione.
2. Scarica hate_crack
Clona con i sottomoduli (richiesto per hashcat-utils, princeprocessor, pcfg_cracker, Corporate_Masks e opzionalmente omen):```bash git clone --recurse-submodules https://github.com/trustedsec/hate_crack.git cd hate_crack
Se hai clonato senza i sottomoduli, inizializzali:```bash
git submodule update --init --recursive
Poi personalizza la configurazione se necessario. hate_crack utilizza due file di configurazione, ognuno dei quali possiede un insieme distinto di impostazioni:
config.json— percorsi delle wordlist, maschere, regole, tuning, potfile, percorso di hashcat, limiti dei candidati, toggle delle notifiche, preferenze predefinite della CLI (35 impostazioni)..env— solo impostazioni di integrazione di terze parti: credenziali Hashview e Hashmob, credenziali Pushover, Ollama e pipal (14 impostazioni). Non tracciato da git, creato con modalità0600.
La linea di demarcazione è lì per un motivo: .env è il file che può contenere segreti. Le credenziali per i servizi di terze parti, e la loro configurazione, vanno nel file non tracciato con permessi 0600; tutto ciò che hate_crack fa localmente rimane in config.json, che è sicuro da condividere, confrontare con diff e inserire nelle tue note. È anche per questo che le credenziali Pushover sono in .env mentre i toggle di attivazione/disattivazione di Pushover sono in config.json — i toggle sono preferenze locali, non segreti.
Ogni chiave ha esattamente una collocazione. Una chiave inserita nell'altro file viene ignorata, e hate_crack stampa un avviso indicando il file a cui appartiene. Qualsiasi chiave può comunque essere sovrascritta per una singola esecuzione esportando la sua variabile d'ambiente. La maggior parte degli utenti può saltare questo passaggio poiché i percorsi predefiniti funzionano out-of-the-box.
config.json è permanente e di prima classe — non è deprecato e non esiste una tempistica di rimozione per esso. Solo le impostazioni di integrazione sono state spostate.
Stai aggiornando da un singolo config.json? hate_crack lo migra automaticamente alla prima esecuzione: le impostazioni di integrazione vengono copiate in un nuovo .env con permessi 0600, poi rimosse da config.json in modo che i due file non le rivendichino entrambi. Stampa quali chiavi sono state spostate (mai i loro valori) e salva l'originale come config.json.pre-split.bak prima di modificarlo. Tutto il resto in config.json viene lasciato esattamente com'era, incluso l'ordine delle chiavi.
Prima esecuzione: hate_crack crea entrambi i file per te, quindi non c'è nulla da fare. Per configurare .env manualmente, invece, copia il template tracciato:```bash
cp .env.example .env
chmod 600 .env
`.env.example` è committato e viene distribuito con ogni chiave di credenziale vuota. `.env` stesso non deve **mai** essere committato — è gitignorato, insieme alle sue solite varianti di backup, e hate_crack lo crea sempre con modalità `0600` (solo lettura/scrittura per il proprietario). `.env.example` è generato dallo schema; rigeneralo dopo aver modificato `hate_crack/config_schema.py` con `uv run python -m hate_crack.config_writer`.
### 3. Installa le dipendenze e hate_crack
Il modo più semplice è eseguire `make` (o `make install`), che rileva automaticamente il tuo sistema operativo e installa:
- Dipendenze esterne (p7zip, transmission-daemon / transmission-remote)
- Compila i sottomoduli (hashcat-utils, princeprocessor, pcfg_cracker e opzionalmente omen) e fa il checkout del set di maschere Corporate_Masks di soli dati
- Dipendenze Python tramite uv e uno shim CLI in `~/.local/bin/hate_crack````bash
make
Questo è idempotente - salta gli strumenti già installati. Per forzare una reinstallazione pulita:```bash make reinstall
**Oppure installa manualmente le dipendenze:**
### Dipendenze esterne
Queste sono necessarie per alcuni flussi di download/estrazione:
- `7z`/`7za` (p7zip) — utilizzato per estrarre archivi `.7z`.
- `transmission-daemon` / `transmission-remote` — utilizzato per scaricare i torrent Weakpass.
Comandi di installazione manuale:
Ubuntu/Kali:```bash
sudo apt-get update
sudo apt-get install -y p7zip-full transmission-daemon
macOS (Homebrew):```bash brew install p7zip transmission-cli # provides transmission-daemon and transmission-remote
Poi installa le dipendenze Python e lo shim CLI:```bash
uv sync
mkdir -p ~/.local/bin
printf '#!/usr/bin/env bash\nset -euo pipefail\nexec uv run --directory %s python -m hate_crack "$@"\n' "$(pwd)" > ~/.local/bin/hate_crack
chmod +x ~/.local/bin/hate_crack
Struttura del progetto
La logica principale è ora suddivisa in moduli sotto hate_crack/:
hate_crack/cli.py: helper argparse e override della configurazione.hate_crack/api.py: integrazioni Hashview, Weakpass e Hashmob (download/menu/helper).hate_crack/attacks.py: gestori degli attacchi da menu.hate_crack/corpus_stats.py: statistiche sulle password dell'intero corpus utilizzate per descrivere un corpus all'LLM.hate_crack/plaintext.py: recupera la password da una riga del corpus (rimozione del prefisso hash, decodifica$HEX[...]); condiviso dalle modalità LLM, corpus_stats e rulegen.hate_crack/llm.py: generazione strutturata (JSON) di candidati LLM tramite Atomic Agents.hate_crack/menu.py: renderer di menu condiviso, inclusa la navigazione opzionale con i tasti freccia.hate_crack/noninteractive.py: dispatcher per i sottocomandi di attacco scriptati.hate_crack/notify/: pacchetto di notifiche (backend Pushover, tailer per singolo crack).hate_crack/username_detect.py: rileva i file di inputusername:hashper decidere l'uso di--usernamedi hashcat.hate_crack/formatting.py,hate_crack/progress.py: helper per la formattazione dell'output e la visualizzazione del progresso.hate_crack/main.py: implementazione principale della CLI.
Il file di primo livello hate_crack.py rimane il punto di ingresso principale e orchestra questi moduli.
Riferimenti e ringraziamenti
Questo progetto dipende da e si ispira a numerosi progetti e servizi esterni. Grazie a:
- Hashview (http://github.com/hashview/)
- Weakpass (https://weakpass.com)
- Hashmob (https://hashmob.net)
Utilizzo
Dopo l'installazione con make, esegui hate_crack da qualsiasi posizione:```bash
hate_crack
or with arguments:
hate_crack <hash_file> <hash_type> [options]
In alternativa, esegui tramite `uv`:```bash
uv run hate_crack.py <hash_file> <hash_type>
Esegui come strumento (consigliato)
Installa usando make dalla radice del repository - questo compila i sottomoduli e raggruppa le risorse:```bash
cd /path/to/hate_crack
make
hate_crack
Il comando `make install` crea un bash shim in `~/.local/bin/hate_crack` che viene eseguito dalla directory del repo, così la configurazione e gli asset vengono sempre trovati indipendentemente dalla directory di lavoro corrente.
La configurazione viene cercata anche in:
- La root del repo e la directory del pacchetto
- `~/.hate_crack`
**Nota:** Il `hcatPath` in `config.json` è solo per la posizione del binario hashcat (opzionale se hashcat è nel PATH). Gli asset di Hate_crack (hashcat-utils, princeprocessor, pcfg_cracker, Corporate_Masks, omen) vengono caricati dalla directory del repository e inclusi automaticamente da `make install`.
### Esecuzione come script
Lo script utilizza uno shebang `uv`. Rendilo eseguibile ed esegui:```bash
chmod +x hate_crack.py
./hate_crack.py
Puoi anche usare Python direttamente:```bash python hate_crack.py
### Utilizzo non interattivo / scriptato
Per l'automazione puoi avviare un singolo attacco direttamente, bypassando il menu. Il nome dell'attacco è il primo argomento, seguito dal file di hash e dal tipo di hash di hashcat. I prompt di pre-elaborazione (filtro degli account computer, brute force LM-first, deduplicazione degli account duplicati) accettano automaticamente i valori predefiniti in questa modalità. Il processo termina con `0` in caso di successo e con un valore diverso da zero in caso di errore (file di hash mancante, tipo di hash non numerico, wordlist mancante o nome di regola sconosciuto).```bash
# Quick crack: one wordlist + optional rule(s) from the rules directory
hate_crack quick hashes.txt 1000 --wordlist rockyou.txt --rules best64.rule
# Chain two rules in a single run
hate_crack quick hashes.txt 1000 --wordlist rockyou.txt --rules best64.rule+d3ad0ne.rule
# Run two rules as two separate passes
hate_crack quick hashes.txt 1000 --wordlist rockyou.txt --rules best64.rule d3ad0ne.rule
# Canned dictionary methodology (uses your configured wordlists)
hate_crack dict hashes.txt 1000
# Brute force lengths 1-8
hate_crack brute hashes.txt 1000 --min 1 --max 8
# Top-mask attack targeting ~4 hours
hate_crack topmask hashes.txt 1000 --target-time 4
Risoluzione dei problemi
Errore: "would clobber existing tag" durante l'aggiornamento
Un clone più vecchio può rifiutarsi di aggiornarsi, stampando un lungo elenco di righe come:``` ! [rejected] v2.5.0 -> v2.5.0 (would clobber existing tag)
Questo riguarda i cloni creati prima di luglio 2026. La cronologia pubblicata è stata riscritta
allora per rimuovere alcuni file che non avrebbero mai dovuto essere committati, il che ha assegnato
a ogni commit un nuovo ID; i tag di un clone più vecchio puntano quindi a oggetti che questo
repository non contiene più, e git rifiuta di spostare un tag che possiede già.
Non c'è nulla di sbagliato nel tuo checkout e nessun dato di cracking è a rischio.
Recupera con un reset una tantum. Questo scarta i commit e le modifiche locali nel
checkout, quindi se hai personalizzato qualcosa tracciato da git (al contrario di
`config.json`, che non è tracciato), committalo prima su un branch:```bash
cd /path/to/hate_crack
git fetch --tags --force origin
git checkout -B main origin/main
make install
--force qui aggiorna solo i tag; non può toccare i tuoi commit. Successivamente
l'updater integrato funziona normalmente. Le versioni precedenti alla 2.18 non potevano eseguire questo
recupero da sole, motivo per cui deve essere fatto manualmente una volta.
Errore: la directory di build non esiste
Se vedi un errore come:``` Error: Build directory /opt/hashcat/hashcat-utils does not exist. Expected to find expander at /opt/hashcat/hashcat-utils/bin/expander.
Questo significa che gli asset di hate_crack non sono stati inclusi nel pacchetto installato.
**Comprendere i percorsi:**
- `hcatPath` in config.json → punta alla **posizione del binario hashcat** (opzionale, può essere nel PATH)
- `hashcat-utils/` e `princeprocessor/` → inclusi nel pacchetto da `make install`
**Soluzione:**
Reinstalla usando il Makefile, che compila i sottomoduli e installa lo strumento:```bash
cd /path/to/hate_crack # the repository checkout
make install
Configurazione predefinita (config.json.example):
La maggior parte degli utenti può utilizzare i valori predefiniti senza personalizzazioni:
hcatWordlists:./wordlists(relativo alla radice del repo o HOME/.hate_crack)hcatOptimizedWordlists:./optimized_wordlists(directory utilizzata da Quick Crack; se non trovata, ricade suhcatWordlists)rules_directory:./hashcat/rules(include le regole del submodule)hcatTuning: `` (stringa vuota - nessun flag di tuning predefinito)
Esempi di personalizzazioni di config.json:```json { "hcatPath": "/usr/local/bin", # Location of hashcat binary (optional, auto-detected from PATH) "hcatBin": "hashcat", # Hashcat binary name "hcatWordlists": "./wordlists", # Dictionary wordlist directory (relative or absolute) "rules_directory": "./hashcat/rules", # Rules directory (relative or absolute) "hcatTuning": "", # Additional hashcat flags (empty by default) ... }
**Caricamento della configurazione:**
- Precedenza per ogni chiave: `os.environ` > il file home della chiave stessa (`.env` o `config.json`) > valore predefinito integrato
- Le chiavi mancanti ricadono sui valori predefiniti integrati; `config.json.example` documenta ogni chiave di `config.json`
- Entrambi i file vengono cercati, indipendentemente l'uno dall'altro, in questo ordine: **radice del repo**, poi la **directory del pacchetto installato**, poi **`~/.hate_crack`**. Vince la prima corrispondenza; è normale che i due file provengano da directory diverse.
- Alla prima esecuzione, entrambi vengono creati — `config.json` da `config.json.example`, `.env` dai valori predefiniti integrati. Se un vecchio `config.json` contiene ancora chiavi di integrazione, vengono copiate nel nuovo `.env` e hate_crack ti indica quali eliminare da `config.json`; non modifica mai quel file da solo.
- A ogni esecuzione, hate_crack stampa i due file che ha effettivamente caricato: ```
[*] config.json: /home/you/.hate_crack/config.json
[*] .env: /home/you/.hate_crack/.env
Leggi quelle due righe prima di eseguire il debug di un'impostazione che "non ha effetto". Esistono a causa di due trappole nell'ordine di ricerca:
- Un checkout ha precedenza sulla tua home directory. La radice del repo viene cercata per prima, quindi un
.envoconfig.jsonpresente in qualsiasi checkout da cui esegui lo strumento ha la meglio su quello in~/.hate_crack— ed eseguire lo strumento da un checkout è esattamente ciò che crea quei file lì in primo luogo. Se questo dovesse oscurare una vera configurazione in~/.hate_crack, hate_crack ora lo segnala con una terza riga[!]che nomina entrambi i percorsi — considera quella riga come "il file sottostante viene ignorato", non come una seconda configurazione altrettanto valida. - La directory di lavoro corrente non viene mai cercata. Un
.envnella directory in cui ti trovi viene ignorato, deliberatamente: le directory di engagement sono piene di file che nessuno intendeva come configurazione. Mettilo nella radice del repo o in~/.hate_crack.
Errore: merge with ref 'refs/heads/master' but no such ref was fetched
Se vedi:``` Your configuration specifies to merge with the ref 'refs/heads/master' from the remote, but no such ref was fetched.
Il branch predefinito è stato rinominato da `master` a `main`. Correggi con:```bash
git remote set-head origin -a
git branch -m master main
git branch --set-upstream-to=origin/main main
git pull
Target del Makefile
Predefinito (installazione completa) - compila i sottomoduli, installa le dipendenze e installa lo strumento:```bash make
or explicitly:
make install
Questo è idempotente - salta gli strumenti già installati.
**Forza la reinstallazione pulita:**```bash
make reinstall
Aggiornamento rapido - ricompila i sottomoduli e reinstalla lo strumento (dopo aver scaricato le modifiche):```bash make update
**Disinstallazione** - rimuove le dipendenze del sistema operativo e lo strumento:```bash
make uninstall
Compila solo hashcat-utils:```bash make hashcat-utils
**Esegui i test** - gestisce automaticamente HATE_CRACK_SKIP_INIT quando necessario:```bash
make test
Report di copertura:```bash make coverage
**Pulisci gli artefatti di build/test:**```bash
make clean
Sviluppo
Configurazione dell'ambiente di sviluppo
Installa il progetto con le dipendenze opzionali di sviluppo (include linter e strumenti di testing):```bash make dev-install
### Esecuzione di Linter e Controlli di Tipo
Prima di effettuare il push delle modifiche, esegui questi controlli in locale. Usa `make lint` per tutto, oppure esegui i singoli controlli:
**Ruff (linting e formattazione):**```bash
make ruff
# or manually:
uv run ruff check hate_crack tests tools packaging hate_crack.py
Correzione automatica dei problemi:```bash uv run ruff format hate_crack tests tools packaging hate_crack.py uv run ruff check --fix hate_crack tests tools packaging hate_crack.py
**ty (controllo dei tipi):**```bash
make ty
# or manually:
uv run ty check hate_crack
Esegui tutti i controlli insieme:```bash make lint
### Esecuzione dei test
I test rilevano automaticamente quando i sottomoduli non sono compilati e impostano `HATE_CRACK_SKIP_INIT=1` automaticamente.```bash
make test
Oppure esegui pytest direttamente:```bash uv run pytest -v
Con copertura:```bash
make coverage
Oppure con pytest:```bash uv run pytest --cov=hate_crack
### Git Hooks (prek)
Gli hook Git sono gestiti da [prek](https://github.com/j178/prek) (v0.3.3+). Installa gli hook con:```bash
prek install --hook-type pre-push --hook-type pre-commit
Questo installa gli hook definiti in prek.toml usando lo schema TOML
local-repo di pre-commit:
- pre-push (hook locali): ruff, ruff-format, ty, pytest, pytest-lima, bandit
- pre-commit (da
pre-commit/pre-commit-hooks): trailing-whitespace, end-of-file-fixer, check-yaml, check-merge-conflict, check-added-large-files, detect-private-key
Gli auto-fixer di pre-commit riscrivono i file sul posto, quindi riesegui lo stage e committa di nuovo dopo che sono stati eseguiti.
Nota: prek 0.3.3 si aspetta repos = [...] al livello superiore. Il vecchio formato [hooks.<stage>] commands = [...] non è supportato.
Navigazione dei menu con i tasti freccia
I menu usano per impostazione predefinita la classica selezione numerata con print() + input(), che
accetta chiavi complete a più cifre.
Per abilitare la navigazione con i tasti freccia tramite simple-term-menu, imposta
HATE_CRACK_ARROW_MENU=1. In quella modalità funzionano solo i tasti di scelta rapida a singola cifra;
le opzioni numerate da 10 in su devono essere raggiunte con i tasti freccia. La modalità
con i tasti freccia richiede anche un TTY, quindi resta disattivata quando l'output è reindirizzato tramite pipe.
Dipendenze di sviluppo
Il gruppo opzionale [dev] include:
- ty - Controllore statico dei tipi
- ruff - Linter e formattatore Python veloce
- pytest - Framework di testing
- pytest-cov - Reportistica della copertura
Opzioni comuni:
--download-hashview: Scarica gli hash da Hashview prima del cracking.--hashview: Menu interattivo di Hashview per gestire hash, wordlist e job.--hashview --help: Mostra le opzioni della riga di comando di Hashview.--weakpass: Scarica le wordlist da Weakpass.--hashmob: Scarica le wordlist da Hashmob.net.--hashmob-masks: Scarica le mask da Hashmob.net.--download-torrent <FILENAME>: Scarica uno specifico file torrent di Weakpass.--download-all-torrents: Scarica tutti i torrent Weakpass disponibili dalla cache.--wordlists-dir <PATH>/--optimized-wordlists-dir <PATH>: Sovrascrive le directory delle wordlist.--pipal-path <PATH>: Sovrascrive il percorso di pipal.--restore-potfile: Ricostruisce<hashfile>.outdal file POT di hashcat all'avvio, sostituendo qualsiasi contenuto esistente, poi prosegue nel menu normale. Senza questo flag la ricerca nel POT viene eseguita solo quando.outnon esiste già. L'opzione 93 del menu fa la stessa cosa su richiesta, con una richiesta di conferma.--maxruntime <SECONDS>: Sovrascrive il tempo massimo di esecuzione.--bandrel-basewords <PATH>: Sovrascrive il file delle basewords di bandrel.--update: Aggiorna all'ultima release e reinstalla. Passa il checkout amainse si trova su un altro branch, poiché i tag di release risiedono lì.--nightly: Aggiorna invece all'ultima nightly, dal branchnightly-dev. Le nightly hanno superato la CI ma non fanno parte di una release pubblicata. Può anche essere scritto--update --nightly.--no-optimized-kernel(o--no-optimize): Non passa mai-Oa hashcat per l'intera esecuzione. SovrascriveoptimizedKernelAttacksinconfig.jsone rimuove qualsiasi-Oinserito inhcatTuning. Nulla viene riscritto nel config, quindi si applica solo a questa esecuzione. Con un sottocomando, inseriscilo prima del sottocomando:./hate_crack.py --no-optimize quick hashes.txt 1000 --wordlist words.txt.--debug: Abilita il logging di debug (scrive su stderr).
Integrazione con Hashview
hate_crack si integra con Hashview per la gestione centralizzata degli hash e il cracking distribuito.
Menu interattivo
Per accedere al menu interattivo di Hashview:```bash hate_crack.py --hashview
Opzioni del menu:
- **(1) Upload Cracked Hashes** - Carica i risultati decifrati dalla sessione corrente su Hashview
- **(2) Upload Wordlist** - Carica un file wordlist su Hashview
- **(3) Download Wordlist** - Scarica una wordlist da Hashview
- **Download Rule** - Scarica un file di regole da Hashview (decompresso in testo semplice, pronto per `hashcat -r`). Inserisci `a` (o `all`) al prompt dell'ID regola per scaricare tutte le regole elencate invece di una sola
- **Download All Rules** - Scarica tutti i file di regole elencati da Hashview in un'unica operazione; gli errori relativi alle singole regole vengono segnalati senza interrompere le altre
- **(4) Download Left Hashes** - Scarica gli hash rimanenti non decifrati (chiede se passare alla loro decifratura)
- **(5) Download Found Hashes** - Scarica gli hash già decifrati con le password in chiaro (per riferimento/analisi)
- **(6) Upload Hashfile and Create Job** - Carica un nuovo hashfile e crea un job di decifratura
- **(99) Back to Main Menu** - Torna al menu principale
**Importante: Download Found vs Download Left**
- **Download Left Hashes (4)**: Scarica gli hash non decifrati che necessitano di decifratura. Si unisce automaticamente a eventuali hash trovati, se disponibili, e chiede se passare a questo hashfile per la decifratura.
- **Download Found Hashes (5)**: Scarica gli hash già decifrati nel formato hash:cleartext. Questi sono per riferimento e non possono essere ulteriormente decifrati. Non viene mostrato alcun prompt di cambio.
#### Interfaccia a riga di comando
Le operazioni di Hashview possono essere eseguite anche tramite riga di comando:
Caricamento degli hash decifrati:```bash
hate_crack.py --hashview upload-cracked --file <output_file>.out --hash-type 1000
Carica una wordlist:```bash hate_crack.py --hashview upload-wordlist --file .txt --name "My Wordlist"
Scarica un file di regole (salvato decompresso, pronto per `hashcat -r`):```bash
hate_crack.py --hashview download-rules --rules-id 4 --output best64.rule
Scarica gli hash rimasti (hash non craccati da craccare):```bash hate_crack.py --hashview download-left --customer-id 1 --hashfile-id 123
Scarica gli hash trovati (hash già crackati con testo in chiaro):```bash
hate_crack.py --hashview download-found --customer-id 1 --hashfile-id 123
Carica il file hash e crea il job:```bash
hate_crack.py --hashview upload-hashfile-job --file hashes.txt --customer-id 1
--hash-type 1000 --job-name "NTLM Crack Job" --hashfile-name "Domain Hashes"
#### Configurazione
Imposta le credenziali di Hashview in `.env` (sono impostazioni di integrazione, quindi non risiedono in `config.json`):```
HASHVIEW_URL=https://hashview.example.com
HASHVIEW_API_KEY=your-api-key-here
HASHVIEW_VERIFY_TLS=true
HASHVIEW_VERIFY_TLS è impostato per impostazione predefinita su true: hate_crack verifica il certificato TLS del server Hashview, e la connessione a un Hashview con un certificato autofirmato o emesso da una CA interna fallirà finché quel certificato non sarà considerato attendibile (aggiungilo al trust store del tuo sistema, oppure usa un certificato emesso da una CA già considerata attendibile dal tuo sistema). Se ciò non è possibile, imposta HASHVIEW_VERIFY_TLS=false -- hate_crack stamperà un avviso di una riga che indica l'host all'avvio di ogni processo quando la verifica è disattivata, poiché disattivarla rimuove la protezione contro un server contraffatto o un attaccante on-path che intercetta la connessione.
Configurazione LLM
L'LLM Attack (opzione 12) e il Rosetta Mask Attack (opzione 23) generano i loro candidati con un modello locale. Configura il modello, la finestra di contesto e il timeout delle richieste in .env:```
LLM_BACKEND=ollama
OLLAMA_MODEL=qwen3:4b-instruct
OLLAMA_NUM_CTX=8192
OLLAMA_TIMEOUT=300
**Le chiavi `OLLAMA_*` riportate di seguito si applicano a ogni backend, non solo a Ollama.** Mantengono quel prefisso perché `OLLAMA_HOST` è la stessa variabile letta dalla CLI di Ollama stessa, e rinominarle romperebbe ogni `.env` esistente senza alcun guadagno funzionale — un server vLLM o compatibile con OpenAI vuole lo stesso host, modello, timeout, contesto e parametri di campionamento con gli stessi nomi. `LLM_BACKEND` seleziona solo come viene strutturata la richiesta.
- **`OLLAMA_MODEL`** — Il modello Ollama usato per la generazione dei candidati (predefinito: `qwen3:4b-instruct`). L'attacco LLM usa output strutturato (JSON), quindi scegli un modello con un buon supporto a tool/JSON.
- **`OLLAMA_NUM_CTX`** — Dimensione della finestra di contesto per il modello (predefinito: `8192`). Era `2048` prima dell'introduzione delle statistiche del corpus, troppo piccolo per contenere il prompt che gli veniva fornito: 500 plaintext campionati occupano all'incirca 2.000–3.500 token prima del system prompt e della risposta, quindi Ollama troncava silenziosamente parte del campione che il sampler aveva distribuito con cura nel file.
- **`OLLAMA_TIMEOUT`** — Secondi di attesa per una risposta di generazione prima di rinunciare (predefinito: `300`). Aumentalo se un modello di grandi dimensioni è ancora in fase di caricamento nella VRAM alla prima richiesta, cosa che altrimenti può superare il timeout; hate_crack stampa il timeout trascorso e il nome di questa impostazione quando scatta.
- **`OLLAMA_MAX_SAMPLE_LINES`** — La soglia al di sotto della quale le modalità LLM incollano anche i plaintext letterali nel prompt (predefinito: `500`). I valori ≤ 0 sono trattati come 500.
Le modalità derivate dal corpus (**Wordlist**, **Cracked passwords**, **Pattern rules**) descrivono sempre l'*intero* corpus statisticamente — quote di baseword, maschere, casing, lunghezze, cifre e simboli finali, anni — invece di incollarne una porzione. L'aggregazione è limitata, quindi un dump di 120.000 password occupa all'incirca lo stesso spazio nel prompt di uno da 500 righe. Quando l'intero corpus rientra sotto questa soglia, vengono inclusi anche i plaintext grezzi, dato che non si guadagna nulla a nascondere un corpus piccolo al modello.
Questo sostituisce il comportamento precedente di incollare un campione uniformemente distribuito di fino a `ollamaMaxSampleLines` password. Un campione di un dump di grandi dimensioni non trasmetteva alcuna informazione sulla frequenza: il modello non poteva distinguere una baseword usata dall'8% dell'organizzazione da una usata da una singola persona, che è precisamente il segnale che rende un tentativo degno di essere eseguito.
- **`OLLAMA_NO_CLOUD`** — Quando è `true`, rifiuta di inviare qualsiasi cosa fuori da questo host, per uno qualsiasi dei tre backend LLM (Ollama, vLLM o un server generico compatibile con OpenAI). Due controlli sono regolati da questa singola impostazione: Ollama inoltra un modello con tag `-cloud` (`gpt-oss:120b-cloud`, `deepseek-v3.1:671b-cloud`) a ollama.com attraverso lo stesso endpoint locale che usa un modello locale, quindi nulla nella richiesta appare diverso — questo viene rifiutato in base al nome del modello. Viene controllato anche l'URL del backend configurato: una destinazione che non è loopback, privata o link-local (e non è `localhost` né un nome `.local`/`.internal`/`.lan`/`.localdomain`) viene rifiutata in base alla destinazione, e anche un hostname che questo controllo non riesce a risolvere viene rifiutato, in modalità fail-closed, invece di lasciar passare una destinazione non verificabile. I prompt di hate_crack contengono plaintext recuperati, statistiche del corpus e il nome, il settore e la posizione del cliente, quindi l'attivazione di uno dei due controlli significa che la richiesta viene rifiutata prima di essere costruita. Predefinito a `false`, così un modello cloud o un server remoto configurato deliberatamente continua a funzionare; attivalo per gli incarichi in cui i dati del cliente non devono lasciare l'host.
- **`OLLAMA_AUTO_RESEARCH`** — Quando è `true` (predefinito), la modalità **Target info** chiede al modello locale di suggerire il settore, la posizione e la società madre / la storia delle acquisizioni non appena hai digitato il nome dell'azienda, e li offre come valori predefiniti modificabili per il prompt. Impostalo a `false` per ottenere sempre prompt vuoti (utile con un modello lento, dato che la ricerca costa un round-trip extra prima che inizi l'attacco).
- **`OLLAMA_HOST`** — Dove è in ascolto il backend configurato. Accetta un semplice `host:port` (`theplague.lan:11434`) o un URL completo con schema (`https://ollama.example.com`); in entrambi i casi l'URL di base viene normalizzato prima dell'uso. Predefinito a `localhost:11434`, che è la porta di Ollama — un server vLLM o compatibile con OpenAI necessita che questo sia impostato sulla propria (vLLM comunemente ascolta su `:8000`). Impostalo in `.env`, oppure esportalo come variabile d'ambiente reale per sovrascrivere quello per una singola esecuzione — è lo stesso nome di variabile letto dalla CLI di Ollama stessa.
- **`LLM_BACKEND`** — A quale server compatibile con OpenAI parlare: `ollama` (predefinito), `vllm`, o `openai` per uno generico. Ogni backend parla la stessa API `/v1` chat-completions, quindi questo seleziona solo i due dettagli di strutturazione della richiesta su cui differiscono: `ollama` riceve `options.num_ctx`, e `vllm` riceve `chat_template_kwargs={"thinking": false}` — senza il quale un server vLLM che esegue un parser di reasoning instrada l'intera risposta strutturata in `message.reasoning`, lascia `message.content` vuoto e rompe il parsing JSON. `openai` non invia nessuno dei due, dato che `num_ctx` non ha un equivalente lì. **Non** cambia da dove provengono host, modello, timeout, contesto o impostazioni di campionamento — quelle sono le chiavi `OLLAMA_*` sopra per tutti e tre.
- **`LLM_API_KEY`** — La credenziale inviata al backend configurato. Predefinita al valore letterale `ollama`, il segnaposto che il server di Ollama stesso ignora, così le richieste di un'installazione esistente restano invariate; un valore vuoto ricade su quello stesso segnaposto perché l'SDK OpenAI rifiuta `api_key=""`. Impostala al valore reale se il server ne impone uno — un server vLLM avviato con `--api-key` restituisce 401 altrimenti.
- Assicurati che Ollama sia in esecuzione e che il modello sia stato scaricato (`ollama pull qwen3:4b-instruct`) prima di usare l'LLM Attack — hate_crack non scarica più automaticamente i modelli mancanti.
L'attacco offre tre modalità di generazione:
1. **Target info** — azienda / settore / posizione / società madre; il modello deriva i candidati da quei dettagli.
Dopo che hai digitato il nome dell'azienda, hate_crack chiede allo stesso modello locale cosa sa già di quell'organizzazione e precompila i prompt **Industry**, **Location** e **Parent Company** con le risposte, mostrate tra parentesi: ```
Company name: Acme Rail Services
[!] The values in parentheses below are the local model's GUESSES, not verified OSINT.
Press Enter to accept, or type your own value to override.
Industry (freight rail maintenance):
Location (Omaha, Nebraska):
Parent company / acquired by:
Premi Invio per accettare un suggerimento o digita sopra di esso. Questi valori sono il ricordo del modello, non OSINT — trattali come un punto di partenza, non come informazioni di intelligence sul cliente. La ricerca utilizza solo il server Ollama locale, quindi il nome del cliente non lascia mai l'host; non ci sono chiamate web o API di terze parti. Se il modello non riconosce l'organizzazione (il caso comune per i piccoli clienti), non restituisce nulla e ottieni semplici prompt vuoti: ``` Company name: Acme Rail Services Industry: Location: Parent company / acquired by:
Un fallimento della ricerca — timeout, Ollama non in esecuzione, risposta vuota — non blocca mai l'attacco; si limita a ripiegare su prompt vuoti. Imposta `ollamaAutoResearch` su `false` per saltare completamente la ricerca.
2. **Wordlist** — deriva le baseword da una wordlist di esempio.
3. **Password craccate** — reimmette i plaintext già recuperati in questa sessione (`<hashfile>.out`) nel modello, così può dedurre le convenzioni di password dell'organizzazione target (baseword, stagioni, anni, suffissi, leetspeak) e generare *nuovi* candidati nello stesso stile. Questa opzione viene elencata solo dopo che almeno un hash è stato craccato; l'intero file viene analizzato statisticamente esattamente come nella modalità Wordlist (vedi `ollamaMaxSampleLines` sopra).
#### Configurazione PCFG
Il PCFG Attack (opzione 20) e il PRINCE-LING Attack (opzione 21) utilizzano il sottomodulo `pcfg_cracker`. Configurali in `config.json`:```json
{
"pcfgRuleset": "DEFAULT",
"pcfgMaxCandidates": 50000000,
"pcfgPrinceLingMaxCandidates": 10000000
}
pcfgRuleset— Nome della grammatica addestrata da utilizzare (predefinito:DEFAULT), risolto inpcfg_cracker/Rules/<name>/. Addestra la tua contrainer.pydi pcfg_cracker e imposta questo valore al nome del ruleset.pcfgMaxCandidates— Numero massimo di candidati chepcfg_guesser.pyemette per l'attacco PCFG (predefinito:50000000).pcfgPrinceLingMaxCandidates— Numero massimo di parole base cheprince_ling.pyscrive nella wordlist base PRINCE memorizzata nella cache (predefinito:10000000).
Kernel ottimizzati (optimizedKernelAttacks)
Il flag -O di hashcat seleziona kernel ottimizzati, che sono sostanzialmente più veloci
ma limitano la lunghezza dei candidati (all'incirca 31 caratteri, inferiore per alcune modalità) e
saltano silenziosamente qualsiasi cosa più lunga. optimizedKernelAttacks in config.json elenca
gli attacchi che vengono eseguiti con -O; ometti un attacco dalla lista per eseguirlo con
kernel a lunghezza completa. La lista in config.json.example corrisponde al valore predefinito integrato che si applica
quando non esiste alcun config.json.
Quattro attacchi rispettano l'impostazione ma non sono ottimizzati per impostazione predefinita, perché
forniscono candidati che possono superare il limite di -O — aggiungili alla lista per
attivarli:
hcatNgramX,hcatOllama,hcatOmen,hcatLMtoNT
Per disattivare -O ovunque per una singola esecuzione senza modificare la configurazione, passa
--no-optimized-kernel (forma breve --no-optimize). Sovrascrive la lista per
ogni attacco e rimuove anche un -O scritto in hcatTuning, che
altrimenti raggiungerebbe hashcat indipendentemente dalla lista.
I nomi vengono confrontati esattamente, e una voce non riconosciuta viene segnalata all'avvio
anziché ignorata. Nota che gli attacchi che delegano a un altro attacco sono
controllati dall'attacco a cui delegano, non dal proprio nome: PRINCE-LING
segue hcatPrince, mentre Spoonman, Rosetta e le modalità di pattern-rule LLM
seguono hcatQuickDictionary.
Tracciamento della copertura degli attacchi (coverage_enabled)
Nel corso di un lungo engagement lo stesso file di hash viene attaccato in molte sessioni con un insieme rotante di wordlist, file di regole e liste di maschere, ed è facile bruciare ore rieseguendo terreno già coperto — specialmente dato che la stessa riga di regola si trova in più di un file di regole. hate_crack registra ciò che ha già eseguito contro ciascun file di hash e offre di saltare la sovrapposizione.
La copertura viene registrata per voce, non per file: singole righe di regole e
singole righe .hcmask, ciascuna abbinata alla wordlist contro cui è stata eseguita. Questo
è ciò che gli permette di riconoscere che un file di regole personalizzato che esegui oggi ripete 40 delle
regole che best64.rule aveva già coperto la settimana scorsa, ed è anche il motivo per cui una regola è
solo "coperta" per la specifica wordlist con cui è stata provata — le stesse regole su
un corpus diverso provano candidati completamente diversi.
Il file di hash è identificato da uno sha256 del suo contenuto, quindi la copertura sopravvive alla rinomina o allo spostamento tra sessioni. Le wordlist sono identificate allo stesso modo, con il digest memorizzato in base a dimensione e mtime in modo che un corpus di più gigabyte venga sottoposto a hash una volta sola anziché a ogni attacco.
Vieni avvisato solo quando c'è genuinamente qualcosa da saltare:``` [*] Coverage: 40 of 45 rules in this Dictionary have already been run against this hash file. [?] Skip them and run only the 5 new rules? [Y/n]:
Rispondi `Y` e hate_crack crea un file di regole temporaneo contenente solo le
voci non ancora provate; rispondi `n` per eseguire comunque tutto. Se *ogni*
voce è un duplicato ti viene chiesto se saltare l'attacco del tutto, così
rieseguire deliberatamente terreno già coperto non richiede mai di riavviare lo
strumento.
Gli attacchi che non vengono mai filtrati sono comunque registrati come eseguiti,
ed è questo che ti permette di rispondere a "ho già eseguito PRINCE contro questo
target?".
Un attacco che seleziona più file di regole contemporaneamente (Quick Crack,
Loopback) pone la domanda di salto **una sola volta per l'intero batch, in
anticipo**, prima di qualsiasi invocazione di hashcat. Quella domanda è
deliberatamente economica — non legge né calcola l'hash di nessuno dei file di
regole selezionati, dato che un batch YOLO può arrivare a milioni di righe e non
dovresti aspettare tutto quel tempo per rispondere a un sì/no. Chiede allo store
solo se questo attacco è già stato eseguito contro questo file di hash **con una
di queste wordlist**; il diff per voce avviene comunque in modo lazy, un file di
regole alla volta, e decide cosa viene effettivamente saltato. Quindi un corpus
nuovo non viene mai segnalato, anche quando le regole su di esso sono state tutte
eseguite contro un corpus diverso.
Tre limiti deliberati:
- **La copertura viene registrata solo quando hashcat esaurisce il keyspace**
(exit 1). Un ctrl-C o un errore non registra nulla, e nemmeno exit 0 — che
significa che ogni hash è stato craccato, cosa che hashcat riporta *senza*
completare il keyspace, e nel caso degenere "tutti gli hash trovati come voci
del potfile" senza provare un singolo candidato. Registrare meno del dovuto
costa solo un'esecuzione ridondante in seguito.
- **I generatori dinamici di candidati non vengono mai filtrati.** PRINCE, PCFG,
OMEN, la brute force Markov e le modalità LLM non hanno un insieme fisso da
confrontare, quindi vengono registrati come eseguiti e per il resto lasciati
stare. I file di regole concatenati (`-r a -r b`) sono tracciati come un'unica
unità anziché per voce, perché hashcat applica il *prodotto cartesiano* dei due
file e rimuovere una singola riga eliminerebbe silenziosamente ogni
combinazione a cui essa partecipava.
- **Le esecuzioni `--loopback` vengono registrate ma mai filtrate.** hashcat
reimmette i plaintext appena craccati come candidati *extra*, quindi
un'esecuzione di questo tipo prova l'intera wordlist e il set di regole più
tutto ciò che quei plaintext riciclati raggiungono. Questo rende le due
direzioni asimmetriche: registrarla è corretto, quindi una successiva
esecuzione ordinaria della stessa wordlist e delle stesse regole viene
correttamente riconosciuta come duplicato, ma una seconda esecuzione loopback
ha più crack da riciclare e non viene mai saltata.
Imposta `coverage_enabled` su `false` in `config.json` per disattivare questa
funzionalità, oppure passa `--no-coverage` per una singola esecuzione — che né
consulta né aggiorna lo store.
#### Ispezionare e reimpostare la copertura
L'opzione **85 — Attack Coverage** del menu principale mostra cosa è stato
eseguito contro il file di hash caricato, la sua cronologia di esecuzione, e può
cancellarla. Le stesse tre azioni sono scriptabili:```bash
# What has already been run against this hash file?
hate_crack coverage status --hashfile hashes.txt
# Every attack that has run against it, oldest first
hate_crack coverage history --hashfile hashes.txt
# Start over for this hash file only (prompts unless --yes)
hate_crack coverage forget --hashfile hashes.txt --yes
Il file hash viene identificato in base al contenuto, quindi questi funzionano indipendentemente da dove sia stato spostato nel frattempo. forget influisce solo su quel singolo target — l'archivio si trova in
~/.hate_crack/coverage/attack_coverage.sqlite3, e l'eliminazione del file reimposta la copertura per ogni target.
Esecuzioni scriptate
Un attacco scriptato che la copertura salta completamente esce comunque con 0 per impostazione predefinita, quindi abilitare la copertura non può iniziare a far fallire un harness esistente. Passa
--exit-code-on-skip per ottenere invece il codice di uscita 3 quando non è stato avviato nulla:```bash
hate_crack --exit-code-on-skip hashes.txt dict
0 = ran, 1 = bad input, 2 = unknown command, 3 = everything was already covered
Exit 3 significa che *non* è stato eseguito nulla. Un passaggio che è stato parzialmente filtrato — alcune voci saltate, alcune tentate — esce comunque con `0`, perché l'attacco ha comunque svolto del lavoro.
### Supporto hashcat brain (`brain_enabled`)
hashcat stesso include un "brain" — un piccolo server a cui un'istanza hashcat in esecuzione invia in streaming le password candidate, così una seconda esecuzione contro lo stesso target può saltare i candidati che la prima ha già provato. hate_crack lo attiva automaticamente, senza alcun passaggio da menu: ogni volta che sta per lanciare un attacco contro un hash mode che hashcat segnala come lento (bcrypt, scrypt e altri mode basati su KDF, dove l'hash stesso è il collo di bottiglia piuttosto che la generazione dei candidati), avvia o riutilizza un server brain locale e aggiunge i flag `--brain-*` all'invocazione di hashcat per te. Un mode veloce viene lasciato in pace, a meno che il suo numero di mode non sia elencato in `brain_modes_force`, e un mode elencato in `brain_modes_exclude` non attiva mai il brain indipendentemente dal verdetto di hashcat — exclude vince sempre.
**Il brain non è la stessa cosa della copertura degli attacchi, e i due sono complementari piuttosto che ridondanti.** La copertura (sopra) deduplica a livello di intere regole, righe di maschera e wordlist — decide cosa lanciare in primo luogo, prima che hashcat venga mai eseguito. Il brain deduplica a livello di singole password candidate, e lo fa tramite un server persistente che sopravvive a qualsiasi singola invocazione di hashcat, così cattura sovrapposizioni che la copertura non può vedere: un candidato raggiungibile attraverso due regole diverse o due wordlist diverse all'interno della stessa esecuzione, e — come dimostra il round trip in `tests/e2e/test_brain_e2e.py` — gli stessi candidati re-inviati in una seconda esecuzione hashcat separata contro lo stesso target. Entrambi possono essere abilitati contemporaneamente senza conflitti.
Sette chiavi in `config.json` lo controllano, tutte sotto il prefisso `brain_*`: `brain_enabled` (interruttore principale, attivo di default), `brain_host` (vuoto significa che hate_crack gestisce un server locale su loopback; un valore significa connettersi solo a quell'host — hate_crack non avvia mai un server che non gli è stato detto di gestire), `brain_port` (default `6863`), `brain_client_features` (`1` password hashate, `2` posizioni di attacco, `3` entrambe — `3` deduplica di più ma costa al server circa 12 byte di RAM per candidato visto), `brain_server_timer` (impostazione propria di hashcat per quanto spesso il server scrive il suo dump `.ldmp`/`.admp` su disco, minimo 60 secondi, default `300`), e `brain_modes_force` / `brain_modes_exclude` (numeri di hash-mode separati da virgola che sovrascrivono il verdetto lento/veloce di hashcat, con exclude che ha priorità).
**Il server auto-avviato non ha alcun timeout di inattività.** `brain_server_timer` non controlla per quanto tempo rimane attivo — nulla lo fa; funziona per tutta la vita del processo che l'ha avviato (o finché `shutdown()`/`atexit` non lo ferma) ed è riutilizzato in ogni attacco della sessione. Al valore predefinito di `300`, ciò significa una scrittura di dump in `~/.hate_crack/brain/` ogni cinque minuti per tutto il tempo in cui hate_crack è in esecuzione.
Un'ottava chiave, `BRAIN_PASSWORD`, risiede in `.env` invece che in `config.json` perché è un segreto condiviso, non perché il brain sia un'integrazione di terze parti — viene usata solo quando ci si connette a un server brain remoto che già gestisci; il server locale auto-avviato genera la propria password casuale per sessione e non necessita di configurazione.
**La password del brain è visibile a `ps` per tutta la durata dell'esecuzione di hashcat,** perché hashcat la accetta solo come argomento da riga di comando — non esiste una forma tramite variabile d'ambiente. Per il server locale auto-avviato questa è una piccola finestra: la password è casuale e limitata a quella singola sessione, quindi un altro utente locale può vederla solo mentre un attacco è effettivamente in esecuzione, ed è inutile una volta terminata la sessione. La password di un server brain remoto condiviso non ha tale mitigazione — è lo stesso valore a ogni invocazione, visibile a qualsiasi altro utente locale sulla macchina per tutto il tempo in cui è in corso qualsiasi esecuzione di hate_crack contro quel server. Trattala di conseguenza su hardware condiviso o multi-tenant.
Passa `--no-brain` per disabilitare il brain per una singola esecuzione indipendentemente da `brain_enabled`, oppure imposta `brain_enabled` a `false` in `config.json` per disattivarlo ovunque.
**Il brain mantiene lo stato in `~/.hate_crack/brain/`** — una piccola cache `slow_modes.json` del verdetto lento/veloce di hashcat per versione di hashcat, più, per il server auto-avviato, i suoi file di dump `.ldmp`/`.admp`. Quei dump sono materiale derivato dai candidati: permettono a un server nuovo di riprendere sapendo cosa è già stato provato contro un target, il che in un ingaggio significa dati derivati dal cliente che si accumulano nella home directory dell'operatore per tutto il tempo in cui il brain è mai stato eseguito lì. Come per il coverage store sopra, eliminare la directory reimposta il brain — un candidato precedentemente rifiutato smette di essere ricordato, al costo di perdere la deduplicazione che quel dump rappresentava. Se il brain sembra saltare lavoro che non dovrebbe (un dump obsoleto da un'esecuzione precedente con scope diverso), questa è la soluzione.
**Eliminare `~/.hate_crack/brain/` non cancella un server orfano.** Il server auto-avviato funziona nella propria sessione (`start_new_session=True`) così sopravvive a un terminale chiuso o a un SIGHUP — solo un kill esplicito, o il processo che l'ha avviato che esce in modo pulito ed esegue il suo handler `atexit`, lo ferma. Un orfano continua a occupare la porta di loopback. Con il `BRAIN_PASSWORD` vuoto predefinito, lo noterai come `"[!] ... no brain server could be reached; running without candidate de-duplication"` su ogni attacco in slow-mode: la password dell'orfano era effimera ed è morta con il processo che l'ha generata, quindi hate_crack rifiuta di adottare la porta su cui è seduto piuttosto che indovinare una password che non può essere verificata. Trovalo e fermalo con:```bash
pgrep -f 'hashcat --brain-server'
kill <pid>
poi il successivo attacco avvia un nuovo server come al solito.
Notifiche (opzione di menu 82)
hate_crack può inviare notifiche push Pushover quando gli attacchi terminano e,
opzionalmente, quando i singoli hash vengono craccati. Tutti i controlli si trovano sotto
l'opzione del menu principale 82 — Notifications:
- Toggle Pushover Notifications [ON/OFF] — interruttore principale. Persiste in
config.jsoncomenotify_enabled. - Toggle Per-Crack Notifications [ON/OFF] — quando è ON, un tailer in background monitora il file
.oute invia una notifica per ogni crack (con aggregazione dei burst per tick). Persiste inconfig.jsoncomenotify_per_crack_enabled. Non può essere abilitato mentre l'interruttore principale è OFF — abilita prima l'opzione 1. - Send Test Pushover Notification — invia una push predefinita così puoi confermare che la tua coppia token/utente Pushover funzioni. Funziona anche quando l'interruttore principale è OFF.
Le credenziali risiedono in .env; i restanti parametri di regolazione sono configurabili solo tramite file in config.json:
NOTIFY_PUSHOVER_TOKEN,NOTIFY_PUSHOVER_USER(in.env) — richiesti affinché qualsiasi push venga inviata. Nulla nel menu li scrive; modifica.envmanualmente.notify_attack_allowlist— nomi degli attacchi che danno consenso automatico senza il prompt[y/N/always]. Popolato automaticamente quando rispondialways.notify_suppress_in_orchestrators(predefinitotrue) — silenzia i singoli attacchi concatenati da Extensive Crack, che invia invece un singolo riepilogo. Imposta afalseper ricevere una notifica per ogni attacco concatenato. Altre voci di menu che eseguono più passaggi (ad esempio Quick Crack con più catene di regole) non sono orchestratori e notificano sempre per ogni passaggio.notify_max_cracks_per_burst(predefinito5),notify_poll_interval_seconds(predefinito5.0) — regolazione del tailer per-crack. Vedihate_crack/notify/tailer.pyper la logica di aggregazione dei burst.
Wordlist Tools (opzione di menu 80)
Il sottomenu Wordlist Tools fornisce utilità di preprocessamento delle wordlist basate sui binari di hashcat-utils, oltre a download di wordlist da Hashmob.net e Weakpass. Accessibile tramite l'opzione 80 nel menu principale.
| Opzione | Binario | Cosa fa |
|---|---|---|
| 1 | len.bin | Filtra per lunghezza - mantiene solo le parole comprese tra una lunghezza minima e massima |
| 2 | req-include.bin | Richiedi classi di caratteri - mantiene solo le parole che contengono tutti i tipi di caratteri richiesti |
| 3 | req-exclude.bin | Escludi classi di caratteri - rimuove le parole che contengono qualsiasi tipo di carattere escluso |
| 4 | cutb.bin | Estrai sottostringa - taglia un intervallo di byte da ogni parola |
| 5 | splitlen.bin | Dividi per lunghezza - crea file separati per ogni lunghezza di parola (file denominati 01-64 in una directory di output) |
| 6 | rli.bin / rli2.bin | Sottrai parole - rimuove le voci che compaiono in uno o più altri file |
| 7 | gate.bin | Shard - estrae ogni N-esima parola per il cracking distribuito su più macchine |
| 8 | - | Ottimizza wordlist - deduplica e suddivide in file per lunghezza nella directory delle wordlist ottimizzate |
| 9 | - | Scarica wordlist da Hashmob.net |
| 10 | - | Scarica wordlist da Weakpass (tramite BitTorrent) |
Bit della maschera delle classi di caratteri (usati dalle opzioni 2 e 3): 1=minuscolo, 2=maiuscolo, 4=cifra, 8=simbolo, 16=altro. Somma i valori: 7 = minuscolo+maiuscolo+cifra.
Come è pensato l'uso dello sharding: lo sharding divide una wordlist in N parti uguali e non sovrapposte, così il lavoro può essere distribuito su più macchine o GPU. Ogni parte è interleaved (ogni N-esima riga), quindi ogni shard è un campione rappresentativo dell'intera lista anziché un blocco contiguo iniziale/finale — nessun singolo nodo è bloccato a craccare solo la coda a bassa probabilità.
Esegui l'opzione 7 una volta, forniscile una wordlist di input, un percorso base di output e un numero di shard (N). Scrive tutte le N parti in un'unica passata, denominate con numeri di parte a zero-padding (base.001, base.002, … fino a base.00N). Copia una parte su ciascun nodo e punta l'esecuzione di hashcat di quel nodo su di essa. Su un sistema con singola GPU lo sharding non offre alcun guadagno di velocità, ma una singola parte è comunque un campione veloce e rappresentativo per una passata di triage rapido prima di impegnarsi sulla lista completa.
Controlli automatici di aggiornamento
hate_crack può controllare automaticamente su GitHub la presenza di nuove release all'avvio. Questa funzionalità è controllata dall'opzione di configurazione check_for_updates:```json
{
"check_for_updates": true
}
- **`check_for_updates`** — Abilita i controlli automatici della versione all'avvio (predefinito: `true`).
- Quando è abilitato, hate_crack recupera le informazioni sull'ultima release da GitHub e mostra un avviso se è disponibile un aggiornamento.
- Il controllo viene eseguito in modo asincrono e non blocca l'avvio. Gli errori di rete vengono ignorati silenziosamente.
##### Canali di aggiornamento
| Canale | Flag | Sorgente | Cosa ottieni |
|---------|------|--------|--------------|
| Release | `--update` | `main` | L'ultima release pubblicata. Questa è l'impostazione predefinita e quella offerta dal controllo all'avvio. |
| Nightly | `--nightly` | `nightly-dev` | Lavoro che ha superato la CI ma non è ancora stato rilasciato. |
Le versioni seguono il normale semver, con l'incremento derivato da ciò che è effettivamente presente
nel batch. La seconda componente si muove **solo per le funzionalità**: un ciclo che contiene
qualsiasi commit `feat` è diretto verso `X.(Y+1).0`, e un ciclo di soli fix,
documentazione e attività di manutenzione è diretto verso `X.Y.(Z+1)`.
`nightly-dev` tagga le release candidate per qualunque versione il batch stia
raggiungendo — `v2.20.1rc1`, `v2.20.1rc2`, … — e il merge verso `main` promuove quello
stesso target alla sua release finale. Le candidate sono vere pre-release PEP 440, quindi
si ordinano correttamente ad entrambe le estremità:
2.20.0 < 2.20.1rc1 < 2.20.1rc2 < 2.20.1 < 2.21.0rc1 < 2.21.0
Il target può cambiare a metà ciclo: il primo `feat` che atterra lo sposta da
`X.Y.(Z+1)` a `X.(Y+1).0`, e la numerazione delle candidate riparte per il nuovo target.
Il numero indica sempre ciò che il batch rilascerebbe oggi.
La componente major non viene mai incrementata automaticamente — un oggetto con `!` o un
footer `BREAKING CHANGE:` conta come funzionalità, perché un major automatico è a una
riga di oggetto digitata male da una release pubblicata irreversibile. Un major è un
atto umano esplicito: taggalo e pushalo a mano.
La policy risiede in `tools/next_version.py`, condivisa da entrambi i workflow di tagging e
testata unitariamente in `tests/test_next_version.py`.
Il controllo all'avvio offre sempre e solo release, perché le build nightly non pubblicano
alcuna release GitHub e il controllo legge l'endpoint "latest release" di GitHub — quindi
abilitare `check_for_updates` non ti porterà mai su una nightly. Due cose tengono
separati i canali ora: quella, e il fatto che una candidate è una vera
pre-release PEP 440, quindi uno strumento che ordina i numeri di versione grezzi la tratta anch'esso come più vecchia della release che diventerà.
Entrambi i flag spostano prima il tuo checkout sul branch corrispondente (e
rifiutano di farlo se hai modifiche non committate). Se stai eseguendo una nightly
e vuoi tornare al codice rilasciato, `--update` ti riporta su `main`.
#### Unione automatica degli hash trovati (solo download left)
Quando si scaricano gli hash left (hash non crackati), hate_crack automaticamente:
1. Tenta di scaricare eventuali hash trovati (crackati) da Hashview come operazione ausiliaria
2. Unisce gli hash trovati con i file `.out` locali (ad esempio, `left_1_123.txt.out` o `left_1_123.nt.txt.out` per il formato pwdump)
3. Rimuove le voci duplicate
4. Pulisce i file temporanei di split dopo l'unione
Questo garantisce che i tuoi risultati di cracking locali rimangano sincronizzati con il database centralizzato di Hashview quando lavori con hash non crackati.
**Nota:** L'opzione download-found scarica gli hash già crackati separatamente a scopo di riferimento e non esegue alcuna unione né richiede il cracking.
Il <hash_type> si ottiene eseguendo `hashcat --help`
Hash di esempio: http://hashcat.net/wiki/doku.php?id=example_hashes```
$ hashcat --help |grep -i ntlm
5500 | NetNTLMv1 | Network protocols
5500 | NetNTLMv1 + ESS | Network protocols
5600 | NetNTLMv2 | Network protocols
1000 | NTLM | Operating-Systems
Utilizzo
python3 CVE-2025-55182.py -u <URL> -c <COMMAND>
Esempi
# Esegui il comando 'id' sul server di destinazione
python3 CVE-2025-55182.py -u http://target.com -c "id"
# Esegui un comando personalizzato
python3 CVE-2025-55182.py -u http://target.com -c "whoami"
# Specifica un percorso diverso
python3 CVE-2025-55182.py -u http://target.com/path -c "ls -la"
Come funziona
Lo script sfrutta la vulnerabilità inviando una richiesta POST appositamente predisposta all'endpoint di destinazione. La richiesta contiene un payload progettato per attivare il percorso di deserializzazione vulnerabile, con conseguente esecuzione di codice in remoto.
Mitigazione
- Aggiorna React: esegui l'aggiornamento alla versione più recente di React e dei pacchetti correlati
- Aggiorna Next.js: esegui l'aggiornamento all'ultima versione stabile di Next.js
- Controlla le dipendenze: verifica eventuali dipendenze vulnerabili utilizzando
npm audit - Monitora: tieni sotto controllo i log del server per rilevare richieste sospette
- WAF: implementa regole WAF per bloccare payload malevoli
Riferimenti
Dichiarazione di non responsabilità
Questo strumento è fornito esclusivamente a scopo didattico e di ricerca sulla sicurezza. Gli autori non sono responsabili per qualsiasi uso improprio o danno causato da questo software. Utilizza questo strumento solo su sistemi di tua proprietà o per i quali disponi di autorizzazione esplicita.
Licenza
Questo progetto è concesso in licenza secondo la Licenza MIT - consulta il file LICENSE per i dettagli.``` $ ./hate_crack.py 1000
/ | _____ / | ____ _ ___ ____________ ____ | | __
/ ~ __ \ / __ \ / \ /_ __ _ \ / | |/ /
\ Y // __ | | \ / \ _| | // __ \ _| <
___| /(__ /| _ >______ /|__| ( /___ >|_
/ / /___/ / / / /
Version 2.0
-------------------------------------------------------------------
## Test
La suite di test è per lo più offline e utilizza mock/fixture. I controlli di rete live e
i controlli delle dipendenze di sistema sono opt-in tramite variabili d'ambiente.
### Eseguire i test in locale```bash
# Run all tests
uv run pytest -v
# Run specific test
uv run pytest tests/test_hashview.py -v
Puoi anche eseguire l'intera suite con make test.
Test Live (Opt-In)
Imposta una qualsiasi delle seguenti variabili per abilitare i controlli live:
HASHMOB_TEST_REAL=1— verifica live della connettività/menu CLI di HashmobHASHVIEW_TEST_REAL=1— verifica live del menu CLI di HashviewWEAKPASS_TEST_REAL=1— verifica live del menu CLI di WeakpassHATE_CRACK_REQUIRE_DEPS=1— fallisce se7z,transmission-daemonotransmission-remotenon sono presenti
Test di Upload Live su Hashview
Il test di upload live su Hashview viene saltato per impostazione predefinita. Per eseguirlo, imposta la
variabile d'ambiente e fornisci credenziali valide in .env:```bash
HATE_CRACK_RUN_LIVE_TESTS=1 uv run pytest tests/test_upload_cracked_hashes.py -v
### Test Live di Hashview su uno Stack Docker Locale
Invece di puntare i test live a un server Hashview remoto, puoi far avviare
alla suite uno stack Docker [Hashview](https://github.com/hashview/hashview)
locale, popolarlo, eseguire i test live su di esso e dismetterlo. Imposta
`HASHVIEW_TEST_LOCAL=1` e punta `HASHVIEW_REPO` a un checkout di Hashview:```bash
HASHVIEW_TEST_LOCAL=1 HASHVIEW_REPO=~/projects/hashview \
HATE_CRACK_SKIP_INIT=1 uv run pytest tests/test_hashview_cli_subcommands_subprocess.py -v
Questo avvia docker compose nel repository Hashview, inizializza una chiave API admin,
un cliente, un hashfile e dati "effective task" craccati, quindi esporta le
variabili d'ambiente HASHVIEW_* che i test leggono. Variabili d'ambiente utili:
HASHVIEW_TEST_LOCAL=1— abilita lo stack locale (no-op altrimenti)HASHVIEW_REPO=<path>— checkout di Hashview (predefinito~/projects/hashview)HASHVIEW_KEEP=1— lascia i container in esecuzione dopo la sessione (riesecuzioni più rapide)HASHVIEW_LOCAL_PORT=5000— porta host su cui l'app viene pubblicata
La CLI hate_crack rispetta le variabili d'ambiente HASHVIEW_URL / HASHVIEW_API_KEY
(sovrascrivendo il .env in cui risiedono queste due chiavi), il che consente alla
suite di puntare la CLI allo stack locale senza modificare la configurazione persistita.
Test di Installazione End-to-End (Locale + Docker)
Installazione locale dello strumento uv + esecuzione dello script (usa una HOME temporanea):```bash HATE_CRACK_RUN_E2E=1 uv run pytest tests/test_e2e_local_install.py -v
Installazione/esecuzione end-to-end basata su Docker (con cache tramite `Dockerfile.test`):```bash
HATE_CRACK_RUN_DOCKER_TESTS=1 uv run pytest tests/test_docker_script_install.py -v
Il test E2E Docker scarica anche un piccolo sottoinsieme di rockyou ed esegue un crack hashcat di base per validare l'integrazione con strumenti esterni.
Test end-to-end della VM Lima (solo macOS):
Prerequisiti: Lima e rsync devono essere installati.```bash
brew install lima
La VM di test viene provisionata automaticamente con tutte le dipendenze Linux (hashcat, build-essential, curl, git, gzip, p7zip-full, transmission-daemon, ocl-icd-libopencl1, pocl-opencl-icd, uv).```bash
HATE_CRACK_RUN_LIMA_TESTS=1 uv run pytest tests/test_lima_vm_install.py -v
Questo test convalida l'installazione e l'esecuzione all'interno di una VM Linux leggera su macOS.
Struttura dei test
- tests/test_hashview.py: Suite di test completa per la classe HashviewAPI con risposte API simulate, che include:
- Elenco clienti e validazione dei dati
- Test di autenticazione e autorizzazione
- Funzionalità di caricamento dei file hash
- Flusso di lavoro completo per la creazione dei job
Tutti i test utilizzano chiamate API simulate, quindi possono essere eseguiti senza connettività a un server Hashview.
(1) Quick Crack (2) Extensive Pure_Hate Methodology Crack (3) Brute Force Attack (4) Top Mask Attack (5) Fingerprint Attack (6) Combinator Attacks (7) Hybrid Attack (8) Pathwell Top 100 Mask Brute Force Crack (9) PRINCE Attack (10) Bandrel Methodology (11) Loopback Attack (12) LLM Attack (13) OMEN Attack (14) Ad-hoc Mask Attack (15) Markov Brute Force Attack (16) N-gram Attack (17) Permutation Attack (18) Random Rules Attack (19) Combipow Passphrase Attack (20) PCFG Attack (21) PRINCE-LING Attack (22) Spoonman Attack (23) Rosetta Attack (24) Corporate Masks Brute Force (25) Smart Mask Attack
(80) Wordlist Tools (81) Rule File Tools (82) Notifications (83) Mask Tools
(93) Regenerate .out from POT file (94) Hashview API (95) Analyze hashes with Pipal (96) Export Output to Excel Format (97) Display Cracked Hashes (98) Display README (99) Quit
Select a task:```
Option 94 — Hashview API is only listed when HASHVIEW_API_KEY is set in .env.
The YOLO, Middle, and Thorough Combinator attacks were previously at keys 10-12. They now live in the Combinator Attacks submenu (option 6) along with Combinator3 and CombinatorX.
Quick Crack
Runs a dictionary attack against wordlists in your hcatOptimizedWordlists directory (falls back to hcatWordlists if not configured) and optionally applies rules. Multiple rules can be selected by comma-separated list, and chains can be created with the '+' symbol. Pressing Enter at the wordlist prompt uses the configured optimized wordlists directory as the default.
Selecting a directory — including that default — expands to the wordlists
directly inside it before hashcat runs. Subdirectories are not searched,
matching hashcat's own behaviour for a directory in the dictionary position, and
dot-files and .7z/.torrent/.out files are skipped, which hashcat would
otherwise try to read. The candidates are the same either way; the expansion is
what lets attack coverage track each wordlist separately, since a directory has
no content fingerprint to key on. If the expansion finds nothing — an empty
directory, or one holding only subdirectories or archives — the attack aborts
rather than launching hashcat with no wordlist, which would put it in stdin
mode and leave it reading the terminal.
Quale regola/regole vorresti eseguire?
(1) best64.rule
(2) d3ad0ne.rule
(3) T0XlC.rule
(4) dive.rule
(99) YOLO...esegui tutte le regole
Inserisci un elenco di regole separate da virgola che vorresti eseguire. Per eseguire regole concatenate usa il simbolo +.
Ad esempio 1+1 eseguirà best64.rule concatenata due volte e 1,2 eseguirà best64.rule e poi d3ad0ne.rule in sequenza.
Scegli saggiamente:```
#### Extensive Pure_Hate Methodology Crack
Runs several attack methods provided by Martin Bos (formerly known as pure_hate):
* Brute Force Attack (7 characters)
* Dictionary Attack
* All wordlists in `hcatWordlists` with `best64.rule`
* `rockyou.txt` with `d3ad0ne.rule`
* `rockyou.txt` with `T0XlC.rule`
* Top Mask Attack (Target Time = 4 Hours)
* Fingerprint Attack
* Smart Mask Attack
* Combinator Attack
* Hybrid Attack
* Extra - Just For Good Measure
- Runs a dictionary attack using `rockyou.txt` with chained `combinator.rule` and `InsidePro-PasswordsPro.rule` rules
#### Brute Force Attack
Brute forces all characters with the choice of a minimum and maximum password length.
#### Top Mask Attack
Uses StatsGen and MaskGen from PACK (https://thesprawl.org/projects/pack/) to perform a top mask attack using passwords already cracked for the current session.
Presents the user a choice of target cracking time to spend (default 4 hours).
#### Fingerprint Attack
https://hashcat.net/wiki/doku.php?id=fingerprint_attack
Runs a fingerprint attack using passwords already cracked for the current session. Expander substring length escalates automatically (7, 14, 21, ... up to the chosen ceiling), and an optional wordlist can be combined against the expanded fragments in addition to self-combination. Set `hcatFingerprintWordlist` in `config.json` to a default wordlist path so the prompt offers it instead of asking for a path every time; leave it as `""` to always ask (or skip).
#### Smart Mask Attack
Looks for literal "skeleton" patterns shared by 3+ already-cracked passwords for the current session -- e.g. a fixed stem like `CrawlingHorse` followed by a run of digits, or `ChangeMe2day` followed by digits and symbols drawn from a consistent charset. Every qualifying pattern runs against the full remaining hash list, so other accounts sharing a stem get swept up even though brute-forcing the stem itself was never tried.
Patterns with a fixed run at either end -- nearly all of them -- are grouped by mask and run as hybrid attacks (`-a 6` when the mask trails the stem, `-a 7` when it leads), with every pattern's literal stem a line in that group's wordlist. Dozens of patterns that vary the same way therefore become one hashcat pass over one wordlist rather than one mask line each. Whatever cannot be grouped that way -- variation at *both* ends, which leaves no fixed run to seed a wordlist with -- falls back to a single `-a 3` mask file, and has its charsets widened (up to `?a`) to compensate, as far as the guardrail below allows.
Prompts once, before the attack starts, for an optional per-pattern candidate-count guardrail (default 50,000,000,000; 0 disables it) that excludes any individual pattern whose keyspace is too large without blocking the rest.
#### Combinator Attack
https://hashcat.net/wiki/doku.php?id=combinator_attack
Runs a combinator attack using the "rockyou.txt" wordlist.
#### Hybrid Attack
https://hashcat.net/wiki/doku.php?id=hybrid_attack
* Runs sixteen hybrid passes per wordlist, cheapest first. Each mask length
from 1 to 4 is tried appended and then prepended, first over `?s?d` and then
over `?a`, and a single ctrl-C abandons the whole attack rather than only the
current pass.
- Hybrid Wordlist + Mask - ?s?d wordlists/rockyou.txt ?1
- Hybrid Mask + Wordlist - ?s?d ?1 wordlists/rockyou.txt
- ... the same for ?1?1, ?1?1?1 and ?1?1?1?1
- Hybrid Wordlist + Mask - wordlists/rockyou.txt ?a
- Hybrid Mask + Wordlist - ?a wordlists/rockyou.txt
- ... the same for ?a?a, ?a?a?a and ?a?a?a?a
`?a` is every printable character, so the second group is a superset of the
first plus letters and roughly 24x the work at the longest mask — over
rockyou.txt those passes alone are ~1.2e15 candidates, about ten hours for
NTLM on hardware doing 32 GH/s. That is why the cheap `?s?d` group runs first
and why the attack as a whole is time-bounded:
- `hcatHybridMaxRuntime` in `config.json`, in seconds, default `3600`, is the
time the **whole attack** may spend — not the time one pass may spend. All
sixteen passes share one deadline, and each is handed whatever is left of it
as hashcat's `--runtime`. Any pass the budget does not reach is reported
rather than skipped quietly. Set it to `0` for no limit, which runs every
pass to exhaustion.
Within each group the order is by mask length across every wordlist rather
than all lengths of one wordlist and then the next, so a budget that runs out
has still given every wordlist its cheap passes.
Each pass declares what it covers to the attack-coverage store, so a repeat
hybrid against the same hash file offers to skip the passes already run. A
pass that runs out of budget is not recorded, so it will be retried.
Wordlist entries may be glob patterns or directories; both are expanded
before hashcat runs, a directory into the wordlists directly inside it.
Subdirectories are not searched, matching hashcat's own behaviour, and
dot-files and `.7z`/`.torrent`/`.out` files are skipped — a Weakpass
download leaves archives in the wordlists directory and hashcat would
otherwise try to read them.
#### Pathwell Top 100 Mask Brute Force Crack
Runs a brute force attack using the top 100 masks from KoreLogic:
https://blog.korelogic.com/blog/2014/04/04/pathwell_topologies
#### PRINCE Attack
https://hashcat.net/events/p14-trondheim/prince-attack.pdf
Runs a PRINCE attack using wordlists/rockyou.txt
#### YOLO Combinator Attack
Runs a continuous combinator attack using random wordlists from the configured wordlists directory for the left and right sides.
#### Middle Combinator Attack
https://jeffh.net/2018/04/26/combinator_methods/
Runs a modified combinator attack adding a middle character mask:
wordlists/rockyou.txt + masks + worklists/rockyou.txt
Where the masks are some of the most commonly used separator characters:
2 4 <space> - _ , + . &
#### Thorough Combinator Attack
https://jeffh.net/2018/04/26/combinator_methods/
* Runs many rounds of different combinator attacks with the rockyou list.
- Standard Combinator attack: rockyou.txt + rockyou.txt
- Middle Combinator attack: rockyou.txt + ?n + rockyou.txt
- Middle Combinator attack: rockyou.txt + ?s + rockyou.txt
- End Combinator attack: rockyou.txt + rockyou.txt + ?n
- End Combinator attack: rockyou.txt + rockyou.txt + ?s
- Hybrid middle/end attack: rockyou.txt + ?n + rockyou.txt + ?n
- Hybrid middle/end attack: rockyou.txt + ?s + rockyou.txt + ?s
#### Bandrel Methodology
Prompts for comma-separated names and creates a pseudo hybrid attack by capitalizing the first letter and adding up to six additional characters at the end. Each word is limited to a total of five minutes.
- Built-in common words (seasons, months) included as a customizable `config.json` entry (`bandrel_common_basedwords`)
- The default five-minute time limit is customizable via `bandrelmaxruntime` in `config.json`
#### Loopback Attack
https://hashcat.net/wiki/doku.php?id=loopback_attack
Uses hashcat's loopback mode to feed cracked passwords from the current session back into the attack pipeline with rules applied. This generates new password candidates based on variations of already-cracked passwords, which is particularly effective for finding related passwords that follow similar patterns.
* Prompts for rule selection to apply to the loopback candidates
* Uses an empty wordlist with the --loopback flag to process previously cracked passwords
* Automatically downloads Hashmob rules if no rules are available locally
#### LLM Attack
Uses a local LLM — Ollama by default, or a vLLM / OpenAI-compatible server via `LLM_BACKEND` — to generate password candidates for a capture-the-flag scenario. Prompts for the fake company name, industry, location, and parent company / acquisition history, then sends these details to the configured LLM model to produce likely password candidates using industry terms and company name permutations. The generated candidates are fed into a hashcat wordlist+rules attack.
* Requires a running server at `OLLAMA_HOST` (default: `http://localhost:11434`, Ollama's port; override in `.env` or the environment) already serving the model — hate_crack does not auto-pull
* Candidate generation uses structured (JSON) output via Atomic Agents, so pick a model with good schema adherence (default: `qwen3:4b-instruct`)
* Configurable backend, model, context window, request timeout, and sample size via `.env` (see [LLM Configuration](#llm-configuration))
* Prompts for target company name, industry, location, and parent company / acquisition history. The industry, location, and parent company prompts are pre-filled with the local model's guesses about the named organization (editable, and clearly labelled as guesses rather than verified OSINT); disable with `ollamaAutoResearch: false`
* Alternatively derives basewords from a sample **wordlist**, or from the **cracked passwords** of the current session (`<hashfile>.out`) so the model mirrors the target organization's own password conventions and produces new candidates in that style (only offered once something has been cracked)
* A live spinner with an elapsed-seconds counter runs during generation, and requests are bounded by `ollamaTimeout` so a model stuck loading into VRAM reports a timeout instead of hanging
**Pattern rules mode** (option 4 in the LLM submenu) takes the same shape as the [Spoonman Attack](#spoonman-attack) — a baseword list run through a rule file, both derived from one corpus — but infers each side with the model instead of extracting it. Spoonman is exact and therefore bounded: its basewords all appear in the corpus and its rules only reproduce transformations the corpus already shows. This asks the model to generalize on both axes, so it can name the *word families* behind a sample (the company and its products, site names, local sports teams, seasons, mascots) and write decorations the corpus does not contain.
* Pattern source is either the current session's cracked passwords (offered first, and only once something has been cracked, since those reveal the target's real conventions) or a sample wordlist
* **You are not asked to pick a rule file.** The model writes one, from the same corpus statistics — a stock rule file encodes the internet's habits, and the point of spending a model round trip is to encode *this* organization's
* Basewords are normalized to lowercase letters only, discarding anything under 3 characters, so the generated rules supply case, digits, and punctuation exactly once
* Generated rules are validated before hashcat sees them, and anything using an op hashcat does not have, a position argument outside `0-9A-Z`, more than 31 functions, or a stray comment or non-ASCII character is discarded. hashcat drops an invalid rule *silently* when valid rules share the file, so an unscreened line would become missing coverage rather than an error. The op table was established by testing hashcat itself, not from its rule documentation, which lists ops hashcat will not actually run
* Local-model yield varies a lot run to run, so a thin answer is asked again once and the two rounds are merged — a handful of rules would waste the pass they are spent on
* If no rule survives validation the basewords still run, unmutated, rather than throwing away the expensive half of the run
* Output lands in `<hashfile>.llm_patterns/` as `basewords.txt` and `rules.rule` — per-run scratch, laid out like `.spoonman/` and removed on exit
#### OMEN Attack
Uses the Ordered Markov ENumerator (OMEN) to train a statistical password model from a wordlist and generate password candidates. This attack learns patterns from known passwords and generates new candidates based on those patterns.
* Requires OMEN binaries (createNG and enumNG) to be built from the omen submodule
* Interactive menu: use existing model, train new model, or cancel
* Training wordlist picker shows available wordlists from configured directory or accepts a custom path
* Validates all 5 required model files (createConfig, CP/IP/EP/LN.level) before running
* Captures and reports enumNG errors instead of failing silently
* Generates up to a specified number of password candidates (configurable via `omenMaxCandidates`)
* Pipes generated candidates directly into hashcat for cracking
* Model files and metadata are stored in `~/.hate_crack/omen/` for persistence across sessions
#### Combinator Attacks Submenu
Opens an interactive submenu with six combinator attack variants (formerly at menu keys 10-12). Consolidates related attacks for cleaner menu organization:
- Combinator Attack - combines two wordlists
- YOLO Combinator Attack - combines all permutations of multiple wordlists
- Middle Combinator Attack - combines wordlists with an extra word in the middle
- Thorough Combinator Attack - comprehensive combination of wordlists with rules
- Combinator3 Attack - combines exactly 3 wordlists using `combinator3.bin`, generating all `word1+word2+word3` combinations piped to hashcat
- CombinatorX Attack - combines 2-8 wordlists using `combinatorX.bin` with optional `--sepFill` separator character between word segments
#### Ad-hoc Mask Attack
Runs hashcat mask attack (mode 3) with a user-specified custom mask string. Allows fine-grained control over character-set brute forcing.
* Opens with a choice between typing a mask and selecting a mask file
* Prompts for a hashcat mask (e.g., `?u?l?l?l?d?d` for uppercase + lowercase + lowercase + lowercase + digit + digit)
* Supports custom character sets for specialized character combinations: `-1` through `-4` on any hashcat, plus `-5` through `-8` on hashcat 7 and newer. A mask using `?5`–`?8` against an older hashcat is flagged before the run rather than failing inside it; if the version cannot be read, the mask is passed through and hashcat decides
* Only prompts for the custom slots the mask actually references — `?1?3?d` asks about `-1` and `-3` and nothing else, and a mask with no custom tokens is never asked at all. Detection is token-aware, so the escaped `??1` is a literal `?1` and prompts for nothing. A slot left blank is still skipped, with a warning that hashcat will reject a mask whose charset is undefined
* Mask files (`.hcmask`) can be selected with tab completion, defaulting to the bundled `masks/` directory; hashcat runs every mask in the file in order. Because a mask file defines its own charsets inline, the `-1` through `-4` prompts are skipped when one is chosen
* Optionally runs the mask incrementally (`--increment`), trying shorter lengths before the full mask. Answering yes prompts for an increment minimum and maximum; either can be left blank, and leaving both blank increments over the mask's full keyspace with hashcat choosing the bounds. Offered for typed masks and mask files alike
* Useful for targeted brute forcing when you know password structure patterns
#### Markov Brute Force Attack
Generates password candidates using Markov chain statistical models. Similar to OMEN but simpler and faster.
* Checks for existing `.hcstat2` Markov table from previous sessions (with option to reuse, regenerate, or cancel)
* Generates table from training source if needed:
- Can use cracked passwords from current session (`.out` file) as training data
- Or select any wordlist from configured directory or custom path
* Interactive menu: choose minimum and maximum password length
* Uses `--increment` flag to test lengths in sequence
* Markov table persists with hash file (filename.out.hcstat2) for fast subsequent runs
* Faster than OMEN for general-purpose brute forcing
#### N-gram Attack
Generates n-gram candidates from a corpus file using `ngramX.bin` from hashcat-utils and pipes them into hashcat.
* Prompts for a corpus file with tab completion, defaulting to the configured wordlist directory
* Prompts for an n-gram group size (default 3)
* Gzip-compressed corpus files are auto-detected and decompressed on the fly
* Useful when you have target-relevant prose (scraped site copy, leaked documents, internal wiki exports) rather than a password list
#### Permutation Attack
Generates all character permutations of each word in a targeted wordlist and pipes them to hashcat via `permute.bin` from hashcat-utils.
* Prompts for a single wordlist file (not a directory)
* Effective against short targeted wordlists where the character set is known but the order is not (company abbreviations, name fragments, known tokens)
* WARNING: Scales as N! per word - an 8-character word produces 40,320 permutations. Only practical for words up to ~8 characters.
* Uses `permute.bin < wordlist | hashcat` pipeline pattern
#### Random Rules Attack
Generates a set of random hashcat mutation rules using `generate-rules.bin`, writes them to a temporary file, then runs hashcat against a chosen wordlist with those rules.
* Prompts for rule count (default 65536)
* Prompts for wordlist path with tab-completion and numbered selection
* Temporary rules file is cleaned up after the run regardless of outcome
* Useful when known rule sets are exhausted - explores random rule-space for additional cracks
#### Combipow Passphrase Attack
Generates all unique non-empty subset combinations from a short wordlist using `combipow.bin` and pipes them into hashcat. Designed for passphrase cracking when you know the pool of words a password was built from.
* Prompts for a wordlist file (max 63 lines - combipow generates up to 2^n-1 combinations)
* Optional space separator (`-s` flag) to insert spaces between words in each combination
* Warns if the wordlist exceeds 20 lines (output volume may be large)
* Aborts with a clear message if the wordlist exceeds 63 lines (hard limit)
* Candidates are piped directly to hashcat stdin
#### PCFG Attack
Uses [pcfg_cracker](https://github.com/lakiw/pcfg_cracker) to generate candidates from a Probabilistic Context-Free Grammar, piping `pcfg_guesser.py` output directly into hashcat's stdin mode. A PCFG models password *structure* (baseword + digits + symbol, capitalization habits, keyboard walks) with learned probabilities, so candidates come out roughly in descending likelihood order.
* Requires the `pcfg_cracker` submodule. Presence is checked at startup and reported non-fatally: if it is missing, the PCFG attacks are simply unavailable. Run `make` to fetch it.
* Uses the trained grammar named by `pcfgRuleset` in `config.json` (default `DEFAULT`), read from `pcfg_cracker/Rules/<name>/`
* Candidate count is capped by `pcfgMaxCandidates` (default 50,000,000)
* hate_crack does not wrap grammar training. To build a grammar from a target-specific password set, run pcfg_cracker's own `trainer.py` and point `pcfgRuleset` at the resulting ruleset name
#### PRINCE-LING Attack
Uses pcfg_cracker's `prince_ling.py` to derive an optimized PRINCE base wordlist from a trained grammar, then hands it to the existing PRINCE attack. PRINCE-LING picks base words the grammar says are actually productive, so the PRINCE combination space is far less wasteful than pointing PRINCE at a generic wordlist.
* Requires the `pcfg_cracker` submodule and a trained ruleset directory, same as the PCFG attack
* The generated wordlist is cached at `<hcatOptimizedWordlists>/pcfg_prince_ling_<ruleset>.txt` and reused across sessions
* Regenerates only when the ruleset directory is newer than the cached wordlist, so retraining a grammar invalidates the cache automatically
* Generation is written to a temporary file and atomically moved into place; a failed or interrupted run cleans up its partial file and leaves any existing cache intact
* Base wordlist size is capped by `pcfgPrinceLingMaxCandidates` (default 10,000,000)
#### Spoonman Attack
Derives a baseword list and a hashcat rule file from a corpus of known plaintext passwords — a previous engagement's cracked output, a leak dump, or any password list — such that the baseword x rule cross product reconstructs the corpus exactly (see the memory bound below for the one case where it does not). Contributed as issue #169 by @Spoonman1091.
Each password is split into its letters-only lowercased core (the baseword) plus a rule that rebuilds the original from it, using `l`/`u`/`c` for casing, `T{p}` toggles, `${x}`/`^{x}` for trailing and leading characters, and `i{p}{x}` for interior ones.
* When the current session already has cracked plaintexts (`<hash file>.out` exists and is non-empty), a picker offers those as the corpus ahead of a free-form path — the target's own recovered passwords derive rules describing that target's actual conventions, which is exactly what you want to fire back at the remaining uncracked hashes. Deriving from `.out` and then cracking the same hash file appends new plaintexts to that same file, growing the corpus for the next run; that is the intended feedback loop, not corruption. Sessions with no cracked output yet see no picker at all — just today's path prompt
* Prompts for the corpus, then for how much of the rule file to run: top 50% coverage (listed first and recommended), top 75%, top 95%, top 99%, or the full set
* Rules are sorted by how many passwords each one rebuilds, so a truncated file keeps the most productive rules. Coverage is extremely long-tailed: on a 98.2M-password sample, 50% coverage needed 4,120 rules while 95% needed 16,119,661 and 100% needed 21,029,696 — the last few percent typically costs orders of magnitude more rules than the first half, which is why the smallest tier is listed first and is usually the right choice
* Output is written beside the hash file in `<hash file>.spoonman/`, alongside the other ephemeral wordlists: `basewords.txt`, `rules.full.rule`, the capped rule files, and `coverage.txt` with per-milestone rule counts. Derivation is skipped on later runs of the same hash file unless the corpus has been modified since, and the directory is removed on exit by the temp-file cleanup
* Derivation is bounded in memory. Both counters would otherwise grow for the whole read with nothing written until the end, so a corpus large enough to exhaust RAM lost the entire pass to an OOM kill and produced no output; a measured run against a 31 GB corpus reached 14.1 GB resident at 11% of the file and was still accelerating. Each counter is now capped at 20 million distinct keys (about 1.6 GB apiece), and the lowest-frequency keys are discarded once it is exceeded. If that happens, the run says so on the console and in `coverage.txt`, the output reconstructs the retained keys rather than 100% of the corpus, and the coverage percentages are relative to those. Corpora below the cap are unaffected
* Passwords that cannot be expressed as a rule are written verbatim as their own baseword with a `:` no-op, so coverage stays complete. This covers two hashcat limits: rule positions cannot address past index 35, and hashcat rejects any rule with more than 31 functions — silently, when valid rules share the file
* A password carrying a literal CR or LF (which arrives hex-wrapped, as `$HEX[...0a]`) cannot go in a baseword at all, because a wordlist line has no escape syntax for one. The break is lifted out into an insert op instead, spelled `\x0a`/`\x0d` in the rule, which hashcat decodes to the byte. When the break sits past addressable index 35 the rule reverses the word first, inserts from the other end, and reverses back. One frame has to hold every break in the password, so what is still skipped is a password with one break outside the first 36 characters *and* another outside the last 36, or one needing more inserts than the 31-function cap leaves room for. Those are counted as `unwritable basewords` in `coverage.txt` and reported, never dropped silently
* The derivation self-checks every password by reconstructing it in-process, and reports any failures rather than reporting success
* Corpus lines may carry a hash in front of the password, as cracked output does. A leading field is dropped only when it has the shape of a hash (a hex digest at a known length, or a crypt-style `$id$` string), so `hash:salt:plain` is handled while a plaintext or wordlist entry containing a colon survives intact. `$HEX[...]` plaintexts are decoded. If most lines look like an uncracked dump rather than cracked output, `coverage.txt` records the count and the attack warns — the derived basewords and rules would otherwise be meaningless without any error being raised
#### Rosetta Attack
Mines hashcat `--debug-mode 5` logs for the basewords and rules that already cracked something, then runs their full cross product. Powered by [HashcatRosetta](https://github.com/bandrel/HashcatRosetta), the same library behind [Analyze Hashcat Rules](#analyze-hashcat-rules-rule-file-tools-option-5).
No setup is needed to feed it: `_add_debug_mode_for_rules` appends `--debug-mode 5 --debug-file` to every rule-based hashcat invocation hate_crack makes, so the logs accumulate in `hcatDebugLogPath` (`~/.hate_crack/hashcat_debug` by default, one file per session) as a side effect of normal use. A mode 5 log records only candidates that cracked a hash, in the form `baseword:rule:candidate:wordlist`, which is what makes both halves known-productive against this target population; the trailing wordlist field also shows which list is earning its keep on a multi-wordlist run. HashcatRosetta parses mode 4 and mode 5 alike, so logs written before the switch are still read.
The value is in the cross product rather than the recorded pairs. A pair present in a log has already cracked its hash and will not crack another, but a rule that worked on one baseword has usually never been tried against the others — so N basewords and M rules yield close to N x M untried candidates.
The menu first asks how to rank rules — choices 1-3 below, plus a fourth, unrelated mode:
* Rules can be ranked by application frequency, by how many distinct basewords each one worked on, or by how many unique candidates each one generated. Frequency is the default; baseword spread is the better choice when the goal is a rule set that generalizes past the specific words it was learned from
* Only after one of those three is picked does hate_crack list the logs found in `hcatDebugLogPath` newest-first with their sizes; pick one, pick all of them (up to 20), or type a path to a log from elsewhere
* Prompts for how many top rules to keep and how many top basewords. Both default to all — a blank answer keeps every winning rule the logs contain, and zero means the same thing. Enter a number to cap either. The keyspace is the product of the two and is printed before hashcat starts
* Output is written beside the hash file in `<hash file>.rosetta/` as `basewords.txt` and `rules.rule`, alongside the other ephemeral wordlists, and the directory is removed on exit by the temp-file cleanup
* Reading stops at 1,000,000 debug lines, since the analyzer needs the whole batch in memory at once. Truncation is reported on the console rather than assumed harmless — logs from a long run routinely exceed this, in which case the newest log is the one worth selecting
* **LLM Mask Attack** (4) - a different mode entirely, and the only one that needs no debug logs. Prompts for a natural-language description of the passwords you expect (length, character patterns, symbols, etc.), sends it to the locally configured Ollama model, writes the returned masks to `<hash file>.hcmask`, and runs a `-a 3` hashcat mask attack against them
#### Corporate Masks Brute Force
Statistical masks (8-14 characters) derived from analysis of 3.2M NTLM hashes cracked on real engagements. Powered by [Corporate_Masks](https://github.com/golem445/Corporate_Masks), these masks encode realistic password patterns from successful penetration tests.
* Prompts for minimum and maximum mask length (default 8-10)
* Longer lengths cost exponentially more keyspace—start with 8-10 for speed, or 8-12 for thoroughness
* Each mask file is run as a separate hashcat invocation in ascending length order
* Gracefully handles missing mask files (skips them) and absent submodule (prints warning and returns)
* Supports optimized kernels (`-O` flag) for faster cracking
* Ctrl-C during one length aborts remaining lengths
#### Wordlist Tools (option 80)
A submenu of wordlist preprocessing utilities using hashcat-utils binaries. All tools read from and write to files on disk. All file and directory path prompts support tab completion.
| Key | Tool | Description |
|-----|------|-------------|
| 1 | Filter by Length | Keep only words between a min and max length (`len.bin`) |
| 2 | Require Char Classes | Keep words that include all char classes in mask (`req-include.bin`). Mask: 1=lower, 2=upper, 4=digit, 8=symbol (additive) |
| 3 | Exclude Char Classes | Remove words containing any char class in mask (`req-exclude.bin`). Same mask encoding |
| 4 | Extract Substring | Cut bytes from each word at a given offset and optional length (`cutb.bin`) |
| 5 | Split by Length | Create per-length files in an output directory (`splitlen.bin`) |
| 6 | Subtract Wordlist | Remove lines from a wordlist that appear in one or more remove files. Mode 1 uses `rli2.bin` (single file); mode 2 uses `rli.bin` (multiple files) |
| 7 | Shard Wordlist | Split a wordlist into N equal, interleaved parts in one run, written as `base.001`…`base.00N` for distributed cracking (`gate.bin`) |
| 8 | Optimize Wordlists | Dedupe and split the selected wordlists into per-length files under an output directory |
| 9 | Download from Hashmob.net | Browse and download wordlists from Hashmob.net into the configured wordlist directory |
| 10 | Download from Weakpass | Browse and download Weakpass wordlist torrents, with automatic extraction |
| 11 | Hashmob Downloads | Access a submenu for downloading Hashmob archives (yearly full-found corpora) and combined-left lists (per-mode uncracked hashes) |
All binaries are in `hate_crack/hashcat-utils/bin/`.
#### Rule File Tools (option 81)
Preprocesses hashcat rule files using `cleanup-rules.bin` and `rules_optimize.bin` from hashcat-utils, and downloads rule files from Hashmob.net.
* **Clean** (1) - removes invalid syntax and duplicate rules using `cleanup-rules.bin`. Useful after combining rule files or downloading rules from external sources.
* **Optimize** (2) - consolidates redundant operations using `rules_optimize.bin`. Reduces rule file size and improves cracking speed.
* **Clean and optimize** (3) - runs both operations in sequence via a temporary file, then writes the final result.
* **Download rules from Hashmob.net** (4) - fetches rule files into the configured `rulesDirectory`.
* **Analyze Hashcat rules** (5) - opcode frequency analysis of a rule file, powered by HashcatRosetta.
The three preprocessing operations read from an input file and write to a separate output file (original is never modified).
#### Download Rules from Hashmob.net (Rule File Tools option 4)
Downloads the latest rule files from Hashmob.net's rule repository. These rules are curated and optimized for password cracking and can be used with the Quick Crack and Loopback Attack modes.
* Downloads rule sets in parallel using a thread pool (up to 4 concurrent downloads)
* Skips rules already downloaded locally
* Reports download summary with success/failure counts
* Stores rules in the configured rules directory
#### Analyze Hashcat Rules (Rule File Tools option 5)
Powered by HashcatRosetta (https://github.com/bandrel/HashcatRosetta), this feature analyzes hashcat rule files to provide detailed insights into rule composition and complexity.
* Prompts for a rule file path
* Displays frequency analysis of rule opcodes (operations)
* Helps understand what transformations a rule set performs
* Useful for rule debugging and optimization
#### Mask Tools (option 83)
Downloads mask files from Hashmob.net. This is a minimal submenu today — masks
have no local file-tooling counterpart to the rule/wordlist cleanup and
optimization utilities, only a download capability.
* **Download masks from Hashmob.net** (1) - fetches mask files into the hate_crack masks directory.
#### Download Masks from Hashmob.net (Mask Tools option 1)
Downloads mask files from Hashmob.net's mask repository into the hate_crack masks directory for use with mask-based attacks.
* Downloads mask sets in parallel using a thread pool (up to 4 concurrent downloads)
* Skips masks already downloaded locally
* Reports download summary with success/failure counts
* Stores masks in the configured masks directory used by the Ad-hoc Mask Attack
* Supports interactive listing, range selection, and browsing of available mask files
#### Download Wordlists from Hashmob.net (Wordlist Tools option 9)
Downloads wordlists from Hashmob.net's collection of cracked passwords and commonly used wordlists.
* Interactive menu for browsing available wordlists
* Progress tracking for large downloads
* Stores wordlists in configured wordlist directory
#### Weakpass Wordlist Menu (Wordlist Tools option 10)
Interactive menu for downloading and managing wordlists from Weakpass.com via BitTorrent.
* Browse available Weakpass wordlist torrents
* Download specific wordlists or entire collections
* Automatic extraction of compressed archives
* Progress tracking for torrent downloads
#### Hashmob Downloads (Wordlist Tools option 11)
Access a submenu for downloading large-scale password corpora and specialized wordlists from Hashmob.net.
**Archives** - Downloads yearly full-found password corpora (multi-GB archives containing all cracked passwords from a given year)
* Requires confirmation before downloading -- these archives are large (the listing may show "(unknown size)" since Hashmob's API doesn't currently report a file size per archive)
* Lists all available archives across every year as one globally-numbered list to browse and pick from by index, rather than a per-year picker
* Accepts `a` (or `all`) at the selection prompt to download every listed archive, one at a time. A single confirmation naming the archive count and the summed size covers the whole batch; an archive already on disk at its listed size is skipped, one whose size does not match is re-downloaded, and a failure is counted rather than aborting the rest
* Stores archives in the configured wordlist directory for extraction and use
**Combined Left Lists** - Downloads per-hashcat-mode combined lists of uncracked ("left") hashes from Hashmob.net
* Each list is a set of hashes, not plaintexts, still awaiting a crack for that hashcat mode
* Useful for spotting overlap between your own hash list and hashes the community hasn't cracked yet
* Supports mode selection from the listed hash counts per algorithm
-------------------------------------------------------------------
### Version History
The full, per-release changelog now lives in [CHANGELOG.md](https://github.com/trustedsec/hate_crack/blob/main/CHANGELOG.md).