Apex-Shift/lyra
GitHub: Apex-Shift/lyra
Lyra 是一个轻量级 Python OSINT 框架,支持调查图谱构建、签名取证 JSON 导出和 SQLite 存储。
Stars: 0 | Forks: 0
# Lyra — OSINT 框架
Lyra 是一个轻量级的 OSINT 框架,用于编排模块、将调查图谱导出为取证 JSON,以及将调查工件存储在本地 SQLite 存储中。该项目同时提供了编程 API 和桌面控制 GUI。
本 README 记录了仓库结构、如何运行 API 和 GUI、如何从 Python 中使用该库、导出格式、存储 schema、测试、CLI 用法以及推荐的开发实践。
## 目录
- 项目概述
- 核心功能
- 仓库布局
- 快速开始
- 前置条件
- 安装
- 运行 API
- 运行 GUI
- 编程用法示例
- InvestigationContext
- LyraExporter
- StorageManager
- 取证 JSON 导出格式
- 存储 (SQLite) schema
- CLI 用法
- 测试
- 开发者工作流
- 建议的后续改进
- 贡献
- 许可证与联系方式
## 项目概述
Lyra 提供:
- 一个核心的 InvestigationContext,用于收集 Entities(节点)和 Pivots(边)。
- 一个导出器,用于写入确定性、已签名的取证 JSON 文件。
- 一个 StorageManager,用于将图谱 payload 摄取到本地 SQLite 数据库中。
- 一个 PySide6 GUI(控制中心),用于通过简单的 HTTP API 列出和运行模块。
本项目专注于可靠性和兼容性:
- 导出器生成规范的 JSON 和 SHA-256 payload 签名。
- 存储器接受当前和传统的 payload 结构,并容忍字段名称上的微小差异。
## 核心功能
- 用于构建调查图谱的编程 API。
- 带有证据保管链签名的确定性取证 JSON 导出。
- 稳健地摄取到 SQLite 中(在适当的情况下具备幂等性)。
- 用于交互式模块执行(通过 API)的桌面 GUI。
- 用于验证端到端往返测试的小型 pytest 脚手架。
## 仓库布局
典型的重要文件和文件夹:
- core/
- context.py — InvestigationContext, TargetEntity, TargetPivot
- exporter.py — LyraExporter(取证 JSON 写入器)
- lyra_gui.py — PySide6 控制中心 GUI
- storage.py — StorageManager (aiosqlite)
- tests/ — pytest 测试(例如 tests/test_roundtrip.py)
- requirements.txt — Python 依赖项
## 快速开始
### 前置条件
- 推荐使用 Python 3.10+
- pip
- GUI 需要:PySide6
- 异步 SQLite 需要:aiosqlite
- HTTP 客户端 (GUI) 需要:httpx
### 安装
```
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txt
```
### 运行 API
启动本地 HTTP API 后端服务器以暴露模块:
```
python lyra_cli.py --api
```
GUI 默认连接到 `http://127.0.0.1:8000` 的本地端点。
### 运行 GUI
启动 PySide6 控制中心应用:
```
python lyra_gui.py
```
- GUI 将尝试联系 API (`/modules`) 并显示模块。
- 在表单中输入模块选项值。GUI 会尽可能保留输入的原始类型值:
- 它首先对输入尝试 `json.loads()`,因此 `true`、`false`、`null`、数字、数组和对象会被保留。
- 如果 JSON 解析失败,将应用安全的回退机制(布尔值和整数)。
## 编程用法
以下是可以在 Python 脚本或测试中使用的示例代码片段。
### InvestigationContext(构建图谱)
```
from core.context import InvestigationContext
import asyncio
ctx = InvestigationContext(case_id="CASE-001")
# 添加 entities (async)
async def build_context():
await ctx.add_entity("e1", "ip", "1.2.3.4", {"source": "scan"})
await ctx.add_entity("e2", "domain", "example.com", {"source": "dns"})
await ctx.add_pivot("e1", "e2", "resolves_to", "dns-module")
asyncio.run(build_context())
graph = ctx.get_graph_data()
# graph -> {"nodes": [...], "edges": [...]}
```
### LyraExporter(导出带有签名的取证 JSON)
```
from core.exporter import LyraExporter
import asyncio
exporter = LyraExporter(export_dir="exports")
# nodes 和 edges 来自于 ctx.get_graph_data()
nodes = graph["nodes"]
edges = graph["edges"]
out_path = asyncio.run(exporter.to_forensic_json("CASE-001", nodes, edges, operator_name="Analyst1"))
print("Export written to:", out_path)
```
注意事项:
- 导出器将 `graph_data` 写为 `{ "nodes": [...], "edges": [...] }`,并包含确定性元数据以及 `payload_hash_signature` (SHA-256)。
- 签名是在规范 JSON(排序的键和紧凑的分隔符)上计算的,以避免意外的顺序差异。
### StorageManager(保存到 SQLite)
```
from storage import StorageManager
import asyncio
sm = StorageManager(db_path="exports/lyra_investigations.db")
# 接受 {"nodes","edges"} 或 legacy 的 {"entities","relations"} 格式
asyncio.run(sm.save_case_graph("CASE-001", {"nodes": nodes, "edges": edges}))
```
存储行为:
- 如果 `cases`、`entities` 和 `pivots` 表不存在,则创建它们。
- `entities` 行使用 `INSERT OR REPLACE` 插入(具备幂等性)。
- 插入 `pivots` 行;摄取代码容忍备用键名(例如 `src`、`dst`、`target_id`)并跳过格式错误的条目。
## 取证 JSON 导出格式
导出器生成具有以下结构的取证 JSON 文件:
```
{
"metadata": {
"framework": "Lyra OSINT Framework v1.0.0",
"case_id": "CASE-001",
"generated_at_utc": "2026-07-31T...Z",
"investigator": "Analyst",
"integrity_protocol": "SHA-256 Chain-of-Custody",
"payload_hash_signature": "..."
},
"graph_data": {
"nodes": [
{ "id": "e1", "type": "ip", "value": "1.2.3.4", "metadata": {...}, "created_at": "..." }
],
"edges": [
{ "source": "e1", "target": "e2", "relation": "resolves_to", "module_source": "dns-module", "timestamp": "..." }
]
}
}
```
重要说明:
- `payload_hash_signature` 是在插入 `payload_hash_signature` 字段之前,对 payload 的规范 JSON 进行计算的;这为证据保管链提供了可重复的完整性检查。
## 存储 (SQLite) schema
StorageManager 创建以下表:
- cases
- case_id TEXT PRIMARY KEY
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
- notes TEXT
- entities
- id TEXT PRIMARY KEY
- case_id TEXT
- type TEXT
- value TEXT
- metadata TEXT (JSON 编码)
- created_at TIMESTAMP
- pivots
- id INTEGER PRIMARY KEY AUTOINCREMENT
- case_id TEXT
- source_id TEXT
- target_id TEXT
- relation TEXT
- module_source TEXT
- timestamp TIMESTAMP
注意事项:
- 实体的 `metadata` 以 JSON 字符串形式存储。
- 存储摄取尽量保持宽容性 — 尽可能处理缺失或替代的字段名称。
## CLI 用法
Lyra 提供了一个命令行界面来编排模块、运行本地 API 服务器,并与存储组件进行交互。
### 前置条件
- Python 3.10+
- 活跃的虚拟环境 (`.venv`)
- 通过 `pip install -r requirements.txt` 安装核心依赖项
### 通过 CLI 传递 JSON 选项
在通过终端传递类型化参数或 JSON payload 时,请确保根据您的操作系统使用正确的 shell 引号:
* **Linux / macOS (bash/zsh):** 在 JSON 字符串周围使用单引号。
'{"target": "example.com", "limit": 10}'
* **Windows (cmd.exe):** 使用双引号,并使用反斜杠对内部引号进行转义。
"{\"target\":\"example.com\",\"limit\":10}"
### 常用命令
#### 1. 启动 API 服务器
启动后端服务器以处理模块执行(默认为 `8000` 端口):
```
python lyra_cli.py --api --host 127.0.0.1 --port 8000
```
#### 2. 运行桌面 GUI
启动 PySide6 控制中心应用程序。它会自动连接到正在运行的本地 API:
```
python lyra_gui.py
```
#### 3. 通过 API 执行模块 (curl)
```
curl -X POST "http://127.0.0" \
-H "Content-Type: application/json" \
-d '{"options":{"target":"example.com","limit":10,"include_subdomains":true}}'
```
使用 httpie 的示例:
```
http POST http://127.0.0.1:8000/modules/some/module/path/run options:='{"target": "example.com", "limit": 10}'
```
4. 通过 Python 在本地快速运行模块(单行命令 / 脚本)
```
python - <<'PY'
from core.context import InvestigationContext
from core.exporter import LyraExporter
from storage import StorageManager
import asyncio, json
# 构建 context
ctx = InvestigationContext("CLI_CASE")
asyncio.run(ctx.add_entity("e1","ip","1.2.3.4"))
asyncio.run(ctx.add_entity("e2","domain","example.com"))
asyncio.run(ctx.add_pivot("e1","e2","resolves_to","cli"))
graph = ctx.get_graph_data()
# export
exporter = LyraExporter(export_dir="exports")
out = asyncio.run(exporter.to_forensic_json("CLI_CASE", graph["nodes"], graph["edges"], "cli-user"))
print("Exported:", out)
PY
```
5. 从已保存的图谱导出案例为取证 JSON(示例)
- 如果您已经在 Python 中构建了图谱,可以像上面那样调用 LyraExporter。
- 导出器会写入规范的 JSON 并附加 metadata.payload_hash_signature (SHA-256)。
6. 初始化或检查 Storage DB 并通过 CLI 摄取图谱
```
python - <<'PY'
import json
from storage import StorageManager
import asyncio
sm = StorageManager(db_path="exports/lyra_investigations.db")
# 加载已 export 的 forensic json
payload = json.load(open("exports/CASE_CLI_CASE_1630000000.json", encoding="utf-8"))
graph_data = payload.get("graph_data", {}) # accepts {"nodes","edges"} or {"entities","relations"}
asyncio.run(sm.save_case_graph("CLI_CASE", graph_data))
print("Saved to DB")
PY
```
快速 DB 检查(sqlite3 CLI):
```
sqlite3 exports/lyra_investigations.db "SELECT case_id, COUNT(*) FROM entities GROUP BY case_id;"
```
7. 运行测试脚手架
```
pip install pytest
pytest -q tests/test_roundtrip.py
```
### 建议的 CLI 改进(未来)
- 添加一个小型的 CLI 包装脚本(例如 `cli.py`),使用 argparse 或 typer 来暴露常用操作:
- `cli.py api --host 127.0.0.1 --port 8000`
- `cli.py gui`
- `cli.py run-module --module some/module/path --options '{"target":"..." }'`
- `cli.py export-case --case CASE_ID --out exports/CASE.json`
- `cli.py ingest --file exports/CASE.json`
- 使用包装器可提供一致的用户体验、内置帮助和一致的选项解析(并且在使用 typer/click 时允许自动进行 shell 补全)。
## 测试
`tests/test_roundtrip.py` 中包含了一个 pytest 端到端测试脚手架。它验证了以下往返过程:
InvestigationContext → LyraExporter → StorageManager
运行测试:
```
pytest -q tests/test_roundtrip.py
```
如果测试失败:
- 检查虚拟环境和已安装的依赖项。
- 确保已检出包含更改的仓库分支。
## 开发者工作流与建议
- 分支:创建短期的功能分支(例如:`fix/context-exporter-storage-compat`)。
- 格式化:使用 `black` 和 `isort`。
- 静态类型:考虑使用 `mypy`(类型提示有助于提高稳定性)。
- 日志记录:将临时的 `print()` 调用替换为 `logging` 和可配置的日志级别。
- CI:添加 GitHub Actions 以在 PR 上运行 `pytest` 和 linter。
推荐的 GitHub Actions(后续步骤):
- `python-app.yml` 用于运行测试、black/isort 检查,以及可选的 mypy。
## 贡献
- Fork 该仓库并创建一个 PR。
- 在创建 PR 之前,请在本地运行测试。
- 保持提交小而专注;包含清晰的 PR 描述和理由。
如果项目涉及隐私敏感信息,请务必小心:在收集/存储任何数据时,请遵守适用的法律和内部政策。
## 路线图(未来改进)
以下是 Lyra 开发计划的下一步:
- 创建一个 `Makefile` 以简化常用命令(`venv`、`install`、`test`)。
- 设置 GitHub Actions 工作流,在每个 Pull Request 上自动运行测试。
- 添加全面的开发者文档(`CONTRIBUTING.md` 和 `CODE_OF_CONDUCT.md`)。
- 针对边缘情况、格式错误的节点和空输入添加严格的验证测试。
## 贡献
欢迎您做出贡献!如果您愿意协助构建 Lyra,请 fork 该仓库并创建一个 Pull Request。对于重大更改,请先创建一个 issue 讨论您希望进行的更改。
## 许可证与联系方式
本项目基于 **MIT License** 授权 — 详情请参阅 [LICENSE](LICENSE) 文件。
如需支持、提交 Bug 报告或有任何疑问,请直接在 [GitHub issue 跟踪器](https://github.com)上创建一个 issue。
标签:ESC4, GUI, OSINT, Python, SQLite, 安全规则引擎, 实时处理, 密码管理, 数字取证, 无后门, 自动化脚本, 运行时操纵, 逆向工具