Microck/jarspect
GitHub: Microck/jarspect
面向 Minecraft 模组的 AI 驱动安全扫描器,通过字节码深度解析和上下文理解检测隐藏恶意行为。
Stars: 0 | Forks: 0
[](LICENSE)
**上传一个 `.jar` 文件,在安装前获取带有可解释指标的风险判定。**
**Jarspect** 这个名字是 **JAR** (Java Archive) 和 **Inspect** 的组合词,体现了其使命:对游戏模组进行深度的自动化检查,以发现隐藏的威胁。
Jarspect 是一款专为 Minecraft 模组设计的 AI 优先安全扫描器。它运行一个三层流水线:MalwareBazaar 威胁情报、字节码能力提取和 Azure OpenAI 判定;将 `.jar` 文件分类为 **CLEAN** (安全)、**SUSPICIOUS** (可疑) 或 **MALICIOUS** (恶意),并提供完整解释。字节码层在常量池和指令级别解析编译后的 `.class` 文件,重构混淆字符串,解析方法调用,对每个归档条目运行 YARA 规则,并将 8 个能力检测器的结果输入到一个结构化配置文件中,供 AI 分析以生成判定。
## 为什么开发这个工具
2023 年 6 月,**fractureiser** 攻击了 CurseForge 和 Bukkit 上的数十个 Minecraft 模组。Stage 0 将 URL 隐藏在 `new String(new byte[]{...})` 中以规避基于字符串的扫描器,然后通过 `URLClassLoader` 反射链加载远程类。Stages 1-3 增加了持久性(Windows Run 键、Linux systemd 单元)、凭证窃取(MSA 令牌、Discord 令牌、浏览器 cookie、加密货币钱包)以及自我复制到其他已安装的模组中。
**BleedingPipe** 利用了流行服务器端模组中不安全的 `ObjectInputStream.readObject()` 调用,允许在 Minecraft 服务器上执行远程代码。**PussyRAT** 使用反射劫持 Minecraft 会话令牌。**Stargazers Ghost Network** 通过虚假 GitHub stars 分发特洛伊木马化模组,传递多阶段 Java 到 .NET 的信息窃取器。
传统的杀毒软件和基于文本的扫描器对这些威胁的评分为 0/100,因为真正的恶意软件存在于**编译后的字节码**中;API 引用作为结构化的常量池条目存在,而不是可以通过 grep 搜索的纯文本。不解析 `.class` 文件的扫描器对此完全视而不见。而且仅靠基于规则的评分无法区分调用 `Runtime.exec()` 进行 GPU 探测的渲染模组与调用它运行 shell 命令的 RAT。
Jarspect 的构建就是为了解决这两个问题。字节码层中的每一种检测技术都可以追溯到现实世界的恶意软件样本或记录在案的攻击载体。AI 判定层理解上下文;它知道 `sodium` 调用 `glxinfo` 是合法的 GPU 检测,而不是进程执行滥用。
## 工作原理
Jarspect 使用一个**三层流水线**,每一层都可以短路到最终判定:
```
POST /upload (multipart .jar)
|
v
upload_id stored at .local-data/uploads/{upload_id}.jar
|
POST /scan (upload_id)
|
Layer 1: MalwareBazaar Threat Intel
| SHA-256 hash lookup against abuse.ch database
| Match? -> MALICIOUS (confidence 1.0, method: malwarebazaar_hash)
| Optional: set JARSPECT_MB_MATCH_CONTINUE_ANALYSIS=1 to still run
| archive traversal + static analysis for reporting artifacts (verdict unchanged)
|
Layer 2: Bytecode Capability Extraction
+-- Archive traversal recursive jar-in-jar extraction with budget gates
+-- Bytecode evidence cafebabe class parsing -> constant pool + invoke resolution
+-- Byte-array strings reconstruct new String(new byte[]{...}) hidden values
+-- YARA per-entry inflate each entry, scan individually, severity from metadata
+-- Metadata checks fabric.mod.json / mods.toml / META-INF/neoforge.mods.toml / plugin.yml / MANIFEST.MF
+-- Capability detectors 8 detectors (exec, network, dynamic load, fs/jar modify,
| persistence, deserialization, native/JNI, credential theft)
+-- Profile builder structured capability profile with extracted artifacts
|
Layer 3: AI Verdict (Azure OpenAI)
| Receives capability profile + extracted URLs, domains, commands, file paths
| Returns: CLEAN / SUSPICIOUS / MALICIOUS with confidence, explanation,
| and per-capability rationale
|
v
scan_id persisted at .local-data/scans/{scan_id}.json
|
GET /scans/{scan_id} -> fetch full result at any time
```
**关键特性:**
- **AI 优先** -- Azure OpenAI (gpt-4o) 分析完整的能力配置文件并决定判定;无基于规则的评分回退
- **静态覆盖层** -- 高置信度静态信号(生产级 YARA 命中和恶意软件特定的复合检测器)通过 `static_override(ai_verdict)` 将 AI 判定覆盖为 MALICIOUS,防止 AI 降级明显的恶意软件
- **保证已知恶意软件检测** -- MalwareBazaar 哈希匹配在任何其他分析之前短路至 MALICIOUS(判定始终使用 `malwarebazaar_hash` 方法)
- **报告友好的工件** -- 扫描 JSON 包含顶层 `sha256` 和(如果可用)`static_findings`,用于提取的 URL/域名/路径/命令
- **字节码原生** -- 解析 `.class` 常量池并解析 `invoke*` 指令,而不是在有损 UTF-8 上运行正则表达式
- **重构隐藏字符串** -- 恢复 `new String(new byte[]{...})` 值,这是 fractureiser Stage 0 用来隐藏 URL 和类名的方法
- **递归归档扫描** -- 通过 `!/` 路径来源和预算限制的解压跟踪 jar-in-jar 嵌套
- **每个条目的 YARA** -- 单独扫描每个解压后的归档条目(而不是压缩的 jar blob),严重性来自规则元数据
- **8 个能力检测器** -- 每个都使用带有类范围相关性门的证据索引进行严重性升级
- **工件提取** -- 从字节码证据中提取 URL、域名、shell 命令和文件路径,并输入给 AI
- **完全可解释** -- AI 为每个能力提供基本原理,解释它发现了什么以及为什么重要(或不重要)
- **单一二进制文件** -- `cargo run` 在同一端口启动 HTTP 服务器和 Web UI
## 检测引擎
### 字节码证据提取
每个 `.class` 条目(由 `0xCAFEBABE` 魔数标识)都使用 `cafebabe` crate 进行解析:
1. **常量池字符串** -- 提取并去重所有 `CONSTANT_Utf8` 和 `CONSTANT_String` 条目。这些包含类名(`java/lang/Runtime`)、方法名(`exec`)、描述符(`(Ljava/lang/String;)Ljava/lang/Process;`)和字符串字面量。
2. **调用解析** -- 通过常量池引用链将每条 `invokevirtual`、`invokestatic`、`invokespecial`、`invokeinterface` 和 `invokedynamic` 指令解析为带有方法名和程序计数器位置元数据的 `(owner, name, descriptor)` 元组。
3. **字节数组字符串重构** -- 一个窄操作码状态机遍历方法字节码,寻找 `newarray T_BYTE` + `dup/bipush/sipush/bastore` + `String.
([B)V` 模式。找到后,字节值被组装成隐藏的字符串。这就是 fractureiser Stage 0 隐藏 `java.net.URLClassLoader` 和远程类名的方式——这些字符串从未出现在常量池中。
### 能力检测器
八个检测器针对从提取的字节码证据构建的 `EvidenceIndex` 运行。每个检测器使用类范围的相关性门:单独的方法调用可能是 `low` 严重性,但在同一个类中同时引用可疑字符串或互补 API 的调用会升级为 `high`。
| ID | Capability | What it catches |
|----|-----------|----------------|
| DETC-01 | Process execution | `Runtime.exec()`, `ProcessBuilder.start()`, shell command strings |
| DETC-02 | Network I/O | `URL`, `HttpURLConnection`, `HttpClient`, socket APIs, extracted URLs |
| DETC-03 | Dynamic class loading | `URLClassLoader`, `ClassLoader.defineClass`, `Class.forName`, reflection chains |
| DETC-04 | Filesystem/JAR modification | `ZipOutputStream`, `JarFile`, `Files.walk`, directory traversal + `.jar` markers |
| DETC-05 | Persistence | Windows Run keys, systemd unit paths, startup folders, `schtasks`/`crontab` |
| DETC-06 | Unsafe deserialization | `ObjectInputStream.readObject()` (BleedingPipe-style vulnerability risk) |
| DETC-07 | Native/JNI loading | `System.load`/`loadLibrary`, embedded `.dll`/`.so`/`.dylib` entries |
| DETC-08 | Credential theft | Discord token paths, browser cookie/login databases, `.minecraft` session files |
### YARA 规则
YARA 规则针对每个**解压后的**归档条目单独运行——而不是压缩的 jar blob。这很关键,因为对整个 JAR 运行 YARA 无法可靠地匹配压缩条目内部。
严重性来自规则元数据(`meta.severity`),回退链依次为 `meta.threat_level`、标签,然后是包默认值。规则 ID 以包来源为前缀(演示规则为 `YARA-DEMO-*`,生产规则为 `YARA-PROD-*`)。
通过 `JARSPECT_RULEPACKS` 环境变量分离演示和生产规则包。
#### 生产 YARA 规则
`prod` 规则包(`data/signatures/prod/rules.yar`)包含 6 条针对已知 Minecraft 模组恶意软件家族的高精度规则:
| Rule | Family / Campaign | What it matches |
|------|------------------|-----------------|
| `minecraft_makslibraries_mcmod_info` | Maks Libraries | Forge `mcmod.info` with `makslibraries` mod ID |
| `minecraft_pussylib_pussygo_class` | PussyRAT | `pussylib/pussygo` class marker |
| `minecraft_loaderclient_staging_helper` | Loader/Stager | `StagingHelper` + JAR staging + HTTP client |
| `minecraft_krypton_loader_stub` | Krypton stealer | Obfuscated Fabric stub with `URLClassLoader` + `a/a/a/Config` + `UTF_16BE` + `Error in hash` |
| `minecraft_maxcoffe_socket_loader_stub` | MaxCoffe / MaksRAT | Socket I/O + JAR staging + `defineClass` + `nothing_to_see_here` marker |
| `minecraft_eth_rpc_endpoint_list` | Fractureiser-tagged | `RPCHelper` class with 6+ hardcoded Ethereum JSON-RPC endpoints |
所有生产规则都使用 `severity = "high"` 并且需要多个佐证字符串(没有单字符串规则)以保持高精度。在 high/critical 严重性级别的生产 YARA 命中会触发 `static_override` 层,保证 MALICIOUS 判定,无论 AI 的评估如何。
### 元数据检查
Jarspect 解析模组元数据文件并将它们与归档内容进行交叉引用:
- **Fabric/Quilt** -- `fabric.mod.json`:验证入口点类是否存在于 JAR 中
- **Forge** -- `META-INF/mods.toml`:检查模组 ID、版本、加载器约束
- **NeoForge** -- `META-INF/neoforge.mods.toml`:检查模组 ID、版本、NeoForge 特定字段
- **Spigot/Bukkit** -- `plugin.yml`:验证主类是否存在
- **MANIFEST.MF** -- 标记高风险 Java 代理属性(`Premain-Class`、`Agent-Class`、`Can-Redefine-Classes` 等)
当存在多个元数据文件时,Jarspect 选择最浅层的(最可能是主模组),以避免捆绑依赖项的噪音。
### 递归归档扫描
Jar 可以包含 jar(Fabric 在 `META-INF/jars/` 下的嵌套 jar,或嵌入载荷归档的恶意软件)。Jarspect 递归提取嵌套归档:
- `!/` 分隔的路径来源(例如 `outer.jar!/META-INF/jars/inner.jar!/com/Evil.class`)
- 预算门:每个条目的大小限制、压缩比限制、总解压字节数上限
- 可配置的深度限制
## 判定流水线
Jarspect 使用三层判定流水线。每一层都可以产生最终判定:
### 第 1 层:MalwareBazaar 威胁情报
在任何静态分析之前,jar 的 SHA-256 哈希会与 [MalwareBazaar](https://bazaar.abuse.ch/) (abuse.ch) 进行核对。如果哈希与已知恶意软件样本匹配,扫描立即返回 **MALICIOUS**,置信度为 `confidence: 1.0`,方法为 `method: malwarebazaar_hash`。
默认情况下,MalwareBazaar 匹配会短路(不进行进一步分析)。如果您需要静态分析工件用于报告/图表,即使是已知恶意软件样本,也可以设置 `JARSPECT_MB_MATCH_CONTINUE_ANALYSIS=1`。最终判定仍然基于 MalwareBazaar。
### 第 2 层:字节码能力提取
如果没有发现威胁情报匹配,则运行完整的字节码分析:归档遍历、类解析、YARA 扫描和 8 个能力检测器。结果被组装成 `CapabilityProfile`,包含:
- 存在哪些能力(网络、执行、持久性等)及证据
- 带有严重性的 YARA 规则匹配
- 模组元数据(加载器、模组 ID、版本、作者、入口点)
- 重构的隐藏字符串
- 可疑的清单条目
- 提取的工件:在字节码证据中发现的 URL、域名、shell 命令、文件路径
### 第 3 层:AI 判定 (Azure OpenAI)
能力配置文件被发送到 Azure OpenAI (gpt-4o),并附带专门的系统提示。AI 结合上下文分析配置文件——理解渲染模组中调用 `glxinfo` 的 `Runtime.exec()` 是合法的 GPU 探测,而不是恶意的进程执行。它返回:
- **判定**:`CLEAN`、`SUSPICIOUS` 或 `MALICIOUS`
- **置信度**:0.0 到 1.0
- **风险评分**:0 到 100
- **解释**:发现和推理的文本描述
- **能力评估**:每个能力的基本原理,解释发现了什么以及为什么重要(或不重要)
AI 被指示引用具体(类路径、提取的 URL)并解释什么会升级/降级 SUSPICIOUS 判定。
### 静态覆盖层
在 AI(或启发式回退)产生判定后,运行最后的守卫:如果存在任何高置信度静态信号,无论 AI 怎么说,判定都会被覆盖为 **MALICIOUS**。这可以防止 AI 降级明显的恶意软件。
触发覆盖的信号:
- 任何在 high/critical 严重性级别的生产 YARA 规则匹配(`YARA-PROD-*`)
- 在 high/critical 级别的 `DETC-03.BASE64_STAGER`
- 在 high/critical 级别的 `DETC-02.DISCORD_WEBHOOK`
- 在 high/critical 级别的 `NET-DISCORD-WEBHOOK` 签名匹配
触发时,判定方法变为 `static_override(ai_verdict)`(或 `static_override(heuristic_fallback)`)。
### 判定类别
## | Verdict | Meaning |
|---------|---------|
| `CLEAN` | No malicious indicators; capabilities are consistent with legitimate mod behavior |
| `SUSPICIOUS` | Some concerning signals but insufficient evidence for a definitive malicious classification |
| `MALICIOUS` | Strong evidence of malicious intent -- known malware hash, or AI-confirmed coordinated malicious behavior |
## 基准测试
我们针对 120 个真实世界的样本测试了 Jarspect——70 个确认的恶意软件和 50 个流行的良性模组——MalwareBazaar 哈希匹配被**禁用**,因此每个判定都必须通过字节码分析、YARA 规则和 AI 推理获得,而不是简单的哈希查找。
**数据集。** 恶意软件语料库是来自 MalwareBazaar 的 70 个 jar,过滤到实际包含 Minecraft 模组元数据的样本(`fractureiser`、`mavenrat`、`maksstealer`、`maksrat` 标签)。良性语料库是 Modrinth 下载量前 50 的模组。两者都记录在 [`docs/corpus-calibration.md`](docs/corpus-calibration.md) 中。报告了 Wilson 95% 置信区间,因为 120 个样本虽然诚实但并不大——我们不想过度声明。
### 结果
| Dataset | n | CLEAN | SUSPICIOUS | MALICIOUS | Rate (Wilson 95% CI) |
|---|---:|---:|---:|---:|---|
| MalwareBazaar strict-modlike | 70 | 0 | 0 | **70** | Detection: **100%** (94.8–100.0%) |
| Modrinth top-50 | 50 | **50** | 0 | 0 | Clean: **100%** (92.9–100.0%) |
在这个语料库上实现了完美分离。没有误报,没有遗漏的恶意软件。
在我们的基线恶意软件语料库中,许多判定由静态覆盖层(`static_override(ai_verdict)`)保证——这意味着生产 YARA 规则或其他高置信度信号在 AI 甚至没有发言权之前就锁定了 MALICIOUS。所有 50 个良性模组都由 `ai_verdict` 分类。
### 各层的贡献
消融研究逐层剥离以展示每一层的作用:
| Configuration | Malware (n=70) | Benign (n=50) |
|---|---|---|
| **Full pipeline** (prod YARA + AI + static override) | 70 MALICIOUS | 50 CLEAN |
| AI alone (derived: no static override) | 7 MALICIOUS | 50 CLEAN |
| **AI disabled** (prod YARA + heuristic + static override) | 70 MALICIOUS | 43 CLEAN, 7 SUSPICIOUS |
| **AI + prod YARA disabled** (demo YARA + heuristic + static override) | 66 MALICIOUS, 3 CLEAN, 1 SUSPICIOUS | 39 CLEAN, 10 SUSPICIOUS, 1 MALICIOUS |
结论:静态覆盖层在基线运行中承担了大部分恶意软件检测重任,但 AI 对于良性准确性至关重要——没有它,良性模组会被标记为 SUSPICIOUS。生产 YARA 规则是在这个语料库中捕捉几乎所有与所有恶意软件样本之间的区别。
消融图(AI 关闭 / 演示 vs 生产)
### 能力指纹
恶意软件和良性模组在字节码级别看起来非常不同。只有在检测器以中等或高严重性触发时才计算能力——排除了低信号噪音。
| Capability | Malware (n=70) | Benign (n=50) |
|---|---:|---:|
| `dynamic_loading` | 94.3% | 2.0% |
| `network` | 78.6% | 18.0% |
| `filesystem` | 75.7% | 6.0% |
| `deserialization` | 0.0% | 8.0% |
| `native_loading` | 0.0% | 8.0% |
| `execution` | 0.0% | 0.0% |
| `persistence` | 0.0% | 0.0% |
| `credential_theft` | 0.0% | 0.0% |
签名模式很清楚:恶意软件在 `dynamic_loading` + `network` + `filesystem` 上高度聚集(URLClassLoader → 远程获取 → 写入磁盘流水线)。良性模组在中/高严重性级别基本上没有能力,只有少量的 `network`(模组更新检查器)和 `deserialization`/`native_loading`(合法用例)。
### 重现这些基准测试
完整的重现步骤、语料库选择标准和聚合脚本记录在 [`docs/benchmarking.md`](docs/benchmarking.md) 和 [`docs/corpus-calibration.md`](docs/corpus-calibration.md) 中。SVG 图表生成使用:
```
bun scripts/render-benchmark-figures.ts \
--baseline-malware-aggregate /aggregate.csv \
--baseline-benign-aggregate /aggregate.csv \
--out-dir docs/benchmarks
```
## 快速开始
**前置条件:** Rust stable 工具链 ([rustup.rs](https://rustup.rs))
```
git clone https://github.com/Microck/jarspect.git
cd jarspect
cargo run
```
服务器默认在 `http://127.0.0.1:18000` 启动。
- **Web UI** -- [http://localhost:18000/](http://localhost:18000/)
- **健康检查** -- [http://localhost:18000/health](http://localhost:18000/health)
运行端到端演示(构建合成的可疑 `.jar` 并演练完整 API):
```
bash scripts/demo_run.sh
```
## 安装
Jarspect 作为单个 Rust 二进制文件发布。不需要外部运行时或数据库。
```
# 1. Install Rust (if you don't have it)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
# 2. Clone and build
git clone https://github.com/Microck/jarspect.git
cd jarspect
cargo build --release
# 3. Run
./target/release/jarspect
```
## 所有持久化数据都保存在相对于工作目录的 `.local-data/` 中(首次运行时自动创建)。
## 用法
完整流程是三个 HTTP 调用:
**步骤 1:上传 `.jar`**
```
curl -X POST http://localhost:18000/upload \
-F "file=@/path/to/yourmod.jar"
```
```
{
"upload_id": "a3f9c1d2e4b56789...",
"filename": "yourmod.jar",
"size_bytes": 204800,
"storage_url": ".local-data/uploads/a3f9c1d2e4b56789....jar"
}
```
**步骤 2:运行扫描**
```
curl -X POST http://localhost:18000/scan \
-H "Content-Type: application/json" \
-d '{"upload_id": "a3f9c1d2e4b56789..."}'
```
响应包含完整的 `ScanRunResponse`(参见 [数据模型](#data-model)),包括 `scan_id`。
**步骤 3:获取结果**
```
curl http://localhost:18000/scans/
```
## 配置
### 服务器
| Variable | Default | Description |
|----------|---------|-------------|
| `JARSPECT_BIND` | `127.0.0.1:18000` | Host and port the HTTP server binds to |
| `JARSPECT_RULEPACKS` | `demo` | Which YARA/signature rulepacks to load: `demo`, `prod`, or `demo,prod` |
| `JARSPECT_AI_ENABLED` | `1` | Enable/disable AI verdict even if Azure OpenAI env vars are set (`0`/`false` to disable) |
| `JARSPECT_UPLOAD_MAX_BYTES` | `52428800` | Maximum accepted upload size in bytes (default 50 MiB) |
| `JARSPECT_MB_HASH_MATCH_ENABLED` | `1` | Enable/disable MalwareBazaar hash matching (`0`/`false` to disable; useful for benchmarking static/AI detectors) |
| `RUST_LOG` | `jarspect=info,tower_http=info` | Log verbosity (uses `tracing-subscriber` env-filter syntax) |
### AI 判定(生产环境必需)
| Variable | Description |
|----------|-------------|
| `AZURE_OPENAI_ENDPOINT` | Azure OpenAI endpoint URL (e.g. `https://your-resource.openai.azure.com`) |
| `AZURE_OPENAI_API_KEY` | Azure OpenAI API key |
| `AZURE_OPENAI_DEPLOYMENT` | Deployment name (e.g. `gpt-4o`) |
| `AZURE_OPENAI_API_VERSION` | API version (default: `2024-10-21`) |
### 威胁情报
| Variable | Description |
|----------|-------------|
| `MALWAREBAZAAR_API_KEY` | MalwareBazaar API key for hash lookups (optional but recommended) |
示例:完整生产配置:
```
JARSPECT_BIND=0.0.0.0:18000 \
JARSPECT_RULEPACKS=prod \
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com \
AZURE_OPENAI_API_KEY=your-key \
AZURE_OPENAI_DEPLOYMENT=gpt-4o \
MALWAREBAZAAR_API_KEY=your-mb-key \
RUST_LOG=jarspect=info \
cargo run --release
```
## API 参考
所有响应均为 JSON。错误响应使用 `{"detail": ""}`。
### `POST /upload`
上传 `.jar` 文件以供稍后扫描。接受带有名为 `file` 字段的 `multipart/form-data`。
**约束:** 需要 `.jar` 扩展名;最大 50 MB。
**响应 `200`:**
```
{
"upload_id": "a3f9c1d2e4b56789abcdef0123456789",
"filename": "suspicious-mod.jar",
"size_bytes": 18432,
"storage_url": ".local-data/uploads/a3f9c1d2e4b56789abcdef0123456789.jar"
}
```
`upload_id` 是一个 32 字符的小写十六进制字符串(UUID v4,简单形式)。
### `POST /scan`
在先前上传的 `.jar` 上运行三层扫描流水线(MalwareBazaar -> 字节码提取 -> AI 判定)。
**请求体:**
```
{
"upload_id": "a3f9c1d2e4b56789abcdef0123456789"
}
```
**响应 `200`:** 完整的 `ScanRunResponse`(参见 [数据模型](#data-model))。
### `GET /scans/{scan_id}`
检索先前持久化的扫描结果。`scan_id` 必须是 32 字符的十六进制字符串。
**响应 `404`:** `{"detail": "Scan not found"}`
### `GET /health`
存活检查。报告 AI 状态、加载的规则包、签名/YARA 规则计数和功能标志。
**响应 `200`:**
```
{
"status": "ok",
"service": "jarspect",
"version": "0.1.0",
"ai_enabled": true,
"rulepacks": "prod",
"signature_count": 12,
"yara_rule_count": 6,
"mb_hash_match_enabled": true,
"upload_max_bytes": 52428800
}
```
## Web UI
启动服务器后打开 [http://localhost:18000/](http://localhost:18000/)。
单页控制台允许您:
1. **将 `.jar` 文件拖放**到上传区域或使用文件选择器
2. **点击 "Run scan"** -- UI 调用 `/upload` 然后 `/scan` 并流式传输状态消息
3. **检查判定** -- 显示 AI 判定(CLEAN / SUSPICIOUS / MALICIOUS)、置信度分数、检测方法和 AI 的完整解释
4. **查看 AI 推理** -- AI 为每个能力提供的基本原理,解释为什么每个检测到的能力令人担忧或不令人担忧
5. **浏览指标** -- 带有严重性徽章、证据文本和来自字节码检测器和威胁情报的基本原理的可过滤列表
## 架构
```
flowchart TB
subgraph Client
UI["Browser UI"]
CLI["CLI / scripts"]
end
subgraph Server["Jarspect (Axum server)"]
H["GET /health"]
UP["POST /upload\n(multipart .jar)"]
SC["POST /scan\n(upload_id)"]
GET["GET /scans/{scan_id}"]
end
subgraph Storage["Local storage (.local-data)"]
UPL[(".local-data/uploads/{upload_id}.jar")]
SCS[(".local-data/scans/{scan_id}.json")]
end
subgraph Pipeline["Scan pipeline (src/scan.rs)"]
SHA["SHA-256"]
MB["Layer 1: MalwareBazaar hash lookup"]
STATIC["Layer 2: Bytecode analysis\n(archive traversal + evidence + YARA + detectors)"]
PROF["Capability profile"]
AI["Layer 3: AI verdict (Azure OpenAI)"]
OVR["Static override (high-confidence)\n(prod YARA + malware-specific detectors)"]
end
subgraph External["External services"]
MBAPI["MalwareBazaar (abuse.ch)"]
AZ["Azure OpenAI"]
end
subgraph Signatures["Signature data"]
SIGS["data/signatures/{demo,prod}/"]
end
UI --> UP
CLI --> UP
UI --> SC
CLI --> SC
UI --> GET
CLI --> GET
UP -->|write jar| UPL
SC -->|read jar| UPL
SC --> SHA --> MB --> MBAPI
MB -->|no match| STATIC
STATIC --> SIGS
STATIC --> PROF --> AI --> AZ
AI --> OVR -->|persist result| SCS
GET -->|read result| SCS
```
扫描流水线位于 `src/scan.rs` 中,作为运行三层流水线的协调器。`src/main.rs` 是 Axum 传输层。
```
POST /scan
|
+- SHA-256 hash sha2::Sha256::digest()
+- MalwareBazaar lookup malwarebazaar::check_hash() - match? -> MALICIOUS
|
+- Archive traversal analysis::read_archive_entries_recursive()
+- Bytecode extraction analysis::extract_bytecode_evidence()
+- YARA per-entry analysis::run_yara_scan()
+- Capability detectors detectors::run_detectors() - 8 detectors against EvidenceIndex
+- Profile builder profile::build_profile() - structured capability summary
|
+- AI verdict verdict::ai_verdict() - Azure OpenAI gpt-4o analysis
returns CLEAN / SUSPICIOUS / MALICIOUS + explanation
```
**签名加载**在启动时发生一次:
- `data/signatures/{demo,prod}/signatures.json` -- 按规则包加载
- `data/signatures/{demo,prod}/rules.yar` -- 通过 `yara_x::Compiler` 编译,存储为 `Arc`
## 两者都保存在 `AppState` 中并通过 `Arc` 在请求间共享。
## 数据模型
扫描结果以美观打印的 JSON 形式持久化在:
```
.local-data/scans/{scan_id}.json
```
顶层结构(`ScanRunResponse`):
| Field | Type | Description |
|-------|------|-------------|
| `scan_id` | `string` | 32-character hex UUID for this scan run |
| `verdict` | object | AI verdict: `result`, `confidence`, `risk_score`, `method`, `explanation`, `capabilities_assessment` |
| `malwarebazaar` | object or null | MalwareBazaar match details (if Layer 1 matched): `sha256_hash`, `family`, `tags`, `first_seen` |
| `capabilities` | object or null | Capability signals per detector: `{ name: { present, evidence[] } }` |
| `yara_hits` | array or null | YARA rule matches: `[{ id, severity, file_path, evidence }]` |
| `metadata` | object or null | Mod metadata from fabric.mod.json / mods.toml / plugin.yml |
| `profile` | object or null | Full `CapabilityProfile` sent to the AI for analysis |
| `intake` | object | Upload metadata: `upload_id`, `storage_path`, `file_count`, `class_file_count` |
判定对象:
## | Field | Type | Description |
|-------|------|-------------|
| `result` | `string` | `CLEAN`, `SUSPICIOUS`, or `MALICIOUS` |
| `confidence` | `f64` | 0.0 to 1.0 confidence the verdict |
| `risk_score` | `u8` | 0 to 100 risk score |
| `method` | `string` | How the verdict was determined: `ai_verdict`, `malwarebazaar_hash`, `static_override(ai_verdict)`, or `heuristic_fallback` |
| `explanation` | `string` | Full prose explanation of findings and reasoning |
| `capabilities_assessment` | `map` | Per-capability rationale from the AI (e.g. `{ "execution": "Runtime.exec used for GPU probing, not malicious" }`) |
## 安全性与局限性
- **无沙箱。** Jarspect 不执行或加载任何 `.class` 文件。所有分析都是纯静态的(字节码级别的常量池和指令解析)。
- **依赖 AI。** 生产判定需要一个有效的 Azure OpenAI 端点。如果没有 AI 配置,扫描将失败并报错。AI 模型的判断是模棱两可情况下的最终权威。
- **速率限制。** Azure OpenAI 端点可能会受到速率限制(429 响应)。Jarspect 以指数退避重试,但如果速率限制时间过长将失败。
- **合成演示装置。** 捆绑的演示规则包匹配来自 `demo/suspicious_sample.jar` 的字符串——由 `demo/build_sample.sh` 构建的合成工件。存储库中不包含真实的恶意软件样本。
- **仅静态分析。** 字节码层从字节码证据中确定性地提取能力和工件,但不执行代码。
- **50 MB 上传上限。** 服务器端强制执行;可通过 `JARSPECT_UPLOAD_MAX_BYTES` 配置。
- **仅限 `.jar`。** 其他归档类型在上传处理程序中被拒绝。
- **预算限制的提取。** 递归归档扫描有每个条目的大小、压缩比、总解压字节数和深度限制,以防止 zip-bomb 拒绝服务。
## 开发
```
# Check for compile errors
cargo check
# Run tests
cargo test
# Build optimized binary
cargo build --release
# Run with verbose logging
RUST_LOG=debug cargo run
# Run with production YARA rules
JARSPECT_RULEPACKS=prod cargo run
```
**项目布局:**
```
src/
main.rs Axum HTTP transport layer
lib.rs core types, static analysis, run_scan() delegation
scan.rs 3-layer scan pipeline orchestrator
verdict.rs AI verdict via Azure OpenAI (prompt, retry, rate-limit handling)
profile.rs capability profile builder (structured AI input)
malwarebazaar.rs MalwareBazaar hash lookup (abuse.ch)
analysis/
mod.rs analysis module exports and shared types
archive.rs recursive jar-in-jar traversal with budget gates
classfile_evidence.rs cafebabe class parsing, constant-pool + invoke resolution
byte_array_strings.rs new String(new byte[]{...}) reconstruction state machine
evidence.rs EvidenceIndex for detector lookups
metadata.rs fabric.mod.json / mods.toml / META-INF/neoforge.mods.toml / plugin.yml / MANIFEST.MF
yara.rs per-entry YARA scanning with rulepack separation
detectors/
mod.rs detector runner and exports
spec.rs detector specification types
index.rs EvidenceIndex builder
capability_exec.rs DETC-01: process execution
capability_network.rs DETC-02: network I/O
capability_dynamic_load.rs DETC-03: dynamic class loading
capability_fs_modify.rs DETC-04: filesystem/JAR modification
capability_persistence.rs DETC-05: persistence mechanisms
capability_deser.rs DETC-06: unsafe deserialization
capability_native.rs DETC-07: native/JNI loading
capability_cred_theft.rs DETC-08: credential theft
capability_base64_stager.rs compound: base64-encoded stager detection
capability_discord_webhook.rs compound: Discord webhook exfiltration
capability_remote_code_load.rs compound: remote code fetch + load correlation
data/signatures/
demo/ demo rulepack (matches synthetic fixtures)
prod/ production rulepack (real bytecode-aware rules)
web/
index.html single-page browser UI
app.js UI logic with verdict rendering
styles.css UI styles (Geist)
docs/
corpus-calibration.md calibration report from corpus testing
benchmarking.md benchmark workflows and aggregation
false-positives.md FP case studies and fixes
brand/ logo assets
scripts/
demo_run.sh end-to-end demo (build sample + scan)
modrinth-top-50-scan.sh benign benchmark: download + scan Modrinth top mods
scan-local-dir.sh batch scan a local directory of jars
malwarebazaar-download.sh download MalwareBazaar samples by tag
select-malwarebazaar-dataset.ts filter downloaded jars to mod-like subset
aggregate-run.ts aggregate a run into CSV + summary JSON
.local-data/ runtime data (gitignored)
uploads/{upload_id}.jar uploaded .jar files
scans/{scan_id}.json persisted scan results
```
要添加新的 YARA 规则,请将规则附加到 `data/signatures/{demo,prod}/rules.yar` 下的相应规则包中。在您的规则中包含 `meta.severity` 以进行自动严重性映射。编译器在启动时运行,会报告任何语法错误。
## 贡献
欢迎在 [github.com/Microck/jarspect](https://github.com/Microck/jarspect) 提交问题和拉取请求。
对于错误报告,请包含 `scan_id` 和触发问题的匿名化 `.jar`(或最小复现)。对于新的检测规则,请包含基本原理和演示匹配的安全合成装置。
## 许可证
Apache-2.0。参见 [`LICENSE`](LICENSE)。
## 起源
构建于 **Microsoft AI Dev Days Hackathon 2026**。 标签:AI安全审计, Azure OpenAI, BleedingPipe, DNS信息、DNS暴力破解, DNS 反向解析, DNS枚举, DNS 解析, Fractureiser, HTTP工具, IP 地址批量处理, JAR文件扫描器, Java反序列化, Java字节码分析, Minecraft模组安全, YARA规则, 云安全监控, 代码混淆检测, 反病毒, 可视化界面, 大语言模型蜜罐, 恶意软件情报, 游戏安全, 网络信息收集, 网络安全审计, 网络安全工具, 通知系统, 静态分析, 风险评分