BillVolz/vk-ai-sensor
GitHub: BillVolz/vk-ai-sensor
一款 Windows 端点安全传感器,通过本地 ETW 检测规则结合可选 AI 分析层,监控并识别主机入侵指标与 AI 驱动的新型威胁。
Stars: 0 | Forks: 0
# vk-ai-sensor





`vk-ai-sensor` 是一款本地优先的 endpoint 传感器,用于监控主机的入侵指标
以及新兴的 AI 驱动威胁:自主恶意 agent、
AI 生成的恶意软件,以及利用 AI 探测或伪装合法系统的攻击者。
检测完全在计算机上运行。可选的 AI 层可以解释、分诊、
并对传感器发现的内容进行推理,但核心功能的运行绝不依赖于它。
这个名称是对《银翼杀手》中 Voight-Kampff 机器的致敬,该设备旨在
区分人类与试图伪装成人类的机器。这也是本项目的目标。
## 目录
- [设计原则](#design-principles)
- [系统要求](#requirements)
- [快速开始](#quick-start)
- [服务模式](#service-modes)
- [检测规则](#detection-rules)
- [训练模式](#training-mode)
- [白名单](#allow-list)
- [受信任发布者抑制](#trusted-publisher-suppression)
- [AI 提供商](#ai-providers)
- [AI 自动放行](#ai-auto-allow)
- [通知](#notifications)
- [进程响应](#process-response)
- [网络隔离](#network-isolation)
- [DNS 查询监控](#dns-query-monitoring)
- [新进程检测](#new-process-detection)
- [密钥管理](#secret-management)
- [完整配置参考](#full-configuration-reference)
- [架构](#architecture)
- [许可证](#license)
## 设计原则
- **本地优先,始终在线。** 核心检测在零网络访问和零 API
密钥的情况下运行。如果 AI 层处于离线、密钥错误或受到速率限制,检测功能不受影响。
- **AI 是增强,而非引擎。** 可选的 AI 层在事后分析警报 —— 解释警报、
对重要事项进行排序,并标记可能的误报。它是意见提供者,永远不会出现在关键路径中。
- **自带提供商。** AI 访问位于抽象层之后,因此您可以将其指向
云模型(Anthropic、OpenAI、Azure OpenAI)或完全本地的模型(Ollama、LM
Studio)。“AI 帮助”本身可以 100% 保留在本地设备上。
- **数据离开计算机需明确选择启用。** 启用云提供商意味着警报
上下文将离开计算机。每个向外发送数据的功能(AI 分析、webhook
通知、VirusTotal 查询)默认均为禁用状态,并有明确的文档说明。
- **妥善存储密钥。** API 密钥使用 Windows DPAPI
(`ProtectedData`,`CurrentUser` 范围)进行静态加密。配置文件中绝不会
出现明文密钥。
## 系统要求
- Windows 10 / Server 2016 或更高版本(64 位)
- .NET 10 运行时
- **管理员 / LocalSystem** — ETW kernel session 需要提升的权限
- 对于 AI 功能:需要 Anthropic、OpenAI 或 Azure OpenAI 的 API 密钥;或者运行中的 Ollama
实例以实现完全本地的 AI
## 快速开始
```
# 构建
dotnet build --configuration Release
# 作为 Windows Service 安装(从提升的提示符运行)
sc.exe create vk-ai-sensor binPath= "C:\path\to\VkAiSensor.Service.exe"
sc.exe start vk-ai-sensor
# 或者交互式运行(按 Ctrl+C 停止)
.\VkAiSensor.Service.exe
```
警报将写入 Windows 事件日志和控制台。要启用 AI 分析或
出站通知,请在启动服务之前编辑 `appsettings.json`(参见下文的
章节)。
## 服务模式
在 `appsettings.json` 中设置 `Service:Mode`:
| 模式 | 描述 |
|---|---|
| `Normal`(默认) | 生产模式。事件将根据所有规则进行评估。警报首先通过白名单过滤,然后发送到配置的接收器(日志、AI、电子邮件、webhook、响应)。 |
| `Training` | 基线收集模式。运行相同的规则,但捕获所有未过滤的警报。在配置的持续时间结束后,传感器会对每项观测进行 AI 审查、写入输出文件并停止。在首次安装时使用此模式来构建白名单和进程基线。 |
## 检测规则
| 规则 ID | 名称 | 严重性 | MITRE | 捕获内容 |
|---|---|---|---|---|
| VK-E001 | EncodedPowerShellRule | High | T1027 | 使用 Base64 编码的 `-EncodedCommand` 参数启动的 PowerShell — 一种常见的混淆技术 |
| VK-E002 | LolBinCommandlineRule | High | T1218 | 使用可疑参数模式调用的 Living-off-the-land 二进制文件(`mshta`、`regsvr32`、`certutil`、`wscript` 等) |
| VK-N001 | ExternalNetworkRule | Medium | T1571 | 来自**未签名**进程的出站网络连接到公共 IP。签名进程在规则级别被抑制 — 只有没有内嵌 Authenticode 签名的进程才会触发此规则。对于您信任的特定未签名进程(内部工具等),请使用白名单 |
| VK-N002 | ScriptingHostNetworkRule | High | T1059 | `wscript.exe`、`cscript.exe` 或 `mshta.exe` 打开网络连接 — 脚本宿主极少需要直接访问互联网 |
| VK-F001 | ExecutableDroppedInUserPathRule | Medium | T1105 | 写入用户可写暂存目录(`AppData\Temp`、`AppData\Roaming`、`ProgramData`、`Users\Public`)的可执行文件或脚本。排除已知的每用户安装路径(`AppData\Local\Programs`、`AppData\Local\Microsoft` 等) |
| VK-F002 | RansomwareFileActivityRule | Critical | T1486 | 创建或写入具有已知勒索软件特定扩展名(`.locked`、`.encrypted`、`.wncry`、`.cerber`、`.ryuk`、`.lockbit`、`.conti`、`.blackcat`,30 多个特定家族变体)或勒索说明文件名模式的文件。通用锁定文件扩展名(`.lock`、`.lck`)被特意排除,以避免备份和 VCS 工具导致的误报 |
| VK-F003 | MassFileWriteRule | High | T1486 | 单个进程在滑动时间窗口内触及超过配置数量的**不同文件路径** — 无论扩展名如何,都能捕获零日勒索软件。计算不同的路径(而非原始打开事件),以避免备份代理重复打开同一文件而导致的误报。注意:底层的 ETW `FileIOCreate` 事件在任何 `NtCreateFile`/`NtOpenFile` 调用(包括读取)时都会触发 — 因此打开大量文件的扫描程序和索引器在高阈值下可能会触发此规则 |
| VK-P001 | TempPathProcessRule | High | T1059 | 直接从 `Temp`、`AppData` 或其他用户可写路径启动的进程映像 — 恶意软件几乎总是从这些位置运行 |
| VK-P002 | OfficeSpawnShellRule | High | T1566 | Microsoft Office 应用程序(`WINWORD`、`EXCEL`、`POWERPNT` 等)启动 shell 或脚本宿主 — 经典的宏/网络钓鱼执行链 |
| VK-P003 | LolBinChildProcessRule | High | T1218 | Living-off-the-land 二进制文件被用作父进程以启动意外的子进程 |
| VK-P004 | NewProcessRule | Medium | T1036 | 在训练基线期间未见过的进程映像路径 — 当 endpoint 上首次出现任何新可执行文件时发出警报 |
| VK-R001 | ScheduledTaskRegistryRule | Medium | T1053 | `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule` 下的注册表键修改 — 通过计划任务实现持久化 |
| VK-R002 | ShadowCopyDeletionRule | Critical | T1490 | `vssadmin`、`diskshadow`、`wmic`、`wbadmin`、`bcdedit` 或删除影子副本或禁用恢复的 PowerShell 命令 — 几乎所有勒索软件都会使用的加密前步骤 |
| VK-C001 | CredentialTheftRule | Critical | T1003 | 已知的凭据窃取工具(mimikatz、wce、fgdump、lazagne、pwdump),通过 procdump 或 `rundll32 comsvcs MiniDump` 针对 LSASS,任何命令行中的 mimikatz 模块调用,ntdsutil IFM 提取,以及 LSASS 转储文件创建 |
| VK-L001 | LateralMovementRule | High | T1021/T1047/T1053 | PsExec 执行,WMI 远程进程创建(`wmic /node:`),远程服务控制(`sc \\host`),远程计划任务(`schtasks /s`),挂载管理共享(`net use \\host\admin$`),以及 PowerShell 远程处理(`Invoke-Command -ComputerName`) |
| VK-D001 | EventLogClearRule | High | T1070.001 | `wevtutil cl`、PowerShell `Clear-EventLog` / `Clear-WinEvent`、`auditpol /clear` 和 `fsutil usn deletejournal` — 攻击者在破坏后用于清除取证证据的清理操作 |
| VK-DNS001 | DnsQueryRule | High/Medium | T1071.004/T1568.002 | DNS 隧道指标(FQDN > 100 字符,> 9 个标签,任何标签 > 40 字符 — High),最左侧标签上类似 DGA 的熵(可选,Medium),以及查询常被滥用的免费 TLD(.tk/.ml/.ga/.cf/.gq 等 — Medium) |
除了 **VK-F003**(每个进程的滑动窗口不同路径计数器)、
**VK-F001**(每个文件的冷却时间,用于去重多块写入事件)和
**VK-P004**(在启动时加载基线文件)之外,所有规则都是无状态的。所有规则都在同一个 pipeline 中进行评估,
并且每个规则都可以通过白名单或受信任发布者过滤器独立抑制。
## 训练模式
训练模式构建两个让传感器在生产环境中发挥作用的工件:
- **`proposed-allowlist.json`** — 要添加到 `Rules:AllowList` 的进程名称,以抑制
已知良好的噪音
- **`known-processes.json`** — VK-P004 用于检测
新/未见过的可执行文件的进程映像路径基线
### 运行训练
1. 在 `appsettings.json` 中将 `Service:Mode` 设置为 `Training`
2. (可选)配置 AI 提供商(`Ai:Provider`),以便通过 AI 审查观测结果,
而不是仅仅通过启发式方法进行分类
3. 启动服务并让其运行配置的 `Service:Training:Duration`(默认
10 分钟;越长越好 — 尽量涵盖正常的工作活动)
4. 服务自动停止并将四个文件写入 `Service:Training:OutputPath`
(默认为可执行文件旁边的 `training-output/`):
| 文件 | 内容 |
|---|---|
| `known-processes.json` | 用作 VK-P004 基线的进程映像路径 |
| `proposed-allowlist.json` | 要复制到 `appsettings.json` 中的白名单补丁 |
| `review-queue.json` | AI 标记为不确定或可疑的观测结果 |
| `all-observations.json` | 包含每次独特观测和 AI 分类的完整审计日志 |
### 训练后
```
// appsettings.json — apply training results
// 1. Copy known-processes.json to the service directory, then enable VK-P004:
"Rules": {
"NewProcess": {
"Enabled": true // was false
}
}
// 2. Paste the contents of proposed-allowlist.json into Rules:AllowList:PerRule
// 3. Switch back to Normal mode:
"Service": {
"Mode": "Normal"
}
```
### 训练配置
```
"Service": {
"Mode": "Training",
"Training": {
"Duration": "00:10:00", // how long to collect (hh:mm:ss)
"OutputPath": "training-output", // relative to exe dir, or absolute
"AiReview": true, // send observations to Ai:Provider for classification
"BatchSize": 25 // observations per AI request
}
}
```
## 白名单
白名单会在任何警报到达接收器或通知之前,抑制已知的良性警报。
它在规则触发之后,但在 AI 层、日志记录或通知之前进行评估。
```
"Rules": {
"AllowList": {
// Processes listed here are suppressed across ALL rules
"GlobalTrustedProcesses": [],
"PerRule": {
"VK-N001": {
"Disabled": false, // set true to turn off the rule entirely
"ProcessNames": [ // suppress by process name (case-insensitive)
"chrome.exe", "msedge.exe", "outlook.exe"
],
"DestinationCidrs": [], // suppress by destination IP/CIDR (IPv4)
"DestinationPorts": [] // suppress by destination port
},
"VK-F001": {
"ProcessNames": ["OneDrive.exe", "teams.exe"]
},
"VK-F003": {
"ProcessNames": ["veeam.exe", "robocopy.exe", "7z.exe"]
}
}
}
}
```
`ProcessNames`、`DestinationCidrs` 和 `DestinationPorts` 会进行独立检查 —
如果其中任何一个匹配,警报就会被抑制。文件和注册表规则还通过 `PathPrefixes` 支持
路径前缀抑制。
## 受信任发布者抑制
受信任发布者过滤器与白名单一起运行,会自动抑制由您信任的发布者签名的进程发出的警报
— 无需配置按进程或按规则划分的
白名单条目。它是大规模减少误报噪音的主要机制。
**工作原理:**
1. `ProcessSignatureCachePopulatorRule` (VK-INTERNAL-SIG) 与其他所有规则一起运行。
在每个进程启动事件中,它会从二进制文件中读取 Authenticode 签名者名称,并
存储在以 PID 为键的进程内 `ProcessSignatureCache` 中。这涵盖了传感器启动后启动的所有进程
— 包括已知良好的 VK-P004 基线中的进程。
2. 对于在传感器启动时已经在运行的进程,缓存中没有条目。
在来自此类进程的第一个警报上,`TrustedPublisherFilter` 会执行实时查找
(`Process.GetProcessById(pid).MainModule.FileName` → Authenticode 签名者)并填充
缓存,因此来自同一 PID 的后续警报永远不会重新读取二进制文件。
3. `TrustedPublisherFilter` 检查每个警报 — 首先是 `SignerName` 事实(直接出现在
VK-P004 警报上),然后是针对所有其他规则(VK-N001、VK-F001、
VK-F003 等)按 PID 进行缓存检查。
4. 如果签名者名称以任何配置的发布者前缀开头,则在它到达任何接收器之前,
该警报将被抑制。
**目录签名的二进制文件(`TrustSystemPaths`):** 许多 Windows 组件和供应商工具
使用 Windows 安全目录签名(`CatRoot` 中的 `.cat` 文件),而不是 PE 文件中内嵌的
Authenticode 证书。这些二进制文件在标准签名检查中显示为未签名,
即使它们是由管理员安装的。当 `TrustSystemPaths: true`
(默认值)时,从 `%ProgramFiles%`、`%ProgramFiles(x86)%` 或
`%SystemRoot%` 运行的任何进程都会自动受信任,即使未找到内嵌签名。恶意软件
如果没有事先提权,就无法安装到这些路径中,这使得该启发式方法在实践中非常可靠。
这意味着单个进程启动事件(或首个警报实时查找)涵盖了该进程实例的所有后续
噪音 — 网络连接、文件写入、注册表更改 —
而无需任何额外的白名单配置。
```
"Rules": {
"TrustedPublishers": {
"Enabled": true,
"PrefixMatch": true, // "Microsoft" matches "Microsoft Corporation", "Microsoft Windows", etc.
"TrustSystemPaths": true, // trust catalog-signed binaries in Program Files / Windows dir
"Publishers": [
"Microsoft",
"Google",
"Slack Technologies",
"Backblaze",
"JetBrains",
"Dell",
"Zoom Video Communications",
"Adobe",
"Logitech",
"Amazon"
// Add any publisher whose signed software you trust on this endpoint
]
}
}
```
**`PrefixMatch: true`(默认值):** `"Microsoft"` 的发布者条目将匹配任何名称以
`"Microsoft"` 开头的签名者,涵盖 `"Microsoft Corporation"`、
`"Microsoft Windows"`、`"Microsoft Windows Publisher"` 以及任何未来的子实体。
设置为 `false` 可进行精确匹配。
**与白名单的关系:** 受信任发布者过滤器首先运行。如果它
抑制了警报,则不会参考白名单。将受信任发布者列表用于广泛的
发布者级别信任,将白名单用于发布者过滤器无法表达的进程级别或目标级别例外
(例如,抑制特定的未签名内部工具或特定目标 IP)。
**范围:** 抑制适用于所有规则。如果您全局信任某个发布者,但希望
特定规则仍然针对其进程触发,请禁用 `TrustedPublishers` 并使用
`AllowList:PerRule` 代替。
## AI 提供商
AI 分析是可选的,并且默认禁用。启用后,传感器会将结构化的
警报上下文(无原始事件遥测数据)发送给配置的提供商,以获取通俗易懂的
解释和分诊。
```
"Ai": {
"Enabled": true,
"Provider": "Anthropic", // Anthropic | OpenAI | AzureOpenAI | Ollama | None
"MinSeverity": "High", // only analyze alerts at or above this severity
"Anthropic": {
"ApiKey": "", // or set env var VK_ANTHROPIC_API_KEY
"Model": "claude-opus-4-8"
},
"OpenAI": {
"ApiKey": "", // or set env var VK_OPENAI_API_KEY
"Model": "gpt-4o"
},
"AzureOpenAI": {
"Endpoint": "",
"ApiKey": "", // or set env var VK_AZUREOPENAI_API_KEY
"DeploymentName": "",
"ApiVersion": "2024-10-21"
},
"Ollama": { // fully local — no data leaves the machine
"BaseUrl": "http://localhost:11434",
"Model": "llama3.2"
}
}
```
API 密钥也可以通过 DPAPI 加密存储(参见[密钥管理](#secret-management))。
环境变量优先于配置文件中的值;DPAPI 密钥优先于环境
变量。
**AI 接收到的内容:** 一个结构化的 `AlertContext` 对象,包含规则 ID、标题、
严重性、描述以及一个命名事实字典(文件路径、进程名称、命令
行等)。永远不会发送原始 ETW 事件。
### AI 自动放行
当 AI 将警报评估为 `likely_false_positive` 时,传感器可以自动将
该进程添加到动态白名单中,以便同一进程永远不会再次触发相同的规则。
这默认处于禁用状态 — 仅在验证了您环境中 AI 的准确性后才启用它。
```
"Ai": {
"AutoAllow": {
"Enabled": false, // master switch — validate AI accuracy before enabling
"TriggerAssessment": "likely_false_positive",
"OutputPath": "training-output/learned-allowlist.json", // persisted across restarts
"EligibleRules": [ // high-confidence threat rules are excluded
"VK-N001",
"VK-F001",
"VK-F003",
"VK-P004",
"VK-DNS001"
]
}
}
```
学习到的白名单以 JSON 格式存储并在启动时加载,因此进程信任决策
在重启后依然有效,无需手动编辑 `appsettings.json`。条目以
规则 ID 和进程名称为键;您可以随时手动检查和精简该文件。
## 通知
出站通知默认为禁用。在 `Notifications` 下启用其中一个或两个。
### Webhook
在每个符合条件的警报上向任何 URL 发布 JSON payload。适用于 Slack 传入
webhook、Microsoft Teams 连接器、PagerDuty Events API、自定义 SIEM pipeline 或
任何 HTTP endpoint。
```
"Notifications": {
"Webhook": {
"Enabled": true,
"Url": "https://hooks.slack.com/services/...",
"Secret": "", // optional: adds X-VkAiSensor-Signature: sha256=
"MinSeverity": "High", // Info | Low | Medium | High | Critical
"TimeoutSeconds": 10
}
}
```
**Payload 结构:**
```
{
"alertId": "3fa85f64-...",
"ruleId": "VK-F002",
"title": "Ransomware file activity: budget.locked",
"severity": "Critical",
"firedAt": "2026-06-07T14:32:00Z",
"description": "...",
"facts": { "FilePath": "...", "Extension": ".locked", ... }
}
```
**HMAC 签名:** 当设置了 `Secret` 时,将添加标头 `X-VkAiSensor-Signature: sha256=`
以便接收方可以验证 payload 未被篡改(与
GitHub webhook 签名模式相同)。
### 电子邮件
通过任何 SMTP 中继(包括 SocketLabs)发送 HTML 电子邮件。
```
"Notifications": {
"Email": {
"Enabled": true,
"SmtpHost": "smtp.socketlabs.com",
"SmtpPort": 587,
"UseSsl": true,
"Username": "your-smtp-user",
"Password": "your-smtp-password",
"From": "vk-ai-sensor@yourdomain.com",
"To": ["security-team@yourdomain.com", "oncall@yourdomain.com"],
"MinSeverity": "High"
}
}
```
主题格式:`[VK-AI-SENSOR] [CRITICAL] VK-F002 — Ransomware file activity detected`
电子邮件正文为格式化的 HTML,带有严重性颜色编码和事实表。
## 进程响应
当规则触发时,传感器可以自动挂起或终止进程。这默认处于禁用
状态,应谨慎使用 — 错误终止关键的系统进程
可能会破坏主机的稳定性。
```
"Response": {
"Enabled": true, // master switch — false by default
"DefaultAction": "Suspend", // None | Suspend | Kill
// Per-rule overrides (any rule ID can be listed)
"PerRule": {
"VK-R002": "Suspend", // shadow copy deletion → freeze the process
"VK-F002": "Suspend", // ransomware extension → freeze immediately
"VK-F003": "Suspend", // mass file write → freeze
"VK-P004": "None" // new process → alert only, don't kill
},
// These processes are NEVER acted on regardless of config
"ProtectedProcesses": [
"System", "smss.exe", "csrss.exe", "wininit.exe",
"winlogon.exe", "services.exe", "lsass.exe", "lsm.exe",
"svchost.exe", "MsMpEng.exe"
]
}
```
**挂起**(`NtSuspendProcess`)会冻结目标进程中的所有线程。它是
可逆的,并能争取时间进行调查。**终止**(`Process.Kill`)是不可逆的 — 仅对
确认的威胁或在针对高置信度规则的 `PerRule` 重写中使用。
PID 重用防护会验证进程名称是否仍与警报的进程名称匹配,然后再
采取行动,以防止对继承了该 PID 的不相关进程采取意外行动。
### 网络隔离
传感器还可以使用 Windows 防火墙阻止规则阻止来自特定进程的所有网络流量。
这独立于进程挂起/终止,并且在您想要切断
命令和控制通道而不一定停止进程时非常有用(例如,为了保持证据完整以供取证)。
```
"Response": {
"NetworkIsolation": {
"Enabled": false, // master switch — false by default
"TriggerRules": [
"VK-C001", // credential theft
"VK-F002", // ransomware file activity
"VK-R002" // mass file write (ransomware rate)
],
"ProtectedProcesses": [
"System", "smss.exe", "csrss.exe", "wininit.exe",
"winlogon.exe", "services.exe", "lsass.exe", "lsm.exe",
"svchost.exe", "MsMpEng.exe"
]
}
}
```
触发时,传感器会调用 `netsh advfirewall firewall add rule` 创建两个规则:
| 规则后缀 | 方向 | 效果 |
|---|---|---|
| `VK-ISOLATE---OUT` | 出站 | 阻止来自该可执行文件的所有出站 TCP/UDP |
| `VK-ISOLATE---IN` | 入站 | 阻止发往该可执行文件的所有入站 TCP/UDP |
规则限定于确切的可执行文件路径(`program=` 过滤器),因此其他进程
不受影响。它们将一直存在,直到使用 `netsh advfirewall firewall delete rule` 手动删除,
或直到调用 `INetworkIsolator.TryLiftIsolation`。
## DNS 查询监控
VK-DNS001 订阅了 `Microsoft-Windows-DNS-Client` ETW 提供商(在所有
现代 Windows endpoint 上可用),并针对三个独立的检查评估每个发出的 DNS 查询,
每个检查都针对不同的攻击类别:
| 检查 | 严重性 | 触发条件 | 攻击技术 |
|---|---|---|---|
| 隧道 — 长 FQDN | High | FQDN > 100 字符 | 通过 iodine、dnscat2 进行 DNS 数据外泄 / C2 |
| 隧道 — 多标签 | High | > 9 个点分隔的标签 | 子域名编码隧道工具 |
| 隧道 — 长标签 | High | 任何单个标签 > 40 字符 | DNS 子域名中的 Base64/十六进制编码 payload |
| DGA 熵(可选) | Medium | 最左侧标签 Shannon 熵 > 3.8 bits | 域名生成算法 |
| 可疑 TLD | Medium | TLD 位于内置滥用列表中 | 托管在免费 TLD 上的恶意软件/网络钓鱼 |
该规则会跳过单标签查询(NETBIOS/LLMNR)、反向 DNS 查找(`.arpa`)、服务
发现记录(前缀 `_`)以及私有后缀(`.local`、`.internal`、`.corp`、
`.lan`、`.home`)。
### 内置可疑 TLD
`.tk` · `.ml` · `.ga` · `.cf` · `.gq`(Freenom 免费 TLD) · `.pw` · `.top` · `.xyz` ·
`.click` · `.zip` · `.mov`
### 配置
```
"Rules": {
"DnsQuery": {
"Enabled": true,
"MaxFqdnLength": 100, // FQDN length above which → High (tunneling)
"MaxLabelCount": 9, // label count above which → High (tunneling)
"MaxLabelLength": 40, // single label length above which → High (tunneling)
// DGA entropy — disabled by default to avoid false positives from CDN hash subdomains
"EntropyCheckEnabled": false,
"EntropyThreshold": 3.8, // bits/char; lower = more sensitive, more FPs
// Suspicious TLD check
"SuspiciousTldCheckEnabled": true,
"AdditionalSuspiciousTlds": [] // add your own without touching the built-in list
}
}
```
### 误报指南
**熵检查**:CDN 服务(CloudFront、Akamai、Azure CDN)和基于 UUID 的服务
名称会产生完全良性的高熵子域名。请将 `EntropyCheckEnabled` 保持
为 `false`,除非您为 CDN 域名配置了白名单,或者您处于
意外高熵子域名确实罕见的受控环境中。
**可疑 TLD**:一些合法的产品和开发人员工具使用 `.xyz` 或 `.top`。
在 `AllowList:PerRule:VK-DNS001` 部分添加条目以抑制已知良好的域名。
## 新进程检测
每当自训练模式构建基线以来首次看到进程映像路径时,VK-P004 就会触发。
每个警报在发送到 AI 层之前,都会丰富从可执行文件收集的 IOC。
### 设置
1. 运行训练模式以生成 `known-processes.json`
2. 将 `known-processes.json` 复制到服务可执行文件目录
3. 设置 `Rules:NewProcess:Enabled = true`
### 丰富
| IOC | 配置标志 | 注意 |
|---|---|---|
| SHA-256 哈希 | `Enrichment:HashEnabled`(默认:开启) | 受 `HashTimeoutMs`(默认 2 秒)限制。只有在同时启用了 VirusTotal 时,哈希才会离开本机。 |
| PE 版本信息 | `Enrichment:PeMetadataEnabled`(默认:开启) | 公司名称、产品名称、原始文件名、文件版本。速度快,无需网络。 |
| Authenticode 签名者 | `Enrichment:SignatureEnabled`(默认:开启) | 签名者主题名称(例如“Microsoft Corporation”)。速度快,无需网络。 |
| 路径类别 | 始终 | `System32` / `ProgramFiles` / `Temp` / `UserAppData` / `UserProfile` / `Other`。Temp 和用户可写路径会在描述中触发警告说明。 |
### VirusTotal 集成
```
"Rules": {
"NewProcess": {
"VirusTotal": {
"Enabled": false, // PRIVACY: hashes sent to external service — opt-in only
"ApiKey": "",
"RateLimitPerMinute": 4, // free tier limit; paid tiers allow more
"TimeoutSeconds": 10
}
}
}
```
启用后,每个新进程的 SHA-256 将通过 VirusTotal Files API v3 进行查找。
查找是即发即忘的 — 它不会阻塞警报 pipeline。结果将在
响应到达后立即记录:
```
[VK-P004] VirusTotal DETECTIONS: 42/72 engines flagged hash abc123... as 'trojan.genericKD'. Alert=...
[VK-P004] VirusTotal CLEAN: 0/71 detections for def456...
[VK-P004] VirusTotal: hash 789abc... not found in database (new/unknown).
```
免费的 VirusTotal API 级别允许每分钟进行 4 次查找。传感器会自动强制执行此限制;
多余的查找将被跳过,并以 Debug 级别记录。
### 完整的 NewProcess 配置
```
"Rules": {
"NewProcess": {
"Enabled": false,
"BaselineFile": "known-processes.json", // relative to exe dir, or absolute
"Severity": "Medium",
"Enrichment": {
"HashEnabled": true,
"HashTimeoutMs": 2000, // disable if large executables cause latency
"PeMetadataEnabled": true,
"SignatureEnabled": true
},
"VirusTotal": {
"Enabled": false, // disabled by default — privacy
"ApiKey": "",
"RateLimitPerMinute": 4,
"TimeoutSeconds": 10
}
}
}
```
## 密钥管理
API 密钥不应在 `appsettings.json` 中以明文形式存储。共有三种
受支持的存储选项,按优先级顺序排列(最高者优先):
### 1. DPAPI(推荐用于服务账户)
```
# 以该服务将运行的相同用户账户运行
.\VkAiSensor.Service.exe secrets set anthropic-api-key sk-ant-...
```
密钥使用 `ProtectedData.Protect(CurrentUser)` 加密并存储在
`%LOCALAPPDATA%\VkAiSensor\secrets.dat` 中。它们只能由同一个
Windows 用户账户解密。
### 2. 环境变量
```
$env:VK_ANTHROPIC_API_KEY = "sk-ant-..."
$env:VK_OPENAI_API_KEY = "sk-..."
$env:VK_AZUREOPENAI_API_KEY = "..."
```
适用于 CI/CD 或容器部署。
### 3. appsettings.json(生产环境不推荐)
```
"Ai": {
"Anthropic": { "ApiKey": "sk-ant-..." }
}
```
对于本地开发可以接受。切勿将真实密钥提交到源代码管理中。
## 完整配置参考
下面是包含每个受支持的键及其默认值的完整 `appsettings.json`。
```
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
// ── Service mode ────────────────────────────────────────────────────────────
"Service": {
"Mode": "Normal", // Normal | Training
"Training": {
"Duration": "00:10:00", // collection window (hh:mm:ss)
"OutputPath": "training-output",
"AiReview": true, // false = use severity heuristic only
"BatchSize": 25 // observations per AI request
}
},
// ── ETW collection ──────────────────────────────────────────────────────────
"Etw": {
"SessionName": "vk-ai-sensor",
"ChannelCapacity": 4096 // bounded channel; oldest events dropped when full
},
// ── Detection rules ─────────────────────────────────────────────────────────
"Rules": {
// VK-DNS001: DNS query monitoring
"DnsQuery": {
"Enabled": true,
"MaxFqdnLength": 100,
"MaxLabelCount": 9, // labels above which → High; set lower than 9 only in controlled envs
"MaxLabelLength": 40,
"EntropyCheckEnabled": false, // disabled by default — CDN hash subdomains cause FPs
"EntropyThreshold": 3.8,
"SuspiciousTldCheckEnabled": true,
"AdditionalSuspiciousTlds": []
},
// VK-F003: mass file write (ransomware rate detection — distinct file paths, not raw write events)
"MassFileWrite": {
"WindowSeconds": 30,
"Threshold": 1000, // distinct file paths per window per process before alert
"AlertCooldownSeconds": 60
},
// VK-P004: new / unknown process
"NewProcess": {
"Enabled": false, // enable after running Training mode
"BaselineFile": "known-processes.json",
"Severity": "Medium",
"Enrichment": {
"HashEnabled": true,
"HashTimeoutMs": 2000,
"PeMetadataEnabled": true,
"SignatureEnabled": true
},
"VirusTotal": {
"Enabled": false, // PRIVACY: opt-in — sends hashes externally
"ApiKey": "",
"RateLimitPerMinute": 4,
"TimeoutSeconds": 10
}
},
// Trusted publisher filter: suppress alerts from processes signed by known-good publishers.
// Runs before the allow-list. PrefixMatch=true means "Microsoft" covers all Microsoft signers.
// TrustSystemPaths=true also trusts catalog-signed binaries in Program Files / Windows dir.
"TrustedPublishers": {
"Enabled": true,
"PrefixMatch": true,
"TrustSystemPaths": true, // trust unsigned-appearing catalog-signed tools in admin-protected paths
"Publishers": [
"Microsoft",
"Google",
"Slack Technologies"
// ... add publishers you trust on this endpoint
]
},
// Allow-list: suppress known-good alerts before any sink
"AllowList": {
"GlobalTrustedProcesses": [],
"PerRule": {
// Each entry keyed by rule ID. All fields optional.
"VK-N001": {
"Disabled": false,
"ProcessNames": [],
"DestinationCidrs": [],
"DestinationPorts": []
}
// ...add entries for any rule ID
}
}
},
// ── Outbound notifications ──────────────────────────────────────────────────
"Notifications": {
"Webhook": {
"Enabled": false,
"Url": "",
"Secret": "", // HMAC-SHA256 signing key (optional)
"MinSeverity": "High",
"TimeoutSeconds": 10
},
"Email": {
"Enabled": false,
"SmtpHost": "",
"SmtpPort": 587,
"UseSsl": true,
"Username": "",
"Password": "",
"From": "",
"To": [],
"MinSeverity": "High"
}
},
// ── Process response ────────────────────────────────────────────────────────
"Response": {
"Enabled": false, // master switch
"DefaultAction": "Suspend", // None | Suspend | Kill
"PerRule": {
// Override default action per rule ID
"VK-R002": "Suspend",
"VK-F002": "Suspend",
"VK-F003": "Suspend"
},
"ProtectedProcesses": [
"System", "smss.exe", "csrss.exe", "wininit.exe",
"winlogon.exe", "services.exe", "lsass.exe", "lsm.exe",
"svchost.exe", "MsMpEng.exe"
],
"NetworkIsolation": {
"Enabled": false,
"TriggerRules": [ "VK-C001", "VK-F002", "VK-R002" ],
"ProtectedProcesses": [
"System", "smss.exe", "csrss.exe", "wininit.exe",
"winlogon.exe", "services.exe", "lsass.exe", "lsm.exe",
"svchost.exe", "MsMpEng.exe"
]
}
},
// ── AI analysis ─────────────────────────────────────────────────────────────
"Ai": {
"Enabled": false,
"Provider": "None", // Anthropic | OpenAI | AzureOpenAI | Ollama | None
"MinSeverity": "High",
"Anthropic": {
"ApiKey": "", // or env VK_ANTHROPIC_API_KEY, or DPAPI
"Model": "claude-opus-4-8"
},
"OpenAI": {
"ApiKey": "", // or env VK_OPENAI_API_KEY
"Model": "gpt-4o"
},
"AzureOpenAI": {
"Endpoint": "",
"ApiKey": "", // or env VK_AZUREOPENAI_API_KEY
"DeploymentName": "",
"ApiVersion": "2024-10-21"
},
"Ollama": {
"BaseUrl": "http://localhost:11434",
"Model": "llama3.2"
},
// Auto-allow: when AI returns likely_false_positive, add the process to the dynamic
// allow-list so it never re-triggers the same rule. Disabled by default.
"AutoAllow": {
"Enabled": false,
"TriggerAssessment": "likely_false_positive",
"OutputPath": "training-output/learned-allowlist.json",
"EligibleRules": [ "VK-N001", "VK-F001", "VK-F003", "VK-P004", "VK-DNS001" ]
}
}
}
```
## 架构
```
ETW kernel session
│ ProcessStart, FileCreate/Write, NetworkConnect, RegistrySet, DnsQuery
▼
Channel (bounded, DropOldest)
│
▼
RuleEngine
├─ IDetectionRule × 17 (evaluate every event synchronously)
├─ IAlertFilter × 2 (suppress before any sink — checked in order)
│ ├─ TrustedPublisherFilter (publisher-level trust via Authenticode signer)
│ └─ AllowListFilter (per-rule / per-process / per-CIDR exceptions)
└─ IAlertSink × N (fan-out, all awaited in order)
├─ LoggingAlertSink → NLog file + console
├─ AiAlertSink → IInsightProvider (AI enrichment)
├─ EmailAlertSink → SMTP
├─ WebhookAlertSink → HTTP POST
├─ VirusTotalSink → VT hash lookup (fire-and-forget)
├─ ProcessResponseSink → NtSuspendProcess / Process.Kill
└─ NetworkIsolationSink → netsh advfirewall block rules
```
**关键设计决策:**
- ETW 类型永远不会流出 `EtwCollector` — 规则只能看到 `HostEvent` 及其
类型化 payload,使得它们无需管理员权限或 ETW session 即可测试。
- `AlertContext`(AI payload)是 `Alert` 的可编转子集。原始 `TriggeringEvents`
永远不会发送到任何外部服务。
- `IAlertFilter` 在任何接收器之前在引擎中运行,因此被抑制的警报永远不会到达
日志记录、AI、电子邮件或响应接收器。
- `ProcessSignatureCachePopulatorRule` 在每个进程启动事件上填充 `ProcessSignatureCache`。对于在传感器启动时已经在运行的进程(缓存未命中),
`TrustedPublisherFilter` 和 `ExternalNetworkRule` 会在第一个警报时执行实时查找
并填充缓存 — 因此无论进程何时启动,每个 PID 的二进制文件都不会被读取多次。没有内嵌 Authenticode 签名的目录签名二进制文件
由 `TrustSystemPaths` 回退机制(Program Files / Windows 目录)覆盖。
- `IProcessController` 抽象在接口之后;在测试中使用 `NullProcessController`,
因此不会影响真实进程。
- `MassFileWriteRule`(不同的文件路径,而非原始写入事件)、`ExecutableDroppedInUserPathRule`
每个文件的冷却时间)和 `NewProcessRule` 是有状态的规则。全部使用事件时间戳
(而非系统时间),因此它们完全可以通过合成时间进行测试。
## 许可证
`vk-ai-sensor` 是双重许可的:
- **开源:** [GNU AGPL-3.0](LICENSE)。根据 AGPL 的条款免费使用、修改和自托管,
包括在作为网络服务运行时共享修改内容的要求。
- **商业:** 为不希望遵守 AGPL 的组织(例如将其构建为闭源或竞争的
商业产品)提供单独的商业许可证。
有关完整说明以及如何获取商业许可证,请参阅 [LICENSING.md](LICENSING.md)。
标签:AI, AMSI绕过, EDR, IP 地址批量处理, 威胁检测, 端点安全, 脆弱性评估, 自动化代码审查, 补丁管理