
Uno strumento per automatizzare le metodologie di cracking tramite Hashcat del team TrustedSec.
___ ___ __ _________ __
/ | \_____ _/ |_ ____ \_ ___ \____________ ____ | | __
/ ~ \__ \\ __\/ __ \ / \ \/\_ __ \__ \ _/ ___\| |/ /
\ Y // __ \| | \ ___/ \ \____| | \// __ \\ \___| <
\___|_ /(____ /__| \___ >____\______ /|__| (____ /\___ >__|_ \
\/ \/ \/_____/ \/ \/ \/ \/
L'installazione dal sorgente è l'unico percorso supportato. hate_crack non è
distribuito su PyPI: pip install hate-crack risolve a un segnaposto 0.0.0
che fallisce di proposito e rimanda qui. Il nome è tenuto solo così nessun altro
può pubblicare un clone con lo stesso nome — vedi
packaging/pypi-placeholder/.
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 sulla sua posizione.
Clona con i sottomoduli (necessari 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, ciascuno con un proprio set distinto di impostazioni:
config.json — percorsi delle wordlist, maschere, regole, tuning, potfile, percorso di hashcat, limiti dei candidati, interruttori di notifica, 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 distinzione cade lì per un motivo: .env è il file che può contenere segreti. Le credenziali e la configurazione dei servizi di terze parti vanno nel file non tracciato con permessi 0600; tutto ciò che hate_crack fa localmente resta in config.json, che è sicuro da condividere, confrontare e includere nei propri appunti. È anche per questo che le credenziali Pushover sono in .env mentre gli interruttori on/off di Pushover sono in config.json — gli interruttori sono preferenze locali, non segreti.
Ogni chiave ha esattamente una sola 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 subito senza modifiche.
config.json è permanente e di prima classe — non è deprecato e non esiste una tempistica di rimozione. Solo le impostazioni di integrazione sono state spostate.
Aggiornamento da un singolo config.json? hate_crack lo migra automaticamente al primo avvio: le impostazioni di integrazione vengono copiate in un nuovo .env con permessi 0600, poi rimosse da config.json così i due file non le rivendicano 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.
Primo avvio: hate_crack crea entrambi i file per te, quindi non c'è nulla da fare. Per configurare .env manualmente, copia il template tracciato:```bash
cp .env.example .env
chmod 600 .env
`.env.example` viene incluso nel repository con ogni chiave di credenziale vuota. `.env` stesso **non** deve mai essere committato — è escluso da git, insieme alle sue solite varianti di backup, e hate_crack lo crea sempre con modalità `0600` (solo lettura/scrittura del proprietario). `.env.example` viene generato dallo schema; rigeneralo dopo aver modificato `hate_crack/config_schema.py` con `uv run python -m hate_crack.config_writer`.
### 3. Installare 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 scarica il set di maschere Corporate_Masks solo 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 le dipendenze manualmente:**
### Dipendenze esterne
Queste sono necessarie per alcuni flussi di download/estrazione:
- `7z`/`7za` (p7zip) — utilizzati per estrarre archivi `.7z`.
- `transmission-daemon` / `transmission-remote` — utilizzati per scaricare i torrent di 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
La logica principale è ora suddivisa in moduli sotto hate_crack/:
hate_crack/cli.py: helper per argparse e override di configurazione.hate_crack/api.py: integrazioni con Hashview, Weakpass e Hashmob (download/menu/helper).hate_crack/attacks.py: gestori degli attacchi dal menu.hate_crack/corpus_stats.py: statistiche sulle password dell'intero corpus, usate 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 condiviso per i menu, 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 input per decidere l'uso di di hashcat.Il file di primo livello hate_crack.py rimane il punto di ingresso principale e orchestra questi moduli.
Questo progetto dipende da ed è ispirato a una serie di progetti e servizi esterni. Grazie a:
Dopo l'installazione con make, esegui hate_crack da qualsiasi posizione:```bash
hate_crack
hate_crack <hash_file> <hash_type> [options]
Alternatively, esegui tramite `uv`:```bash
uv run hate_crack.py <hash_file> <hash_type>
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 uno shim bash in `~/.local/bin/hate_crack` che viene eseguito dalla directory del repository, così config e asset vengono sempre trovati indipendentemente dalla tua directory di lavoro corrente.
La configurazione viene cercata anche in:
- La radice del repository e la directory del pacchetto
- `~/.hate_crack`
**Nota:** Il campo `hcatPath` in `config.json` serve 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 usa 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 / tramite script
Per l'automazione puoi lanciare un singolo attacco direttamente, bypassando il menu. Il nome dell'attacco è il primo argomento, seguito dal file degli 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 loro valori predefiniti in questa modalità. Il processo termina con `0` in caso di successo e con un valore non zero in caso di errore (file degli hash mancante, tipo di hash non numerico, wordlist mancante o nome di file di regole 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
Un clone meno recente 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
in quel momento per rimuovere alcuni file che non avrebbero mai dovuto essere committati, il che ha
assegnato a ogni commit un nuovo ID; di conseguenza, i tag di un clone più vecchio puntano a oggetti
che questo repository non contiene più, e git rifiuta di spostare un tag che già possiede.
Non c'è nulla di sbagliato nel tuo checkout e nessun dato di cracking è a rischio.
Ripristina con un reset una tantum. Questo scarta commit locali e modifiche nel
checkout, quindi se hai personalizzato qualcosa tracciato da git (a differenza 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 ripristino da sole, motivo per cui deve essere fatto a mano una volta.
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 tramite `make install`
**Soluzione:**
Reinstallare utilizzando 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 le impostazioni predefinite senza personalizzazioni:
hcatWordlists: ./wordlists (relativo alla radice del repository o a HOME/.hate_crack)hcatOptimizedWordlists: ./optimized_wordlists (directory utilizzata da Quick Crack; ripiega su hcatWordlists se non trovata)rules_directory: ./hashcat/rules (include le regole del sottomodulo)hcatTuning: `` (stringa vuota - nessun flag di ottimizzazione predefinito)Esempio di personalizzazioni 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 di quella chiave (`.env` o `config.json`) > default integrato
- Le chiavi mancanti ricadono sui default integrati; `config.json.example` documenta ogni chiave di `config.json`
- Entrambi i file vengono cercati, indipendentemente l'uno dall'altro, in questo ordine: **root del repository**, poi **directory del pacchetto installato**, poi **`~/.hate_crack`**. La prima corrispondenza vince; è normale che i due file provengano da directory diverse.
- Al primo avvio, entrambi vengono creati — `config.json` da `config.json.example`, `.env` dai default integrati. Se un `config.json` più vecchio contiene ancora chiavi di integrazione, queste vengono copiate nel nuovo `.env` e hate_crack ti dice 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 insidie nell'ordine di ricerca:
.env o config.json presente in qualsiasi checkout da cui esegui lo strumento ha la precedenza su quello in ~/.hate_crack — ed eseguire lo strumento da un checkout è esattamente ciò che crea quei file lì in primo luogo. Se questo oscura una configurazione reale di ~/.hate_crack, hate_crack ora lo segnala con una terza riga [!] che indica entrambi i percorsi — tratta quella riga come "il file sottostante viene ignorato", non come una seconda configurazione ugualmente valida..env nella directory in cui ti trovi viene ignorato, deliberatamente: le directory di ingaggio sono piene di file che nessuno intendeva come configurazione. Mettilo nella radice del repository o in ~/.hate_crack.Se vedi:``` Your configuration specifies to merge with the ref 'refs/heads/master' from the remote, but no such ref was fetched.
La rama predefinita è stata rinominata 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
Predefinito (installazione completa) - compila i sottomoduli, installa le dipendenze e installa lo strumento:```bash make
make install
Questo è idempotente: salta gli strumenti già installati.
**Reinstallazione pulita forzata:**```bash
make reinstall
Aggiornamento rapido - ricompila i sottomoduli e reinstallare 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
Rapporto di copertura:```bash make coverage
**Pulire gli artefatti di build/test:**```bash
make clean
Installa il progetto con le dipendenze di sviluppo opzionali (include linter e strumenti di test):```bash make dev-install
### Esecuzione di Linter e Controlli di Tipo
Prima di inviare le modifiche, esegui questi controlli localmente. 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
Auto-correggi i 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
Or 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)
I Git hook 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-commit/pre-commit-hooks): trailing-whitespace,
end-of-file-fixer, check-yaml, check-merge-conflict, check-added-large-files,
detect-private-keyGli auto-fixer di pre-commit riscrivono i file sul posto, quindi ri-aggiungi allo 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.
I menu usano di default la classica selezione numerata print() + input(), che
accetta chiavi complete a più cifre.
Per abilitare la navigazione con le frecce tramite simple-term-menu, imposta
HATE_CRACK_ARROW_MENU=1. In quella modalità funzionano solo i tasti di scelta rapida a una cifra;
le opzioni numerate da 10 in su devono essere raggiunte con le frecce. La modalità
a frecce richiede anche un TTY, quindi resta disattivata quando l'output è reindirizzato.
Il gruppo opzionale [dev] include:
Opzioni comuni:
--download-hashview: Scarica gli hash da Hashview prima del cracking.--hashview: Menu interattivo Hashview per gestire hash, wordlist e job.--hashview --help: Mostra le opzioni da riga di comando di Hashview.--weakpass: Scarica wordlist da Weakpass.--hashmob: Scarica wordlist da Hashmob.net.--hashmob-masks: Scarica maschere da Hashmob.net.--download-torrent <FILENAME>: Scarica un file torrent specifico di Weakpass.--download-all-torrents: Scarica tutti i torrent Weakpass disponibili dalla cache.--wordlists-dir <PATH> / --optimized-wordlists-dir <PATH>: Sostituisce le directory delle wordlist.--pipal-path <PATH>: Sostituisce il percorso di pipal.--restore-potfile: Ricostruisce dal file POT di hashcat all'avvio, sostituendo qualsiasi contenuto esistente, poi continua nel menu normale. Senza questo flag la ricerca nel POT viene eseguita solo quando non esiste già. L'opzione 93 del menu fa la stessa cosa su richiesta, con un prompt di conferma.hate_crack si integra con Hashview per la gestione centralizzata degli hash e il cracking distribuito.
Accedi al menu interattivo Hashview:```bash hate_crack.py --hashview
Opzioni del menu:
- **(1) Carica hash craccati** - Carica i risultati craccati della sessione corrente su Hashview
- **(2) Carica wordlist** - Carica un file wordlist su Hashview
- **(3) Scarica wordlist** - Scarica una wordlist da Hashview
- **Scarica regola** - Scarica un file di regole da Hashview (decompresso in testo semplice, pronto per `hashcat -r`)
- **Scarica tutte le regole** - Scarica ogni file di regole elencato da Hashview in un'unica passata; gli errori per singola regola vengono segnalati senza interrompere il resto
- **(4) Scarica hash rimanenti** - Scarica gli hash non ancora craccati (chiede di passare a questi per il cracking)
- **(5) Scarica hash trovati** - Scarica gli hash già craccati con le password in chiaro (per riferimento/analisi)
- **(6) Carica hashfile e crea job** - Carica un nuovo hashfile e crea un job di cracking
- **(99) Torna al menu principale** - Torna al menu principale
**Importante: Scarica trovati vs Scarica rimanenti**
- **Scarica hash rimanenti (4)**: Scarica gli hash non craccati che necessitano di cracking. Unisce automaticamente eventuali hash trovati se disponibili e chiede di passare a questo hashfile per il cracking.
- **Scarica hash trovati (5)**: Scarica gli hash già craccati in formato hash:testochiaro. Questi servono come riferimento e non possono essere craccati ulteriormente. Non viene mostrata alcuna richiesta di cambio.
#### Interfaccia a riga di comando
Le operazioni Hashview possono essere eseguite anche tramite riga di comando:
Carica hash craccati:```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 rimanenti (hash non decifrati da crackare):```bash hate_crack.py --hashview download-left --customer-id 1 --hashfile-id 123
Download degli hash trovati (hash già decifrati con testo in chiaro):```bash
hate_crack.py --hashview download-found --customer-id 1 --hashfile-id 123
Upload hashfile e crea 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
L'LLM Attack (opzione 12) e la 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_*` qui sotto si applicano a ogni backend, non solo a Ollama.** Mantengono quel prefisso perché `OLLAMA_HOST` è la stessa variabile che legge la CLI di Ollama stessa, e rinominarle romperebbe ogni `.env` esistente senza alcun guadagno funzionale — un server vLLM o compatibile con OpenAI vuole gli stessi parametri di host, modello, timeout, contesto e campionamento sotto gli stessi nomi. `LLM_BACKEND` seleziona solo come viene modellata la richiesta.
- **`OLLAMA_MODEL`** — Il modello Ollama usato per la generazione dei candidati (default: `qwen3:4b-instruct`). L'attacco LLM usa output strutturato (JSON), quindi scegli un modello con un buon supporto per strumenti/JSON.
- **`OLLAMA_NUM_CTX`** — Dimensione della finestra di contesto per il modello (default: `8192`). Prima dell'introduzione delle statistiche sul corpus era `2048`, troppo piccola per contenere il prompt che veniva fornito: 500 plaintext campionati occupano circa 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 (default: `300`). Alzalo se un modello grande sta ancora caricando in 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 (default: `500`). Valori ≤ 0 vengono trattati come 500.
Le modalità derivate dal corpus (**Wordlist**, **Cracked passwords**, **Pattern rules**) descrivono sempre l'*intero* corpus in modo statistico — quote delle parole base, maschere, maiuscole/minuscole, lunghezze, cifre e simboli finali, anni — invece di incollarne una fetta. L'aggregazione è limitata, quindi un dump di 120.000 password costa più o meno lo stesso spazio di prompt di uno da 500 righe. Quando l'intero corpus rientra sotto questa soglia, vengono inclusi anche i plaintext grezzi, poiché non si guadagna nulla nascondendo un piccolo corpus al modello.
Questo sostituisce il comportamento precedente di incollare un campione uniformemente distribuito di fino a `ollamaMaxSampleLines` password. Un campione di un grande dump non trasmetteva alcuna informazione sulla frequenza: il modello non poteva distinguere una parola base usata dall'8% dell'organizzazione da una usata da una singola persona, che è proprio il segnale che rende utile provare una supposizione.
- **`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 usato da un modello locale, quindi nulla nella richiesta appare diverso — questo viene rifiutato in base al nome del modello. Viene anche controllato l'URL del backend configurato: una destinazione che non è loopback, privata o link-local (e non è `localhost` o un nome `.local`/`.internal`/`.lan`/`.localdomain`) viene rifiutata in base alla destinazione, e un hostname che questo controllo non riesce a risolvere viene rifiutato anch'esso, con chiusura fail-closed, piuttosto che lasciar passare una destinazione non verificabile. I prompt di hate_crack trasportano plaintext recuperati, statistiche sul corpus e il nome, il settore e la posizione del cliente, quindi se uno dei due controlli scatta la richiesta viene rifiutata prima che venga costruita. Il default è `false`, quindi un modello cloud o un server remoto configurato deliberatamente continua a funzionare; attivalo per incarichi in cui i dati del cliente non devono lasciare l'host.
- **`OLLAMA_AUTO_RESEARCH`** — Quando è `true` (default), la modalità **Target info** chiede al modello locale di suggerire settore, posizione e società madre / storia di acquisizioni non appena hai digitato il nome dell'azienda, e li offre come default modificabili nei prompt. Impostalo su `false` per ottenere sempre prompt vuoti (utile con un modello lento, poiché la ricerca costa un round-trip extra prima che l'attacco inizi).
- **`OLLAMA_HOST`** — Dove sta ascoltando 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. Il default è `localhost:11434`, che è la porta di Ollama — un server vLLM o compatibile con OpenAI richiede che sia impostato sulla propria (vLLM ascolta comunemente su `:8000`). Impostalo in `.env`, oppure esportalo come variabile d'ambiente reale per sovrascriverlo per una singola esecuzione — è lo stesso nome di variabile che legge la CLI di Ollama stessa.
- **`LLM_BACKEND`** — Con quale server compatibile con OpenAI parlare: `ollama` (default), `vllm` o `openai` per uno generico. Ogni backend parla la stessa API chat-completions `/v1`, quindi questo seleziona solo i due dettagli di modellazione 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 ragionamento instrada l'intera risposta strutturata in `message.reasoning`, lascia `message.content` vuoto e rompe il parsing JSON. `openai` non invia nessuno dei due, poiché `num_ctx` non ha un equivalente lì. Non cambia da dove provengono le impostazioni di host, modello, timeout, contesto o campionamento — quelle sono le chiavi `OLLAMA_*` sopra per tutti e tre.
- **`LLM_API_KEY`** — La credenziale inviata al backend configurato. Il default è il letterale `ollama`, il segnaposto che il server di Ollama stesso ignora, quindi le richieste di un'installazione esistente restano invariate; un valore vuoto ricade su quello stesso segnaposto perché l'SDK OpenAI rifiuta `api_key=""`. Impostalo sul 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 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 questi dettagli.
Dopo aver 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:
Premere Invio per accettare un suggerimento o digitare sopra di esso. Questi valori sono il ricordo del modello, non OSINT — trattali come un punto di partenza, non come informazioni 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 piccoli clienti), non restituisce nulla e ottieni semplici prompt vuoti: ``` Company name: Acme Rail Services Industry: Location: Parent company / acquired by:
Un errore di 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 del tutto la ricerca.
2. **Wordlist** — deriva le parole base da una wordlist di esempio.
3. **Password crackate** — fornisci al modello i testi in chiaro già recuperati in questa sessione (`<hashfile>.out`) così che possa dedurre le convenzioni sulle password dell'organizzazione target (parole base, stagioni, anni, suffissi, leetspeak) e generare *nuovi* candidati nello stesso stile. Questa opzione viene elencata solo dopo che almeno un hash è stato crackato; l'intero file viene analizzato statisticamente esattamente come nella modalità Wordlist (vedi `ollamaMaxSampleLines` sopra).
#### Configurazione PCFG
L'Attacco PCFG (opzione 20) e l'Attacco PRINCE-LING (opzione 21) utilizzano il sottomodulo `pcfg_cracker`. Configurali in `config.json`:```json
{
"pcfgRuleset": "DEFAULT",
"pcfgMaxCandidates": 50000000,
"pcfgPrinceLingMaxCandidates": 10000000
}
pcfgRuleset — Nome della grammatica addestrata da usare (default: DEFAULT), risolto in pcfg_cracker/Rules/<name>/. Addestra la tua con trainer.py di pcfg_cracker e imposta questo campo sul nome del ruleset.pcfgMaxCandidates — Numero massimo di candidati che pcfg_guesser.py genera per l'attacco PCFG (default: 50000000).pcfgPrinceLingMaxCandidates — Numero massimo di parole base che prince_ling.py scrive nella wordlist PRINCE di base memorizzata in cache (default: 10000000).optimizedKernelAttacks)Il flag -O di hashcat seleziona i kernel ottimizzati, che sono sostanzialmente più veloci
ma limitano la lunghezza dei candidati (circa 31 caratteri, meno 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 dall'elenco per eseguirlo con
kernel a lunghezza completa. L'elenco in config.json.example corrisponde al default integrato
che si applica quando non esiste alcun config.json.
Quattro attacchi rispettano l'impostazione ma non sono ottimizzati di default, perché
forniscono candidati che possono superare il limite di -O — aggiungili all'elenco per
attivarli:
hcatNgramX, hcatOllama, hcatOmen, hcatLMtoNTPer disattivare -O ovunque per una singola esecuzione senza modificare la configurazione, passa
--no-optimized-kernel (forma breve --no-optimize). Sovrascrive l'elenco per
ogni attacco e rimuove anche un -O scritto in hcatTuning, che altrimenti
raggiungerebbe hashcat indipendentemente dall'elenco.
I nomi vengono confrontati esattamente e una voce non riconosciuta viene segnalata all'avvio
piuttosto che 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à pattern-rule LLM
seguono hcatQuickDictionary.
coverage_enabled)Nel corso di un impegno lungo, lo stesso file di hash viene attaccato in molte sessioni con un set rotante di wordlist, file di regole e liste di maschere, ed è facile bruciare ore ri-eseguendo terreno già coperto — soprattutto perché la stessa riga di regola vive 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 con cui è stata eseguita. Questo
è ciò che le consente di riconoscere che un file di regole personalizzato che esegui oggi ripete 40
delle regole che best64.rule ha già coperto la scorsa settimana, ed è anche il motivo per cui una regola è
"coperta" solo per la specifica wordlist con cui è stata provata — le stesse regole su
un corpus diverso provano candidati completamente diversi.
Il file di hash viene identificato da uno sha256 del suo contenuto, quindi la copertura sopravvive alla rinomina o allo spostamento tra sessioni. Le wordlist vengono identificate allo stesso modo, con il digest memorizzato in cache rispetto a dimensione e mtime, così un corpus multi-gigabyte viene sottoposto a hash una volta sola piuttosto che a ogni attacco.
Ti viene richiesto solo quando c'è davvero 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 l'intera operazione. Se *ogni* voce è una ripetizione
ti viene chiesto se saltare del tutto l'attacco, così ri-eseguire deliberatamente terreno già coperto non richiede mai di riavviare lo strumento.
Gli attacchi che non vengono mai filtrati vengono comunque registrati come eseguiti, il che è ciò 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 lotto, in anticipo**, prima di qualsiasi invocazione di hashcat. Quella domanda è volutamente economica — non legge né calcola l'hash di nessuno
dei file di regole selezionati, poiché un batch YOLO può arrivare a milioni di righe e
non dovresti aspettare tutto quel tempo per rispondere a un sì/no. Chiede solo allo store
se questo attacco è già stato eseguito contro questo file di hash **con una di queste
wordlist**; il diff per singola voce avviene comunque in modo pigro, 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 uno diverso.
Tre limiti deliberati:
- **La copertura viene registrata solo quando hashcat esaurisce il keyspace** (exit 1). Un
ctrl-C o un errore non registrano nulla, e nemmeno l'exit 0 — che significa che ogni
hash è stato crackato, cosa che hashcat riporta *senza* terminare il keyspace, e nel
caso degenere di "tutti gli hash trovati come voci potfile" senza provare un
singolo candidato. Una sotto-registrazione costa solo una riesecuzione ridondante in seguito.
- **I generatori dinamici di candidati non vengono mai filtrati.** PRINCE, PCFG, OMEN,
brute force Markov e le modalità LLM non hanno un insieme fisso su cui fare il diff, quindi vengono
registrati come eseguiti e per il resto lasciati stare. I file di regole concatenati (`-r a -r b`)
vengono tracciati come un'unica unità piuttosto che per singola voce, perché hashcat applica il
*prodotto cartesiano* dei due file e rimuovere una singola riga
eliminerebbe silenziosamente ogni combinazione a cui partecipava.
- **Le esecuzioni `--loopback` vengono registrate ma mai filtrate.** hashcat reimmette i
plaintext appena crackati come *candidati extra*, quindi tale esecuzione prova la wordlist
completa e il set di regole più tutto ciò che quei plaintext riciclati raggiungono. Questo rende
le due direzioni asimmetriche: registrarlo è corretto, così una successiva esecuzione ordinaria
della stessa wordlist e delle stesse regole viene correttamente riconosciuta come ripetizione, ma una
seconda esecuzione loopback ha più crack da riciclare e non viene mai saltata.
Imposta `coverage_enabled` su `false` in `config.json` per disattivarlo, oppure passa
`--no-coverage` per una singola esecuzione — che non consulta né aggiorna lo store.
#### Ispezione e ripristino della copertura
L'opzione **85 — Attack Coverage** del menu principale mostra cosa è stato eseguito contro il
file di hash caricato, la sua cronologia delle esecuzioni, 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 dal contenuto, quindi funziona indipendentemente da dove sia stato
spostato in seguito. forget influisce solo su quel singolo target: lo store risiede in
~/.hate_crack/coverage/attack_coverage.sqlite3, e l'eliminazione del file reimposta la copertura
per ogni target.
Un attacco scriptato che la copertura salta completamente esce comunque con codice 0 di default, quindi
abilitare la copertura non può far fallire un harness esistente. Passa
--exit-code-on-skip per ottenere invece il codice di uscita 3 quando non è stato lanciato nulla:```bash
hate_crack --exit-code-on-skip hashes.txt dict
L'uscita 3 significa che *non* è stato eseguito nulla. Un passaggio parzialmente filtrato — alcune voci saltate, altre tentate — esce comunque con `0`, perché l'attacco ha comunque svolto del lavoro.
### Notifiche (opzione di menu 82)
hate_crack può inviare notifiche push Pushover al completamento degli attacchi e, opzionalmente, quando vengono crackati singoli hash. Tutti i controlli si trovano sotto l'opzione del menu principale `82 — Notifiche`:
1. **Attiva/Disattiva Notifiche Pushover [ON/OFF]** — interruttore principale. Viene salvato in `config.json` come `notify_enabled`.
2. **Attiva/Disattiva Notifiche Per-Crack [ON/OFF]** — quando è ON, un tailer in background monitora il file `.out` e invia una notifica per ogni crack (con aggregazione a raffica per tick). Viene salvato in `config.json` come `notify_per_crack_enabled`. Non può essere attivato mentre l'interruttore principale è OFF — abilita prima l'opzione 1.
3. **Invia Notifica Pushover di Test** — invia una notifica predefinita per confermare che la coppia token/utente Pushover funzioni. Funziona anche quando l'interruttore principale è OFF.
Le credenziali si trovano in `.env`; le restanti opzioni di regolazione sono solo nel file di configurazione `config.json`:
- `NOTIFY_PUSHOVER_TOKEN`, `NOTIFY_PUSHOVER_USER` (in `.env`) — richiesti affinché qualsiasi push venga inviato. Nessuna voce del menu li scrive; modifica tu stesso `.env`.
- `notify_attack_allowlist` — nomi di attacco che danno il consenso automatico senza il prompt `[y/N/always]`. Viene popolato automaticamente quando rispondi `always`.
- `notify_suppress_in_orchestrators` (default `true`) — silenzia i singoli attacchi concatenati da Extensive Crack, che invece invia un unico riepilogo. Impostalo su `false` per 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` (default `5`), `notify_poll_interval_seconds` (default `5.0`) — regolazione del tailer per-crack. Vedi `hate_crack/notify/tailer.py` per la logica di aggregazione a raffica.
### Strumenti per Wordlist (opzione di menu 80)
Il sottomenu Strumenti per Wordlist fornisce utilità di pre-elaborazione delle wordlist basate sui binari di hashcat-utils, oltre al 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 - mantieni solo le parole tra una lunghezza minima e massima |
| 2 | `req-include.bin` | Richiedi classi di caratteri - mantieni solo le parole contenenti tutti i tipi di caratteri richiesti |
| 3 | `req-exclude.bin` | Escludi classi di caratteri - rimuovi le parole contenenti 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 - rimuovi le voci che compaiono in uno o più altri file |
| 7 | `gate.bin` | Shard - estrai ogni N-esima parola per cracking distribuito su più macchine |
| 8 | - | Ottimizza wordlist - deduplica e dividi 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`=minuscole, `2`=maiuscole, `4`=cifre, `8`=simboli, `16`=altro. Somma i valori: `7` = minuscole+maiuscole+cifre.
**Come si intende usare lo 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 piuttosto che un blocco contiguo iniziale/finale — nessun singolo nodo resta bloccato a crackare solo la coda a bassa probabilità.
Esegui l'opzione 7 una volta, fornisci una wordlist di input, un percorso di base di output e un numero di shard (N). Scrive tutte le N parti in un unico passaggio, denominate con numeri di parte con zero padding (`base.001`, `base.002`, … fino a `base.00N`). Copia una parte su ogni nodo e punta l'esecuzione di hashcat di quel nodo su di essa. Su un sistema a singola GPU lo sharding non dà alcun aumento di velocità, ma una singola parte è comunque un campione rapido e rappresentativo per un passaggio di triage veloce prima di impegnarsi sulla lista completa.
#### Controlli automatici degli aggiornamenti
hate_crack può controllare automaticamente GitHub per 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).| Canale | Flag | Sorgente | Cosa ottieni |
|---|---|---|---|
| Release |
Le versioni seguono il normale semver, con l'incremento derivato da ciò che è effettivamente presente
nel batch. Il secondo componente si muove solo per le funzionalità: un ciclo contenente
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 i release candidate per la versione verso cui il batch è diretto
— v2.20.1rc1, v2.20.1rc2, … — e l'unione in main promuove quello
stesso target alla sua release finale. I candidate sono vere pre-release PEP 440, quindi
si ordinano correttamente a 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 arriva lo sposta da
X.Y.(Z+1) a X.(Y+1).0, e la numerazione dei candidate riparte per il nuovo target.
Il numero indica sempre ciò che il batch rilascerebbe oggi.
Il componente principale non viene mai incrementato automaticamente — un soggetto con ! o un
footer BREAKING CHANGE: conta come funzionalità, perché un major automatico è a un
soggetto scritto male di distanza da una release pubblicata irreversibile. Un major è un
atto umano esplicito: taggalo e pubblicalo 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 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: questo, e il fatto che un candidate è una vera pre-release PEP 440,
quindi uno strumento che classifica i numeri di versione grezzi lo tratta anche come più vecchio
della release in cui si trasforma.
Entrambi i flag portano prima il tuo checkout sul ramo 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.
Quando scarichi gli hash di sinistra (hash non decifrati), hate_crack automaticamente:
.out locali (ad es., left_1_123.txt.out o left_1_123.nt.txt.out per il formato pwdump)Questo garantisce che i tuoi risultati di decifratura locali rimangano sincronizzati con il database centralizzato di Hashview quando lavori con hash non decifrati.
Nota: L'opzione di download degli hash trovati scarica gli hash già decifrati separatamente a scopo di riferimento e non esegue alcuna unione né richiede la decifratura.
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
Since the input is empty, there is no content to translate. Please provide the chunk text you'd like me to translate.```
$ ./hate_crack.py <hash file> 1000
___ ___ __ _________ __
/ | \_____ _/ |_ ____ \_ ___ \____________ ____ | | __
/ ~ \__ \\ __\/ __ \ / \ \/\_ __ \__ \ _/ ___\| |/ /
\ Y // __ \| | \ ___/ \ \____| | \// __ \\ \___| <
\___|_ /(____ /__| \___ >____\______ /|__| (____ /\___ >__|_ \
\/ \/ \/_____/ \/ \/ \/ \/
Version 2.0
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 opzionali tramite variabili d'ambiente.
uv run pytest -v
uv run pytest tests/test_hashview.py -v
You can also run the full suite with `make test`.
### Live Tests (Opt-In)
Set any of the following to enable live checks:
- `HASHMOB_TEST_REAL=1` — live Hashmob connectivity/CLI menu check
- `HASHVIEW_TEST_REAL=1` — live Hashview CLI menu check
- `WEAKPASS_TEST_REAL=1` — live Weakpass CLI menu check
- `HATE_CRACK_REQUIRE_DEPS=1` — fail if `7z`, `transmission-daemon`, or `transmission-remote` is missing
### Live Hashview Upload Test
The live Hashview upload test is skipped by default. To run it, set the
environment variable and provide valid credentials in `.env`:```bash
HATE_CRACK_RUN_LIVE_TESTS=1 uv run pytest tests/test_upload_cracked_hashes.py -v
Invece di puntare i test live a un server Hashview remoto, puoi far
avviare alla suite uno stack Docker locale di Hashview,
popolarlo, eseguire i test live contro di esso e poi smontarlo. 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, inserisce una chiave API admin,
un cliente, un hashfile e dati "effective task" decifrati, quindi esporta
le variabili d'ambiente `HASHVIEW_*` che i test leggono. Variabili d'ambiente utili:
- `HASHVIEW_TEST_LOCAL=1` — abilita lo stack locale (nessun effetto altrimenti)
- `HASHVIEW_REPO=<percorso>` — checkout di Hashview (predefinito `~/projects/hashview`)
- `HASHVIEW_KEEP=1` — lascia i container in esecuzione dopo la sessione (riesecuzioni più veloci)
- `HASHVIEW_LOCAL_PORT=5000` — porta host su cui l'app è pubblicata
La CLI hate_crack rispetta le variabili d'ambiente `HASHVIEW_URL` / `HASHVIEW_API_KEY`
(sovrascrivendo il `.env` in cui risiedono quelle due chiavi), ed è ciò che consente alla
suite di puntare la CLI allo stack locale senza modificare la tua configurazione persistente.
### Test di Installazione End-to-End (Locale + Docker)
Installazione dello strumento uv locale + esecuzione dello script (usa una HOME temporanea):```bash
HATE_CRACK_RUN_E2E=1 uv run pytest tests/test_e2e_local_install.py -v
Docker-based end-to-end install/run (cached via 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](https://lima-vm.io/) 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 valida l'installazione e l'esecuzione all'interno di una VM Linux leggera su macOS.
### Struttura del Test
- **tests/test_hashview.py**: Suite di test completa per la classe HashviewAPI con risposte API simulate, inclusi:
- Elenco dei client e validazione dei dati
- Test di autenticazione e autorizzazione
- Funzionalità di caricamento dei file hash
- Flusso completo di creazione dei job
Tutti i test utilizzano chiamate API simulate, quindi possono essere eseguiti senza connettività a un server Hashview.
-------------------------------------------------------------------
(1) Crack Rapido
(2) Crack Estensivo con Metodologia Pure_Hate
(3) Attacco a Forza Bruta
(4) Attacco con Maschera Top
(5) Attacco con Impronta Digitale
(6) Attacchi Combinator
(7) Attacco Ibrido
(8) Crack a Forza Bruta con Maschere Top 100 di Pathwell
(9) Attacco PRINCE
(10) Metodologia Bandrel
(11) Attacco Loopback
(12) Attacco LLM
(13) Attacco OMEN
(14) Attacco con Maschera Ad-hoc
(15) Attacco a Forza Bruta Markov
(16) Attacco N-gram
(17) Attacco a Permutazione
(18) Attacco con Regole Casuali
(19) Attacco con Passphrase Combipow
(20) Attacco PCFG
(21) Attacco PRINCE-LING
(22) Attacco Spoonman
(23) Attacco Rosetta
(24) Forza Bruta con Maschere Aziendali
(25) Attacco con Maschera Intelligente
(80) Strumenti per Wordlist
(81) Strumenti per File di Regole
(82) Notifiche
(83) Strumenti per Maschere
(93) Rigenera .out dal file POT
(94) API Hashview
(95) Analizza gli hash con Pipal
(96) Esporta Output in Formato Excel
(97) Mostra Hash Decifrati
(98) Mostra README
(99) Esci
Seleziona un'attività:```
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/i regola/e desideri eseguire? (1) best64.rule (2) d3ad0ne.rule (3) T0XlC.rule (4) dive.rule (99) YOLO...esegui tutte le regole Inserisci un elenco separato da virgole delle regole che desideri 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 con saggezza:```
Runs several attack methods provided by Martin Bos (formerly known as pure_hate):
hcatWordlists with best64.rulerockyou.txt with d3ad0ne.rulerockyou.txt with T0XlC.rulerockyou.txt with chained combinator.rule and InsidePro-PasswordsPro.rule rulesBrute forces all characters with the choice of a minimum and maximum password length.
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).
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).
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.
https://hashcat.net/wiki/doku.php?id=combinator_attack
Runs a combinator attack using the "rockyou.txt" wordlist.
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.
?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.Runs a brute force attack using the top 100 masks from KoreLogic: https://blog.korelogic.com/blog/2014/04/04/pathwell_topologies
https://hashcat.net/events/p14-trondheim/prince-attack.pdf
Runs a PRINCE attack using wordlists/rockyou.txt
Runs a continuous combinator attack using random wordlists from the configured wordlists directory for the left and right sides.
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 - _ , + . &
https://jeffh.net/2018/04/26/combinator_methods/
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.
config.json entry (bandrel_common_basedwords)bandrelmaxruntime in config.jsonhttps://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.
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.
OLLAMA_HOST (default: http://localhost:11434, Ollama's port; override in .env or the environment) already serving the model — hate_crack does not auto-pullqwen3:4b-instruct).env (see LLM Configuration)ollamaAutoResearch: false<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)ollamaTimeout so a model stuck loading into VRAM reports a timeout instead of hangingPattern rules mode (option 4 in the LLM submenu) takes the same shape as the 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.
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<hashfile>.llm_patterns/ as basewords.txt and rules.rule — per-run scratch, laid out like .spoonman/ and removed on exitUses 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.
omenMaxCandidates)~/.hate_crack/omen/ for persistence across sessionsOpens an interactive submenu with six combinator attack variants (formerly at menu keys 10-12). Consolidates related attacks for cleaner menu organization:
combinator3.bin, generating all word1+word2+word3 combinations piped to hashcatcombinatorX.bin with optional --sepFill separator character between word segmentsRuns hashcat mask attack (mode 3) with a user-specified custom mask string. Allows fine-grained control over character-set brute forcing.
?u?l?l?l?d?d for uppercase + lowercase + lowercase + lowercase + digit + digit)-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?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 undefinedGenerates password candidates using Markov chain statistical models. Similar to OMEN but simpler and faster.
.hcstat2 Markov table from previous sessions (with option to reuse, regenerate, or cancel).out file) as training data--increment flag to test lengths in sequenceGenerates n-gram candidates from a corpus file using ngramX.bin from hashcat-utils and pipes them into hashcat.
Generates all character permutations of each word in a targeted wordlist and pipes them to hashcat via permute.bin from hashcat-utils.
permute.bin < wordlist | hashcat pipeline patternGenerates 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.
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.
-s flag) to insert spaces between words in each combinationUses 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.
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.pcfgRuleset in config.json (default DEFAULT), read from pcfg_cracker/Rules/<name>/pcfgMaxCandidates (default 50,000,000)trainer.py and point pcfgRuleset at the resulting ruleset nameUses 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.
pcfg_cracker submodule and a trained ruleset directory, same as the PCFG attack<hcatOptimizedWordlists>/pcfg_prince_ling_<ruleset>.txt and reused across sessionspcfgPrinceLingMaxCandidates (default 10,000,000)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.
<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<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 cleanupMines hashcat --debug-mode 5 logs for the basewords and rules that already cracked something, then runs their full cross product. Powered by HashcatRosetta, the same library behind Analyze Hashcat Rules.
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:
hcatDebugLogPath newest-first with their sizes; pick one, pick all of them (up to 20), or type a path to a log from elsewhere<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<hash file>.hcmask, and runs a -a 3 hashcat mask attack against themStatistical masks (8-14 characters) derived from analysis of 3.2M NTLM hashes cracked on real engagements. Powered by Corporate_Masks, these masks encode realistic password patterns from successful penetration tests.
-O flag) for faster crackingA 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.
All binaries are in hate_crack/hashcat-utils/bin/.
Preprocesses hashcat rule files using cleanup-rules.bin and rules_optimize.bin from hashcat-utils, and downloads rule files from Hashmob.net.
cleanup-rules.bin. Useful after combining rule files or downloading rules from external sources.rules_optimize.bin. Reduces rule file size and improves cracking speed.rulesDirectory.The three preprocessing operations read from an input file and write to a separate output file (original is never modified).
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.
Powered by HashcatRosetta (https://github.com/bandrel/HashcatRosetta), this feature analyzes hashcat rule files to provide detailed insights into rule composition and complexity.
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.
Downloads mask files from Hashmob.net's mask repository into the hate_crack masks directory for use with mask-based attacks.
Downloads wordlists from Hashmob.net's collection of cracked passwords and commonly used wordlists.
Interactive menu for downloading and managing wordlists from Weakpass.com via BitTorrent.
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)
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 restCombined Left Lists - Downloads per-hashcat-mode combined lists of uncracked ("left") hashes from Hashmob.net
The full, per-release changelog now lives in CHANGELOG.md.
username:hash--usernamehate_crack/formatting.py, hate_crack/progress.py: helper per la formattazione dell'output e la visualizzazione dell'avanzamento.hate_crack/main.py: implementazione principale della CLI.<hashfile>.out.out--maxruntime <SECONDS>: Sostituisce il tempo massimo di esecuzione.--bandrel-basewords <PATH>: Sostituisce il file delle parole base di bandrel.--update: Aggiorna all'ultima release e reinstalla. Passa il checkout al ramo main se si trova su un altro ramo, poiché i tag delle release vivono lì.--nightly: Aggiorna invece all'ultima nightly, dal ramo nightly-dev. Le nightly hanno superato la CI ma non fanno parte di una release tagliata. Può anche essere scritto come --update --nightly.--no-optimized-kernel (o --no-optimize): Non passare mai -O a hashcat per l'intera esecuzione. Sostituisce optimizedKernelAttacks in config.json e rimuove qualsiasi -O che hai inserito in hcatTuning. Non viene scritto nulla di nuovo nella configurazione, quindi si applica solo a questa esecuzione. Con un sottocomando, mettilo prima del sottocomando: ./hate_crack.py --no-optimize quick hashes.txt 1000 --wordlist words.txt.--debug: Abilita il logging di debug (scrive su stderr).--update |
main |
| L'ultima release pubblicata. Questa è l'impostazione predefinita e ciò che offre il controllo all'avvio. |
| Nightly | --nightly | nightly-dev | Lavoro che ha superato la CI ma non è ancora stato rilasciato. |
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.
.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--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 alikecoverage.txt: 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$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$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| 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) |