Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
hate_crack — Инструмент от команды TrustedSec для автоматизации методологий взлома с помощью Hashcat. | Kitploit
Инструменты/GitHubGitHub/trustedsec/hate_crack
Взлом паролейАтаки на ПаролиАнализ хэшейТестирование на Проникновение
GitHubtrustedsec/hate_crack

hate_crack

Инструмент от команды TrustedSec для автоматизации методологий взлома с помощью Hashcat.

Репозиторий
1.9k2874119 ч 45 мин назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Сайт
```
  ___ ___         __             _________                       __
 /   |   \_____ _/  |_  ____     \_   ___ \____________    ____ |  | __
/    ~    \__  \\   __\/ __ \    /    \  \/\_  __ \__  \ _/ ___\|  |/ /
\    Y    // __ \|  | \  ___/    \     \____|  | \// __ \\  \___|    <
 \___|_  /(____  /__|  \___  >____\______  /|__|  (____  /\___  >__|_ \
       \/      \/          \/_____/      \/            \/     \/     \/
```

## Установка

Установка из исходного кода — единственный поддерживаемый способ. hate_crack **не**
распространяется через PyPI: `pip install hate-crack` разрешается в `0.0.0` заглушку,
которая намеренно не работает и указывает обратно сюда. Имя зарезервировано только для того, чтобы никто другой
не мог опубликовать под ним похожий пакет — см.
[`packaging/pypi-placeholder/`](https://github.com/trustedsec/hate_crack/blob/main/packaging/pypi-placeholder).

### 1. Установите hashcat

Hashcat должен быть установлен и доступен в вашем PATH:

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

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

Или скачайте готовый бинарный файл с https://hashcat.net/hashcat/ и укажите `hcatPath` в `config.json` путь к нему.

### 2. Скачайте hate_crack

Клонируйте с подмодулями (требуется для hashcat-utils, princeprocessor, pcfg_cracker, Corporate_Masks и, опционально, omen):

```bash
git clone --recurse-submodules https://github.com/trustedsec/hate_crack.git
cd hate_crack
```

Если вы клонировали без подмодулей, инициализируйте их:

```bash
git submodule update --init --recursive
```

Затем настройте конфигурацию при необходимости. hate_crack использует два файла конфигурации, каждый из которых отвечает за свой набор параметров:

- **`config.json`** — пути к словарям, маски, правила, тонкая настройка, potfile, путь к hashcat, лимиты кандидатов, переключатели уведомлений, значения по умолчанию для CLI (35 параметров).
- **`.env`** — только параметры интеграции со сторонними сервисами: учётные данные Hashview и Hashmob, учётные данные Pushover, Ollama и pipal (14 параметров). Не отслеживается git, создаётся с правами `0600`.

Разделение проходит именно здесь по одной причине: `.env` — это файл, который может содержать секреты. Учётные данные для сторонних сервисов и их конфигурация попадают в неотслеживаемый файл с правами `0600`; всё, что hate_crack делает локально, остаётся в `config.json`, который безопасно делиться, сравнивать и сохранять в своих заметках. Именно поэтому *учётные данные* Pushover находятся в `.env`, а *переключатели* Pushover вкл/выкл — в `config.json`: переключатели — это локальные предпочтения, а не секреты.

У каждого ключа есть ровно одно место. Ключ, размещённый в другом файле, игнорируется, и hate_crack выводит предупреждение с указанием файла, которому он принадлежит. Любой ключ по-прежнему можно переопределить для одного запуска, экспортировав его переменную окружения. Большинство пользователей могут пропустить этот шаг, так как пути по умолчанию работают из коробки.

`config.json` является постоянным и первостепенным — он не устарел, и сроков его удаления нет. Переместились только параметры интеграции.

**Обновляетесь с единого `config.json`?** hate_crack мигрирует его за вас при первом запуске: параметры интеграции копируются в новый `.env` с правами `0600`, затем удаляются из `config.json`, чтобы оба файла не претендовали на них одновременно. Он выводит, какие ключи переместились (никогда их значения), и сохраняет ваш оригинал как `config.json.pre-split.bak` перед тем, как его изменить. Всё остальное в `config.json` остаётся точно таким, как было, включая порядок ключей.

**Первый запуск:** hate_crack создаёт оба файла за вас, так что делать ничего не нужно. Чтобы настроить `.env` вручную, скопируйте отслеживаемый шаблон:

```bash
cp .env.example .env
chmod 600 .env
```

`.env.example` включён в репозиторий и поставляется с пустыми значениями всех ключей учётных данных. Сам `.env` **никогда** не должен попадать в репозиторий — он указан в gitignore вместе с обычными вариантами резервных копий, и hate_crack всегда создаёт его с правами `0600` (только чтение/запись для владельца). `.env.example` генерируется из схемы; перегенерируйте его после изменения `hate_crack/config_schema.py` с помощью `uv run python -m hate_crack.config_writer`.

### 3. Установка зависимостей и hate_crack

Самый простой способ — запустить `make` (или `make install`), который автоматически определяет вашу ОС и устанавливает:
- Внешние зависимости (p7zip, transmission-daemon / transmission-remote)
- Собирает подмодули (hashcat-utils, princeprocessor, pcfg_cracker и, опционально, omen) и извлекает набор масок Corporate_Masks, содержащий только данные
- Python-зависимости через uv и CLI-обёртку в `~/.local/bin/hate_crack`

```bash
make
```

Это идемпотентно — уже установленные инструменты пропускаются. Чтобы принудительно выполнить чистую переустановку:

```bash
make reinstall
```

**Или установите зависимости вручную:**

### Внешние зависимости
Они требуются для некоторых сценариев загрузки/извлечения:

- `7z`/`7za` (p7zip) — используется для извлечения архивов `.7z`.
- `transmission-daemon` / `transmission-remote` — используется для загрузки торрентов Weakpass.

Команды ручной установки:

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
```

Затем установите зависимости Python и 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
```

-------------------------------------------------------------------
## Структура проекта
Основная логика теперь разделена на модули в каталоге `hate_crack/`:

- `hate_crack/cli.py`: вспомогательные функции argparse и переопределения конфигурации.
- `hate_crack/api.py`: интеграции с Hashview, Weakpass и Hashmob (загрузки/меню/вспомогательные функции).
- `hate_crack/attacks.py`: обработчики атак из меню.
- `hate_crack/corpus_stats.py`: статистика паролей по всему корпусу, используемая для описания корпуса LLM.
- `hate_crack/plaintext.py`: извлекает пароль из строки корпуса (отсечение префикса хеша, декодирование `$HEX[...]`); используется совместно режимами LLM, corpus_stats и rulegen.
- `hate_crack/llm.py`: структурированная (JSON) генерация кандидатов через LLM с помощью Atomic Agents.
- `hate_crack/menu.py`: общий рендерер меню, включая опциональную навигацию стрелками.
- `hate_crack/noninteractive.py`: диспетчер для скриптовых подкоманд атак.
- `hate_crack/notify/`: пакет уведомлений (бэкенд Pushover, tailer для каждого взлома).
- `hate_crack/username_detect.py`: определяет входные файлы вида `username:hash` для выбора опции hashcat `--username`.
- `hate_crack/formatting.py`, `hate_crack/progress.py`: вспомогательные функции форматирования вывода и отображения прогресса.
- `hate_crack/main.py`: основная реализация CLI.

Файл `hate_crack.py` верхнего уровня остаётся главной точкой входа и оркестрирует эти модули.

-------------------------------------------------------------------
## Ссылки и благодарности

Этот проект зависит от ряда внешних проектов и сервисов и вдохновлён ими. Благодарности:

- Hashview (http://github.com/hashview/)
- Weakpass (https://weakpass.com)
- Hashmob (https://hashmob.net)

-------------------------------------------------------------------
## Использование

После установки с помощью `make` запускайте hate_crack из любого места:

```bash
hate_crack
# or with arguments:
hate_crack <hash_file> <hash_type> [options]
```

Кроме того, можно запустить через `uv`:

```bash
uv run hate_crack.py <hash_file> <hash_type>
```

### Запуск как инструмента (рекомендуется)

Установите с помощью `make` из корня репозитория — это собирает подмодули и упаковывает ресурсы:

```bash
cd /path/to/hate_crack
make
hate_crack
```

Команда `make install` создаёт bash-обёртку в `~/.local/bin/hate_crack`, которая запускается из каталога репозитория, поэтому конфигурация и ресурсы всегда находятся независимо от вашего текущего рабочего каталога.

Конфигурация также ищется в:
- Корне репозитория и каталоге пакета
- `~/.hate_crack`

**Примечание:** `hcatPath` в `config.json` предназначен только для указания расположения бинарного файла hashcat (необязательно, если hashcat находится в PATH). Ресурсы Hate_crack (hashcat-utils, princeprocessor, pcfg_cracker, Corporate_Masks, omen) загружаются из каталога репозитория и автоматически включаются в комплект командой `make install`.

### Запуск в виде скрипта
Скрипт использует shebang `uv`. Сделайте его исполняемым и запустите:

```bash
chmod +x hate_crack.py
./hate_crack.py
```

Вы также можете использовать Python напрямую:

```bash
python hate_crack.py
```

### Неинтерактивное / скриптовое использование

Для автоматизации можно запустить одну атаку напрямую, минуя меню. Имя атаки — первый аргумент, за которым следуют файл хешей и тип хеша hashcat. Запросы предварительной обработки (фильтрация компьютерных учётных записей, брутфорс с приоритетом LM, дедупликация дублирующихся учётных записей) автоматически принимают значения по умолчанию в этом режиме. Процесс завершается с кодом `0` при успехе и ненулевым кодом при ошибке (отсутствующий файл хешей, нечисловой тип хеша, отсутствующий словарь или неизвестное имя файла правил).

```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
```

Большинство атак из меню доступны одинаковым способом. Для них не требуется ничего, кроме файла хеша и типа хеша:

```bash
hate_crack fingerprint hashes.txt 1000
hate_crack pathwell    hashes.txt 1000
hate_crack prince      hashes.txt 1000
hate_crack pcfg        hashes.txt 1000
hate_crack princeling  hashes.txt 1000
hate_crack smartmask   hashes.txt 1000
hate_crack corporate   hashes.txt 1000
hate_crack combinator  hashes.txt 1000     # configured wordlists
hate_crack hybrid      hashes.txt 1000     # configured wordlists
```

Каждый также принимает настройки, которые запрашивает его пункт меню:

```bash
# Fingerprint, tuned: escalate to 24-character fragments and cap the keyspace
hate_crack fingerprint hashes.txt 1000 --max-expander-len 24 \
    --run-hybrid-on-expanded --keyspace-limit 50000000000

# Skip the fragment/wordlist combination step entirely
hate_crack fingerprint hashes.txt 1000 --no-dictionary-wordlist

# Override the configured wordlists (combinator needs at least two).
# Two wordlists use combinator, three use combinator3, more -- or any
# --separator -- use combinatorX, matching what the menu does.
hate_crack combinator hashes.txt 1000 --wordlist first.txt second.txt
hate_crack combinator hashes.txt 1000 --wordlist a.txt b.txt c.txt
hate_crack combinator hashes.txt 1000 --wordlist a.txt b.txt --separator -
hate_crack hybrid     hashes.txt 1000 --wordlist rockyou.txt

# Corporate masks, lengths 8-12 only
hate_crack corporate hashes.txt 1000 --min 8 --max 12

# Smart mask, skipping templates over 10 billion candidates
hate_crack smartmask hashes.txt 1000 --keyspace-limit 10000000000
```

Остальные принимают один вход, который запрашивает их пункт меню:

```bash
# Bandrel methodology (comma-separate multiple companies)
hate_crack bandrel hashes.txt 1000 --company "Acme,Acme Corp"

# Permutation attack over a short targeted wordlist
hate_crack permute hashes.txt 1000 --wordlist names.txt

# Ad-hoc mask -- a literal mask or a .hcmask file, optionally incrementing
hate_crack adhocmask hashes.txt 1000 --mask '?u?l?l?l?d?d'
hate_crack adhocmask hashes.txt 1000 --mask masks/corporate.hcmask
hate_crack adhocmask hashes.txt 1000 --mask '?a?a?a?a?a?a?a?a' \
    --increment-min 4 --increment-max 8
hate_crack adhocmask hashes.txt 1000 --mask '?a?a?a?a' --increment

# N-gram candidates from a corpus
hate_crack ngram hashes.txt 1000 --corpus corpus.txt --group-size 3

# Combipow passphrases (wordlist capped at 63 lines: it generates 2^n-1)
hate_crack combipow hashes.txt 1000 --wordlist words.txt
hate_crack combipow hashes.txt 1000 --wordlist words.txt --no-spaces

# Spoonman: basewords and rules derived from a corpus of known passwords
hate_crack spoonman hashes.txt 1000 --corpus previous-engagement.txt
hate_crack spoonman hashes.txt 1000 --corpus previous.txt --rule-coverage 95
# --rule-coverage accepts 50, 75, 95 or 99 -- the only capped rule files
# derived. Omit it for the full rule set.

# OMEN -- requires a model trained beforehand from the interactive menu
hate_crack omen hashes.txt 1000 --max-candidates 1000000

# Loopback: re-run rules against the plaintexts already cracked
hate_crack loopback hashes.txt 1000 --rules best64.rule
```

`fingerprint` — единственная команда, чья форма без аргументов не совпадает с её пунктом меню: пункт меню 5 всегда запускает гибридные проходы по расширенным фрагментам, тогда как подкоманда по умолчанию использует собственное значение `hcatFingerprint` — выключено. Передайте `--run-hybrid-on-expanded`, чтобы соответствовать меню.

Пять пунктов меню по-прежнему доступны только в интерактивном режиме, поскольку им требуется ввод, который не может передать один флаг: перебор по Маркову, случайные правила, атака Rosetta, атака LLM и методология Extensive Pure_Hate (оркестратор над остальными, а не отдельная атака).

#### Коды выхода

| Код | Значение |
|---|---|
| `0` | Атака выполнена |
| `1` | Некорректный ввод — отсутствует файл хешей или словарь, нечисловой тип хеша, неизвестное имя файла правил, аргумент вне диапазона |
| `2` | Неизвестная подкоманда — в этой сборке hate_crack её нет |
| `3` | Только с `--exit-code-on-skip`: покрытие уже видело каждый проход, поэтому ничего не было запущено |

Коды выхода `2` и `3` позволяют скриптовому драйверу отличать «эта версия не может запустить эту атаку» и «она была избыточной» от «она запустилась и ничего не нашла». `--exit-code-on-skip` включается по желанию, чтобы включение покрытия не приводило к сбоям в старых тестовых стендах.

-------------------------------------------------------------------
## Устранение неполадок

### Ошибка: "would clobber existing tag" при обновлении

Старый клон может отказаться обновляться, выводя длинный список строк вида:

```
 ! [rejected]        v2.5.0     -> v2.5.0  (would clobber existing tag)
```

Это затрагивает клоны, созданные до июля 2026 года. Опубликованная история была переписана
тогда, чтобы удалить некоторые файлы, которые никогда не должны были быть закоммичены, что дало
каждому коммиту новый ID; поэтому теги более старого клона указывают на объекты, которых этот
репозиторий больше не содержит, и git отказывается перемещать тег, который у него уже есть.
С вашей рабочей копией всё в порядке, и никакие данные для взлома не подвергаются риску.

Восстановите с помощью однократного сброса. Это отбросит локальные коммиты и правки в
рабочей копии, поэтому если вы что-либо настроили из отслеживаемого git (в отличие от
`config.json`, который не отслеживается), сначала закоммитьте это в ветку:

```bash
cd /path/to/hate_crack
git fetch --tags --force origin
git checkout -B main origin/main
make install
```

`--force` здесь только обновляет теги; он не может изменить ваши коммиты. После этого
встроенный механизм обновления работает нормально. Версии до 2.18 не могли выполнить это
восстановление самостоятельно, поэтому его приходится делать вручную один раз.

### Ошибка: каталог сборки не существует

Если вы видите ошибку вроде:
```
Error: Build directory /opt/hashcat/hashcat-utils does not exist.
Expected to find expander at /opt/hashcat/hashcat-utils/bin/expander.
```

Это означает, что ресурсы hate_crack не были включены в установленный пакет.

**Понимание путей:**
- `hcatPath` в config.json → указывает на **расположение бинарного файла hashcat** (необязательно, может находиться в PATH)
- `hashcat-utils/` и `princeprocessor/` → включаются в пакет с помощью `make install`

**Решение:**
Переустановите с помощью Makefile, который собирает подмодули и устанавливает инструмент:
```bash
cd /path/to/hate_crack  # the repository checkout
make install
```

**Конфигурация по умолчанию (config.json.example):**

Большинство пользователей могут использовать значения по умолчанию без настройки:
- `hcatWordlists`: `./wordlists` (относительно корня репозитория или HOME/.hate_crack)
- `hcatOptimizedWordlists`: `./optimized_wordlists` (каталог, используемый Quick Crack; если не найден, используется `hcatWordlists`)
- `rules_directory`: `./hashcat/rules` (включает правила подмодулей)
- `hcatTuning`: `` (пустая строка — без флагов настройки по умолчанию)

**Примеры настроек 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)
  ...
}
```

**Загрузка конфигурации:**
- Приоритет для каждого ключа: `os.environ` > собственный домашний файл этого ключа (`.env` или `config.json`) > встроенное значение по умолчанию
- Отсутствующие ключи используют встроенные значения по умолчанию; `config.json.example` документирует каждый ключ `config.json`
- Оба файла ищутся независимо друг от друга в следующем порядке: **корень репозитория**, затем **каталог установленного пакета**, затем **`~/.hate_crack`**. Побеждает первое совпадение; нормально, если два файла находятся в разных каталогах.
- При первом запуске создаются оба файла — `config.json` из `config.json.example`, `.env` из встроенных значений по умолчанию. Если более старый `config.json` всё ещё содержит ключи интеграции, они копируются в новый `.env`, и hate_crack сообщает, какие из них нужно удалить из `config.json`; сам он этот файл никогда не редактирует.
- При каждом запуске hate_crack выводит два файла, которые он фактически загрузил:

  ```
  [*] config.json: /home/you/.hate_crack/config.json
  [*] .env:        /home/you/.hate_crack/.env
  ```

  Прочитайте эти две строки, прежде чем отлаживать настройку, которая «не вступает в силу». Они существуют из-за двух ловушек в порядке поиска:

  - **Рабочая копия имеет приоритет над вашим домашним каталогом.** Корень репозитория ищется первым, поэтому `.env` или `config.json`, находящийся в *любой* рабочей копии, из которой вы запускаете инструмент, имеет приоритет над файлом в `~/.hate_crack` — а запуск инструмента из рабочей копии как раз и создаёт эти файлы там в первую очередь. Если это когда-либо затеняет настоящую конфигурацию `~/.hate_crack`, hate_crack теперь сообщает об этом третьей строкой `[!]` с указанием обоих путей — воспринимайте эту строку как «файл ниже игнорируется», а не как вторую, столь же действительную конфигурацию.
  - **Текущий рабочий каталог никогда не ищется.** `.env` в каталоге, в котором вы случайно находитесь, игнорируется намеренно: каталоги проектов полны файлов, которые никто не предназначал для конфигурации. Поместите его в корень репозитория или в `~/.hate_crack`.

### Ошибка: merge with ref 'refs/heads/master' but no such ref was fetched

Если вы видите:
```
Your configuration specifies to merge with the ref 'refs/heads/master'
from the remote, but no such ref was fetched.
```

Ветка по умолчанию была переименована с `master` на `main`. Исправление:
```bash
git remote set-head origin -a
git branch -m master main
git branch --set-upstream-to=origin/main main
git pull
```

-------------------------------------------------------------------
### Цели Makefile

**По умолчанию (полная установка)** — собирает подмодули, устанавливает зависимости и устанавливает инструмент:

```bash
make
# or explicitly:
make install
```

Это идемпотентно — уже установленные инструменты пропускаются.

**Принудительная чистая переустановка:**

```bash
make reinstall
```

**Быстрое обновление** — пересобирает подмодули и переустанавливает инструмент (после получения изменений):

```bash
make update
```

**Удаление** — удаляет зависимости ОС и инструмент:

```bash
make uninstall
```

**Собрать только hashcat-utils:**

```bash
make hashcat-utils
```

**Запуск тестов** — автоматически обрабатывает HATE_CRACK_SKIP_INIT при необходимости:

```bash
make test
```

**Отчёт о покрытии:**

```bash
make coverage
```

**Очистка артефактов сборки/тестирования:**

```bash
make clean
```

## Разработка

### Настройка среды разработки

Установите проект с необязательными зависимостями для разработки (включает линтеры и инструменты тестирования):

```bash
make dev-install
```

### Запуск линтеров и проверок типов

Перед отправкой изменений запустите эти проверки локально. Используйте `make lint` для всего или запускайте отдельные проверки:

**Ruff (линтинг и форматирование):**
```bash
make ruff
# or manually:
uv run ruff check hate_crack tests tools packaging hate_crack.py
```

Автоисправление проблем:
```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 (проверка типов):**
```bash
make ty
# or manually:
uv run ty check hate_crack
```

**Запустить все проверки вместе:**
```bash
make lint
```

### Запуск тестов

Тесты автоматически определяют, когда подмодули не собраны, и устанавливают `HATE_CRACK_SKIP_INIT=1` автоматически.

```bash
make test
```

Или запустите pytest напрямую:

```bash
uv run pytest -v
```

С покрытием:

```bash
make coverage
```

Или с pytest:

```bash
uv run pytest --cov=hate_crack
```

### Git-хуки (prek)

Git-хуки управляются через [prek](https://github.com/j178/prek) (v0.3.3+). Установите хуки с помощью:

```bash
prek install --hook-type pre-push --hook-type pre-commit
```

Это устанавливает хуки, определённые в `prek.toml`, используя TOML-схему локального репозитория pre-commit:
- **pre-push** (локальные хуки): ruff, ruff-format, ty, pytest, pytest-lima, bandit
- **pre-commit** (из `pre-commit/pre-commit-hooks`): trailing-whitespace,
  end-of-file-fixer, check-yaml, check-merge-conflict, check-added-large-files,
  detect-private-key

Автоисправления pre-commit перезаписывают файлы на месте, поэтому после их запуска нужно снова добавить файлы в индекс и закоммитить.

Примечание: prek 0.3.3 ожидает `repos = [...]` на верхнем уровне. Старый формат `[hooks.<stage>] commands = [...]` не поддерживается.

### Навигация по меню стрелками

По умолчанию меню используют классический выбор через нумерованный `print()` + `input()`, который принимает полные многозначные клавиши.

Чтобы включить навигацию стрелками через `simple-term-menu`, установите
`HATE_CRACK_ARROW_MENU=1`. В этом режиме можно либо перемещаться стрелками,
либо ввести номер опции (включая многозначные, например `99`) и
нажать Enter. Ввод чего-либо другого фильтрует список. Режим стрелок также
требует TTY, поэтому он остаётся выключенным, когда вывод передаётся по конвейеру.

Средства выбора, которые выводят список, а затем принимают ввод (списки слов, правила,
список Weakpass, список слов и ID правил Hashview), принимают Up/Down на любом бэкенде,
без `HATE_CRACK_ARROW_MENU`. Up подставляет последнюю показанную клавишу, Up снова —
предыдущую, Down возвращается назад; при этом всё ещё можно ввести число, путь или список
вроде `1,3`. Символ `,`, `+` или `-`, введённый сразу после подставленной стрелкой
клавиши, расширяет её. В бэкендах `plain` и `rich` это работает путём загрузки
показанных клавиш в историю readline для этого одного приглашения, поэтому ваша собственная история
восстанавливается после этого и недоступна изнутри приглашения списка.

### Зависимости для разработки

Необязательная группа `[dev]` включает:
- **ty** — статический проверщик типов
- **ruff** — быстрый линтер и форматтер Python
- **pytest** — фреймворк для тестирования
- **pytest-cov** — отчёт о покрытии

-------------------------------------------------------------------
Общие опции:
- `--download-hashview`: скачать хеши из Hashview перед взломом.
- `--hashview`: интерактивное меню Hashview для управления хешами, списками слов и заданиями.
- `--hashview --help`: показать опции командной строки Hashview.
- `--weakpass`: скачать списки слов из Weakpass.
- `--rank`: показывать только списки слов Weakpass определённого уровня (0=все, -1=уровни S/A/B). Ранги: 7=S, 6=A, 5=B, 4=C, 3=D, 2=E, 1=F.
- `--hashmob`: скачать списки слов с Hashmob.net.
- `--hashmob-masks`: скачать маски с Hashmob.net.
- `--download-torrent <FILENAME>`: скачать конкретный торрент-файл Weakpass.
- `--download-all-torrents`: скачать все доступные торренты Weakpass из кэша.
- `--wordlists-dir <PATH>` / `--optimized-wordlists-dir <PATH>`: переопределить каталоги списков слов.
- `--pipal-path <PATH>`: переопределить путь к pipal.
- `--restore-potfile`: пересобрать `<hashfile>.out` из POT-файла hashcat при запуске, заменив любое существующее содержимое, затем продолжить в обычном меню. Без этого флага поиск в POT выполняется только когда `.out` ещё не существует. Пункт меню 93 делает то же самое по требованию, с запросом подтверждения.
- `--maxruntime <SECONDS>`: переопределить максимальное время выполнения.
- `--bandrel-basewords <PATH>`: переопределить файл базовых слов bandrel.
- `--update`: обновиться до последнего релиза и переустановить. Переключает рабочую копию на `main`, если она находится на другой ветке, поскольку теги релизов находятся там.
- `--nightly`: вместо этого обновиться до последней nightly-сборки из ветки `nightly-dev`. Nightly-сборки прошли CI, но не являются частью выпущенного релиза. Также можно записать как `--update --nightly`.
- `--no-optimized-kernel` (или `--no-optimize`): никогда не передавать `-O` в hashcat на протяжении всего запуска. Переопределяет `optimizedKernelAttacks` в `config.json` и удаляет любой `-O`, который вы указали в `hcatTuning`. В конфиг ничего не записывается, поэтому это применяется только к текущему запуску. С подкомандой указывайте это перед подкомандой: `./hate_crack.py --no-optimize quick hashes.txt 1000 --wordlist words.txt`.
- `--debug`: включить отладочное логирование (пишет в stderr).

### Интеграция с Hashview

hate_crack интегрируется с Hashview для централизованного управления хешами и распределённого взлома.

#### Интерактивное меню

Доступ к интерактивному меню Hashview:
```bash
hate_crack.py --hashview
```

Параметры меню:
- **(1) Upload Cracked Hashes** — загрузить взломанные результаты текущей сессии в Hashview
- **(2) Upload Wordlist** — загрузить файл словаря в Hashview
- **(3) Download Wordlist** — скачать словарь из Hashview
- **Download Rule** — скачать файл правил из Hashview (распакованный в открытый текст, готовый для `hashcat -r`). Введите `a` (или `all`) в приглашении rule ID, чтобы скачать все перечисленные правила вместо одного
- **Download All Rules** — скачать все файлы правил, перечисленные Hashview, за один проход; сбои для отдельных правил сообщаются без прерывания остальных
- **(4) Download Left Hashes** — скачать оставшиеся невзломанные хеши (предлагает переключиться для взлома)
- **(5) Download Found Hashes** — скачать уже взломанные хеши с паролями в открытом виде (для справки/анализа)
- **(6) Upload Hashfile and Create Job** — загрузить новый файл хешей и создать задание на взлом
- **(99) Back to Main Menu** — вернуться в главное меню

**Важно: Download Found vs Download Left**
- **Download Left Hashes (4)**: скачивает невзломанные хеши, которые нужно взломать. Автоматически объединяет с любыми найденными хешами, если они доступны, и предлагает переключиться на этот файл хешей для взлома.
- **Download Found Hashes (5)**: скачивает уже взломанные хеши в формате hash:cleartext. Они предназначены для справки и не могут быть взломаны дальше. Приглашение на переключение не отображается.

#### Интерфейс командной строки

Операции Hashview также можно выполнять через командную строку:

Загрузка взломанных хешей:
```bash
hate_crack.py --hashview upload-cracked --file <output_file>.out --hash-type 1000
```

Загрузите список слов:
```bash
hate_crack.py --hashview upload-wordlist --file <wordlist>.txt --name "My Wordlist"
```

Скачать файл правил (сохраняется распакованным, готовым для `hashcat -r`):
```bash
hate_crack.py --hashview download-rules --rules-id 4 --output best64.rule
```

Скачать оставшиеся хеши (невзломанные хеши для взлома):
```bash
hate_crack.py --hashview download-left --customer-id 1 --hashfile-id 123
```

Скачать найденные хеши (уже взломанные хеши с открытым текстом):
```bash
hate_crack.py --hashview download-found --customer-id 1 --hashfile-id 123
```

Загрузите файл хешей и создайте задачу:
```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"
```

#### Конфигурация

Укажите учётные данные Hashview в `.env` (это настройки интеграции, поэтому они не хранятся в `config.json`):
```
HASHVIEW_URL=https://hashview.example.com
HASHVIEW_API_KEY=your-api-key-here
HASHVIEW_VERIFY_TLS=true
```

`HASHVIEW_VERIFY_TLS` по умолчанию имеет значение `true`: hate_crack проверяет TLS-сертификат сервера Hashview, и подключение к Hashview с самоподписанным сертификатом или сертификатом внутреннего центра сертификации будет завершаться ошибкой до тех пор, пока этот сертификат не будет признан доверенным (добавьте его в системное хранилище доверенных сертификатов или используйте сертификат, выданный центром сертификации, которому ваша система уже доверяет). Если это невозможно, установите `HASHVIEW_VERIFY_TLS=false` -- hate_crack будет выводить однострочное предупреждение с именем хоста при каждом запуске процесса, когда проверка отключена, поскольку её отключение устраняет защиту от подмены сервера или атаки «человек посередине», перехватывающего соединение.

#### Конфигурация LLM

LLM Attack (опция 12) и Rosetta Mask Attack (опция 23) генерируют свои кандидаты с помощью локальной модели. Настройте модель, окно контекста и тайм-аут запроса в `.env`:

```
LLM_BACKEND=ollama
OLLAMA_MODEL=qwen3:4b-instruct
OLLAMA_NUM_CTX=8192
OLLAMA_TIMEOUT=300
```

**Ключи `OLLAMA_*`, приведённые ниже, применяются к каждому бэкенду, а не только к Ollama.** Они сохраняют этот префикс, потому что `OLLAMA_HOST` — та же переменная, которую читает собственный CLI Ollama, и её переименование сломало бы каждый существующий `.env` без какого-либо функционального выигрыша — сервер vLLM или OpenAI-совместимый сервер хочет тот же хост, модель, таймаут, контекст и параметры сэмплирования под теми же именами. `LLM_BACKEND` лишь выбирает, как формируется запрос.

- **`OLLAMA_MODEL`** — Модель Ollama, используемая для генерации кандидатов (по умолчанию: `qwen3:4b-instruct`). LLM-атака использует структурированный (JSON) вывод, поэтому выбирайте модель с хорошей поддержкой инструментов/JSON.
- **`OLLAMA_NUM_CTX`** — Размер контекстного окна для модели (по умолчанию: `8192`). До введения статистики по корпусу здесь было `2048`, что было слишком мало для подаваемого промпта: 500 сэмплированных открытых текстов занимают примерно 2 000–3 500 токенов до системного промпта и ответа, поэтому Ollama молча обрезала часть выборки, которую сэмплер тщательно распределил по файлу.
- **`OLLAMA_TIMEOUT`** — Секунды ожидания ответа генерации до отказа (по умолчанию: `300`). Увеличьте это значение, если большая модель всё ещё загружается в VRAM при первом запросе, что иначе может превысить таймаут; hate_crack выводит истёкший таймаут и имя этого параметра при срабатывании.
- **`OLLAMA_MAX_SAMPLE_LINES`** — Порог, ниже которого режимы LLM также вставляют буквальные открытые тексты в промпт (по умолчанию: `500`). Значения ≤ 0 трактуются как 500.

  Режимы, основанные на корпусе (**Wordlist**, **Cracked passwords**, **Pattern rules**), всегда описывают *весь* корпус статистически — доли базовых слов, маски, регистр, длины, завершающие цифры и символы, годы — вместо вставки его фрагмента. Агрегация ограничена, поэтому дамп из 120 000 паролей занимает примерно столько же места в промпте, как и 500-строчный. Когда весь корпус укладывается под этот порог, сырые открытые тексты также включаются, поскольку нет смысла скрывать от модели небольшой корпус.

  Это заменяет прежнее поведение со вставкой равномерно распределённой выборки до `ollamaMaxSampleLines` паролей. Выборка из большого дампа вообще не передавала информацию о частоте: модель не могла отличить базовое слово, используемое 8% организации, от используемого одним человеком, а это именно тот сигнал, который делает догадку стоящей запуска.
- **`OLLAMA_NO_CLOUD`** — Когда `true`, запрещает отправлять что-либо с этого хоста для любого из трёх LLM-бэкендов (Ollama, vLLM или универсального OpenAI-совместимого сервера). Этой одной настройкой управляются две проверки: Ollama проксирует модель с тегом `-cloud` (`gpt-oss:120b-cloud`, `deepseek-v3.1:671b-cloud`) на ollama.com через тот же локальный эндпоинт, который использует локальная модель, поэтому в запросе ничего не выглядит иначе — такой запрос отклоняется по имени модели. Также проверяется настроенный URL бэкенда: назначение, которое не является loopback, частным или link-local (и не является `localhost` или именем `.local`/`.internal`/`.lan`/`.localdomain`), отклоняется по назначению, а имя хоста, которое эта проверка не может разрешить, также отклоняется, по принципу fail-closed, вместо того чтобы пропустить непроверяемое назначение. Промпты hate_crack содержат восстановленные открытые тексты, статистику корпуса, а также название, отрасль и местоположение клиента, поэтому срабатывание любой из проверок означает, что запрос отклоняется до его формирования. По умолчанию `false`, поэтому намеренно настроенная облачная модель или удалённый сервер продолжает работать; включите это для проектов, где данные клиента не должны покидать хост.
- **`OLLAMA_AUTO_RESEARCH`** — Когда `true` (по умолчанию), режим **Target info** просит локальную модель предложить отрасль, местоположение и материнскую компанию / историю поглощений, как только вы ввели название компании, и предлагает их как редактируемые значения по умолчанию для промпта. Установите `false`, чтобы всегда получать пустые промпты (полезно с медленной моделью, поскольку исследование стоит одного дополнительного обращения до начала атаки).
- **`OLLAMA_HOST`** — Где слушает настроенный бэкенд. Принимает как простой `host:port` (`theplague.lan:11434`), так и полный URL со схемой (`https://ollama.example.com`); в любом случае базовый URL нормализуется перед использованием. По умолчанию `localhost:11434`, что является портом Ollama — серверу vLLM или OpenAI-совместимому серверу нужно установить это значение на свой собственный (vLLM обычно слушает на `:8000`). Задайте его в `.env` или экспортируйте как настоящую переменную окружения, чтобы переопределить это для одного запуска — это то же имя переменной, которое читает собственный CLI Ollama.
- **`LLM_BACKEND`** — С каким OpenAI-совместимым сервером общаться: `ollama` (по умолчанию), `vllm` или `openai` для универсального. Каждый бэкенд говорит на одном и том же API чат-завершений `/v1`, поэтому это выбирает только две детали формирования запроса, которыми они различаются: `ollama` получает `options.num_ctx`, а `vllm` получает `chat_template_kwargs={"thinking": false}` — без чего сервер vLLM, запущенный с парсером рассуждений, направляет весь структурированный ответ в `message.reasoning`, оставляет `message.content` пустым и ломает разбор JSON. `openai` не отправляет ни то, ни другое, поскольку `num_ctx` там не имеет эквивалента. Это **не** меняет, откуда берутся хост, модель, таймаут, контекст или настройки сэмплирования — для всех трёх это ключи `OLLAMA_*` выше.
- **`LLM_API_KEY`** — Учётные данные, отправляемые настроенному бэкенду. По умолчанию — литерал `ollama`, заполнитель, который игнорирует собственный сервер Ollama, поэтому запросы существующей установки не меняются; пустое значение откатывается к тому же заполнителю, потому что OpenAI SDK отвергает `api_key=""`. Установите реальное значение, если сервер его требует — сервер vLLM, запущенный с `--api-key`, иначе возвращает 401.
- Убедитесь, что Ollama запущена и модель загружена (`ollama pull qwen3:4b-instruct`) перед использованием LLM Attack — hate_crack больше не загружает отсутствующие модели автоматически.

Атака предлагает три режима генерации:

1. **Target info** — компания / отрасль / местоположение / материнская компания; модель выводит кандидатов из этих сведений.

   После того как вы введёте название компании, hate_crack спрашивает у той же локальной модели, что она уже знает об этой организации, и предзаполняет промпты **Industry**, **Location** и **Parent Company** ответами, показанными в скобках:

   ```
   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:
   ```

   Нажмите Enter, чтобы принять подсказку, или введите поверх неё. Эти значения — воспоминания модели, **не OSINT** — относитесь к ним как к отправной точке, а не как к разведданным о клиенте. Поиск использует только локальный сервер Ollama, поэтому имя клиента никогда не покидает хост; никаких веб- или сторонних API-вызовов нет. Если модель не распознаёт организацию (обычный случай для небольших клиентов), она ничего не возвращает, и вы получаете обычные пустые приглашения:

   ```
   Company name: Acme Rail Services
   Industry:
   Location:
   Parent company / acquired by:
   ```

   Сбой исследования — тайм-аут, Ollama не запущена, пустой ответ — никогда не блокирует атаку; он просто откатывается к пустым подсказкам. Установите `ollamaAutoResearch` в `false`, чтобы полностью пропустить исследование.
2. **Список слов** — извлечение базовых слов из образца списка слов.
3. **Взломанные пароли** — передайте открытые тексты, уже восстановленные в этой сессии (`<hashfile>.out`), обратно модели, чтобы она могла вывести собственные соглашения о паролях целевой организации (базовые слова, сезоны, годы, суффиксы, leetspeak) и сгенерировать *новые* кандидаты в том же стиле. Этот вариант отображается только после того, как взломан хотя бы один хеш; весь файл анализируется статистически точно так же, как в режиме «Список слов» (см. `ollamaMaxSampleLines` выше).

#### Конфигурация PCFG

Атака PCFG (опция 20) и атака PRINCE-LING (опция 21) используют подмодуль `pcfg_cracker`. Настройте их в `config.json`:

```json
{
  "pcfgRuleset": "DEFAULT",
  "pcfgMaxCandidates": 50000000,
  "pcfgPrinceLingMaxCandidates": 10000000
}
```

- **`pcfgRuleset`** — Имя обученной грамматики для использования (по умолчанию: `DEFAULT`), разрешается в `pcfg_cracker/Rules/<name>/`. Обучите свою собственную с помощью `trainer.py` из pcfg_cracker и укажите здесь имя набора правил.
- **`pcfgMaxCandidates`** — Максимальное количество кандидатов, которое `pcfg_guesser.py` выдаёт для PCFG-атаки (по умолчанию: `50000000`).
- **`pcfgPrinceLingMaxCandidates`** — Максимальное количество базовых слов, которое `prince_ling.py` записывает в кэшированный список базовых слов PRINCE (по умолчанию: `10000000`).

### Оптимизированные ядра (`optimizedKernelAttacks`)

Флаг `-O` в hashcat выбирает оптимизированные ядра, которые работают существенно быстрее,
но ограничивают длину кандидата (примерно 31 символ, меньше для некоторых режимов) и
молча пропускают всё, что длиннее. `optimizedKernelAttacks` в `config.json` перечисляет
атаки, которые запускаются с `-O`; исключите атаку из списка, чтобы запустить её с
ядрами полной длины. Список в `config.json.example` соответствует встроенному
значению по умолчанию, которое применяется, когда `config.json` отсутствует.

Четыре атаки учитывают эту настройку, но **не** оптимизированы по умолчанию, поскольку
они подают кандидатов, которые могут превысить потолок `-O` — добавьте их в список, чтобы
включить оптимизацию:

- `hcatNgramX`, `hcatOllama`, `hcatOmen`, `hcatLMtoNT`

Чтобы отключить `-O` везде для одного запуска без редактирования конфигурации, передайте
`--no-optimized-kernel` (краткая форма `--no-optimize`). Это переопределяет список для
каждой атаки, а также удаляет `-O`, записанный в `hcatTuning`, который иначе
дошёл бы до hashcat независимо от списка.

Имена сопоставляются точно, и нераспознанная запись сообщается при запуске,
а не игнорируется. Обратите внимание, что атаки, которые делегируют другой атаке,
управляются той атакой, которой они делегируют, а не своим собственным именем: PRINCE-LING
следует за `hcatPrince`, тогда как Spoonman, Rosetta и режимы правил шаблонов LLM
следуют за `hcatQuickDictionary`.

### Отслеживание покрытия атак (`coverage_enabled`)

В ходе длительного взаимодействия один и тот же файл хешей атакуется во многих сессиях с
меняющимся набором списков слов, файлов правил и списков масок, и легко потратить
часы на повторное прохождение уже пройденного — особенно учитывая, что одна и та же строка
правила встречается более чем в одном файле правил. hate_crack записывает, что уже было
запущено против каждого файла хешей, и предлагает пропустить пересечение.

Покрытие записывается **по элементу, а не по файлу**: отдельные строки правил и
отдельные строки `.hcmask`, каждая в паре со списком слов, против которого она запускалась. Именно
это позволяет распознать, что пользовательский файл правил, который вы запускаете сегодня, повторяет 40 из
правил, уже покрытых `best64.rule` на прошлой неделе, и именно поэтому правило считается
«покрытым» только для конкретного списка слов, с которым оно было опробовано — те же правила над
другим корпусом пробуют совершенно иных кандидатов.

Файл хешей идентифицируется по sha256 его содержимого, поэтому покрытие сохраняется при
переименовании или перемещении между сессиями. Списки слов идентифицируются таким же образом,
причём дайджест мемоизируется по размеру и mtime, так что корпус размером в несколько гигабайт
хешируется один раз, а не при каждой атаке.

Запрос выводится только тогда, когда действительно есть что пропустить:

```
[*] 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]:
```

Ответьте `Y`, и hate_crack создаст временный файл правил, содержащий только непроверенные
записи; ответьте `n`, чтобы запустить всё в любом случае. Если *каждая* запись является повтором,
вас спросят, пропустить ли атаку полностью, так что намеренный повторный запуск уже
покрытой области никогда не требует перезапуска инструмента.

Атаки, которые никогда не фильтруются, всё равно записываются как выполненные, что и
позволяет ответить на вопрос "я уже запускал PRINCE против этой цели?".

Атака, выбирающая несколько файлов правил одновременно (Quick Crack, Loopback), задаёт вопрос
о пропуске **один раз для всей партии, заранее**, до любого вызова hashcat. Этот вопрос
намеренно дешёвый — он не читает и не хеширует ни один из выбранных файлов правил,
поскольку партия YOLO может достигать миллионов строк, и вы не должны ждать этого, чтобы
ответить да/нет. Он спрашивает у хранилища только о том, запускалась ли эта атака уже против
этого хеш-файла **с одним из этих словарей**; пофайловое сравнение всё ещё происходит лениво,
по одному файлу правил за раз, и решает, что именно будет пропущено. Так что свежий корпус
никогда не помечается, даже когда все правила на нём уже запускались против другого.

Три намеренных ограничения:

- **Покрытие записывается только когда hashcat исчерпывает пространство ключей** (код выхода 1). Ctrl-C или ошибка не записывают ничего, как и код выхода 0 — это означает, что все
  хеши взломаны, о чём hashcat сообщает *без* завершения пространства ключей, а в
  вырожденном случае "все хеши найдены как записи в potfile" — без попытки хотя бы
  одного кандидата. Недостаточная запись стоит лишь избыточного запуска позже.
- **Динамические генераторы кандидатов никогда не фильтруются.** PRINCE, PCFG, OMEN,
  перебор Маркова и режимы LLM не имеют фиксированного набора для сравнения, поэтому они
  регистрируются как выполненные и в остальном не трогаются. Сцепленные файлы правил (`-r a -r b`)
  отслеживаются как единое целое, а не по записям, потому что hashcat применяет
  *декартово произведение* двух файлов, и удаление отдельной строки молча удалило бы
  каждую комбинацию, в которой она участвовала.
- **Запуски `--loopback` записываются, но никогда не фильтруются.** hashcat подаёт свежевзломанные
  открытые тексты обратно как *дополнительных* кандидатов, поэтому такой запуск пробует полный
  словарь и набор правил плюс всё, чего достигают эти переработанные открытые тексты. Это делает
  два направления асимметричными: запись его корректна, поэтому более поздний обычный запуск
  того же словаря и правил правильно распознаётся как повтор, но второй запуск loopback имеет
  больше взломов для переработки и никогда не пропускается.

Установите `coverage_enabled` в `false` в `config.json`, чтобы отключить это, или передайте
`--no-coverage` для одного запуска — который ни обращается к хранилищу, ни обновляет его.

#### Просмотр и сброс покрытия

Пункт главного меню **85 — Attack Coverage** показывает, что было запущено против
загруженного хеш-файла, его историю запусков и может её очистить. Те же три действия
доступны для скриптов:

```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
```

Файл хешей идентифицируется по содержимому, поэтому они работают независимо от того, куда он был перемещён с тех пор. `forget` влияет только на одну эту цель — хранилище находится в
`~/.hate_crack/coverage/attack_coverage.sqlite3`, и удаление файла сбрасывает
покрытие для *каждой* цели.

#### Скриптовые запуски

Скриптовая атака, которую покрытие полностью пропускает, всё равно по умолчанию завершается с кодом `0`, поэтому
включение покрытия не может привести к сбою существующего харнесса. Передайте
`--exit-code-on-skip`, чтобы вместо этого получить код выхода **3**, когда ничего не было запущено:

```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 означает, что *ничего* не запускалось. Проход, который был частично отфильтрован — некоторые записи пропущены, некоторые опробованы — всё равно завершается с кодом `0`, потому что атака всё же выполнила работу.

### Поддержка hashcat brain (`brain_enabled`)

Сам hashcat поставляется с «brain» — небольшим сервером, которому запущенный экземпляр hashcat передаёт потоки кандидатов в пароли, чтобы второй запуск против той же цели мог пропустить кандидатов, уже опробованных первым. hate_crack задействует его автоматически, без какого-либо шага в меню: всякий раз, когда он собирается запустить атаку против хеш-режима, который hashcat считает медленным (bcrypt, scrypt и другие режимы на основе KDF, где узким местом является сам хеш, а не генерация кандидатов), он запускает или переиспользует локальный brain-сервер и добавляет флаги `--brain-*` к вызову hashcat за вас. Быстрый режим не трогается, если только его номер режима не указан в `brain_modes_force`, а режим, указанный в `brain_modes_exclude`, никогда не задействует brain независимо от собственного вердикта hashcat — exclude всегда побеждает.

**Brain — это не то же самое, что покрытие атак, и эти две вещи дополняют друг друга, а не дублируют.** Покрытие (см. выше) устраняет дубликаты на уровне целых правил, строк масок и словарей — оно решает, что запускать в первую очередь, ещё до того, как hashcat вообще запустится. Brain устраняет дубликаты на уровне отдельных кандидатов в пароли, и делает это через постоянный сервер, который переживает любой отдельный вызов hashcat, поэтому он ловит пересечения, которых покрытие не видит: кандидат, достижимый через два разных правила или два разных словаря в рамках одного запуска, и — как демонстрирует круговой тест в `tests/e2e/test_brain_e2e.py` — те же кандидаты, повторно отправленные во втором, отдельном запуске hashcat против той же цели. Оба могут быть включены одновременно без конфликта.

Семь ключей в `config.json` управляют этим, все с префиксом `brain_*`: `brain_enabled` (главный переключатель, по умолчанию включён), `brain_host` (пустое значение означает, что hate_crack управляет локальным сервером на loopback; значение означает подключение только к этому хосту — hate_crack никогда не порождает сервер, которым ему не было сказано управлять), `brain_port` (по умолчанию `6863`), `brain_client_features` (`1` — хешированные пароли, `2` — позиции атаки, `3` — оба; `3` устраняет больше всего дубликатов, но стоит серверу примерно 12 байт ОЗУ на каждого увиденного кандидата), `brain_server_timer` (собственная настройка hashcat, определяющая, как часто сервер записывает свой дамп `.ldmp`/`.admp` на диск, минимум 60 секунд, по умолчанию `300`), и `brain_modes_force` / `brain_modes_exclude` (разделённые запятыми номера хеш-режимов, переопределяющие собственный вердикт hashcat о медленности/быстроте, при этом exclude имеет приоритет).

**У автоматически порождённого сервера вообще нет тайм-аута простоя.** `brain_server_timer` не управляет тем, как долго он остаётся запущенным — этим не управляет ничто; он работает в течение всей жизни породившего его процесса (или пока `shutdown()`/`atexit` его не остановит) и переиспользуется во всех атаках в рамках сессии. При значении по умолчанию `300` это означает запись дампа в `~/.hate_crack/brain/` каждые пять минут, пока hate_crack работает.

Восьмой ключ, `BRAIN_PASSWORD`, находится в `.env`, а не в `config.json`, потому что это общий секрет, а не потому что brain является сторонней интеграцией — он используется только при подключении к удалённому brain-серверу, который вы уже запускаете; автоматически порождённый локальный сервер генерирует собственный случайный пароль для каждой сессии и не требует настройки.

**Пароль brain виден через `ps` в течение всей жизни запуска hashcat,** потому что hashcat принимает его только как аргумент командной строки — формы в виде переменной окружения не существует. Для локального автоматически порождённого сервера это небольшое окно: пароль случаен и ограничен этой одной сессией, поэтому другой локальный пользователь может увидеть его только пока атака действительно выполняется, и он бесполезен после завершения сессии. Пароль общего удалённого brain-сервера не имеет такого смягчения — это одно и то же значение при каждом вызове, видимое любому другому локальному пользователю на машине, пока выполняется любой запуск hate_crack против этого сервера. Относитесь к нему соответственно на общем или мультитенантном оборудовании.

Передайте `--no-brain`, чтобы отключить brain для одного запуска независимо от `brain_enabled`, или установите `brain_enabled` в `false` в `config.json`, чтобы отключить его везде.

**Brain хранит состояние в `~/.hate_crack/brain/`** — небольшой кэш `slow_modes.json` с собственным вердиктом hashcat о медленности/быстроте для каждой версии hashcat, плюс, для автоматически порождённого сервера, его файлы дампов `.ldmp`/`.admp`. Эти дампы являются материалом, производным от кандидатов: они позволяют свежему серверу возобновить работу, зная, что уже было опробовано против цели, что в рамках проекта означает накопление данных, производных от клиента, в домашнем каталоге оператора столько, сколько brain там когда-либо работал. Как и с хранилищем покрытия выше, удаление каталога сбрасывает brain — ранее отклонённый кандидат перестаёт запоминаться, ценой потери устранения дубликатов, которое представлял этот дамп. Если кажется, что brain пропускает работу, которую не должен (устаревший дамп из предыдущего запуска с другим охватом), это и есть решение.

**Удаление `~/.hate_crack/brain/` не очищает осиротевший сервер.** Автоматически порождённый сервер работает в собственной сессии (`start_new_session=True`), поэтому он переживает закрытие терминала или SIGHUP — его останавливает только явное убийство, либо чистый выход породившего его процесса с выполнением обработчика `atexit`. Осиротевший процесс продолжает удерживать loopback-порт. При пустом значении `BRAIN_PASSWORD` по умолчанию вы заметите это как `"[!] ... no brain server could be reached; running without candidate de-duplication"` при каждой атаке в медленном режиме: пароль осиротевшего процесса был эфемерным и умер вместе с породившим его процессом, поэтому hate_crack отказывается принимать порт, на котором тот сидит, вместо того чтобы угадывать пароль, который невозможно проверить. Найдите и остановите его с помощью:

```bash
pgrep -f 'hashcat --brain-server'
kill <pid>
```

после чего следующая атака запускает новый сервер как обычно.

### Уведомления (пункт меню 82)

hate_crack может отправлять push-уведомления Pushover по завершении атак и,
опционально, при взломе отдельных хешей. Все настройки находятся в
пункте главного меню `82 — Notifications`:

1. **Toggle Pushover Notifications [ON/OFF]** — главный переключатель. Сохраняется в `config.json` как `notify_enabled`.
2. **Toggle Per-Crack Notifications [ON/OFF]** — при включении фоновый tailer следит за файлом `.out` и отправляет уведомление на каждый взлом (с агрегацией всплесков за тик). Сохраняется в `config.json` как `notify_per_crack_enabled`. Не может быть включён, пока главный переключатель выключен — сначала включите пункт 1.
3. **Send Test Pushover Notification** — отправляет тестовый push, чтобы вы могли убедиться, что ваша пара токен/пользователь Pushover работает. Работает даже при выключенном главном переключателе.

Учётные данные хранятся в `.env`; остальные параметры настройки доступны только в файле `config.json`:

- `NOTIFY_PUSHOVER_TOKEN`, `NOTIFY_PUSHOVER_USER` (в `.env`) — обязательны для отправки любого push. Ничто в меню их не записывает; редактируйте `.env` самостоятельно.
- `notify_attack_allowlist` — имена атак, которые автоматически соглашаются без запроса `[y/N/always]`. Заполняется автоматически, когда вы отвечаете `always`.
- `notify_suppress_in_orchestrators` (по умолчанию `true`) — заглушает отдельные атаки, объединённые в цепочку Extensive Crack, который вместо этого отправляет одно сводное уведомление. Установите `false`, чтобы получать уведомление на каждую атаку в цепочке. Другие пункты меню, выполняющие несколько проходов (например, Quick Crack с несколькими цепочками правил), не являются оркестраторами и всегда уведомляют о каждом проходе.
- `notify_max_cracks_per_burst` (по умолчанию `5`), `notify_poll_interval_seconds` (по умолчанию `5.0`) — настройка tailer для отдельных взломов. Логику агрегации всплесков см. в `hate_crack/notify/tailer.py`.

### Инструменты для словарей (пункт меню 80)

Подменю Wordlist Tools предоставляет утилиты предобработки словарей на основе бинарников hashcat-utils, а также загрузку словарей с Hashmob.net и Weakpass. Доступ через пункт **80** в главном меню.

| Пункт | Бинарник | Что делает |
|--------|--------|--------------|
| 1 | `len.bin` | Фильтрация по длине — оставить только слова длиной от минимума до максимума |
| 2 | `req-include.bin` | Требуемые классы символов — оставить только слова, содержащие все требуемые типы символов |
| 3 | `req-exclude.bin` | Исключаемые классы символов — удалить слова, содержащие любой исключаемый тип символов |
| 4 | `cutb.bin` | Извлечение подстроки — вырезать диапазон байтов из каждого слова |
| 5 | `splitlen.bin` | Разделение по длине — создать отдельные файлы для каждой длины слова (файлы с именами `01`-`64` в выходном каталоге) |
| 6 | `rli.bin` / `rli2.bin` | Вычитание слов — удалить записи, встречающиеся в одном или нескольких других файлах |
| 7 | `gate.bin` | Шардинг — извлечь каждое N-е слово для распределённого взлома на нескольких машинах |
| 8 | - | Оптимизация словарей — дедупликация и разделение на файлы по длине в каталоге оптимизированных словарей |
| 9 | - | Загрузка словарей с Hashmob.net |
| 10 | - | Загрузка словарей с Weakpass (через BitTorrent) |

**Биты маски классов символов** (используются в пунктах 2 и 3): `1`=строчные, `2`=прописные, `4`=цифра, `8`=символ, `16`=прочее. Складывайте значения: `7` = строчные+прописные+цифры.

**Как предполагается использовать шардинг**: шардинг разбивает один словарь на N равных непересекающихся частей, чтобы работу можно было распределить между несколькими машинами или GPU. Каждая часть *чередуется* (каждая N-я строка), поэтому каждый шард является репрезентативной выборкой всего списка, а не непрерывным фрагментом начала/конца — ни один узел не застревает на взломе только маловероятного хвоста.

Запустите пункт 7 один раз, укажите входной словарь, базовый путь вывода и количество шардов (N). Он записывает все N частей за один проход, с именами из номеров частей с ведущими нулями (`base.001`, `base.002`, … до `base.00N`). Скопируйте одну часть на каждый узел и направьте запуск hashcat на этом узле на неё. На системе с одним GPU шардинг не даёт ускорения, но одна часть всё равно остаётся быстрой репрезентативной выборкой для быстрого пробного прохода перед тем, как браться за полный список.

#### Автоматические проверки обновлений

hate_crack может автоматически проверять GitHub на наличие новых релизов при запуске. Эта функция управляется параметром конфигурации `check_for_updates`:

```json
{
  "check_for_updates": true
}
```

- **`check_for_updates`** — Включает автоматическую проверку версий при запуске (по умолчанию: `true`).
- Когда эта функция включена, hate_crack получает информацию о последнем релизе с GitHub и отображает уведомление, если доступно обновление.
- Проверка выполняется асинхронно и не блокирует запуск. Сетевые ошибки игнорируются без вывода сообщений.

##### Каналы обновлений

| Канал | Флаг | Источник | Что вы получаете |
|---------|------|--------|--------------|
| Release | `--update` | `main` | Последний выпущенный релиз. Это значение по умолчанию и то, что предлагает проверка при запуске. |
| Nightly | `--nightly` | `nightly-dev` | Работа, прошедшая CI, но ещё не выпущенная. |

Версии следуют обычному semver, при этом повышение определяется тем, что фактически
содержится в пакете. Второй компонент меняется **только для новых возможностей**: цикл, содержащий
любой коммит `feat`, направляется к `X.(Y+1).0`, а цикл, состоящий только из исправлений,
документации и рутинных задач, направляется к `X.Y.(Z+1)`.

`nightly-dev` помечает тегами релиз-кандидаты для той версии, к которой направляется пакет
— `v2.20.1rc1`, `v2.20.1rc2`, … — и слияние в `main` повышает ту же
целевую версию до её финального релиза. Кандидаты являются настоящими предрелизами PEP 440, поэтому
они правильно упорядочиваются с обеих сторон:

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

Целевая версия может измениться в середине цикла: первый `feat`, который попадёт в пакет, переводит её с
`X.Y.(Z+1)` на `X.(Y+1).0`, и нумерация кандидатов начинается заново для новой цели.
Номер всегда называет то, чем пакет был бы выпущен на сегодняшний день.

Основной компонент никогда не повышается автоматически — тема с `!` или
футер `BREAKING CHANGE:` считается новой возможностью, потому что автоматическое повышение основного компонента находится в одной
опечатке в строке темы от необратимого опубликованного релиза. Повышение основного компонента — это
явное действие человека: пометьте тегом и отправьте вручную.

Политика находится в `tools/next_version.py`, используется обоими рабочими процессами тегирования и
покрыта модульными тестами в `tests/test_next_version.py`.

Проверка при запуске всегда предлагает только релизы, потому что ночные сборки вообще не публикуют
релиз на GitHub, а проверка читает конечную точку GitHub "latest release" — поэтому
включение `check_for_updates` никогда не переведёт вас на ночную сборку. Сейчас каналы разделяют две вещи:
это, и тот факт, что кандидат является настоящим предрелизом PEP 440, поэтому инструмент, ранжирующий
необработанные номера версий, также считает его старше релиза, которым он становится.

Любой из флагов сначала переключает вашу рабочую копию на соответствующую ветку (и
отказывается это делать, если у вас есть незакоммиченные изменения). Если вы используете ночную сборку
и хотите вернуться к выпущенному коду, `--update` переводит вас обратно на `main`.

#### Автоматическое слияние найденных хешей (только для скачивания left)

При скачивании left-хешей (невзломанных хешей) hate_crack автоматически:
1. Пытается скачать любые найденные (взломанные) хеши из Hashview в качестве вспомогательной операции
2. Объединяет найденные хеши с локальными файлами `.out` (например, `left_1_123.txt.out` или `left_1_123.nt.txt.out` для формата pwdump)
3. Удаляет дублирующиеся записи
4. Очищает временные разделённые файлы после слияния

Это гарантирует, что ваши локальные результаты взлома остаются синхронизированными с централизованной базой данных Hashview при работе с невзломанными хешами.

**Примечание:** Опция download-found скачивает уже взломанные хеши отдельно для справочных целей и не выполняет никакого слияния и не запрашивает взлом.

<hash_type> получается запуском `hashcat --help`

Примеры хешей: 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
```

```
$ ./hate_crack.py <hash file> 1000

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

## Тестирование

Набор тестов в основном работает офлайн и использует моки/фикстуры. Проверки живой сети и
проверки системных зависимостей включаются опционально через переменные окружения.

### Запуск тестов локально

```bash
# Run all tests
uv run pytest -v

# Run specific test
uv run pytest tests/test_hashview.py -v
```

Полный набор тестов также можно запустить командой `make test`.

### Живые тесты (по желанию)

Установите любую из следующих переменных, чтобы включить живые проверки:

- `HASHMOB_TEST_REAL=1` — проверка подключения к Hashmob в реальном времени и меню CLI
- `HASHVIEW_TEST_REAL=1` — проверка меню CLI Hashview в реальном времени
- `WEAKPASS_TEST_REAL=1` — проверка меню CLI Weakpass в реальном времени
- `HATE_CRACK_REQUIRE_DEPS=1` — завершить с ошибкой, если отсутствует `7z`, `transmission-daemon` или `transmission-remote`

### Живой тест загрузки в Hashview

Живой тест загрузки в Hashview по умолчанию пропускается. Чтобы запустить его, установите
переменную окружения и укажите действительные учётные данные в `.env`:

```bash
HATE_CRACK_RUN_LIVE_TESTS=1 uv run pytest tests/test_upload_cracked_hashes.py -v
```

### Живые тесты Hashview против локального Docker-стека

Вместо того чтобы направлять живые тесты на удалённый сервер Hashview, вы можете
заставить набор тестов развернуть локальный Docker-стек [Hashview](https://github.com/hashview/hashview),
заполнить его данными, запустить живые тесты против него и удалить его. Установите
`HASHVIEW_TEST_LOCAL=1` и укажите `HASHVIEW_REPO` на копию репозитория 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
```

Это поднимает `docker compose` в репозитории Hashview, заполняет admin API key,
customer, hashfile и взломанные данные "effective task", затем экспортирует
переменные окружения `HASHVIEW_*`, которые читают тесты. Полезные переменные окружения:

- `HASHVIEW_TEST_LOCAL=1` — включить локальный стек (иначе no-op)
- `HASHVIEW_REPO=<path>` — чекаут Hashview (по умолчанию `~/projects/hashview`)
- `HASHVIEW_KEEP=1` — оставить контейнеры запущенными после сессии (быстрее при повторных запусках)
- `HASHVIEW_LOCAL_PORT=5000` — порт хоста, на котором публикуется приложение

CLI hate_crack учитывает переменные окружения `HASHVIEW_URL` / `HASHVIEW_API_KEY`
(переопределяя `.env`, в котором живут эти два ключа), что позволяет
набору тестов направить CLI на локальный стек без редактирования вашей сохранённой конфигурации.

### End-to-End Install Tests (Local + Docker)

Локальная установка uv tool + выполнение скрипта (использует временный HOME):

```bash
HATE_CRACK_RUN_E2E=1 uv run pytest tests/test_e2e_local_install.py -v
```

Установка/запуск end-to-end на базе Docker (с кэшированием через `Dockerfile.test`):

```bash
HATE_CRACK_RUN_DOCKER_TESTS=1 uv run pytest tests/test_docker_script_install.py -v
```

Docker E2E-тест также загружает небольшое подмножество rockyou и запускает базовый
взлом hashcat для проверки интеграции с внешними инструментами.

Сквозной тест Lima VM (только macOS):

Предварительные требования: должны быть установлены [Lima](https://lima-vm.io/) и `rsync`.

```bash
brew install lima
```

Тестовая виртуальная машина автоматически подготавливается со всеми зависимостями Linux (hashcat, build-essential, curl, git, gzip, p7zip-full, transmission-daemon, ocl-icd-libopencl1, pocl-opencl-icd, uv).

```bash
HATE_CRACK_RUN_LIMA_TESTS=1 uv run pytest tests/test_lima_vm_install.py -v
```

Этот тест проверяет установку и выполнение в лёгкой Linux VM на macOS.

### Структура тестов

- **tests/test_hashview.py**: Комплексный набор тестов для класса HashviewAPI с имитированными ответами API, включая:
  - Список клиентов и проверку данных
  - Тесты аутентификации и авторизации
  - Функциональность загрузки хеш-файлов
  - Полный рабочий процесс создания задачи

Все тесты используют имитированные вызовы API, поэтому они могут выполняться без подключения к серверу Hashview.

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

  (1) Быстрый взлом
  (2) Расширенный взлом по методологии Pure_Hate
  (3) Атака перебором
  (4) Атака по топ-маскам
  (5) Атака по отпечаткам
  (6) Комбинаторные атаки
  (7) Гибридная атака
  (8) Взлом перебором по топ-100 маскам Pathwell
  (9) Атака PRINCE
  (10) Методология Bandrel
  (11) Атака Loopback
  (12) Атака LLM
  (13) Атака OMEN
  (14) Атака по произвольным маскам
  (15) Перебор по цепям Маркова
  (16) Атака по N-граммам
  (17) Атака перестановками
  (18) Атака по случайным правилам
  (19) Атака по парольным фразам Combipow
  (20) Атака PCFG
  (21) Атака PRINCE-LING
  (22) Атака Spoonman
  (23) Атака Rosetta
  (24) Перебор по корпоративным маскам
  (25) Атака по умным маскам

  (80) Инструменты для словарей
  (81) Инструменты для файлов правил
  (82) Уведомления
  (83) Инструменты для масок

  (93) Перегенерировать .out из POT-файла
  (94) Hashview API
  (95) Анализ хешей с помощью Pipal
  (96) Экспорт вывода в формат Excel
  (97) Показать взломанные хеши
  (98) Показать README
  (99) Выход

Выберите задачу:
```

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.

```
Какое(ие) правило(а) вы хотите запустить?
(1) best64.rule
(2) d3ad0ne.rule
(3) T0XlC.rule
(4) dive.rule
(99) YOLO...запустить все правила
Введите список правил, разделённых запятыми, которые вы хотите запустить. Для последовательного применения правил используйте символ +.
Например, 1+1 запустит best64.rule дважды подряд, а 1,2 запустит best64.rule, а затем d3ad0ne.rule последовательно.
Выбирайте с умом:
```




#### 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
```

---

[Read more](https://github.com/trustedsec/hate_crack)
Скачать инструмент