iklobato/avai

GitHub: iklobato/avai

avai 是一个无需 agent 和 SIEM 的主机安全遥测收集器,结合 17 个威胁情报源和 LLM 对 macOS/Linux 端点发现进行自动化威胁研判,并通过单页 Web 仪表盘呈现结果。

Stars: 15 | Forks: 2

avai logo

avai

[![PyPI](https://img.shields.io/pypi/v/avai-monitor?color=10b981&label=pypi)](https://pypi.org/project/avai-monitor/) [![Docker](https://img.shields.io/docker/pulls/iklob1/avai?color=10b981&label=docker%20pulls)](https://hub.docker.com/r/iklob1/avai) [![License](https://img.shields.io/github/license/iklobato/avai?color=10b981)](LICENSE) [![Site](https://img.shields.io/badge/site-getavai.com-10b981)](https://getavai.com) `avai` 会在 macOS 上为你主机的 26 个角落(在 Linux 上为 21 个)生成快照 —— 包括进程、USB、持久化、文件完整性、浏览器扩展、exec 事件 —— 并利用多达 **17 个威胁情报源**(VirusTotal、MalwareBazaar、URLhaus、CISA KEV、Shodan、 AbuseIPDB、OSV、NVD 等)来丰富每一个新发现,然后让 Claude 级别的 LLM 告诉你哪些是 值得关注的内容。判定结果会以 **恶意** / **可疑** / **未知** / **良性** 的形式返回,并附带 MITRE 对齐的分类、置信度以及单行修复建议。 - 无需 agent 契约,无需 SIEM,无需云端控制平面。 - 基于内容哈希去重 —— 同一个制品(artifact)绝对不会被发送给 LLM 两次。 - 在 LLM 背后有 17 个即插即用的威胁情报源 —— 请参阅 [`.env.example`](.env.example);缺失的密钥会直接禁用对应源。 - 位于 `:8765` 的只读 Flask + HTMX + Chart.js 仪表盘。 - 自带密钥(`ANTHROPIC_API_KEY` / `CLAUDE_CODE_OAUTH_TOKEN`),或者切换到任何 litellm 支持的提供商。 → 营销网站与截图: → 源码: ## 截图 位于 `:8765` 的只读 Flask + HTMX + Chart.js 仪表盘。每个面板都是 从监控器写入的同一个 SQLite 快照中渲染出来的 —— 没有独立的控制平面。 ### 仪表盘 —— 概览 一目了然的系统健康度:存储的运行次数、最新周期中的收集器(包含任何 故障)、自上次运行以来的判定结果,以及判定总量环形图 (恶意 / 可疑 / 未知 / 良性)。macOS 的 **系统完整性** 面板 会显示 FileVault、防火墙、Gatekeeper 和远程访问开关;**收集器 错误** 显示了失败的内容(例如 TCC 权限问题);12 小时的图表则追踪了 判定结果随时间的变化。下方的发现表格会流式加载活动的、非良性的 结果。 ![avai dashboard overview](https://static.pigsec.cn/wp-content/uploads/repos/cas/38/38afc4f730e7fb5939c2d4f8cc0d844f727dad4c301787110b9d6a3b77f3e2f7.png) ### 发现、收集器与运行记录 发现表格可以按状态、判定结果、收集器和类别进行过滤。 在它下方,**每个收集器的行数** 显示了每个收集器在 最近一次运行中提取了多少数据,而 **最近的运行** 列出了运行历史,包含成功/失败计数以及 回溯时间窗口。 ![avai findings, collectors and runs](https://static.pigsec.cn/wp-content/uploads/repos/cas/a7/a7a6a9ca79d3a956be64a2f803d4ec2396cb2919ace3e3bda0ed777767a43899.png) ### 发现详情 展开任意发现,可以查看 LLM 的 **推理过程**、具体的 **修复** 步骤,以及判定背后的确切 **收集数据** —— 对于一个进程 这意味着 pid/ppid、完整的 `cmdline`、运行中的用户/uid、状态、用于 去重的内容哈希,以及首次判定时间与最后发现时间。 ![avai finding detail](https://static.pigsec.cn/wp-content/uploads/repos/cas/b2/b2550bdbdb062215288e7ff7812ab6ebfc3b5262a645f339f9ec4f99b9bdcba9.png) ### 网络流 tcpdump 聚合器按目的地对流量进行分组,以便分类器能够对其进行推理: 这里到一个异常高端口的 IPv6 连接被标记为 **可疑**,被视为潜在的 C2 信标,而 CDN、mDNS 和 LAN 流量则返回 **良性** —— 每一项都带有一句“原因”解释。 ![avai network flows](https://static.pigsec.cn/wp-content/uploads/repos/cas/21/21661d4d3aba800909925f989e86ef91b546e0db11daf838f19bc95f9f93425a.png) ### 网络流 —— 富化后 同一个视图按目的地进行了富化,显示了所属的 **进程**、ASN/地理位置、 流量大小,以及每个判定结果的理由。 ![avai enriched network flows](https://static.pigsec.cn/wp-content/uploads/repos/cas/cd/cd53c341ba33b7aa4cff899514f3d2e07e146e1ab9e6f9eb53bb48da0d41d525.png) ### 另一台主机上的同一个仪表盘 在不同主机/周期上运行 —— 这里有 61 次运行记录和 3,426 个判定结果 —— 并显示了可疑的 AirWatch/MDM 持久化项供审查。 ![avai dashboard on another host](https://static.pigsec.cn/wp-content/uploads/repos/cas/fa/fa2146ed5b4d0d2228b9647df9ffb31c0b77b3f2c6512149b833e0802fa20bf0.png) ## 功能 **主机遥测 —— macOS 上有 26 个收集器,Linux 上有 21 个**,对恶意软件 隐藏、驻留和回传的每个位置进行快照: - **进程与执行** —— 正在运行的进程,以及触发时的 `execve` 执行事件。 - **网络** —— 活动连接、监听端口、tcpdump **流聚合器** (按目的地分组,与拥有它的进程绑定)、DNS 查询、网络接口、Wi-Fi 状态。 - **持久化** —— 启动项(LaunchDaemons/Agents、systemd 单元、cron), 内核与系统扩展、MDM/配置描述文件、已安装的应用。 - **访问与身份** —— 认证事件(统一日志 / `journalctl`)、SSH `authorized_keys`、TCC 隐私授权(摄像头/麦克风/位置/屏幕/全盘), 权限配置、setuid 二进制文件。 - **完整性与安全姿态** —— 系统完整性(FileVault、防火墙、Gatekeeper、SIP、 SELinux/AppArmor/ufw 等)、文件完整性(passwd/shadow/sudoers/SSH/dotfiles), `/etc/hosts`、隔离事件、挂载点。 - **硬件** —— USB 和蓝牙设备。 - **浏览器** —— 已安装的浏览器扩展。 **LLM 威胁分类器** —— 一个 Claude 级别的模型会将每个新制品 标记为 **恶意 / 可疑 / 未知 / 良性**,并附带 **MITRE 对齐的分类**、 **置信度** 和 **单行修复建议**。请自带您的密钥 (`ANTHROPIC_API_KEY` / `CLAUDE_CODE_OAUTH_TOKEN`)或使用任何 litellm 支持的提供商。 **每个判定背后有 17 个威胁情报源** —— 指标(哈希、IP、域名、 URL、CVE、软件包、OS 版本)在模型看到它们 *之前* 就已被富化: VirusTotal · MalwareBazaar · URLhaus · ThreatFox · Feodo Tracker · AbuseIPDB · GreyNoise · Shodan InternetDB · CISA KEV · NVD · OSV · GitHub Advisory · CIRCL hashlookup · crt.sh · PhishTank · Google Safe Browsing · endoflife.date (外加 IP 地理位置)。无需密钥的源始终运行;需要密钥的源会在您添加 密钥后启用,而缺失密钥会直接禁用该源。结果会被缓存在 SQLite 中,并带有每个源的 TTL。 **只读仪表盘**(位于 `:8765` 的 Flask + HTMX + Chart.js)—— 判定总量环形图、 macOS 系统完整性面板、收集器错误、12 小时判定图表,以及 一个在各个部分都具备搜索 / 过滤 / 排序 / 分页功能的发现表格。展开任意 发现即可查看模型的推理过程、修复方案和原始收集数据。 每 30–60 秒自动刷新,并在出现新的 恶意/可疑发现时弹出 Toast **+ 音频警报**。 **旨在不打扰您的方式构建** - **一条 `docker run` 命令** —— 一个镜像同时运行监控器 *和* 仪表盘(通过 supervisord),因此开箱即用。 - **无需 agent 契约,无需 SIEM,无需云端控制平面** —— 它直接在您的主机上运行。 - **基于内容哈希去重** —— 同一个制品绝对不会被发送给 LLM 两次。 - **仅仅是一个 SQLite 文件** —— 将仪表盘指向任何操作系统上的任何 `avai.db` 即可。 - **也支持原生安装**:`pip install avai-monitor`。 完整参考见下文:[收集了什么](#whats-collected-one-line-summary) · [仪表盘](#dashboard) · [威胁情报富化](#threat-intel-enrichment)。 ## 为什么选择 avai —— 优势 - **给出答案,而非日志。** 每个发现都会以简明易懂的文字返回,附带判定结果、 置信度、MITRE 分类和具体的修复方法 —— 无需查询语言,无需分流电子表格。 - **零基础设施。** 一个容器。无需 SIEM,无需注册 agent,无需运行或付费的 控制平面。 - **默认私密。** 一切都在您的机器上运行;您自带模型 密钥,并且只有 *新* 的发现才会被发送出去 —— 用于您选择的威胁情报查询或 LLM 调用。 - **运行成本低。** 内容哈希去重意味着每个制品仅被判定一次 —— 一台繁忙的 主机并不意味着高昂的账单 —— 而且缓存的情报命中会完全跳过网络。 - **真正的广度。** 26 个主机攻击面 × 17 个情报源支持一个判定 —— 拥有 EDR 般的广度,却不需要 agent。 - **跨平台。** macOS 和 Linux 使用同一款工具。 - **开放且属于您。** 采用 MIT 许可证,可审计,且与模型无关 —— 只需一个环境变量即可切换到任何 litellm 提供商。 - **可安全指向生产环境。** 收集器仅执行 *读取* 操作;仪表盘是只读的。 - **可移植的历史记录。** 整个状态就是一个单一的 SQLite 文件 —— 在服务器上扫描, 在笔记本电脑上查看,存档快照,或随时间进行对比。 ## 一个镜像,两种角色 | 运行方式 | 命令 | 适用场景 | |---|---|---| | 监控器 + 仪表盘(默认) | `docker run -p 8765:8765 -v "$PWD":/data iklob1/avai` | 任意主机 —— 在 supervisord 下同时运行两者;位于 :8765 的仪表盘由容器内的监控器提供数据 | | 完整的主机可见性 | `docker run --pid=host --network=host ... iklob1/avai` | **Linux 主机** —— 容器内的监控器可以查看到真实的宿主机 | | 单一角色 | `docker run ... iklob1/avai avai dashboard`(或 `avai monitor`) | 仅运行一种角色(例如针对现有 `avai.db` 的仪表盘,或仅运行监控器的容器) | 镜像的默认 `CMD` 指令通过 supervisord 将两个角色运行在一起(它们 共享 `/data/avai.db` —— 监控器负责写入,仪表盘实时读取 —— 如果其中一个退出,两者都会自动重启)。可以覆盖该命令以 运行单一角色。LLM 判定器在运行时仍然需要凭据 (`-e CLAUDE_CODE_OAUTH_TOKEN=…` / `ANTHROPIC_API_KEY` / `OPENAI_API_KEY`); 如果没有,监控器将回退到 NullJudge(仅收集)。原生 安装同样有效:`pip install avai-monitor`,然后运行 `avai monitor` / `avai dashboard`。 镜像针对仪表盘的 `/api/notifications/new` 端点携带了 `HEALTHCHECK` —— 首次 启动时约 10 秒内状态变为 `starting → healthy`。`docker compose ps` 和 `docker inspect --format '{{.State.Health.Status}}'` 都会反映出该状态。 ## TL;DR —— 60 秒测试,无需 LLM 密钥 在任意主机(macOS 或 Linux)上进行安全的首次运行,无需 特权,无需凭据,无需主机目录绑定挂载。会生成一个填有数据的 DB 和一个 您可以随意查看的绿色仪表盘。 ``` mkdir -p ~/.avai && cd ~/.avai # 用容器视图的一个 snapshot 填充 DB docker run --rm -v "$PWD":/data iklob1/avai \ avai monitor --once --no-streaming --no-judge --db /data/avai.db # 运行它 docker run -d --name avai -p 8765:8765 -v "$PWD":/data iklob1/avai open http://localhost:8765/ # macOS; xdg-open on Linux ``` 您会看到大约 14 个收集器的数据行(`processes`、 `network_connections`、`listening_ports`、`network_interfaces`、 `usb_devices`、`launch_items`、`installed_apps`、`mounts`、 `setuid_files` 等)—— 因为上面的运行没有绑定挂载主机状态,所以这些是 从容器本身读取的,而不是来自主机。要获取真实 数据,请跳至下文的 §2 / §3。 使用 `docker stop avai && docker rm avai` 停止运行。 ## 1 —— 仅仪表盘(任意主机,包括 macOS) 仪表盘读取由监控器(或由之前的 运行)写入的 SQLite 数据库。它不需要特权,不需要主机 命名空间,不需要 capabilities —— 只需将一个包含 `avai.db` 的目录挂载到 `/data` 即可。 ``` mkdir -p ~/.avai && cd ~/.avai docker run -d \ --name avai-dashboard \ -p 8765:8765 \ -v "$PWD":/data \ iklob1/avai open http://localhost:8765/ ``` 如果数据库文件不存在,仪表盘会在启动时 创建一个空的 schema,并且在监控器产生 数据行之前,每个面板都将呈现空白。使用 `docker stop avai-dashboard && docker rm avai-dashboard` 停止运行。 ### 覆盖端口或 DB 路径 ``` docker run --rm -p 9000:9000 \ -v /var/lib/avai:/data \ iklob1/avai \ avai dashboard --host 0.0.0.0 --port 9000 --db /data/custom.db ``` 镜像入口点是 `avai`;镜像名称后面的任何内容都会 传递给它。 ## 2 —— 监控器:一次性扫描(Linux 主机) 在本地 Linux 主机上进行单个周期。没有流式传输,没有 LLM 判定 —— 这是一个快速的冒烟测试,用于验证绑定挂载是否配置正确。 ``` mkdir -p ~/.avai && cd ~/.avai docker run --rm \ --pid=host \ --network=host \ --user 0:0 \ --cap-add SYS_PTRACE --cap-add NET_ADMIN --cap-add NET_RAW --cap-add DAC_READ_SEARCH \ -e HOST_PREFIX=/host \ -v /proc:/host/proc:ro \ -v /sys:/host/sys:ro \ -v /etc:/host/etc:ro \ -v /var/lib/bluetooth:/host/var/lib/bluetooth:ro \ -v /var/lib/dpkg:/host/var/lib/dpkg:ro \ -v /usr/share/applications:/host/usr/share/applications:ro \ -v /lib/systemd:/host/lib/systemd:ro \ -v /usr/lib/systemd:/host/usr/lib/systemd:ro \ -v /run/systemd:/run/systemd:ro \ -v /run/dbus:/run/dbus:ro \ -v /etc/machine-id:/etc/machine-id:ro \ -v /dev/mapper:/dev/mapper:ro \ -v /home:/host/home:ro \ -v /root:/host/root:ro \ -v "$PWD":/data \ iklob1/avai \ avai monitor --once --no-streaming --no-judge --db /data/avai.db ``` 当命令退出时,`~/.avai/avai.db` 会包含一条 `collection_runs` 记录以及填充好的收集器表。验证: ``` docker run --rm -v "$PWD":/data iklob1/avai python -c " import sqlite3 c = sqlite3.connect('/data/avai.db') for n, in c.execute(\"select name from sqlite_master where type='table'\"): print(f'{n:<22} {c.execute(f\"select count(*) from {n}\").fetchone()[0]}')" ``` 要在 macOS 上进行没有绑定挂载的冒烟测试(没有主机数据,但 可以证明工具链有效),请参阅上文的 §0。 ## 3 —— 监控器:持续运行,带 LLM 判定(Linux 主机) 使用与 §2 相同的绑定挂载,但是以分离模式运行,并启用 LLM 判定。 判定器需要一个凭据 —— 可以是 `ANTHROPIC_API_KEY`(标准 Anthropic API),也可以是 `CLAUDE_CODE_OAUTH_TOKEN` —— 并且 默认使用 **Claude Haiku 4.5**(`claude-haiku-4-5-20251001`)。 使用 `--judge-model` 覆盖它,可将 litellm 指向任何其他提供商。 威胁情报富化会自动使用环境变量(`VT_API_KEY`、`ABUSE_CH_AUTH_KEY`、`ABUSEIPDB_API_KEY`、 …)中提供的任何密钥运行。最简单的模式是使用项目本地的 `.env`: ``` cp .env.example .env && vi .env # fill in only the keys you have docker run -d --env-file .env --name avai-monitor ... iklob1/avai ``` 请参阅下文的 **§ 威胁情报富化** 以获取完整的源列表和 每个源的触发条件。 ``` mkdir -p ~/.avai && cd ~/.avai docker run -d --name avai-monitor --restart unless-stopped \ --pid=host --network=host --user 0:0 \ --cap-add SYS_PTRACE --cap-add NET_ADMIN --cap-add NET_RAW --cap-add DAC_READ_SEARCH \ -e HOST_PREFIX=/host \ -e DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket \ -e ANTHROPIC_API_KEY \ -v /proc:/host/proc:ro -v /sys:/host/sys:ro -v /etc:/host/etc:ro \ -v /var/lib/bluetooth:/host/var/lib/bluetooth:ro \ -v /var/lib/dpkg:/host/var/lib/dpkg:ro \ -v /usr/share/applications:/host/usr/share/applications:ro \ -v /lib/systemd:/host/lib/systemd:ro \ -v /usr/lib/systemd:/host/usr/lib/systemd:ro \ -v /var/log/journal:/host/var/log/journal:ro \ -v /var/spool/cron:/host/var/spool/cron:ro \ -v /run/systemd:/run/systemd:ro -v /run/dbus:/run/dbus:ro \ -v /etc/machine-id:/etc/machine-id:ro \ -v /dev/mapper:/dev/mapper:ro \ -v /home:/host/home:ro -v /root:/host/root:ro \ -v "$PWD":/data \ iklob1/avai \ avai monitor --db /data/avai.db --interval 300 docker logs -f avai-monitor # watch the cycle ``` `avai monitor` 中的默认设置: | 标志 | 默认值 | 效果 | |---|---|---| | `--interval` | `300` | 快照周期间的秒数 | | `--lookback-min` | `6` | 每次运行时获取的日志历史分钟数 | | `--max-db-mb` | `1024` | 轮转上限(0 表示禁用);在每个周期后,最旧的运行记录会被修剪 + 并执行 `VACUUM` | | `--judge-model` | `claude-haiku-4-5-20251001` | 任意 litellm 模型 ID | | `--judge-batch-size` | `20` | 每次 LLM 调用的条目数 | | `--judge-max-per-collector` | `25` | 每个收集器每个周期判定新条目的上限 | | `--no-streaming` | (关闭) | 禁用 `auth_events` + `process_exec_events` 跟踪器 | | `--no-judge` | (关闭) | 运行收集器但不存储判定结果 | | `--no-enrich` | (关闭) | 跳过整个威胁情报层;收集器 → 直接判定 | | `--enrich-only NAME` | (所有) | 将链路限制为单个指定的源(可重复);用于调试 | 在 `docker run … iklob1/avai avai monitor …` 命令后追加任意标志即可进行覆盖。完整参考:`docker run --rm iklob1/avai avai monitor --help`。 ## 4 —— 使用 docker-compose 运行两个服务(Linux 主机) `docker-compose.yml`: ``` x-avai-image: &avai-image image: iklob1/avai:latest services: monitor: <<: *avai-image container_name: avai-monitor command: ["avai","monitor","--db","/data/avai.db","--interval","300"] user: "0:0" pid: host network_mode: host cap_add: [SYS_PTRACE, NET_ADMIN, NET_RAW, DAC_READ_SEARCH] # Loads LLM-judge + every threat-intel API key from .env. Copy # .env.example to .env and fill in only the keys you have. env_file: [.env] environment: - HOST_PREFIX=/host - DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket volumes: - ./data:/data - /proc:/host/proc:ro - /sys:/host/sys:ro - /etc:/host/etc:ro - /var/lib/bluetooth:/host/var/lib/bluetooth:ro - /var/lib/dpkg:/host/var/lib/dpkg:ro - /usr/share/applications:/host/usr/share/applications:ro - /lib/systemd:/host/lib/systemd:ro - /usr/lib/systemd:/host/usr/lib/systemd:ro - /var/log/journal:/host/var/log/journal:ro - /var/spool/cron:/host/var/spool/cron:ro - /run/systemd:/run/systemd:ro - /run/dbus:/run/dbus:ro - /etc/machine-id:/etc/machine-id:ro - /dev/mapper:/dev/mapper:ro - /home:/host/home:ro - /root:/host/root:ro restart: unless-stopped dashboard: <<: *avai-image container_name: avai-dashboard # uses the image's default CMD ports: ["8765:8765"] volumes: ["./data:/data"] restart: unless-stopped ``` 然后: ``` mkdir -p data cp .env.example .env && vi .env # fill in the keys you have docker compose up -d docker compose logs -f monitor open http://localhost:8765/ ``` ## 5 —— 针对现有 DB 运行的仪表盘(任意主机) 如果您已经有一个 `avai.db`(由监控器在不同的 机器上生成,并放入了当前目录等): ``` docker run --rm -p 8765:8765 -v "$PWD":/data iklob1/avai ``` 仪表盘会以 `?mode=ro&immutable=1` 模式打开该文件,因此它绝不会 进行写入,也绝不会持有锁 —— 可以安全地指向一个正在由另一个 容器中的监控器写入的实时数据库。 ## 6 —— 常用操作命令 ``` # 检查内置的 CLI docker run --rm iklob1/avai avai --help docker run --rm iklob1/avai avai monitor --help docker run --rm iklob1/avai avai dashboard --help docker run --rm iklob1/avai avai --version # Healthcheck + 状态 docker inspect avai-dashboard --format '{{.State.Health.Status}}' # healthy|unhealthy|starting docker compose ps # if using compose docker logs -f avai-monitor # follow monitor cycles # 实际运行中的 DB rotation — 观察 size cap 生效 docker exec avai-monitor du -h /data/avai.db # 停止 / 清理 docker compose down # if using compose docker stop avai-dashboard avai-monitor 2>/dev/null docker rm avai-dashboard avai-monitor 2>/dev/null # 清除 database(同时清除 verdicts;monitor 将从头重新判定) rm -f data/avai.db data/avai.db-wal data/avai.db-shm # Pull 最新的 image docker pull iklob1/avai ``` ## 7 —— 配方 基础操作之外的实用、可直接复制粘贴的场景。 ### 在 Linux 服务器上原生安装(完整的主机可见性) 在真实的 Linux 主机上的容器内,监控器已经可以工作了,但是 监控服务器的最简单方法是原生安装它,让它 直接查看所有内容: ``` pip install avai-monitor # includes the LLM judge (litellm + anthropic) export ANTHROPIC_API_KEY=sk-ant-... # or CLAUDE_CODE_OAUTH_TOKEN export ABUSE_CH_AUTH_KEY=... # optional, free — adds 3 sources sudo -E avai monitor --db /var/lib/avai/avai.db --interval 300 & avai dashboard --db /var/lib/avai/avai.db --host 0.0.0.0 --port 8765 ``` `sudo` 允许收集器读取 root 拥有的状态(`/etc/shadow`、 其他用户的 crontabs、每一个进程)。`-E` 会跨越 sudo 边界保留您的 API 密钥。 ### 使用 systemd 保持运行 `/etc/systemd/system/avai.service`: ``` [Unit] Description=avai host monitor After=network-online.target [Service] Environment=ANTHROPIC_API_KEY=sk-ant-... Environment=ABUSE_CH_AUTH_KEY=... ExecStart=/usr/local/bin/avai monitor --db /var/lib/avai/avai.db --interval 300 Restart=always User=root [Install] WantedBy=multi-user.target ``` ``` sudo systemctl enable --now avai journalctl -u avai -f # watch cycles ``` ### 直接从命令行读取发现(无需仪表盘) 一切都存放在一个 SQLite 文件中,因此您可以直接查询它 —— 非常适合脚本编写、cron 邮件或没有浏览器的服务器: ``` # 活动的 dangerous + suspicious findings,最新的优先 sqlite3 -box /var/lib/avai/avai.db " SELECT verdict, collector, substr(reasoning,1,60) AS why FROM judgements WHERE verdict IN ('malicious','suspicious') ORDER BY created_at DESC LIMIT 20;" # 按 verdict 计数 sqlite3 /var/lib/avai/avai.db \ "SELECT verdict, count(*) FROM judgements GROUP BY verdict;" # threat-intel 源是怎么说的? sqlite3 -box /var/lib/avai/avai.db " SELECT source, verdict_hint, substr(summary,1,70) FROM enrichment_evidence WHERE verdict_hint IN ('malicious','suspicious');" ``` ### 从 cron 运行一次性扫描(取代常驻 daemon) ``` # /etc/cron.d/avai — 每小时扫描一次,无 streaming 0 * * * * root ANTHROPIC_API_KEY=sk-ant-... \ avai monitor --once --no-streaming --db /var/lib/avai/avai.db ``` ### 拆分设置:监控器在服务器上,仪表盘在您的笔记本电脑上 监控器写入 DB;仪表盘仅读取它。同步该文件 (rsync/scp/NFS),就可以在任何地方查看它: ``` # 在 server 上(writer) avai monitor --db /var/lib/avai/avai.db --interval 300 # pull 到你的笔记本电脑并查看(reader — 任何 OS,无需权限) scp server:/var/lib/avai/avai.db ./avai.db docker run --rm -p 8765:8765 -v "$PWD":/data iklob1/avai ``` ### 保持较低的 LLM 成本 ``` avai monitor \ --judge-model claude-haiku-4-5-20251001 \ # cheapest tier (default) --judge-max-per-collector 20 \ # cap new items judged per cycle --judge-batch-size 20 # entries per API call ``` 无论如何,在稳定状态下成本几乎为零 —— 只有 *新* 的制品会被 判定,而且威胁情报的判定结果会被缓存,因此安静的主机在 第一个周期过后几乎不会发起 API 调用。 ### 开启/关闭富化并调试单个源 ``` avai monitor --no-enrich # collectors + judge only avai monitor --enrich-only cisa_kev # just this source (repeatable) avai monitor --enrich-only virustotal --enrich-only abuseipdb ``` 源名称:`malware_bazaar` `urlhaus` `threatfox` `circl_hashlookup` `shodan_internetdb` `feodo_tracker` `osv` `cisa_kev` `nvd` `endoflife` `crtsh` `virustotal` `abuseipdb` `greynoise` `safe_browsing` `phishtank` `github_advisory`。 ### 使用您自己的 LLM 提供商 `--judge-model` 是一个 [litellm](https://docs.litellm.ai/docs/providers) 模型 ID,因此任何支持的提供商都可以使用: ``` avai monitor --judge-model gpt-4o-mini # OpenAI (OPENAI_API_KEY) avai monitor --judge-model ollama/llama3.1 # local, free, offline avai monitor --judge-model gemini/gemini-1.5-pro # Google ``` ## 收集了什么(一句话总结) 快照收集器(每个周期运行,默认 300 秒): | 组别 | 来源 | |---|---| | 进程 / 网络 | `processes`, `network_connections`, `listening_ports`, `network_interfaces` (psutil) | | 硬件 | `usb_devices` (/sys/bus/usb), `bluetooth_devices` (/var/lib/bluetooth), `wifi_state` (sysfs + `iw`) | | 持久化 | `launch_items` (systemd unit files + cron) | | 文件 | `file_integrity` (passwd / shadow / sudoers / SSH config / dotfiles), `setuid_files`, `mounts` | | 应用 | `installed_apps` (dpkg-query + XDG `.desktop`), `browser_extensions` | | 姿态 | `system_integrity` (SELinux / AppArmor / ufw / sshd / vnc / LUKS) | | 姿态(仅限 macOS) | `tcc_permissions` (摄像头/麦克风/位置/屏幕授权), `quarantine_events`, `mdm_profiles`, `kernel_extensions`, `system_extensions` | 流式收集器(事件发生时即刻捕获): | 收集器 | 来源 | |---|---| | `auth_events` | `journalctl -f` (Linux) / macOS 统一日志 (macOS),过滤至与安全相关的子系统。由唯一的 `(process, subsystem, message)` 模式进行 LLM 判定 —— 无论触发多少次,每个事件模板只判定一次。 | | `process_exec_events` | `journalctl -f _AUDIT_TYPE_NAME=EXECVE` (需要 auditd `auditctl -a always,exit -F arch=b64 -S execve` 规则) | 对于收集到的每一个实体(根据收集器的“判定字段”上的内容哈希进行去重),LLM 判定器会将其 分类为 `恶意` / `可疑` / `未知` / `良性`,并附带置信度、 MITRE 对齐的分类和单行修复建议。判定结果会被 持久化;同一个制品绝不会发送两次。 ## 仪表盘 位于 `:8765` 的 Flask + HTMX 仪表盘在每个表格上都有完整的过滤和分页功能: - **发现** —— 按判定结果、收集器、类别、状态(活动/已解决)过滤,支持自由文本搜索;可排序的列;可配置的每页显示数量(10/25/50/100)。 - **网络流** —— 按判定结果和 IP/主机/进程搜索进行过滤;提供汇总统计(目的地、流量、恶意数量)。 - **监听端口** —— 按判定结果和绑定范围(所有接口 / 可路由 / 回环)过滤;进程搜索。 - **DNS 查询** —— 按判定结果、解析级别(DoH / 外部 DNS / 本地解析器)、域名搜索进行过滤。 - **持久化** —— SSH 授权密钥、`/etc/hosts` 映射和权限配置,各自具有独立的分页。 - **认证事件** —— 根据唯一的 `(进程, 子系统, 消息)` 模式进行聚合,并带有发生次数和最后发现时间戳。按子系统(TCC、securityd、syspolicy、loginwindow、Authorization)或判定结果过滤。按计数或判定结果的严重程度排序。随着模式的分类完成,会出现 LLM 判定结果。 - **TCC 权限** (macOS) —— 每个应用的摄像头、麦克风、位置、屏幕录制和全盘访问权限的授权/拒绝,并带有 LLM 判定结果和认证状态过滤器。 所有部分都会自动刷新(30–60 秒)。对于新的恶意/可疑判定,会触发 Toast 通知 + 音频警报。 ## 威胁情报富化 在每个发现进入 LLM 之前,avai 会提取指标(SHA256、 IPv4、域名、URL、CVE、软件包、操作系统版本),并通过 外部威胁情报 API 运行它们。然后,判定器会 在 prompt 中内联看到原始证据,这极大地收紧了判定结果。 每个源都是可选的。无需密钥的源始终运行。需要密钥的源 只有在设置了下方的环境变量时才会注册 —— 请参阅 [`.env.example`](.env.example) 获取可复制粘贴的模板。 | 来源 | 指标 | 环境变量 | 配额 | 增加的内容 | |---|---|---|---|---| | **MalwareBazaar** (abuse.ch) | SHA256/1/MD5 | `ABUSE_CH_AUTH_KEY` | 不限 | 已知的恶意软件家族 | | **CIRCL hashlookup** (NSRL) | SHA256/1/MD5 | — | 不限 | 已知良好的供应商二进制文件(白名单) | | **Shodan InternetDB** | IPv4 | — | 1 rps | 开放端口、CVE、标签 | | **URLhaus** (abuse.ch) | URL, domain | `ABUSE_CH_AUTH_KEY` | 不限 | 恶意软件分发 URL | | **Feodo Tracker** (abuse.ch) | IPv4 | — | 不限 | 僵尸网络 C2 IP(缓存的 feed) | | **ThreatFox** (abuse.ch) | IPv4 / domain / URL / hash | `ABUSE_CH_AUTH_KEY` | 不限 | 混合 IOC 搜索 | | **OSV.dev** | CVE, package | — | 不限 | 开源安全公告 | | **CISA KEV** | CVE | — | 静态 feed | 正在被利用的 CVE | | **NVD** | CVE | `NVD_API_KEY` (可选) | 5 → 50 / 30 s | CVSS + 描述 | | **crt.sh** | domain | — | 适度 | 证书透明度历史 | | **endoflife.date** | OS version | — | 不限 | 已停止支持的 OS / 运行时 | | **VirusTotal** | SHA256/1/MD5, URL, domain, IPv4 | `VT_API_KEY` | 4/min, 500/day | 多引擎信誉 | | **AbuseIPDB** | IPv4 | `ABUSEIPDB_API_KEY` | 1000/day | 滥用置信度评分 | | **GreyNoise Community** | IPv4 | `GREYNOISE_API_KEY` | 50/day | "这个 IP 只是干扰吗?" | | **Google Safe Browsing** | URL | `GOOGLE_SAFE_BROWSING_API_KEY` | 10k/day | 钓鱼 / 恶意软件判定 | | **PhishTank** | URL | `PHHTANK_API_KEY` | 宽松 | 社区钓鱼数据库 | | **GitHub Advisory** | CVE | `GITHUB_TOKEN` | 高 | 精选的安全公告 + 修复版本 | 每个指标的结果都会被缓存在同一个 SQLite(`enrichment_evidence` 表)中,并带有针对特定源的 TTL(6 小时 – 14 天)。新鲜的缓存命中会完全跳过 网络;该缓存在重启后依然存在。 使用以下命令切换: ``` avai monitor # all enabled sources, default avai monitor --no-enrich # collectors + judge, no external lookups avai monitor --enrich-only malware_bazaar # debugging: only this one ``` ## 为什么本 README 中不涉及 macOS 监控器依赖于 Linux 原生工具 —— `pid=host` 访问 主机的 `/proc`,位于 `/sys/bus/usb` 的 sysfs,搭配 `auditd` 的 `journalctl`、`systemctl is-active`、`dpkg-query`、用于 LUKS 的 `dmsetup`。 macOS 上的 Docker Desktop 仅公开了其附带的 Linux VM,而 不是 macOS 主机,因此 macOS 上的容器化监控器报告的是该 VM(内容 空洞/无趣),而不是 Mac。仪表盘角色在 macOS Docker 上运行良好 —— 您 只需要从其他地方写入该数据库即可。 如果您想要完整的 macOS 覆盖,请以原生方式安装(`pip install avai-monitor`)并使用 `sudo` 运行 `avai monitor`。那是另外一条 路径,不在此文档赘述。 ## 开发与测试 该测试套件不需要网络,并在几秒钟内运行完毕。仓库的开发版 Python 可能带有插件冲突,因此请在一次性的 venv 中运行它: ``` python3 -m venv /tmp/venv && /tmp/venv/bin/pip install -e . pytest /tmp/venv/bin/python -m pytest tests/ -q # 320+ unit tests ``` 测试覆盖范围涵盖了富化框架和全部 18 个源、 指标提取器、HTTP 客户端(速率限制 / 退避 / 429)、 CLI 调度器、SQLAlchemy 仓库 + 数据库轮转、LLM 判定器的解析、仪表盘端点,以及 Linux 收集器的 文件解析(systemd / cron / `.desktop` / BlueZ)。这些测试的编写目的在于 一旦实现逻辑遭到破坏就会失败 —— 这是通过变异测试验证的, 而不仅仅是基于覆盖率。 无人值守 Docker 冒烟测试(构建镜像,运行 CLI 界面, 一次冷收集器遍历,以及无需密钥的富化注册表检查): ``` tests/local.sh # all phases; exits non-zero on any failure ``` 请参阅 [`CHANGELOG.md`](CHANGELOG.md) 获取版本历史。 ## 许可证 MIT —— 请参阅 `LICENSE`。
标签:AMSI绕过, EDR, PE 加载器, Python, x64dbg, 威胁情报, 威胁检测, 安全遥测, 开发者工具, 无后门, 网络信息收集, 脆弱性评估, 请求拦截, 逆向工具