toneillcodes/HoundTrainer

GitHub: toneillcodes/HoundTrainer

BloodHound 自定义节点类型与 Cypher 查询的批量管理工具,支持从 CSV 创建模型并上传至 BloodHound 实例。

Stars: 12 | Forks: 1

# 概述 HoundTrainer 是一个用于在 BloodHound 中管理自定义节点类型和 Cypher 查询的工具。 ## 快速开始与前置条件 HoundTrainer 需要 Python 3.x。 Pandas 对于模型创建是可选的,如果导入不可用,脚本将回退到标准库进行 CSV 解析。 1. 克隆仓库 ``` $ git clone https://github.com/toneillcodes/HoundTrainer.git $ cd HoundTrainer ``` 2. 安装依赖 ``` $ pip install -r requirements.txt ``` ## 用法 ``` $ python houndtrainer.py -h usage: houndtrainer.py [-h] {create,get,list,upload,export,delete,deleteall} ... Manage custom types and cypher queries in BloodHound. positional arguments: {create,get,list,upload,export,delete,deleteall} create Create a schema model from CSV definitions. get Retrieve a specific resource list List custom node or cypher resources upload Upload custom node or cypher resources export Export custom node or cypher resources delete Delete a custom node or cypher resource deleteall Delete all custom node or cypher resources options: -h, --help show this help message and exit $ ``` ## 操作 * [create](#create-operation) * [list](#list-operation) * [get](#get-operation) * [upload](#upload-operation) * [export](#export-operation) * [delete](#delete-operation) * [deleteall](#deleteall-operation) 注意:对于 Cypher 操作,当未提供 ```--scope``` 参数时,使用的默认 scope 是 'owned'。 ### Create(创建)操作 #### 创建自定义节点类型模型 根据 CSV 定义创建模型 ``` Kind Name,Icon Name,Color ExampleUser,user,#4D93D9 ExampleRole,user-group,#47D359 ``` 解析 CSV(--csv)并生成 JSON(--file) ``` $ python houndtrainer.py create --type model --csv examples\example-model.csv --file examples\example-model.json Success: Data written to examples\example-model.json [INFO] Successfully wrote model from 'examples\example-model.csv' to file 'examples\example-model.json'. [INFO] Done. $ ``` 参考: * [examples/example-model.csv](examples/example-model.csv) * [examples/example-model.json](examples/example-model.json) ### List(列出)操作 #### 列出自定义节点类型 列出自定义节点类型 ``` $ python houndtrainer.py list --type node --url http://127.0.0.1:8080 [INFO] Listing all custom types... Enter JWT: [INFO] ID: 280, Kind Name: ExampleUser [INFO] ID: 281, Kind Name: ExampleRole [INFO] Done. $ ``` 未找到自定义节点类型时的列出输出 ``` $ python houndtrainer.py list --type node --url http://127.0.0.1:8080 [INFO] Listing all custom types... Enter JWT: [INFO] No custom kinds found. [INFO] Done. $ ``` #### 列出 Cypher 查询 包含 Cypher 查询的列出输出 ``` $ python houndtrainer.py list --type cypher --url http://127.0.0.1:8080 [INFO] Listing all cypher queries under scope: 'owned'... Enter JWT: [INFO] ID: 14, Query: Test Query [INFO] Done. ``` 未找到 Cypher 查询时的列出输出 ``` $ python houndtrainer.py list --type cypher --url http://127.0.0.1:8080 [INFO] Listing all cypher queries under scope: 'owned'... Enter JWT: [INFO] No cypher queries found. [INFO] Done. $ ``` ### Get(获取)操作 #### 获取自定义节点类型 通过 kind 名称(--name)检索自定义节点类型详情 ``` $ python houndtrainer.py get --type node --url http://127.0.0.1:8080 --name ExampleUser [INFO] Listing custom type for kind_name 'ExampleUser'... Enter JWT: [INFO] ID: 280, Name: ExampleUser, type: font-awesome, Name: user, Color: #4D93D9 [INFO] Done. $ ``` #### 获取 Cypher 查询 通过 ID(--id)检索 Cypher 查询详情 ``` $ python houndtrainer.py get --type cypher --url http://127.0.0.1:8080 --id 14 [INFO] Retrieving cypher query for ID: '14'... Enter JWT: [INFO] ID: 14, Name: Test Query, Created_At: 2025-11-29T15:05:37.546016Z, Updated_At: 2025-11-29T18:02:40.993889Z, User_id: 0f916532-08f7-47f4-bf1b-37b2317cce1b, Description: Testing, Query: "match(a:ExampleUser)\nwhere a.objectid = 'Bob'\nreturn a" [INFO] Done. $ ``` ### Upload(上传)操作 #### 上传自定义节点类型模型 上传 example-model.json ``` $ python houndtrainer.py upload --type node --url http://127.0.0.1:8080 --file examples\example-model.json [INFO] Uploading model from file: examples\example-model.json... Enter JWT: [INFO] Model uploaded successfully. [INFO] Operation 'upload' for type 'node' with file examples\example-model.json was successful. [INFO] Done. $ ``` 确认上传成功 ``` $ python houndtrainer.py list --type node --url http://127.0.0.1:8080 [INFO] Listing all custom types... Enter JWT: [INFO] ID: 282, Kind Name: ExampleUser [INFO] ID: 283, Kind Name: ExampleRole [INFO] Done. $ ``` 参考: * [examples/example-model.json](examples/example-model.json) #### 上传单个 Cypher 查询 检查 Cypher 查询列表 ``` $ python houndtrainer.py list --type cypher --url http://127.0.0.1:8080 [INFO] Listing all cypher queries under scope: 'owned'... Enter JWT: [INFO] No cypher queries found. [INFO] Done. ``` 上传示例 Cypher 查询文件 ```examples\example-cypher.json``` ``` $ python houndtrainer.py upload --type cypher --url http://127.0.0.1:8080 --file examples\example-cypher.json [INFO] Uploading query JSON from file: examples\example-cypher.json... Enter JWT: [INFO] Cypher query uploaded successfully. [INFO] Operation 'upload' for type 'cypher' with file examples\example-cypher.json was successful. [INFO] Done. ``` 检查 Cypher 查询列表 ``` $ python houndtrainer.py list --type cypher --url http://127.0.0.1:8080 [INFO] Listing all cypher queries under scope: 'owned'... Enter JWT: [INFO] ID: 17, Query: Test [INFO] Done. $ ``` 参考: * [examples/example-cypher.json](examples/example-cypher.json) #### 上传 Cypher 查询包(ZIP) 上传 Cypher 查询包 ``` $ python houndtrainer.py upload --type cypher --url http://127.0.0.1:8080 --file examples\example-cypher-pack.zip [INFO] Uploading query zip from archive: examples\example-cypher-pack.zip... Enter JWT: [INFO] Query ZIP uploaded successfully. [INFO] Operation 'upload' for type 'cypher' with file examples\example-cypher-pack.zip was successful. [INFO] Done. $ ``` 检查 Cypher 查询列表 ``` $ python houndtrainer.py list --type cypher --url http://127.0.0.1:8080 [INFO] Listing all cypher queries under scope: 'owned'... Enter JWT: [INFO] ID: 22, Query: Test [INFO] ID: 23, Query: Another Test [INFO] ID: 24, Query: Find Helpdesk Admins [INFO] ID: 25, Query: Find DA Users [INFO] Done. $ ``` ### Export(导出)操作 #### 导出自定义节点类型 通过 kind 名称(--name)导出自定义节点类型 ``` $ python houndtrainer.py export --type node --url http://127.0.0.1:8080 --name ExampleRole --file examples\example-custom-type.json [INFO] Listing custom type for kind_name 'ExampleRole'... Enter JWT: Success: Data written to examples\example-custom-type.json [INFO] Successfully wrote 'node' data to file 'examples\example-custom-type.json'. [INFO] Done. $ ``` 参考: * [examples/example-custom-type.json](examples/example-custom-type.json) #### 导出所有自定义节点类型 将所有自定义节点类型导出到一个 JSON 文件中 ``` $ python houndtrainer.py export --type node --url http://127.0.0.1:8080 --all --file examples\example-custom-types.json [INFO] Exporting all custom types... [INFO] Listing all custom types... Enter JWT: [INFO] kindName found: ExampleUser. [INFO] kindName found: ExampleRole. [INFO] Successfully exported 'node' data to file 'examples\example-custom-types.json'. [INFO] Done. $ ``` 参考: * [examples/example-custom-type.json](examples/example-custom-type.json) #### 导出 Cypher 查询 通过 ID(--id)导出 Cypher 查询 ``` $ python houndtrainer.py export --type cypher --url http://127.0.0.1:8080 --id 16 --file examples\example-cypher.json [INFO] Exporting cypher query ID '16'... Enter JWT: Success: Data written to examples\example-cypher.json [INFO] Successfully wrote 'cypher' data to file 'examples\example-cypher.json'. [INFO] Done. $ ``` 参考: * [examples/example-cypher.json](examples/example-cypher.json) #### 导出所有 Cypher 查询 将所有 Cypher 查询导出为 ZIP(--file) ``` $ python houndtrainer.py export --type cypher --url http://127.0.0.1:8080 --all --file examples\example-cypher-pack.zip [INFO] Exporting cypher queries for scope 'owned'... Enter JWT: [INFO] Saving cypher archive as: 'examples\example-cypher-pack.zip' [INFO] Successfully exported 'cypher' data to file 'examples\example-cypher-pack.zip'. [INFO] Done. $ ``` ### Delete(删除)操作 #### 通过 kind 名称删除自定义节点类型 通过 kind 名称(--name)删除自定义节点类型 ``` $ python houndtrainer.py delete --type node --url http://127.0.0.1:8080 --name ExampleUser [INFO] Deleting custom type: ExampleUser Enter JWT: [INFO] Deleted custom type: ExampleUser [INFO] Successfully completed delete for node. [INFO] Done. $ ``` 确认删除 ``` $ python houndtrainer.py list --type node --url http://127.0.0.1:8080 [INFO] Listing all custom types... Enter JWT: [INFO] ID: 283, Kind Name: ExampleRole [INFO] Done. $ ``` #### 通过 ID 删除 Cypher 查询 通过 ID(--id)删除 Cypher 查询 ``` $ python houndtrainer.py delete --type cypher --url http://127.0.0.1:8080 --id 14 [INFO] Deleting cypher query ID: '14' Enter JWT: [INFO] Deleted custom type: 14 [INFO] Successfully completed operation 'delete' for cypher. [INFO] Done. $ ``` 确认删除 ``` $ python houndtrainer.py list --type cypher --url http://127.0.0.1:8080 [INFO] Listing all cypher queries under scope: 'owned'... Enter JWT: [INFO] No cypher queries found. [INFO] Done. $ ``` ### Deleteall(删除所有)操作 #### 删除所有自定义节点类型 删除所有自定义类型 ``` $ python houndtrainer.py list --type node --url http://127.0.0.1:8080 [INFO] Listing all custom types... Enter JWT: [INFO] ID: 280, Kind Name: ExampleUser [INFO] ID: 281, Kind Name: ExampleRole [INFO] Done. $ $ python houndtrainer.py deleteall --type node --url http://127.0.0.1:8080 [INFO] Running operation 'deleteall' for type 'node'. Enter JWT: [INFO] Operation deleteall requires confirmation. Enter 'Y' to continue and 'N' to cancel: Y [INFO] Deleting all custom types... [INFO] Listing all custom types... [INFO] Deleting custom type: ExampleUser [INFO] Deleted custom type: ExampleUser [INFO] Deleting custom type: ExampleRole [INFO] Deleted custom type: ExampleRole [INFO] Successfully completed operation 'deleteall' for type 'node'. $ $ python houndtrainer.py list --type node --url http://127.0.0.1:8080 [INFO] Listing all custom types... Enter JWT: [INFO] No custom kinds found. [INFO] Done. $ ``` #### 删除所有 Cypher 查询 ``` $ python houndtrainer.py deleteall --type cypher --url http://127.0.0.1:8080 Enter JWT: [INFO] Deleting all custom types... [INFO] Listing custom types... [INFO] Deleting custom type: ExampleUser [INFO] Deleted custom type: ExampleUser [INFO] Deleting custom type: ExampleSecurityUser [INFO] Deleted custom type: ExampleSecurityUser [INFO] Deleting custom type: ExampleGroup [INFO] Deleted custom type: ExampleGroup [INFO] Deleting custom type: ExampleClass [INFO] Deleted custom type: ExampleClass [INFO] Done. $ $ python houndtrainer.py list --type cypher --url http://127.0.0.1:8080 Enter JWT: [INFO] Listing custom types... [INFO] No custom kinds found. [INFO] Done. $ ``` ## 认证 * 此脚本使用 JWT 进行认证,并期望在运行时提供该值。 * 要(合法地)获取 JWT,请登录您的 BHE 或 CE 实例,并在您选择的浏览器中查看“开发者工具”中的“网络”选项卡。 * 此方法符合 SpecterOps 对于快速 API 调用的建议 https://bloodhound.specterops.io/integrations/bloodhound-api/working-with-api#use-a-jwt%2Fbearer-token ## API 参考 所有操作使用以下端点 | 操作类型 | 端点 | | ---- | ---- | | node| custom-nodes | | cypher | saved-queries | ## 待办事项 * ~~将所有自定义类型详情打印到 STDOUT~~ 已于 11/29/25 添加 * ~~将节点数据输出到文件~~ 已于 11/29/25 添加 * 支持使用 API 密钥进行认证 * 能够为 get/export 操作传递 ID 或 Kind Name 列表 * 验证操作以验证图标和 OG schemas ## 致谢 * [c0kernel](https://github.com/C0KERNEL):感谢其在测试、文档更新和建议方面的帮助。
标签:Azure AD, BloodHound, Cypher查询, HTTP/HTTPS抓包, Python, Web报告查看器, 二进制发布, 安全管理, 开源工具, 态势感知, 攻击路径规划, 无后门, 权限分析, 活动目录, 网络安全, 自定义节点, 隐私保护