Retour aux mises à jour
New releaseSep 4, 2026

hate_crack v2.36.1

Un outil pour automatiser les méthodologies de craquage via Hashcat, développé par l'équipe TrustedSec.

Partager
  ___ ___         __             _________                       __
 /   |   \_____ _/  |_  ____     \_   ___ \____________    ____ |  | __
/    ~    \__  \\   __\/ __ \    /    \  \/\_  __ \__  \ _/ ___\|  |/ /
\    Y    // __ \|  | \  ___/    \     \____|  | \// __ \\  \___|    <
 \___|_  /(____  /__|  \___  >____\______  /|__|  (____  /\___  >__|_ \
       \/      \/          \/_____/      \/            \/     \/     \/

Installation

L'installation à partir des sources est la seule voie prise en charge. hate_crack n'est pas distribué sur PyPI : pip install hate-crack renvoie à un espace réservé 0.0.0 qui échoue volontairement et renvoie ici. Le nom n'est conservé que pour que personne d'autre ne puisse publier un clone sous celui-ci — voir packaging/pypi-placeholder/.

1. Installer hashcat

Hashcat doit être installé et disponible dans votre PATH :

Ubuntu/Kali :```bash sudo apt-get install -y hashcat

macOS (Homebrew) :```bash
brew install hashcat

Ou téléchargez un binaire pré-compilé depuis https://hashcat.net/hashcat/ et définissez hcatPath dans config.json sur son emplacement.

2. Télécharger hate_crack

Clonez avec les sous-modules (requis pour hashcat-utils, princeprocessor, pcfg_cracker, Corporate_Masks, et optionnellement omen) :```bash git clone --recurse-submodules https://github.com/trustedsec/hate_crack.git cd hate_crack

Si vous avez cloné sans les sous-modules, initialisez-les :```bash
git submodule update --init --recursive

Ensuite, personnalisez la configuration si nécessaire. hate_crack utilise deux fichiers de configuration, chacun gérant un ensemble distinct de paramètres :

  • config.json — chemins des wordlists, masques, règles, réglages, potfile, chemin de hashcat, limites de candidats, bascules de notifications, préférences par défaut de l'interface en ligne de commande (35 paramètres).
  • .env — uniquement les paramètres d'intégration tiers : identifiants Hashview et Hashmob, identifiants Pushover, Ollama et pipal (14 paramètres). Non suivi par git, créé avec le mode 0600.

La ligne se trouve là pour une seule raison : .env est le fichier qui peut contenir des secrets. Les identifiants et la configuration des services tiers vont dans le fichier non suivi, en mode 0600 ; tout ce que hate_crack fait localement reste dans config.json, qui peut être partagé, comparé et archivé en toute sécurité dans vos propres notes. C'est aussi pourquoi les identifiants Pushover sont dans .env tandis que les bascules d'activation/désactivation Pushover sont dans config.json — les bascules sont des préférences locales, pas des secrets.

Chaque clé a exactement un emplacement. Une clé placée dans l'autre fichier est ignorée, et hate_crack affiche un avertissement indiquant le fichier auquel elle appartient. Toute clé peut néanmoins être remplacée pour une seule exécution en exportant sa variable d'environnement. La plupart des utilisateurs peuvent ignorer cette étape, car les chemins par défaut fonctionnent immédiatement.

config.json est permanent et de première classe — il n'est pas obsolète et aucun calendrier de suppression n'est prévu. Seuls les paramètres d'intégration ont été déplacés.

Mise à niveau depuis un config.json unique ? hate_crack le migre pour vous lors de la première exécution : les paramètres d'intégration sont copiés dans un nouveau .env en mode 0600, puis supprimés de config.json afin que les deux fichiers ne les revendiquent pas tous les deux. Il affiche quelles clés ont été déplacées (jamais leurs valeurs) et enregistre votre original sous config.json.pre-split.bak avant de le modifier. Tout le reste dans config.json est laissé exactement tel quel, ordre des clés inclus.

Première exécution : hate_crack crée les deux fichiers pour vous, il n'y a donc rien à faire. Pour configurer .env manuellement à la place, copiez le modèle suivi :```bash cp .env.example .env chmod 600 .env

`.env.example` est commité et est livré avec chaque clé de credential vide. `.env` lui-même ne doit **jamais** être commité — il est gitignoré, ainsi que ses orthographes de sauvegarde habituelles, et hate_crack le crée toujours en mode `0600` (lecture/écriture propriétaire uniquement). `.env.example` est généré à partir du schéma ; régénérez-le après avoir modifié `hate_crack/config_schema.py` avec `uv run python -m hate_crack.config_writer`.

### 3. Installer les dépendances et hate_crack

Le moyen le plus simple est d'exécuter `make` (ou `make install`), qui détecte automatiquement votre système d'exploitation et installe :
- Les dépendances externes (p7zip, transmission-daemon / transmission-remote)
- Compile les sous-modules (hashcat-utils, princeprocessor, pcfg_cracker, et optionnellement omen) et récupère l'ensemble de masques Corporate_Masks (données uniquement)
- Les dépendances Python via uv et un shim CLI à `~/.local/bin/hate_crack````bash
make

Ceci est idempotent - il ignore les outils déjà installés. Pour forcer une réinstallation propre :```bash make reinstall

**Ou installer les dépendances manuellement :**

### Dépendances externes
Ces dépendances sont requises pour certains flux de téléchargement/extraction :

- `7z`/`7za` (p7zip) — utilisé pour extraire les archives `.7z`.
- `transmission-daemon` / `transmission-remote` — utilisé pour télécharger les torrents Weakpass.

Commandes d'installation manuelle :

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

Alors installez les dépendances Python et le 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

Structure du projet

La logique principale est désormais répartie en modules sous hate_crack/ :

  • hate_crack/cli.py : helpers argparse et remplacements de configuration.
  • hate_crack/api.py : intégrations Hashview, Weakpass et Hashmob (téléchargements/menus/helpers).
  • hate_crack/attacks.py : gestionnaires d'attaques du menu.
  • hate_crack/corpus_stats.py : statistiques de mots de passe sur l'ensemble du corpus, utilisées pour décrire un corpus au LLM.
  • hate_crack/plaintext.py : récupère le mot de passe depuis une ligne du corpus (suppression du préfixe de hash, décodage $HEX[...]) ; partagé par les modes LLM, corpus_stats et rulegen.
  • hate_crack/llm.py : génération structurée (JSON) de candidats LLM via Atomic Agents.
  • hate_crack/menu.py : moteur de rendu de menu partagé, avec navigation optionnelle par touches fléchées.
  • hate_crack/noninteractive.py : répartiteur pour les sous-commandes d'attaque scriptées.
  • hate_crack/notify/ : paquet de notifications (backend Pushover, suivi par crack).
  • hate_crack/username_detect.py : détecte les fichiers d'entrée username:hash pour décider de l'option --username de hashcat.
  • hate_crack/formatting.py, hate_crack/progress.py : helpers de formatage de sortie et d'affichage de progression.
  • hate_crack/main.py : implémentation principale du CLI.

Le fichier de premier niveau hate_crack.py reste le point d'entrée principal et orchestre ces modules.


Références et remerciements

Ce projet dépend de plusieurs projets et services externes et s'en inspire. Merci à :


Utilisation

Après installation avec make, exécutez hate_crack depuis n'importe où :```bash hate_crack

or with arguments:

hate_crack <hash_file> <hash_type> [options]

Alternativement, exécutez via `uv` :```bash
uv run hate_crack.py <hash_file> <hash_type>

Exécuter en tant qu’outil (recommandé)

Installez à l’aide de make depuis la racine du dépôt — cela compile les sous-modules et regroupe les ressources :```bash cd /path/to/hate_crack make hate_crack

La commande `make install` crée un shim bash à `~/.local/bin/hate_crack` qui s'exécute depuis le répertoire du dépôt, afin que la configuration et les ressources soient toujours trouvées quel que soit votre répertoire de travail actuel.

La configuration est également recherchée dans :
- La racine du dépôt et le répertoire du paquet
- `~/.hate_crack`

**Remarque :** Le `hcatPath` dans `config.json` sert uniquement à l'emplacement du binaire hashcat (facultatif si hashcat est dans le PATH). Les ressources de Hate_crack (hashcat-utils, princeprocessor, pcfg_cracker, Corporate_Masks, omen) sont chargées depuis le répertoire du dépôt et regroupées automatiquement par `make install`.

### Exécution en tant que script
Le script utilise un shebang `uv`. Rendez-le exécutable et exécutez-le :```bash
chmod +x hate_crack.py
./hate_crack.py

Vous pouvez également utiliser Python directement :```bash python hate_crack.py

### Utilisation non interactive / scriptée

Pour l'automatisation, vous pouvez lancer une seule attaque directement, en contournant le menu. Le nom de l'attaque est le premier argument, suivi du fichier de hachages et du type de hachage hashcat. Les invites de prétraitement (filtrage des comptes machines, force brute LM en premier, déduplication des comptes en double) acceptent automatiquement leurs valeurs par défaut dans ce mode. Le processus se termine avec le code `0` en cas de succès et un code non nul en cas d'erreur (fichier de hachages manquant, type de hachage non numérique, fichier de dictionnaire manquant ou nom de fichier de règles inconnu).```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

Dépannage

Erreur : « would clobber existing tag » lors de la mise à jour

Un ancien clone peut refuser de se mettre à jour, en affichant une longue liste de lignes comme :``` ! [rejected] v2.5.0 -> v2.5.0 (would clobber existing tag)

Cela concerne les clones créés avant juillet 2026. L'historique publié a été réécrit
à ce moment-là pour supprimer certains fichiers qui n'auraient jamais dû être commités, ce qui a
donné un nouvel ID à chaque commit ; les tags d'un clone plus ancien pointent donc vers des objets
que ce dépôt ne contient plus, et git refuse de déplacer un tag qu'il possède déjà.
Rien ne cloche dans votre checkout et aucune donnée de cracking n'est en danger.

Récupérez avec une réinitialisation unique. Cela supprime les commits locaux et les modifications dans le
checkout, donc si vous avez personnalisé quoi que ce soit suivi par git (par opposition à
`config.json`, qui n'est pas suivi), commitez-le d'abord sur une branche :```bash
cd /path/to/hate_crack
git fetch --tags --force origin
git checkout -B main origin/main
make install

--force ici ne met à jour que les tags ; il ne peut pas toucher à vos commits. Ensuite, le programme de mise à jour intégré fonctionne normalement. Les versions antérieures à 2.18 ne pouvaient pas effectuer cette récupération elles-mêmes, c'est pourquoi elle doit être faite manuellement une fois.

Erreur : le répertoire de build n'existe pas

Si vous voyez une erreur comme :``` Error: Build directory /opt/hashcat/hashcat-utils does not exist. Expected to find expander at /opt/hashcat/hashcat-utils/bin/expander.

Cela signifie que les ressources hate_crack n'ont pas été incluses dans le paquet installé.

**Comprendre les chemins :**
- `hcatPath` dans config.json → pointe vers **l'emplacement du binaire hashcat** (optionnel, peut être dans le PATH)
- `hashcat-utils/` et `princeprocessor/` → inclus dans le paquet via `make install`

**Solution :**
Réinstallez en utilisant le Makefile, qui compile les sous-modules et installe l'outil :```bash
cd /path/to/hate_crack  # the repository checkout
make install

Configuration par défaut (config.json.example) :

La plupart des utilisateurs peuvent utiliser les valeurs par défaut sans personnalisation :

  • hcatWordlists : ./wordlists (relatif à la racine du dépôt ou à HOME/.hate_crack)
  • hcatOptimizedWordlists : ./optimized_wordlists (répertoire utilisé par Quick Crack ; revient à hcatWordlists s'il n'est pas trouvé)
  • rules_directory : ./hashcat/rules (inclut les règles du sous-module)
  • hcatTuning : `` (chaîne vide - aucun indicateur de réglage par défaut)

Exemple de personnalisations 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) ... }

**Chargement de la configuration :**
- Priorité pour chaque clé : `os.environ` > le fichier personnel de cette clé (`.env` ou `config.json`) > la valeur par défaut intégrée
- Les clés manquantes reviennent aux valeurs par défaut intégrées ; `config.json.example` documente chaque clé de `config.json`
- Les deux fichiers sont recherchés, indépendamment l'un de l'autre, dans cet ordre : **racine du dépôt**, puis **répertoire du paquet installé**, puis **`~/.hate_crack`**. La première correspondance gagne ; il est normal que les deux fichiers proviennent de répertoires différents.
- Lors de la première exécution, les deux sont créés — `config.json` à partir de `config.json.example`, `.env` à partir des valeurs par défaut intégrées. Si un ancien `config.json` contient encore des clés d'intégration, elles sont copiées dans le nouveau `.env` et hate_crack vous indique lesquelles supprimer de `config.json` ; il ne modifie jamais ce fichier lui-même.
- À chaque exécution, hate_crack affiche les deux fichiers qu'il a réellement chargés :  ```
  [*] config.json: /home/you/.hate_crack/config.json
  [*] .env:        /home/you/.hate_crack/.env

Lisez ces deux lignes avant de déboguer un paramètre qui « ne prend pas effet ». Elles existent à cause de deux pièges dans l'ordre de recherche :

  • Un checkout prime sur votre répertoire personnel. La racine du dépôt est recherchée en premier, donc un .env ou config.json situé dans n'importe quel checkout depuis lequel vous exécutez l'outil l'emporte sur celui de ~/.hate_crack — et exécuter l'outil depuis un checkout est précisément ce qui crée ces fichiers là en premier lieu. Si cela masque un jour une vraie config ~/.hate_crack, hate_crack le signale désormais avec une troisième ligne [!] nommant les deux chemins — traitez cette ligne comme « le fichier ci-dessous est ignoré », et non comme une seconde config tout aussi valide.
  • Le répertoire de travail courant n'est jamais recherché. Un .env dans le répertoire où vous vous trouvez est ignoré, délibérément : les répertoires d'engagement sont pleins de fichiers que personne n'a destinés à être une configuration. Placez-le à la racine du dépôt ou dans ~/.hate_crack.

Erreur : merge avec la ref 'refs/heads/master' mais aucune ref de ce type n'a été récupérée

Si vous voyez :``` Your configuration specifies to merge with the ref 'refs/heads/master' from the remote, but no such ref was fetched.

La branche par défaut a été renommée de `master` à `main`. Corrigez avec :```bash
git remote set-head origin -a
git branch -m master main
git branch --set-upstream-to=origin/main main
git pull

Cibles Makefile

Par défaut (installation complète) - compile les sous-modules, installe les dépendances et installe l'outil :```bash make

or explicitly:

make install

Ceci est idempotent - il ignore les outils déjà installés.

**Réinstallation propre forcée :**```bash
make reinstall

Mise à jour rapide - reconstruit les sous-modules et réinstalle l'outil (après avoir récupéré les modifications) :```bash make update

**Désinstallation** - supprime les dépendances du système d'exploitation et l'outil :```bash
make uninstall

Compiler uniquement hashcat-utils :```bash make hashcat-utils

**Exécuter les tests** - gère automatiquement HATE_CRACK_SKIP_INIT lorsque nécessaire :```bash
make test

Rapport de couverture :```bash make coverage

**Nettoyer les artefacts de build/test :**```bash
make clean

Développement

Configuration de l'environnement de développement

Installez le projet avec les dépendances de développement optionnelles (inclut les linters et les outils de test) :```bash make dev-install

### Exécution des linters et vérifications de types

Avant de pousser des modifications, exécutez ces vérifications localement. Utilisez `make lint` pour tout, ou exécutez des vérifications individuelles :

**Ruff (linting et formatage) :**```bash
make ruff
# or manually:
uv run ruff check hate_crack tests tools packaging hate_crack.py

Auto-corriger les problèmes :```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 (vérification de type) :**```bash
make ty
# or manually:
uv run ty check hate_crack

Exécuter toutes les vérifications ensemble :```bash make lint

### Exécution des tests

Les tests détectent automatiquement lorsque les sous-modules ne sont pas compilés et définissent `HATE_CRACK_SKIP_INIT=1` automatiquement.```bash
make test

Or exécutez pytest directement :```bash uv run pytest -v

Avec la couverture :```bash
make coverage

Ou avec pytest :```bash uv run pytest --cov=hate_crack

### Hooks Git (prek)

Les hooks Git sont gérés par [prek](https://github.com/j178/prek) (v0.3.3+). Installez les hooks avec :```bash
prek install --hook-type pre-push --hook-type pre-commit

Cette installation configure les hooks définis dans prek.toml en utilisant le schéma TOML du dépôt local pre-commit :

  • pre-push (hooks locaux) : ruff, ruff-format, ty, pytest, pytest-lima, bandit
  • pre-commit (depuis pre-commit/pre-commit-hooks) : trailing-whitespace, end-of-file-fixer, check-yaml, check-merge-conflict, check-added-large-files, detect-private-key

Les auto-correcteurs pre-commit réécrivent les fichiers sur place, donc re-stagez et committez à nouveau après leur exécution.

Remarque : prek 0.3.3 attend repos = [...] au niveau supérieur. L'ancien format [hooks.<stage>] commands = [...] n'est pas pris en charge.

Les menus utilisent par défaut une sélection classique numérotée print() + input(), qui accepte les clés complètes à plusieurs chiffres.

Pour activer la navigation avec les flèches via simple-term-menu, définissez HATE_CRACK_ARROW_MENU=1. Dans ce mode, seules les touches de raccourci à un seul chiffre fonctionnent ; les options numérotées 10 et plus doivent être atteintes avec les flèches. Le mode flèches nécessite également un TTY, il reste donc désactivé lorsque la sortie est redirigée.

Dépendances de développement

Le groupe optionnel [dev] comprend :

  • ty - Vérificateur de types statique
  • ruff - Linter et formateur Python rapide
  • pytest - Framework de test
  • pytest-cov - Rapport de couverture

Options courantes :

  • --download-hashview : Télécharger les hashes depuis Hashview avant le cracking.
  • --hashview : Menu Hashview interactif pour gérer les hashes, les listes de mots et les tâches.
  • --hashview --help : Afficher les options en ligne de commande de Hashview.
  • --weakpass : Télécharger les listes de mots depuis Weakpass.
  • --hashmob : Télécharger les listes de mots depuis Hashmob.net.
  • --hashmob-masks : Télécharger les masques depuis Hashmob.net.
  • --download-torrent <FILENAME> : Télécharger un fichier torrent Weakpass spécifique.
  • --download-all-torrents : Télécharger tous les torrents Weakpass disponibles depuis le cache.
  • --wordlists-dir <PATH> / --optimized-wordlists-dir <PATH> : Remplacer les répertoires de listes de mots.
  • --pipal-path <PATH> : Remplacer le chemin de pipal.
  • --restore-potfile : Reconstruire <hashfile>.out à partir du fichier POT de hashcat au démarrage, en remplaçant tout contenu existant, puis continuer dans le menu normal. Sans ce drapeau, la recherche POT ne s'exécute que lorsque .out n'existe pas déjà. L'option de menu 93 fait la même chose à la demande, avec une invite de confirmation.
  • --maxruntime <SECONDS> : Remplacer la durée d'exécution maximale.
  • --bandrel-basewords <PATH> : Remplacer le fichier de mots de base bandrel.
  • --update : Mettre à jour vers la dernière version et réinstaller. Bascule le checkout sur main s'il est sur une autre branche, car les tags de version s'y trouvent.
  • --nightly : Mettre à jour vers la dernière version nightly à la place, depuis la branche nightly-dev. Les nightly ont passé la CI mais ne font pas partie d'une version publiée. Peut également s'écrire --update --nightly.
  • --no-optimized-kernel (ou --no-optimize) : Ne jamais passer -O à hashcat pour toute l'exécution. Remplace optimizedKernelAttacks dans config.json et supprime tout -O que vous avez placé dans hcatTuning. Rien n'est réécrit dans la configuration, cela s'applique donc uniquement à cette exécution. Avec une sous-commande, placez-le avant la sous-commande : ./hate_crack.py --no-optimize quick hashes.txt 1000 --wordlist words.txt.
  • --debug : Activer la journalisation de débogage (écrit sur stderr).

Intégration Hashview

hate_crack s'intègre à Hashview pour la gestion centralisée des hashes et le cracking distribué.

Accéder au menu interactif Hashview :```bash hate_crack.py --hashview

Options du menu :
- **(1) Téléverser les hashes crackés** - Téléverse les résultats crackés de la session en cours vers Hashview
- **(2) Téléverser une wordlist** - Téléverse un fichier de wordlist vers Hashview
- **(3) Télécharger une wordlist** - Télécharge une wordlist depuis Hashview
- **Télécharger une règle** - Télécharge un fichier de règle depuis Hashview (décompressé en texte brut, prêt pour `hashcat -r`)
- **Télécharger toutes les règles** - Télécharge tous les fichiers de règles listés par Hashview en une seule passe ; les échecs par règle sont signalés sans interrompre le reste
- **(4) Télécharger les hashes restants** - Télécharge les hashes non crackés restants (invite à basculer pour le cracking)
- **(5) Télécharger les hashes trouvés** - Télécharge les hashes déjà crackés avec les mots de passe en clair (pour référence/analyse)
- **(6) Téléverser un fichier de hashes et créer un job** - Téléverse un nouveau fichier de hashes et crée un job de cracking
- **(99) Retour au menu principal** - Retourne au menu principal

**Important : Télécharger les hashes trouvés vs Télécharger les hashes restants**
- **Télécharger les hashes restants (4)** : Télécharge les hashes non crackés qui nécessitent un cracking. Fusionne automatiquement avec les hashes trouvés si disponibles, et invite à basculer vers ce fichier de hashes pour le cracking.
- **Télécharger les hashes trouvés (5)** : Télécharge les hashes déjà crackés au format hash:texte-clair. Ceux-ci servent de référence et ne peuvent plus être crackés. Aucune invite de bascule n'est affichée.

#### Interface en ligne de commande

Les opérations Hashview peuvent également être effectuées via la ligne de commande :

Téléverser les hashes crackés :```bash
hate_crack.py --hashview upload-cracked --file <output_file>.out --hash-type 1000

Téléchargez une liste de mots :```bash hate_crack.py --hashview upload-wordlist --file .txt --name "My Wordlist"

Téléchargez un fichier de règles (enregistré décompressé, prêt pour `hashcat -r`) :```bash
hate_crack.py --hashview download-rules --rules-id 4 --output best64.rule

Télécharger les hashes restants (hashes non craqués pour le cracking) :```bash hate_crack.py --hashview download-left --customer-id 1 --hashfile-id 123

Télécharger les hashs trouvés (hashs déjà cassés avec texte en clair) :```bash
hate_crack.py --hashview download-found --customer-id 1 --hashfile-id 123

Upload hashfile and create 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"

#### Configuration

Définissez les identifiants Hashview dans `.env` (il s'agit de paramètres d'intégration, ils ne figurent donc pas dans `config.json`) :```
HASHVIEW_URL=https://hashview.example.com
HASHVIEW_API_KEY=your-api-key-here

Configuration du LLM

L'attaque par LLM (option 12) et l'attaque par masque Rosetta (option 23) génèrent leurs candidats avec un modèle local. Configurez le modèle, la fenêtre de contexte et le délai d'expiration des requêtes dans .env :``` LLM_BACKEND=ollama OLLAMA_MODEL=qwen3:4b-instruct OLLAMA_NUM_CTX=8192 OLLAMA_TIMEOUT=300

**Les clés `OLLAMA_*` ci-dessous s'appliquent à tous les backends, pas seulement à Ollama.** Elles conservent ce préfixe car `OLLAMA_HOST` est la même variable que lit le propre CLI d'Ollama, et les renommer casserait tous les `.env` existants sans gain fonctionnel — un serveur vLLM ou compatible OpenAI veut les mêmes réglages d'hôte, de modèle, de délai d'attente, de contexte et d'échantillonnage sous les mêmes noms. `LLM_BACKEND` ne sélectionne que la manière dont la requête est façonnée.

- **`OLLAMA_MODEL`** — Le modèle Ollama utilisé pour la génération de candidats (défaut : `qwen3:4b-instruct`). L'attaque LLM utilise une sortie structurée (JSON), choisissez donc un modèle avec un bon support des outils/JSON.
- **`OLLAMA_NUM_CTX`** — Taille de la fenêtre de contexte pour le modèle (défaut : `8192`). Elle était de `2048` avant l'introduction des statistiques de corpus, ce qui était trop petit pour contenir l'invite fournie : 500 textes clairs échantillonnés représentent environ 2 000 à 3 500 jetons avant l'invite système et la réponse, donc Ollama tronquait silencieusement une partie de l'échantillon que l'échantillonneur avait soigneusement réparti dans le fichier.
- **`OLLAMA_TIMEOUT`** — Secondes d'attente d'une réponse de génération avant d'abandonner (défaut : `300`). Augmentez cette valeur si un gros modèle est encore en cours de chargement en VRAM lors de la première requête, ce qui peut sinon dépasser le délai ; hate_crack affiche le délai écoulé et le nom de ce réglage lorsqu'il se déclenche.
- **`OLLAMA_MAX_SAMPLE_LINES`** — Le seuil en dessous duquel les modes LLM collent également les textes clairs littéraux dans l'invite (défaut : `500`). Les valeurs ≤ 0 sont traitées comme 500.

  Les modes dérivés du corpus (**Wordlist**, **Mots de passe craqués**, **Règles de motifs**) décrivent toujours statistiquement l'*ensemble* du corpus — parts de mots de base, masques, casse, longueurs, chiffres et symboles finaux, années — plutôt que d'y coller une tranche. L'agrégation est bornée, donc un dump de 120 000 mots de passe coûte à peu près le même espace d'invite qu'un fichier de 500 lignes. Lorsque l'ensemble du corpus tient sous ce seuil, les textes clairs bruts sont également inclus, car rien n'est gagné à cacher un petit corpus au modèle.

  Cela remplace le comportement précédent qui collait un échantillon espacé uniformément de jusqu'à `ollamaMaxSampleLines` mots de passe. Un échantillon d'un gros dump ne transmettait aucune information de fréquence : le modèle ne pouvait pas distinguer un mot de base utilisé par 8 % de l'organisation de celui utilisé par une seule personne, ce qui est précisément le signal qui rend une supposition digne d'être exécutée.
- **`OLLAMA_NO_CLOUD`** — Lorsqu'il est `true`, refuse d'envoyer quoi que ce soit hors de cet hôte, pour l'un des trois backends LLM (Ollama, vLLM ou un serveur générique compatible OpenAI). Deux vérifications sont contrôlées par ce seul réglage : Ollama proxifie un modèle balisé `-cloud` (`gpt-oss:120b-cloud`, `deepseek-v3.1:671b-cloud`) vers ollama.com via le même point de terminaison local qu'un modèle local, donc rien dans la requête ne semble différent — cela est refusé par nom de modèle. L'URL du backend configuré est également vérifiée : une destination qui n'est ni loopback, ni privée, ni link-local (et qui n'est pas `localhost` ni un nom `.local`/`.internal`/`.lan`/`.localdomain`) est refusée par destination, et un nom d'hôte que cette vérification ne peut pas résoudre est également refusé, en mode fail-closed, plutôt que de laisser passer une destination invérifiable. Les invites de hate_crack transportent des textes clairs récupérés, des statistiques de corpus, ainsi que le nom, le secteur et la localisation du client, donc si l'une ou l'autre vérification se déclenche, la requête est refusée avant d'être construite. Par défaut `false`, donc un modèle cloud ou un serveur distant délibérément configuré continue de fonctionner ; activez-le pour les engagements où les données client ne doivent pas quitter l'hôte.
- **`OLLAMA_AUTO_RESEARCH`** — Lorsqu'il est `true` (défaut), le mode **Infos cible** demande au modèle local de suggérer le secteur, la localisation et la société mère / l'historique d'acquisitions dès que vous avez tapé le nom de l'entreprise, et les propose comme valeurs par défaut modifiables des invites. Réglez-le sur `false` pour toujours obtenir des invites vides (utile avec un modèle lent, car la recherche coûte un aller-retour supplémentaire avant le début de l'attaque).
- **`OLLAMA_HOST`** — Où le backend configuré écoute. Accepte un simple `hôte:port` (`theplague.lan:11434`) ou une URL complète avec un schéma (`https://ollama.example.com`) ; dans les deux cas, l'URL de base est normalisée avant utilisation. Par défaut `localhost:11434`, qui est le port d'Ollama — un serveur vLLM ou compatible OpenAI doit définir cela sur son propre port (vLLM écoute couramment sur `:8000`). Définissez-le dans `.env`, ou exportez-le comme une vraie variable d'environnement pour le remplacer pour une seule exécution — c'est le même nom de variable que lit le propre CLI d'Ollama.
- **`LLM_BACKEND`** — À quel serveur compatible OpenAI parler : `ollama` (défaut), `vllm`, ou `openai` pour un serveur générique. Chaque backend parle la même API de complétions de chat `/v1`, donc cela ne sélectionne que les deux détails de façonnage de requête sur lesquels ils diffèrent : `ollama` reçoit `options.num_ctx`, et `vllm` reçoit `chat_template_kwargs={"thinking": false}` — sans quoi un serveur vLLM exécutant un analyseur de raisonnement route toute la réponse structurée dans `message.reasoning`, laisse `message.content` vide et casse l'analyse JSON. `openai` n'envoie ni l'un ni l'autre, car `num_ctx` n'a pas d'équivalent là-bas. Cela ne change **pas** d'où proviennent les réglages d'hôte, de modèle, de délai, de contexte ou d'échantillonnage — ce sont les clés `OLLAMA_*` ci-dessus pour les trois.
- **`LLM_API_KEY`** — La référence envoyée au backend configuré. Par défaut, le littéral `ollama`, le placeholder qu'ignore le propre serveur d'Ollama, donc les requêtes d'une installation existante restent inchangées ; une valeur vide retombe sur ce même placeholder car le SDK OpenAI refuse `api_key=""`. Définissez-la sur la valeur réelle si le serveur en impose une — un serveur vLLM démarré avec `--api-key` renvoie sinon une erreur 401.
- Assurez-vous qu'Ollama est en cours d'exécution et que le modèle est téléchargé (`ollama pull qwen3:4b-instruct`) avant d'utiliser l'attaque LLM — hate_crack ne télécharge plus automatiquement les modèles manquants.

L'attaque propose trois modes de génération :

1. **Infos cible** — entreprise / secteur / localisation / société mère ; le modèle dérive des candidats à partir de ces détails.

   Après avoir tapé le nom de l'entreprise, hate_crack demande au même modèle local ce qu'il sait déjà de cette organisation et pré-remplit les invites **Secteur**, **Localisation** et **Société mère** avec les réponses, affichées entre parenthèses :   ```
   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:

Appuyez sur Entrée pour accepter une suggestion ou saisissez par-dessus. Ces valeurs sont la réminiscence du modèle, pas de l'OSINT — traitez-les comme un point de départ, pas comme des renseignements sur le client. La recherche n'utilise que le serveur Ollama local, donc le nom du client ne quitte jamais l'hôte ; aucun appel web ou API tiers n'est effectué. Si le modèle ne reconnaît pas l'organisation (cas courant pour les petits clients), il ne renvoie rien et vous obtenez des invites vides et simples : ``` Company name: Acme Rail Services Industry: Location: Parent company / acquired by:

Un échec de recherche — délai dépassé, Ollama non démarré, réponse vide — ne bloque jamais l'attaque ; il retombe simplement sur des invites vides. Définissez `ollamaAutoResearch` sur `false` pour ignorer entièrement la recherche.
2. **Wordlist** — dériver les mots de base à partir d'une wordlist d'exemple.
3. **Mots de passe craqués** — renvoyer les textes en clair déjà récupérés lors de cette session (`<hashfile>.out`) au modèle afin qu'il puisse déduire les conventions de mots de passe propres à l'organisation cible (mots de base, saisons, années, suffixes, leetspeak) et générer de *nouveaux* candidats dans le même style. Cette option n'est listée qu'une fois qu'au moins un hash a été craqué ; le fichier entier est analysé statistiquement exactement comme en mode Wordlist (voir `ollamaMaxSampleLines` ci-dessus).

#### Configuration PCFG

L'attaque PCFG (option 20) et l'attaque PRINCE-LING (option 21) utilisent le sous-module `pcfg_cracker`. Configurez-les dans `config.json` :```json
{
"pcfgRuleset": "DEFAULT",
"pcfgMaxCandidates": 50000000,
"pcfgPrinceLingMaxCandidates": 10000000
}
  • pcfgRuleset — Nom de la grammaire entraînée à utiliser (par défaut : DEFAULT), résolu en pcfg_cracker/Rules/<name>/. Entraînez la vôtre avec trainer.py de pcfg_cracker et définissez ce paramètre sur le nom du ruleset.
  • pcfgMaxCandidates — Nombre maximal de candidats que pcfg_guesser.py émet pour l’attaque PCFG (par défaut : 50000000).
  • pcfgPrinceLingMaxCandidates — Nombre maximal de mots de base que prince_ling.py écrit dans la wordlist PRINCE en cache (par défaut : 10000000).

Noyaux optimisés (optimizedKernelAttacks)

Le drapeau -O de hashcat sélectionne les noyaux optimisés, nettement plus rapides mais qui plafonnent la longueur des candidats (environ 31 caractères, moins pour certains modes) et ignorent silencieusement tout ce qui est plus long. optimizedKernelAttacks dans config.json liste les attaques qui s’exécutent avec -O ; omettez une attaque de la liste pour l’exécuter avec des noyaux pleine longueur. La liste dans config.json.example correspond au défaut intégré appliqué lorsqu’aucun config.json n’existe.

Quatre attaques respectent ce paramètre mais ne sont pas optimisées par défaut, car elles alimentent des candidats pouvant dépasser le plafond de -O — ajoutez-les à la liste pour y adhérer :

  • hcatNgramX, hcatOllama, hcatOmen, hcatLMtoNT

Pour désactiver -O partout pour une seule exécution sans modifier la config, passez --no-optimized-kernel (forme courte --no-optimize). Cela remplace la liste pour chaque attaque et supprime également un -O écrit dans hcatTuning, qui atteindrait sinon hashcat indépendamment de la liste.

Les noms sont comparés exactement, et une entrée non reconnue est signalée au démarrage plutôt qu’ignorée. Notez que les attaques qui délèguent à une autre attaque sont contrôlées par l’attaque à laquelle elles délèguent, et non par leur propre nom : PRINCE-LING suit hcatPrince, tandis que Spoonman, Rosetta et les modes de règles de motifs LLM suivent hcatQuickDictionary.

Suivi de la couverture des attaques (coverage_enabled)

Au cours d’un engagement long, le même fichier de hash est attaqué dans de nombreuses sessions avec un ensemble tournant de wordlists, de fichiers de règles et de listes de masques, et il est facile de brûler des heures à re-exécuter un terrain déjà couvert — surtout puisque la même ligne de règle vit dans plus d’un fichier de règles. hate_crack enregistre ce qu’il a déjà exécuté contre chaque fichier de hash et propose de sauter le chevauchement.

La couverture est enregistrée par entrée, pas par fichier : des lignes de règles individuelles et des lignes .hcmask individuelles, chacune associée à la wordlist contre laquelle elle a été exécutée. C’est ce qui lui permet de reconnaître qu’un fichier de règles personnalisé que vous exécutez aujourd’hui répète 40 des règles que best64.rule a déjà couvertes la semaine dernière, et c’est aussi pourquoi une règle n’est « couverte » que pour la wordlist spécifique avec laquelle elle a été essayée — les mêmes règles sur un corpus différent essaient des candidats entièrement différents.

Le fichier de hash est identifié par un sha256 de son contenu, donc la couverture survit au renommage ou au déplacement entre sessions. Les wordlists sont identifiées de la même manière, avec le digest mémorisé en fonction de la taille et de la mtime afin qu’un corpus de plusieurs gigaoctets soit haché une seule fois plutôt qu’à chaque attaque.

Vous n’êtes invité que lorsqu’il y a réellement quelque chose à sauter :``` [*] 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]:

Répondez `Y` et hate_crack construit un fichier de règles temporaire contenant uniquement les entrées non encore testées ; répondez `n` pour exécuter l’ensemble quand même. Si *toutes* les entrées sont des doublons, il vous est demandé si vous souhaitez ignorer complètement l’attaque, afin que relancer délibérément un terrain déjà couvert ne nécessite jamais de redémarrer l’outil.

Les attaques qui ne sont jamais filtrées sont tout de même enregistrées comme ayant été exécutées, ce qui vous permet de répondre à la question « ai-je déjà lancé PRINCE contre cette cible ? ».

Une attaque qui sélectionne plusieurs fichiers de règles à la fois (Quick Crack, Loopback) pose la question de l’ignorance **une seule fois pour tout le lot, au préalable**, avant toute invocation de hashcat. Cette question est volontairement légère — elle ne lit ni ne hache aucun des fichiers de règles sélectionnés, car un lot YOLO peut atteindre des millions de lignes et vous ne devriez pas attendre tout cela pour répondre à un oui/non. Elle demande uniquement au registre si cette attaque a déjà été exécutée contre ce fichier de hachages **avec l’une de ces listes de mots** ; la comparaison entrée par entrée reste différée, un fichier de règles à la fois, et décide de ce qui est réellement ignoré. Ainsi, un corpus neuf n’est jamais signalé, même lorsque les règles qui lui sont appliquées ont toutes été exécutées contre un autre.

Trois limites délibérées :

- **La couverture n’est enregistrée que lorsque hashcat épuise l’espace de clés** (code de sortie 1). Un ctrl-C ou une erreur n’enregistre rien, et le code de sortie 0 non plus — cela signifie que tous les hachages ont été cassés, ce que hashcat rapporte *sans* terminer l’espace de clés, et dans le cas dégénéré « tous les hachages trouvés comme entrées de potfile » sans essayer un seul candidat. Une sous-enregistrement ne coûte qu’une exécution redondante plus tard.
- **Les générateurs de candidats dynamiques ne sont jamais filtrés.** PRINCE, PCFG, OMEN, la force brute de Markov et les modes LLM n’ont pas d’ensemble fixe à comparer, ils sont donc enregistrés comme ayant été exécutés et sinon laissés tranquilles. Les fichiers de règles chaînés (`-r a -r b`) sont suivis comme une unité unique plutôt que par entrée, car hashcat applique le *produit cartésien* des deux fichiers et supprimer une ligne individuelle retirerait silencieusement chaque combinaison à laquelle elle participait.
- **Les exécutions `--loopback` sont enregistrées mais jamais filtrées.** hashcat réinjecte les textes clairs fraîchement cassés comme candidats *supplémentaires*, donc une telle exécution essaie la liste de mots et l’ensemble de règles complets plus tout ce que ces textes clairs recyclés atteignent. Cela rend les deux directions asymétriques : l’enregistrer est fiable, donc une exécution ordinaire ultérieure de la même liste de mots et des mêmes règles est correctement reconnue comme un doublon, mais une seconde exécution en boucle a davantage de cassures à recycler et n’est jamais ignorée.

Définissez `coverage_enabled` sur `false` dans `config.json` pour désactiver cela, ou passez `--no-coverage` pour une seule exécution — qui ne consulte ni ne met à jour le registre.

#### Inspection et réinitialisation de la couverture

L’option **85 — Attack Coverage** du menu principal affiche ce qui a été exécuté contre le fichier de hachages chargé, son historique d’exécution, et peut l’effacer. Les trois mêmes actions sont scriptables :```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

Le fichier de hachage est identifié par son contenu, ces opérations fonctionnent donc quel que soit l'endroit où il a été déplacé depuis. forget n'affecte que cette seule cible — le stockage se trouve dans ~/.hate_crack/coverage/attack_coverage.sqlite3, et la suppression du fichier réinitialise la couverture pour toutes les cibles.

Exécutions scriptées

Une attaque scriptée que la couverture ignore entièrement se termine toujours avec le code 0 par défaut, donc activer la couverture ne peut pas faire échouer un harnais existant. Passez --exit-code-on-skip pour obtenir le code de sortie 3 à la place lorsque rien n'a été lancé :```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 signifie que *rien* n'a été exécuté. Une passe partiellement filtrée — certaines entrées ignorées, d'autres tentées — se termine toujours avec le code `0`, car l'attaque a bien effectué du travail.

### Notifications (option de menu 82)

hate_crack peut envoyer des notifications push Pushover lorsque les attaques se terminent et, éventuellement, lorsque des hashes individuels sont craqués. Tous les contrôles se trouvent sous l'option `82 — Notifications` du menu principal :

1. **Activer/Désactiver les notifications Pushover [ON/OFF]** — interrupteur principal. Persiste dans `config.json` sous `notify_enabled`.
2. **Activer/Désactiver les notifications par crack [ON/OFF]** — lorsqu'activé, un tailer en arrière-plan surveille le fichier `.out` et pousse une notification par crack (avec agrégation par rafales par tick). Persiste dans `config.json` sous `notify_per_crack_enabled`. Ne peut pas être activé tant que l'interrupteur principal est désactivé — activez d'abord l'option 1.
3. **Envoyer une notification Pushover de test** — déclenche une notification prédéfinie pour confirmer que votre paire token/utilisateur Pushover fonctionne. Fonctionne même lorsque l'interrupteur principal est désactivé.

Les identifiants se trouvent dans `.env` ; les autres paramètres de réglage sont uniquement dans le fichier de configuration `config.json` :

- `NOTIFY_PUSHOVER_TOKEN`, `NOTIFY_PUSHOVER_USER` (dans `.env`) — requis pour que toute notification soit envoyée. Rien dans le menu ne les écrit ; modifiez `.env` vous-même.
- `notify_attack_allowlist` — noms d'attaques qui consentent automatiquement sans l'invite `[y/N/always]`. Rempli automatiquement lorsque vous répondez `always`.
- `notify_suppress_in_orchestrators` (par défaut `true`) — masque les attaques individuelles enchaînées par Extensive Crack, qui déclenche plutôt un résumé unique. Mettez `false` pour recevoir une notification par attaque enchaînée. Les autres entrées de menu qui exécutent plusieurs passes (par exemple Quick Crack avec plusieurs chaînes de règles) ne sont pas des orchestrators et notifient toujours par passe.
- `notify_max_cracks_per_burst` (par défaut `5`), `notify_poll_interval_seconds` (par défaut `5.0`) — réglage du tailer par crack. Voir `hate_crack/notify/tailer.py` pour la logique d'agrégation par rafales.

### Outils de listes de mots (option de menu 80)

Le sous-menu Outils de listes de mots fournit des utilitaires de prétraitement de listes de mots basés sur les binaires hashcat-utils, ainsi que des téléchargements de listes de mots depuis Hashmob.net et Weakpass. Accès via l'option **80** du menu principal.

| Option | Binaire | Fonction |
|--------|---------|----------|
| 1 | `len.bin` | Filtrer par longueur — conserver uniquement les mots entre une longueur minimale et maximale |
| 2 | `req-include.bin` | Exiger des classes de caractères — conserver uniquement les mots contenant tous les types de caractères requis |
| 3 | `req-exclude.bin` | Exclure des classes de caractères — supprimer les mots contenant tout type de caractère exclu |
| 4 | `cutb.bin` | Extraire une sous-chaîne — découper une plage d'octets de chaque mot |
| 5 | `splitlen.bin` | Diviser par longueur — créer des fichiers séparés par longueur de mot (fichiers nommés `01`-`64` dans un répertoire de sortie) |
| 6 | `rli.bin` / `rli2.bin` | Soustraire des mots — supprimer les entrées présentes dans un ou plusieurs autres fichiers |
| 7 | `gate.bin` | Fragmenter — extraire chaque N-ième mot pour un craquage distribué sur plusieurs machines |
| 8 | - | Optimiser les listes de mots — dédupliquer et diviser en fichiers par longueur sous le répertoire des listes optimisées |
| 9 | - | Télécharger des listes de mots depuis Hashmob.net |
| 10 | - | Télécharger des listes de mots depuis Weakpass (via BitTorrent) |

**Bits de masque de classes de caractères** (utilisés par les options 2 et 3) : `1`=minuscules, `2`=majuscules, `4`=chiffres, `8`=symboles, `16`=autres. Additionnez les valeurs : `7` = minuscules+majuscules+chiffres.

**Comment la fragmentation est censée être utilisée** : la fragmentation divise une liste de mots en N parties égales et non chevauchantes afin que le travail puisse être réparti sur plusieurs machines ou GPU. Chaque partie est *entrelacée* (chaque N-ième ligne), donc chaque fragment est un échantillon représentatif de l'ensemble de la liste plutôt qu'un bloc contigu début/fin — aucun nœud n'est bloqué à craquer uniquement la queue à faible probabilité.

Exécutez l'option 7 une fois, fournissez une liste de mots d'entrée, un chemin de base de sortie et un nombre de fragments (N). Elle écrit toutes les N parties en une seule passe, nommées avec des numéros de partie à zéros de remplissage (`base.001`, `base.002`, … jusqu'à `base.00N`). Copiez une partie sur chaque nœud et pointez l'exécution hashcat de ce nœud dessus. Sur un système à GPU unique, la fragmentation n'apporte aucun gain de vitesse, mais une seule partie reste un échantillon rapide et représentatif pour une passe de triage rapide avant de s'engager sur la liste complète.

#### Vérifications automatiques de mises à jour

hate_crack peut automatiquement vérifier sur GitHub les nouvelles versions au démarrage. Cette fonctionnalité est contrôlée par l'option de configuration `check_for_updates` :```json
{
  "check_for_updates": true
}
  • check_for_updates — Active les vérifications automatiques de version au démarrage (par défaut : true).
  • Lorsque cette option est activée, hate_crack récupère les dernières informations de version depuis GitHub et affiche un avis si une mise à jour est disponible.
  • La vérification s'exécute de manière asynchrone et ne bloque pas le démarrage. Les erreurs réseau sont ignorées silencieusement.
Canaux de mise à jour
CanalOptionSourceCe que vous obtenez
Release--updatemainLa dernière version publiée. C'est le canal par défaut et celui proposé par la vérification au démarrage.
Nightly--nightlynightly-devLe travail qui a passé la CI mais qui n'a pas encore été publié.

Les versions suivent le semver classique, avec l'incrément dérivé de ce qui se trouve réellement dans le lot. Le deuxième composant évolue uniquement pour les fonctionnalités : un cycle contenant un commit feat se dirige vers X.(Y+1).0, et un cycle composé uniquement de correctifs, de documentation et de tâches ménagères se dirige vers X.Y.(Z+1).

nightly-dev étiquette les candidats à la publication pour la version vers laquelle le lot se dirige — v2.20.1rc1, v2.20.1rc2, … — et la fusion vers main promeut cette même cible vers sa version finale. Les candidats sont de véritables pré-versions PEP 440, ils se classent donc correctement aux deux extrémités :

2.20.0  <  2.20.1rc1  <  2.20.1rc2  <  2.20.1  <  2.21.0rc1  <  2.21.0

La cible peut changer en cours de cycle : le premier feat qui arrive la fait passer de X.Y.(Z+1) à X.(Y+1).0, et la numérotation des candidats redémarre pour la nouvelle cible. Le numéro désigne toujours ce que le lot publierait aujourd'hui.

Le composant majeur n'est jamais incrémenté automatiquement — un sujet avec ! ou un pied de page BREAKING CHANGE: compte comme une fonctionnalité, car une version majeure automatique n'est qu'une ligne de sujet mal saisie loin d'une publication irréversible. Une version majeure est un acte humain explicite : étiquetez-la et poussez-la à la main.

La politique se trouve dans tools/next_version.py, partagée par les deux workflows d'étiquetage et testée unitairement dans tests/test_next_version.py.

La vérification au démarrage ne propose jamais que des versions publiées, car les builds nightly ne publient aucune version GitHub et la vérification lit le point de terminaison « latest release » de GitHub — activer check_for_updates ne vous fera donc jamais passer sur une nightly. Deux éléments maintiennent les canaux séparés : cela, et le fait qu'un candidat est une véritable pré-version PEP 440, donc un outil classant les numéros de version bruts le traite également comme plus ancien que la version qu'il devient.

Chacune des deux options bascule d'abord votre copie de travail vers la branche correspondante (et refuse de le faire si vous avez des modifications non validées). Si vous exécutez une nightly et souhaitez revenir au code publié, --update vous ramène sur main.

Fusion automatique des hash trouvés (téléchargement de gauche uniquement)

Lors du téléchargement des hash de gauche (hash non crackés), hate_crack automatiquement :

  1. Tente de télécharger les hash trouvés (crackés) depuis Hashview en tant qu'opération auxiliaire
  2. Fusionne les hash trouvés avec les fichiers .out locaux (par exemple, left_1_123.txt.out ou left_1_123.nt.txt.out pour le format pwdump)
  3. Supprime les entrées en double
  4. Nettoie les fichiers temporaires de découpage après la fusion

Cela garantit que vos résultats de cracking locaux restent synchronisés avec la base de données centralisée de Hashview lorsque vous travaillez avec des hash non crackés.

Remarque : L'option de téléchargement des hash trouvés télécharge séparément les hash déjà crackés à des fins de référence et n'effectue aucune fusion ni invite de cracking.

Le <hash_type> est obtenu en exécutant hashcat --help

Exemples de hash : 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

📦 Installation

Option 1: Install via pip

pip install kitploit-tool

Option 2: Install from source

git clone https://github.com/example/kitploit-tool.git
cd kitploit-tool
pip install -r requirements.txt
python setup.py install

Option 3: Use Docker

docker pull kitploit/tool:latest
docker run -it --rm kitploit/tool:latest

🚀 Quick Start

After installation, you can start using the tool immediately:

kitploit-tool --help

To run a basic scan:

kitploit-tool scan --target example.com

⚙️ Configuration

The tool reads its configuration from ~/.kitploit/config.yaml. You can generate a default configuration file with:

kitploit-tool init

Example configuration:

target: example.com
threads: 10
timeout: 30
output: results.txt
verbose: false

🛠️ Usage Examples

Basic scan

kitploit-tool scan --target example.com --output results.txt

Advanced scan with custom options

kitploit-tool scan --target example.com --threads 20 --timeout 60 --verbose

Export results in different formats

kitploit-tool scan --target example.com --format json
kitploit-tool scan --target example.com --format csv

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

$ ./hate_crack.py <hash file> 1000

  ___ ___         __             _________                       __
 /   |   \_____ _/  |_  ____     \_   ___ \____________    ____ |  | __
/    ~    \__  \\   __\/ __ \    /    \  \/\_  __ \__  \ _/ ___\|  |/ /
\    Y    // __ \|  | \  ___/    \     \____|  | \// __ \\  \___|    <
 \___|_  /(____  /__|  \___  >____\______  /|__|  (____  /\___  >__|_ \
       \/      \/          \/_____/      \/            \/     \/     \/
                          Version 2.0
```
## Tests

La suite de tests est principalement hors ligne et utilise des mocks/fixtures. Les vérifications réseau en direct et les vérifications des dépendances système sont facultatives via des variables d'environnement.

### Exécution des tests localement```bash
# Run all tests
uv run pytest -v

# Run specific test
uv run pytest tests/test_hashview.py -v
```
Vous pouvez également exécuter la suite complète avec `make test`.

### Tests en direct (adhésion facultative)

Définissez l'une des variables suivantes pour activer les vérifications en direct :

- `HASHMOB_TEST_REAL=1` — vérification en direct de la connectivité Hashmob/menu CLI
- `HASHVIEW_TEST_REAL=1` — vérification en direct du menu CLI Hashview
- `WEAKPASS_TEST_REAL=1` — vérification en direct du menu CLI Weakpass
- `HATE_CRACK_REQUIRE_DEPS=1` — échoue si `7z`, `transmission-daemon` ou `transmission-remote` est manquant

### Test de téléversement Hashview en direct

Le test de téléversement Hashview en direct est ignoré par défaut. Pour l'exécuter, définissez la
variable d'environnement et fournissez des identifiants valides dans `.env` :```bash
HATE_CRACK_RUN_LIVE_TESTS=1 uv run pytest tests/test_upload_cracked_hashes.py -v
```
### Tests Live de Hashview Contre une Pile Docker Locale

Au lieu de pointer les tests live vers un serveur Hashview distant, vous pouvez
faire en sorte que la suite démarre une pile Docker locale
[Hashview](https://github.com/hashview/hashview), la prépare, exécute les tests
live contre elle, puis la démonte. Définissez
`HASHVIEW_TEST_LOCAL=1` et pointez `HASHVIEW_REPO` vers un checkout de 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
```
Cela lance `docker compose` dans le dépôt Hashview, initialise une clé API admin,
un client, un fichier de hash et des données de « tâches efficaces » crackées, puis exporte
les variables d'environnement `HASHVIEW_*` que les tests lisent. Variables d'environnement utiles :

- `HASHVIEW_TEST_LOCAL=1` — active la pile locale (sans effet sinon)
- `HASHVIEW_REPO=<chemin>` — checkout Hashview (par défaut `~/projects/hashview`)
- `HASHVIEW_KEEP=1` — laisse les conteneurs tourner après la session (relances plus rapides)
- `HASHVIEW_LOCAL_PORT=5000` — port hôte sur lequel l'application est publiée

Le CLI hate_crack respecte les variables d'environnement `HASHVIEW_URL` / `HASHVIEW_API_KEY`
(remplaçant le `.env` dans lequel ces deux clés se trouvent), ce qui permet à la
suite de pointer le CLI vers la pile locale sans modifier votre configuration persistée.

### Tests d'installation de bout en bout (local + Docker)

Installation locale de l'outil uv + exécution du script (utilise un HOME temporaire) :```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
```
Le test E2E Docker télécharge également un petit sous-ensemble de rockyou et exécute un
crack hashcat de base pour valider l’intégration des outils externes.

Test de bout en bout de la machine virtuelle Lima (macOS uniquement) :

Prérequis : [Lima](https://lima-vm.io/) et `rsync` doivent être installés.```bash
brew install lima
```
The test VM provisions automatically with all Linux dependencies (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
```
Ce test valide l’installation et l’exécution dans une VM Linux légère sur macOS.

### Structure du test

- **tests/test_hashview.py** : Suite de tests complète pour la classe HashviewAPI avec des réponses API simulées, incluant :
  - Liste des clients et validation des données
  - Tests d’authentification et d’autorisation
  - Fonctionnalité de téléversement de fichiers de hachage
  - Workflow complet de création de tâches

Tous les tests utilisent des appels API simulés, ils peuvent donc être exécutés sans connexion à un serveur Hashview.

-------------------------------------------------------------------

  (1) Crack rapide
  (2) Crack méthodologique Pure_Hate étendu
  (3) Attaque par force brute
  (4) Attaque par masque Top
  (5) Attaque par empreinte
  (6) Attaques par combinateur
  (7) Attaque hybride
  (8) Crack par force brute avec masque Pathwell Top 100
  (9) Attaque PRINCE
  (10) Méthodologie Bandrel
  (11) Attaque en boucle
  (12) Attaque LLM
  (13) Attaque OMEN
  (14) Attaque par masque ad hoc
  (15) Attaque par force brute Markov
  (16) Attaque par n-grammes
  (17) Attaque par permutation
  (18) Attaque par règles aléatoires
  (19) Attaque par phrase de passe Combipow
  (20) Attaque PCFG
  (21) Attaque PRINCE-LING
  (22) Attaque Spoonman
  (23) Attaque Rosetta
  (24) Force brute par masques d’entreprise
  (25) Attaque par masque intelligent

  (80) Outils de listes de mots
  (81) Outils de fichiers de règles
  (82) Notifications
  (83) Outils de masques

  (93) Régénérer le .out à partir du fichier POT
  (94) API Hashview
  (95) Analyser les hachages avec Pipal
  (96) Exporter la sortie au format Excel
  (97) Afficher les hachages craqués
  (98) Afficher le README
  (99) Quitter

Sélectionnez une tâche :```

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.

```
Quelle(s) règle(s) souhaitez-vous exécuter ?
(1) best64.rule
(2) d3ad0ne.rule
(3) T0XlC.rule
(4) dive.rule
(99) YOLO... exécuter toutes les règles
Saisissez la liste des règles à exécuter, séparées par des virgules. Pour exécuter des règles en chaîne, utilisez le symbole +.
Par exemple, 1+1 exécutera best64.rule enchaînée deux fois et 1,2 exécutera best64.rule puis d3ad0ne.rule séquentiellement.
Choisissez judicieusement :```




#### 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).

Catégories