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.9k287411天前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/ 下载预编译的二进制文件,并在 `config.json` 中将 `hcatPath` 设置为其所在位置。

### 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 会在首次运行时为你迁移:集成设置会被复制到新的 `0600` `.env` 中,然后从 `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` 由 schema 生成;在修改 `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 掩码集
- 通过 uv 安装 Python 依赖项,并在 `~/.local/bin/hate_crack` 处创建 CLI 垫片

```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`:通过 Atomic Agents 生成结构化(JSON)LLM 候选。
- `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` 命令会在 `~/.local/bin/hate_crack` 创建一个 bash shim,该 shim 从仓库目录运行,因此无论你当前的工作目录是什么,配置和资源都能被找到。

配置还会在以下位置搜索:
- 仓库根目录和包目录
- `~/.hate_crack`

**注意:** `config.json` 中的 `hcatPath` 仅用于指定 hashcat 二进制文件的位置(如果 hashcat 已在 PATH 中,则此项可选)。Hate_crack 资源(hashcat-utils、princeprocessor、pcfg_cracker、Corporate_Masks、omen)从仓库目录加载,并由 `make install` 自动打包。

### 作为脚本运行
该脚本使用 `uv` shebang。使其可执行并运行:

```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` 以与菜单行为一致。

五个菜单项仍然仅支持交互式使用,因为它们需要单个标志无法携带的输入:Markov 暴力破解、Random Rules、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 年 7 月之前创建的克隆。当时已发布的历史被重写,以移除一些本就不应被提交的文件,这导致每个提交都获得了新的 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 资源并未打包到已安装的软件包中。

**理解路径:**
- config.json 中的 `hcatPath` → 指向 **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` > 该键自身的 home 文件(`.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
```

### 运行 Linter 和类型检查

在推送更改之前,请在本地运行这些检查。使用 `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 Hooks (prek)

Git hooks 由 [prek](https://github.com/j178/prek)(v0.3.3+)管理。使用以下命令安装 hooks:

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

这会使用 pre-commit 本地仓库 TOML schema 安装 `prek.toml` 中定义的钩子:
- **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,因此当输出被管道传输时会保持关闭。

那些先打印列表再接受键入输入的选取器(wordlists、rules、Weakpass 列表、Hashview wordlist 和 rule ID)在所有后端上都接受 Up/Down,无需 `HATE_CRACK_ARROW_MENU`。Up 填入最后列出的键,再按 Up 填入前一个,Down 则返回;你仍然可以改为输入数字、路径或像 `1,3` 这样的列表。在方向键填入的键之后直接输入 `,`、`+` 或 `-` 会扩展它。在 `plain` 和 `rich` 后端下,这是通过将列出的键加载到该次提示的 readline 历史记录中实现的,因此你自己的历史记录会在之后恢复,并且无法从列表提示内部访问。

### 开发依赖

可选的 `[dev]` 组包括:
- **ty** - 静态类型检查器
- **ruff** - 快速的 Python linter 和格式化工具
- **pytest** - 测试框架
- **pytest-cov** - 覆盖率报告

-------------------------------------------------------------------
常用选项:
- `--download-hashview`:在破解前从 Hashview 下载哈希。
- `--hashview`:交互式 Hashview 菜单,用于管理哈希、wordlists 和任务。
- `--hashview --help`:显示 Hashview 命令行选项。
- `--weakpass`:从 Weakpass 下载 wordlists。
- `--rank`:仅显示特定层级的 Weakpass wordlists(0=全部,-1=S/A/B 层级)。等级:7=S,6=A,5=B,4=C,3=D,2=E,1=F。
- `--hashmob`:从 Hashmob.net 下载 wordlists。
- `--hashmob-masks`:从 Hashmob.net 下载 masks。
- `--download-torrent <FILENAME>`:下载特定的 Weakpass torrent 文件。
- `--download-all-torrents`:从缓存下载所有可用的 Weakpass torrents。
- `--wordlists-dir <PATH>` / `--optimized-wordlists-dir <PATH>`:覆盖 wordlist 目录。
- `--pipal-path <PATH>`:覆盖 pipal 路径。
- `--restore-potfile`:启动时从 hashcat POT 文件重建 `<hashfile>.out`,替换任何现有内容,然后继续进入正常菜单。没有此标志时,POT 查找仅在 `.out` 尚不存在时运行。菜单选项 93 可按需执行相同操作,并带有确认提示。
- `--maxruntime <SECONDS>`:覆盖最大运行时间。
- `--bandrel-basewords <PATH>`:覆盖 bandrel basewords 文件。
- `--update`:更新到最新版本并重新安装。如果检出位于其他分支,则将其切换到 `main`,因为发布标签位于该分支。
- `--nightly`:改为从 `nightly-dev` 分支更新到最新 nightly。Nightlies 已通过 CI,但不属于已发布的版本。也可以写作 `--update --nightly`。
- `--no-optimized-kernel`(或 `--no-optimize`):在整个运行过程中绝不向 hashcat 传递 `-O`。覆盖 `config.json` 中的 `optimizedKernelAttacks`,并移除你在 `hcatTuning` 中放入的任何 `-O`。不会向配置写回任何内容,因此仅适用于本次运行。与子命令一起使用时,请将其放在子命令之前:`./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`)。在规则 ID 提示符处输入 `a`(或 `all`)可下载所有列出的规则,而不是单个规则
- **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 与 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"
```

#### 配置

在 `.env` 中设置 Hashview 凭据(它们是集成设置,因此不存放在 `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 会验证 Hashview 服务器的 TLS 证书,连接到使用自签名或内部 CA 证书的 Hashview 将会失败,直到该证书被信任(将其添加到系统信任存储中,或使用由系统已信任的 CA 签发的证书)。如果无法做到这一点,请设置 `HASHVIEW_VERIFY_TLS=false` —— 当验证关闭时,hate_crack 会在每次进程启动时打印一行警告,指明主机名,因为禁用验证会失去对伪造服务器或路径上攻击者拦截连接的保护。

#### LLM 配置

LLM 攻击(选项 12)和 Rosetta 掩码攻击(选项 23)使用本地模型生成候选。在 `.env` 中配置模型、上下文窗口和请求超时:

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

**下面的 `OLLAMA_*` 键适用于所有后端,而不仅仅是 Ollama。** 它们保留该前缀是因为 `OLLAMA_HOST` 与 Ollama 自身 CLI 读取的是同一个变量,重命名它们会破坏所有现有的 `.env` 文件,且没有任何功能上的收益——vLLM 或 OpenAI 兼容服务器也希望在相同的名称下使用相同的主机、模型、超时、上下文和采样参数。`LLM_BACKEND` 仅选择请求的构造方式。

- **`OLLAMA_MODEL`** — 用于候选生成的 Ollama 模型(默认:`qwen3:4b-instruct`)。LLM 攻击使用结构化(JSON)输出,因此请选择具有良好工具/JSON 支持的模型。
- **`OLLAMA_NUM_CTX`** — 模型的上下文窗口大小(默认:`8192`)。在引入语料库统计之前,该值为 `2048`,太小而无法容纳所给的提示:500 个采样明文在系统提示和响应之前大约有 2,000–3,500 个 token,因此 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 也会被检查:不是环回、私有或链路本地(且不是 `localhost` 或 `.local`/`.internal`/`.lan`/`.localdomain` 名称)的目标会因目标而被拒绝,此检查无法解析的主机名也会被拒绝,故障关闭,而不是让无法验证的目标通过。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` 中设置它,或将其导出为真实环境变量以在单次运行中覆盖该值——它与 Ollama 自身 CLI 读取的是同一个变量名。
- **`LLM_BACKEND`** — 要与之通信的 OpenAI 兼容服务器:`ollama`(默认)、`vllm` 或 `openai`(用于通用服务器)。每个后端都使用相同的 `/v1` 聊天补全 API,因此这仅选择它们不同的两个请求构造细节:`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=""`。如果服务器强制要求,请将其设置为真实值——使用 `--api-key` 启动的 vLLM 服务器否则会返回 401。
- 在使用 LLM Attack 之前,确保 Ollama 正在运行且模型已拉取(`ollama pull qwen3:4b-instruct`)——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. **Wordlist** — 从样本词表派生基础词。
3. **Cracked passwords** — 将本次会话中已恢复的明文(`<hashfile>.out`)反馈给模型,使其能够推断目标组织自身的密码习惯(基础词、季节、年份、后缀、leet 变体),并生成相同风格的*新*候选密码。此选项仅在至少破解出一个哈希后才会列出;整个文件会像 Wordlist 模式一样进行统计分析(参见上文 `ollamaMaxSampleLines`)。

#### PCFG 配置

PCFG Attack(选项 20)和 PRINCE-LING Attack(选项 21)使用 `pcfg_cracker` 子模块。在 `config.json` 中配置它们:

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

- **`pcfgRuleset`** — 要使用的已训练语法名称(默认:`DEFAULT`),解析为 `pcfg_cracker/Rules/<name>/`。使用 pcfg_cracker 的 `trainer.py` 训练你自己的语法,并将此项设置为规则集名称。
- **`pcfgMaxCandidates`** — `pcfg_guesser.py` 为 PCFG 攻击输出的最大候选数(默认:`50000000`)。
- **`pcfgPrinceLingMaxCandidates`** — `prince_ling.py` 写入缓存的 PRINCE 基础词表的最大基础词数(默认:`10000000`)。

### 优化内核(`optimizedKernelAttacks`)

hashcat 的 `-O` 标志会选择优化内核,这些内核速度显著更快,但会限制候选长度(大约 31 个字符,某些模式下更低),并会静默跳过任何更长的内容。`config.json` 中的 `optimizedKernelAttacks` 列出了使用 `-O` 运行的攻击;从列表中省略某个攻击即可使用全长内核运行它。`config.json.example` 中的列表与不存在 `config.json` 时应用的內置默认值一致。

有四种攻击遵循该设置,但默认**不**进行优化,因为它们提供的候选可能超过 `-O` 上限——将它们添加到列表中以选择启用:

- `hcatNgramX`、`hcatOllama`、`hcatOmen`、`hcatLMtoNT`

要在单次运行中在不编辑配置的情况下全局关闭 `-O`,请传递 `--no-optimized-kernel`(短形式 `--no-optimize`)。它会覆盖所有攻击的列表,并且还会移除写入 `hcatTuning` 中的 `-O`,否则无论列表如何,该 `-O` 都会传递给 hashcat。

名称精确匹配,无法识别的条目会在启动时报告,而不是被忽略。请注意,委托给另一个攻击的攻击由它所委托的攻击控制,而不是由它自己的名称控制:PRINCE-LING 遵循 `hcatPrince`,而 Spoonman、Rosetta 和 LLM 模式规则模式遵循 `hcatQuickDictionary`。

### 攻击覆盖跟踪(`coverage_enabled`)

在长期任务中,同一个哈希文件会在许多会话中被攻击,使用轮换的词表、规则文件和掩码列表,很容易花费数小时重新运行你已经覆盖过的内容——尤其是因为同一条规则行存在于多个规则文件中。hate_crack 记录它已经针对每个哈希文件运行过的内容,并提供跳过重叠部分。

覆盖是**按条目记录,而不是按文件记录**:单个规则行和单个 `.hcmask` 行,每个都与其运行时所针对的词表配对。这正是它能够识别出你今天运行的自定义规则文件重复了 `best64.rule` 上周已覆盖的 40 条规则的原因,也是为什么一条规则仅对它尝试过的特定词表才被视为“已覆盖”——相同的规则在不同的语料库上会尝试完全不同的候选。

哈希文件通过其内容的 sha256 来标识,因此覆盖在重命名或在会话之间移动后仍然有效。词表以相同方式标识,摘要会根据大小和 mtime 进行记忆化,因此多 GB 的语料库只会被哈希一次,而不是在每次攻击时都进行哈希。

只有在确实有可跳过的内容时,你才会被提示:

```
[*] 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、Markov 暴力破解和 LLM 模式没有固定的集合可供差异比较,因此它们会被记录为已运行,除此之外不做处理。链式规则文件(`-r a -r b`)作为单个单元跟踪,而不是逐条目跟踪,因为 hashcat 会应用两个文件的*笛卡尔积*,丢弃单独一行会静默地移除它所参与的每一个组合。
- **`--loopback` 运行会被记录,但永远不会被过滤。** hashcat 会将新破解的明文作为*额外*候选重新输入,因此这样的运行会尝试完整的词表和规则集,再加上那些回收明文所能达到的任何内容。这使得两个方向不对称:记录它是合理的,因此之后对同一词表和规则的普通运行会被正确识别为重复,但第二次 loopback 运行有更多破解可回收,并且永远不会被跳过。

在 `config.json` 中将 `coverage_enabled` 设置为 `false` 可关闭此功能,或为单次运行传递 `--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 意味着*什么都没*运行。一个被部分过滤的 pass —— 有些条目被跳过,有些被尝试 —— 仍然以 `0` 退出,因为攻击确实做了工作。

### hashcat brain 支持(`brain_enabled`)

hashcat 本身自带一个 "brain" —— 一个小型服务器,运行中的 hashcat 实例会将候选密码流式传输给它,这样针对同一目标的第二次运行就可以跳过第一次已经尝试过的候选密码。hate_crack 会自动启用它,无需任何菜单步骤:每当它即将针对 hashcat 报告为慢速的哈希模式(bcrypt、scrypt 以及其他由 KDF 支持的模式,其中哈希本身而非候选密码生成才是瓶颈)发起攻击时,它会启动或复用一个本地 brain 服务器,并为你向 hashcat 调用添加 `--brain-*` 标志。快速模式则不会被处理,除非其模式编号列在 `brain_modes_force` 中;而列在 `brain_modes_exclude` 中的模式无论 hashcat 自己的判定如何都绝不会启用 brain —— exclude 始终优先。

**Brain 与攻击覆盖率不是一回事,两者是互补的而非冗余的。** 覆盖率(上文)在整条规则、掩码行和字典的层面上进行去重 —— 它决定一开始要启动什么,在 hashcat 运行之前就已完成。Brain 则在单个候选密码的层面上进行去重,并且它通过一个持久化服务器来实现,该服务器的生命周期长于任何一次 hashcat 调用,因此它能捕获覆盖率看不到的重叠:同一次运行中可通过两条不同规则或两个不同字典到达的候选密码,以及 —— 正如 `tests/e2e/test_brain_e2e.py` 中的往返测试所演示的 —— 在针对同一目标的第二次独立 hashcat 运行中重新发送的相同候选密码。两者可以同时启用而不会冲突。

`config.json` 中有七个键控制它,全部位于 `brain_*` 前缀下:`brain_enabled`(主开关,默认开启)、`brain_host`(为空表示 hate_crack 在回环地址上管理一个本地服务器;有值表示仅连接到该主机 —— hate_crack 绝不会生成一个它未被要求管理的服务器)、`brain_port`(默认 `6863`)、`brain_client_features`(`1` 哈希密码,`2` 攻击位置,`3` 两者 —— `3` 去重最多,但服务器每看到一个候选密码大约消耗 12 字节 RAM)、`brain_server_timer`(hashcat 自身的设置,控制服务器将 `.ldmp`/`.admp` 转储写入磁盘的频率,最小 60 秒,默认 `300`),以及 `brain_modes_force` / `brain_modes_exclude`(逗号分隔的哈希模式编号,用于覆盖 hashcat 自身的慢速/快速判定,exclude 优先)。

**自动生成的服务器完全没有空闲超时。** `brain_server_timer` 并不控制它保持运行的时间 —— 没有任何东西控制;它会运行到生成它的进程结束(或直到 `shutdown()`/`atexit` 停止它),并在整个会话中的每次攻击中被复用。在默认值 `300` 下,这意味着只要 hate_crack 在运行,每五分钟就会向 `~/.hate_crack/brain/` 写入一次转储。

第八个键 `BRAIN_PASSWORD` 位于 `.env` 而非 `config.json` 中,因为它是共享密钥,而不是因为 brain 是第三方集成 —— 它仅在你连接到已自行运行的远程 brain 服务器时使用;自动生成的本地服务器会为每个会话生成自己的随机密码,无需配置。

**brain 密码在 hashcat 运行的整个生命周期内对 `ps` 可见,** 因为 hashcat 只接受它作为命令行参数 —— 没有环境变量形式。对于本地自动生成的服务器,这是一个很小的窗口:密码是随机的且仅限该会话,因此其他本地用户只能在攻击实际运行时看到它,而一旦会话结束它就无用了。共享远程 brain 服务器的密码则没有这样的缓解措施 —— 它在每次调用中都是相同的值,只要有任何针对该服务器的 hate_crack 运行正在进行,机器上的任何其他本地用户都能看到它。在共享或多租户硬件上应据此对待。

传入 `--no-brain` 可在单次运行中禁用 brain,无论 `brain_enabled` 如何;或在 `config.json` 中将 `brain_enabled` 设为 `false` 以在所有地方关闭它。

**Brain 将状态保存在 `~/.hate_crack/brain/` 中** —— 一个小的 `slow_modes.json` 缓存,保存 hashcat 自身针对每个 hashcat 版本的慢速/快速判定,另外对于自动生成的服务器,还有其 `.ldmp`/`.admp` 转储文件。这些转储是候选密码派生的材料:它们让新服务器在恢复时知道针对某个目标已经尝试过什么,这在一次渗透项目中意味着客户派生的数据会在操作员的主目录中累积,只要 brain 曾在那里运行过。与上面的覆盖率存储一样,删除该目录会重置 brain —— 之前被拒绝的候选密码不再被记住,代价是失去该转储所代表的去重能力。如果 brain 看起来在跳过它不该跳过的工作(来自之前一次范围不同的运行的陈旧转储),这就是解决办法。

**删除 `~/.hate_crack/brain/` 并不会清除孤立的服务器。** 自动生成的服务器在自己的会话中运行(`start_new_session=True`),因此它能在终端关闭或 SIGHUP 后存活 —— 只有显式 kill,或生成它的进程干净退出并运行其 `atexit` 处理器,才能停止它。孤立的服务器会继续占用回环端口。在默认的空 `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 可以在攻击完成时发送 Pushover 推送通知,并且可选地在单个哈希被破解时也发送通知。所有控制项都位于主菜单选项 `82 — Notifications` 下:

1. **切换 Pushover 通知 [开/关]** — 总开关。会以 `notify_enabled` 持久化到 `config.json`。
2. **切换每次破解通知 [开/关]** — 开启时,后台 tailer 会监视 `.out` 文件,并为每次破解推送一条通知(带每 tick 突发聚合)。会以 `notify_per_crack_enabled` 持久化到 `config.json`。总开关为关时无法启用 — 请先启用选项 1。
3. **发送测试 Pushover 通知** — 触发一条预设推送,以便你确认自己的 Pushover token/user 对可用。即使总开关为关也能工作。

凭据位于 `.env` 中;其余调优参数仅通过配置文件 `config.json` 设置:

- `NOTIFY_PUSHOVER_TOKEN`、`NOTIFY_PUSHOVER_USER`(位于 `.env`)— 任何推送触发都需要它们。菜单中没有任何内容会写入这些值;请自行编辑 `.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)

字典工具子菜单提供由 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` 中进行单元测试。

启动检查只会提供发布版本,因为 nightly 构建根本不发布任何 GitHub release,而该检查读取的是 GitHub 的“latest release”端点——因此启用 `check_for_updates` 永远不会将你拉到 nightly 上。现在有两件事将通道区分开来:这一点,以及候选版本是真正的 PEP 440 预发布版本,因此对原始版本号进行排序的工具也会将其视为比它最终成为的发布版本更旧。

任一标志都会先将你的检出切换到对应分支(如果有未提交的更改则拒绝执行)。如果你正在运行 nightly 并想回到已发布的代码,`--update` 会将你移回 `main`。

#### 自动合并已找到的哈希(仅下载未破解哈希)

在下载左侧哈希(未破解哈希)时,hate_crack 会自动:
1. 尝试从 Hashview 下载任何已找到(已破解)的哈希作为辅助操作
2. 将已找到的哈希与本地 `.out` 文件合并(例如,对于 pwdump 格式为 `left_1_123.txt.out` 或 `left_1_123.nt.txt.out`)
3. 移除重复条目
4. 合并后清理临时拆分文件

这确保你在处理未破解哈希时,本地破解结果与 Hashview 的集中数据库保持同步。

**注意:** 下载已找到选项会单独下载已破解的哈希以供参考,不会执行任何合并或提示进行破解。

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

## 测试

测试套件主要离线运行,使用 mock/fixture。实时网络检查和系统依赖检查通过环境变量选择启用。

### 本地运行测试

```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` — 实时 Hashview CLI 菜单检查
- `WEAKPASS_TEST_REAL=1` — 实时 Weakpass CLI 菜单检查
- `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
```

### 针对本地 Docker 栈的实时 Hashview 测试

无需将实时测试指向远程 Hashview 服务器,你可以让测试套件启动一个本地 [Hashview](https://github.com/hashview/hashview) Docker 栈,对其进行初始化,针对其运行实时测试,然后将其拆除。设置 `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
```

这会在 Hashview 仓库中启动 `docker compose`,初始化一个管理员 API 密钥、一个客户、一个哈希文件以及破解的“有效任务”数据,然后导出测试所读取的 `HASHVIEW_*` 环境变量。有用的环境变量:

- `HASHVIEW_TEST_LOCAL=1` — 启用本地栈(否则为空操作)
- `HASHVIEW_REPO=<path>` — Hashview 检出目录(默认 `~/projects/hashview`)
- `HASHVIEW_KEEP=1` — 会话结束后保留容器运行(加快重新运行速度)
- `HASHVIEW_LOCAL_PORT=5000` — 应用发布的主机端口

hate_crack CLI 遵循 `HASHVIEW_URL` / `HASHVIEW_API_KEY` 环境变量(覆盖这两个键所在的 `.env` 文件),这使得测试套件可以将 CLI 指向本地栈,而无需编辑你持久化的配置。

### 端到端安装测试(本地 + Docker)

本地 uv 工具安装 + 脚本执行(使用临时 HOME):

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

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

测试 VM 会自动配置所有 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
```

此测试验证在 macOS 上的轻量级 Linux 虚拟机中的安装和执行。

### 测试结构

- **tests/test_hashview.py**:HashviewAPI 类的综合测试套件,使用模拟 API 响应,包括:
  - 客户列表和数据验证
  - 身份验证和授权测试
  - Hashfile 上传功能
  - 完整的任务创建工作流

所有测试均使用模拟 API 调用,因此无需连接到 Hashview 服务器即可运行。

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

  (1) 快速破解
  (2) 广泛的 Pure_Hate 方法论破解
  (3) 暴力破解攻击
  (4) 顶级掩码攻击
  (5) 指纹攻击
  (6) 组合攻击
  (7) 混合攻击
  (8) Pathwell Top 100 掩码暴力破解
  (9) PRINCE 攻击
  (10) Bandrel 方法论
  (11) 回环攻击
  (12) LLM 攻击
  (13) OMEN 攻击
  (14) 临时掩码攻击
  (15) 马尔可夫暴力破解攻击
  (16) N-gram 攻击
  (17) 排列攻击
  (18) 随机规则攻击
  (19) Combipow 密码短语攻击
  (20) PCFG 攻击
  (21) PRINCE-LING 攻击
  (22) Spoonman 攻击
  (23) Rosetta 攻击
  (24) 企业掩码暴力破解
  (25) 智能掩码攻击

  (80) 词表工具
  (81) 规则文件工具
  (82) 通知
  (83) 掩码工具

  (93) 从 POT 文件重新生成 .out
  (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
* Corpus lines may carry a hash in front of the password, as cracked output does. A leading field is dropped only when it has the shape of a hash (a hex digest at a known length, or a crypt-style `$id$` string), so `hash:salt:plain` is handled while a plaintext or wordlist entry containing a colon survives intact. `$HEX[...]` plaintexts are decoded. If most lines look like an uncracked dump rather than cracked output, `coverage.txt` records the count and the attack warns — the derived basewords and rules would otherwise be meaningless without any error being raised

#### Rosetta Attack
Mines hashcat `--debug-mode 5` logs for the basewords and rules that already cracked something, then runs their full cross product. Powered by [HashcatRosetta](https://github.com/bandrel/HashcatRosetta), the same library behind [Analyze Hashcat Rules](#analyze-hashcat-rules-rule-file-tools-option-5).

No setup is needed to feed it: `_add_debug_mode_for_rules` appends `--debug-mode 5 --debug-file` to every rule-based hashcat invocation hate_crack makes, so the logs accumulate in `hcatDebugLogPath` (`~/.hate_crack/hashcat_debug` by default, one file per session) as a side effect of normal use. A mode 5 log records only candidates that cracked a hash, in the form `baseword:rule:candidate:wordlist`, which is what makes both halves known-productive against this target population; the trailing wordlist field also shows which list is earning its keep on a multi-wordlist run. HashcatRosetta parses mode 4 and mode 5 alike, so logs written before the switch are still read.

The value is in the cross product rather than the recorded pairs. A pair present in a log has already cracked its hash and will not crack another, but a rule that worked on one baseword has usually never been tried against the others — so N basewords and M rules yield close to N x M untried candidates.

The menu first asks how to rank rules — choices 1-3 below, plus a fourth, unrelated mode:

* Rules can be ranked by application frequency, by how many distinct basewords each one worked on, or by how many unique candidates each one generated. Frequency is the default; baseword spread is the better choice when the goal is a rule set that generalizes past the specific words it was learned from
* Only after one of those three is picked does hate_crack list the logs found in `hcatDebugLogPath` newest-first with their sizes; pick one, pick all of them (up to 20), or type a path to a log from elsewhere
* Prompts for how many top rules to keep and how many top basewords. Both default to all — a blank answer keeps every winning rule the logs contain, and zero means the same thing. Enter a number to cap either. The keyspace is the product of the two and is printed before hashcat starts
* Output is written beside the hash file in `<hash file>.rosetta/` as `basewords.txt` and `rules.rule`, alongside the other ephemeral wordlists, and the directory is removed on exit by the temp-file cleanup
* Reading stops at 1,000,000 debug lines, since the analyzer needs the whole batch in memory at once. Truncation is reported on the console rather than assumed harmless — logs from a long run routinely exceed this, in which case the newest log is the one worth selecting
* **LLM Mask Attack** (4) - a different mode entirely, and the only one that needs no debug logs. Prompts for a natural-language description of the passwords you expect (length, character patterns, symbols, etc.), sends it to the locally configured Ollama model, writes the returned masks to `<hash file>.hcmask`, and runs a `-a 3` hashcat mask attack against them

#### Corporate Masks Brute Force
Statistical masks (8-14 characters) derived from analysis of 3.2M NTLM hashes cracked on real engagements. Powered by [Corporate_Masks](https://github.com/golem445/Corporate_Masks), these masks encode realistic password patterns from successful penetration tests.

* Prompts for minimum and maximum mask length (default 8-10)
* Longer lengths cost exponentially more keyspace—start with 8-10 for speed, or 8-12 for thoroughness
* Each mask file is run as a separate hashcat invocation in ascending length order
* Gracefully handles missing mask files (skips them) and absent submodule (prints warning and returns)
* Supports optimized kernels (`-O` flag) for faster cracking
* Ctrl-C during one length aborts remaining lengths

#### Wordlist Tools (option 80)
A submenu of wordlist preprocessing utilities using hashcat-utils binaries. All tools read from and write to files on disk. All file and directory path prompts support tab completion.

| Key | Tool | Description |
|-----|------|-------------|
| 1 | Filter by Length | Keep only words between a min and max length (`len.bin`) |
| 2 | Require Char Classes | Keep words that include all char classes in mask (`req-include.bin`). Mask: 1=lower, 2=upper, 4=digit, 8=symbol (additive) |
| 3 | Exclude Char Classes | Remove words containing any char class in mask (`req-exclude.bin`). Same mask encoding |
| 4 | Extract Substring | Cut bytes from each word at a given offset and optional length (`cutb.bin`) |
| 5 | Split by Length | Create per-length files in an output directory (`splitlen.bin`) |
| 6 | Subtract Wordlist | Remove lines from a wordlist that appear in one or more remove files. Mode 1 uses `rli2.bin` (single file); mode 2 uses `rli.bin` (multiple files) |
| 7 | Shard Wordlist | Split a wordlist into N equal, interleaved parts in one run, written as `base.001`…`base.00N` for distributed cracking (`gate.bin`) |
| 8 | Optimize Wordlists | Dedupe and split the selected wordlists into per-length files under an output directory |
| 9 | Download from Hashmob.net | Browse and download wordlists from Hashmob.net into the configured wordlist directory |
| 10 | Download from Weakpass | Browse and download Weakpass wordlist torrents, with automatic extraction |
| 11 | Hashmob Downloads | Access a submenu for downloading Hashmob archives (yearly full-found corpora) and combined-left lists (per-mode uncracked hashes) |

All binaries are in `hate_crack/hashcat-utils/bin/`.

#### Rule File Tools (option 81)
Preprocesses hashcat rule files using `cleanup-rules.bin` and `rules_optimize.bin` from hashcat-utils, and downloads rule files from Hashmob.net.

* **Clean** (1) - removes invalid syntax and duplicate rules using `cleanup-rules.bin`. Useful after combining rule files or downloading rules from external sources.
* **Optimize** (2) - consolidates redundant operations using `rules_optimize.bin`. Reduces rule file size and improves cracking speed.
* **Clean and optimize** (3) - runs both operations in sequence via a temporary file, then writes the final result.
* **Download rules from Hashmob.net** (4) - fetches rule files into the configured `rulesDirectory`.
* **Analyze Hashcat rules** (5) - opcode frequency analysis of a rule file, powered by HashcatRosetta.

The three preprocessing operations read from an input file and write to a separate output file (original is never modified).

#### Download Rules from Hashmob.net (Rule File Tools option 4)
Downloads the latest rule files from Hashmob.net's rule repository. These rules are curated and optimized for password cracking and can be used with the Quick Crack and Loopback Attack modes.

* Downloads rule sets in parallel using a thread pool (up to 4 concurrent downloads)
* Skips rules already downloaded locally
* Reports download summary with success/failure counts
* Stores rules in the configured rules directory

#### Analyze Hashcat Rules (Rule File Tools option 5)
Powered by HashcatRosetta (https://github.com/bandrel/HashcatRosetta), this feature analyzes hashcat rule files to provide detailed insights into rule composition and complexity.

* Prompts for a rule file path
* Displays frequency analysis of rule opcodes (operations)
* Helps understand what transformations a rule set performs
* Useful for rule debugging and optimization

#### Mask Tools (option 83)
Downloads mask files from Hashmob.net. This is a minimal submenu today — masks
have no local file-tooling counterpart to the rule/wordlist cleanup and
optimization utilities, only a download capability.

* **Download masks from Hashmob.net** (1) - fetches mask files into the hate_crack masks directory.

#### Download Masks from Hashmob.net (Mask Tools option 1)
Downloads mask files from Hashmob.net's mask repository into the hate_crack masks directory for use with mask-based attacks.

* Downloads mask sets in parallel using a thread pool (up to 4 concurrent downloads)
* Skips masks already downloaded locally
* Reports download summary with success/failure counts
* Stores masks in the configured masks directory used by the Ad-hoc Mask Attack
* Supports interactive listing, range selection, and browsing of available mask files

#### Download Wordlists from Hashmob.net (Wordlist Tools option 9)
Downloads wordlists from Hashmob.net's collection of cracked passwords and commonly used wordlists.

* Interactive menu for browsing available wordlists
* Progress tracking for large downloads
* Stores wordlists in configured wordlist directory

#### Weakpass Wordlist Menu (Wordlist Tools option 10)
Interactive menu for downloading and managing wordlists from Weakpass.com via BitTorrent, pulling the listing from Weakpass's public REST API.

* Browse available Weakpass wordlists, showing tier (S-F) and crack rate (%)
* Filter by tier using the `--rank` flag (7=S, 6=A, 5=B, 4=C, 3=D, 2=E, 1=F; -1 defaults to S/A/B)
* Download specific wordlists by selection
* Automatic extraction of compressed archives
* Progress tracking for torrent downloads

#### Hashmob Downloads (Wordlist Tools option 11)
Access a submenu for downloading large-scale password corpora and specialized wordlists from Hashmob.net.

**Archives** - Downloads yearly full-found password corpora (multi-GB archives containing all cracked passwords from a given year)
* Requires confirmation before downloading -- these archives are large (the listing may show "(unknown size)" since Hashmob's API doesn't currently report a file size per archive)
* Lists all available archives across every year as one globally-numbered list to browse and pick from by index, rather than a per-year picker
* Accepts `a` (or `all`) at the selection prompt to download every listed archive, one at a time. A single confirmation naming the archive count and the summed size covers the whole batch; an archive already on disk at its listed size is skipped, one whose size does not match is re-downloaded, and a failure is counted rather than aborting the rest
* Stores archives in the configured wordlist directory for extraction and use

**Combined Left Lists** - Downloads per-hashcat-mode combined lists of uncracked ("left") hashes from Hashmob.net
* Each list is a set of hashes, not plaintexts, still awaiting a crack for that hashcat mode
* Useful for spotting overlap between your own hash list and hashes the community hasn't cracked yet
* Supports mode selection from the listed hash counts per algorithm

-------------------------------------------------------------------
### Version History

The full, per-release changelog now lives in [CHANGELOG.md](https://github.com/trustedsec/hate_crack/blob/main/CHANGELOG.md).
下载工具