baobao26/mcp-hayabusa
GitHub: baobao26/mcp-hayabusa
一个封装 Hayabusa CLI 的 MCP 服务,通过 Model Context Protocol 让 AI 客户端能够扫描 Windows EVTX 事件日志并浏览检测规则。
Stars: 0 | Forks: 0
# mcp-hayabusa
一个封装了 [Hayabusa](https://github.com/Yamato-Security/hayabusa) CLI 的 MCP server,通过 Model Context Protocol 暴露了用于分析 Windows EVTX 事件日志文件的 `scan_evtx` 工具,以及用于浏览其检测规则集的 `get_hayabusa_rules` 工具。
## 环境要求
- Python 3.10+(使用了 `X | None` 类型提示语法)
- `mcp` 库(`pip install -r requirements.txt`)
- Hayabusa CLI,解压至 `./hayabusa/`(参见下方的安装说明)
## 安装说明
```
pip install -r requirements.txt
python scripts/download_hayabusa.py
```
`download_hayabusa.py` 会检测您的操作系统/架构,从 Hayabusa 最新的 GitHub release 下载匹配的发布资产,并将其解压到 `./hayabusa/`(包含二进制文件、`rules/`、`config/`)。此目录已被 gitignore —— 克隆仓库后请重新运行此脚本,或者在您想获取更新的 Hayabusa 版本时运行。
可选操作,用于手动测试:
```
python scripts/download_sample_evtx.py
```
从 [EVTX-ATTACK-SAMPLES](https://github.com/sbousseaden/EVTX-ATTACK-SAMPLES) 下载一个真实的攻击技术样本(`4794_DSRM_password_change_t1098.evtx`)到 `./samples/`(同样已被 gitignore)。
## 运行服务器
```
python server.py
```
该服务器通过 stdio 通信,因此它旨在由 MCP 客户端(例如 Claude Code)启动,而不是以交互方式运行。在没有连接客户端的情况下,它会从 stdin 读取到 EOF 并立即退出 —— 这是预期行为,不是 bug。
要在本地将其注册到 Claude Code,请将其添加到项目根目录下的 `.mcp.json` 中:
```
{
"mcpServers": {
"hayabusa": {
"command": "python",
"args": ["server.py"],
"cwd": "C:/path/to/mcp-hayabusa"
}
}
}
```
MCP server 的定义不会从 `settings.json`/`settings.local.json` 中读取(这些文件用于配置 permissions/hooks/env)—— `.mcp.json` 才是 Claude Code 实际检查的文件。它在此处被 gitignore 是因为 `cwd` 是一个绝对且特定于机器的路径;每个协作者都需要创建自己的文件。
### 注册到 Claude Desktop
Claude Desktop 使用与 `.mcp.json` 不同的独立配置文件,并且不支持 `cwd` 键,因此请改为在 `args` 中向 `server.py` 传递绝对路径:
```
{
"mcpServers": {
"hayabusa": {
"command": "python",
"args": ["C:/path/to/mcp-hayabusa/server.py"]
}
}
}
```
在 Windows 上,找到正确的编辑文件需要稍微注意一下:
- 在标准(非 Store)安装中,它是 `%APPDATA%\Claude\claude_desktop_config.json`。
- 对于 MSIX 打包的 Store 版本,Windows 会将应用程序的 `%APPDATA%` 重定向到一个虚拟化路径 —— 从应用程序外部(例如终端)编辑 `%APPDATA%\Claude\...` 只会改动一个应用程序永远不会读取的无效文件。真正的文件位于 `%LOCALAPPDATA%\Packages\\LocalCache\Roaming\Claude\claude_desktop_config.json`。如果您不确定自己使用的是哪个版本,请检查 `%LOCALAPPDATA%\Packages` 中以 `Claude_` 开头的文件夹。
编辑完成后,请完全退出并重新启动 Claude Desktop(不仅仅是关闭窗口)。每个服务器的连接日志会存放在配置文件旁边的 `logs\mcp-server-hayabusa.log` 中 —— 如果服务器显示为断开连接,请首先检查该文件;它会记录用于启动它的确切 command/args/cwd 以及来自进程的任何 stderr。
## `scan_evtx` 工具
```
scan_evtx(
file_path: str,
min_severity: str | None = None,
rule_filter: str | None = None,
output_format: str = "summary",
max_results: int | None = None,
) -> dict
```
| 参数 | 必需 | 描述 |
| --- | --- | --- |
| `file_path` | 是 | 要扫描的 `.evtx` 文件路径 |
| `min_severity` | 否 | 包含的最低严重级别:`informational`、`low`、`medium`、`high` 或 `critical`。过滤发生在 Hayabusa 自身内部(`--min-level`)。 |
| `rule_filter` | 否 | 与每个发现结果的规则标题进行匹配的不区分大小写的子字符串(例如 `"lateral"` 或 `"mimikatz"`)。仅返回匹配的发现结果。 |
| `output_format` | 否 | `"summary"`(默认)为每个发现结果返回精简的字段集;`"full"` 返回 Hayabusa 生成的每个字段。 |
| `max_results` | 否 | 限制返回的发现结果数量。 |
### 成功响应
```
{
"file": "samples/4794_DSRM_password_change_t1098.evtx",
"min_severity": null,
"rule_filter": null,
"output_format": "summary",
"count": 1,
"returned": 1,
"truncated": false,
"findings": [
{
"Timestamp": "2017-06-09 15:21:26.968 -04:00",
"RuleTitle": "Password Change on Directory Service Restore Mode (DSRM) Account",
"Level": "high",
"Computer": "2016dc.hqcorp.local",
"EventID": 4794,
"RecordID": 3139859
}
]
}
```
`count` 是应用 `rule_filter` 后匹配到的发现结果总数(应用任何 `max_results` 限制之前);`returned` 是实际包含在 `findings` 中的数量;如果 `max_results` 截断了列表,则 `truncated` 为 `true`。传入 `output_format="full"` 可获取 Hayabusa 生成的所有字段(`Channel`、`Details`、`ExtraFieldInfo`、`RuleID` 等),而不是上面显示的精简摘要格式。
### 错误响应
每种失败情况都会返回 `{"error": "..."}`(视情况可能附带 `stderr`/`returncode`),而不是抛出异常:
| 情况 | 错误示例 |
| --- | --- |
| 文件不存在 | `EVTX file not found: ` |
| 无效的 `min_severity` | `Invalid min_severity 'bogus'. Must be one of: informational, low, medium, high, critical` |
| 无效的 `output_format` | `Invalid output_format 'bogus'. Must be one of: summary, full` |
| 无效的 `max_results` | `Invalid max_results '-1'. Must be >= 0.` |
| Hayabusa 二进制文件缺失 | `Hayabusa executable not found in ` |
| Hayabusa 非零退出 | `Hayabusa scan failed`(附带 `returncode`,`stderr`) |
| 扫描耗时过长 | `Hayabusa scan timed out after 300s` |
| 输出无法解析 | `Failed to parse Hayabusa output: ...` |
## `get_hayabusa_rules` 工具
```
get_hayabusa_rules(keyword: str | None = None, max_results: int | None = 50) -> dict
```
列出本地 `./hayabusa/rules/` 检出目录中的检测规则(约 5,000 条 Sigma + Hayabusa 原生规则)—— 可用于在扫描前发现现有规则及其确切标题/标签(例如,为 `scan_evtx` 的 `rule_filter` 选择合适的值)。
| 参数 | 必需 | 描述 |
| --- | --- | --- |
| `keyword` | 否 | 与每条规则的标题、描述和标签进行匹配的不区分大小写的子字符串。 |
| `max_results` | 否 | 限制返回的规则数量。默认为 `50`;传入 `null` 表示不限制。 |
### 成功响应
```
{
"keyword": "mimikatz",
"count": 24,
"returned": 24,
"truncated": false,
"rules": [
{
"title": "Mimikatz Use",
"id": "06d71506-7beb-4f22-8888-e2e5e2ca7fd8",
"level": null,
"status": "test",
"ruletype": "sigma",
"tags": ["attack.s0002", "attack.lateral-movement", "attack.t1003.002"],
"description": "This method detects mimikatz keywords in different Eventlogs..."
}
]
}
```
规则字段是通过轻量级的逐行扫描提取的,而不是使用完整的 YAML 解析器(参见下方的注意事项),因此当特定规则未在顶层定义某个字段时,`level`/`status`/`tags`/`description` 的值将为 `null` 或空。
### 错误响应
| 情况 | 错误示例 |
| --- | --- |
| 规则目录缺失 | `Hayabusa rules directory not found: ` |
| 无效的 `max_results` | `Invalid max_results '-1'. Must be >= 0.` |
## 测试
```
python tests/test_scan_evtx.py
```
一个手动测试脚本(不是 pytest 套件),用于测试这两个工具:针对由 `download_sample_evtx.py` 下载的样本运行 `scan_evtx`(包括默认/完整 `output_format`、`min_severity`、`rule_filter`、`max_results` 以及错误情况);以及针对本地规则集运行 `get_hayabusa_rules`(包括默认上限、`keyword` 过滤以及错误情况)。
## 注意事项
- 严重级别过滤委托给 Hayabusa 自身的 `-m/--min-level` 标志,而不是在 Python 中重新实现;`rule_filter`、`output_format` 和 `max_results` 没有对应的 Hayabusa CLI 选项,因此它们是作为 Python 中的后处理步骤应用的。
- 输出解析使用了 Hayabusa 的 `-L`/JSONL 模式。Hayabusa 默认的 `-o`(非 `-L`)输出是格式化的 JSON 对象串联在一起,没有数组包裹 —— 这不是合法的 JSON 或 JSONL —— 因此必须使用 `-L` 才能进行可靠的解析。
- `get_hayabusa_rules` 使用正则表达式逐行扫描来解析规则 YAML,而不是使用完整的 YAML 解析器,以避免为仅仅是一个模糊列表工具引入 PyYAML 依赖 —— 当规则实际用于扫描时,Hayabusa 自身会进行真正的 YAML 解析。
标签:AMSI绕过, MCP服务, Python, 威胁检测, 无后门, 逆向工具