RedSideSecurity/PCAPGraph
GitHub: RedSideSecurity/PCAPGraph
一款 BloodHound 风格的网络流量捕获可视化分诊工具,通过交互式可下钻图表结合在线/离线威胁情报,帮助安全团队快速发现恶意通信指标。
Stars: 1 | Forks: 0
# PCAPGraph — 威胁狩猎可视化工具
这是一款 BloodHound 风格的数据包捕获可视化工具。直接拖入 `.pcap` / `.pcapng` 文件,即可通过交互式、可下钻的节点链接图来探索谁在与谁通信——专为实现捕获数据的**快速分诊**以及迅速发现**恶意 IP / 域名指标**而构建。
**RDPGraph** 的姊妹项目(针对 Windows RDP 事件日志实现相同功能)。

## 诞生背景
该项目起源于威胁狩猎/IR(事件响应)团队。当团队拿到一个数据包捕获文件进行调查时,目标是**快速分诊**——迅速回答“这里面有没有恶意行为,是谁接触了它?”
Wireshark 在深度数据包分析方面表现出色,但它**并非为快速响应而生**:你需要逐个流地阅读流量,而重构“哪个内部主机与哪个外部实体进行了通信,以及该实体是否已知恶意的?”是一项缓慢的手工作业。它在处理最首要的分诊问题时尤其薄弱:
- *我们实际联系了哪些外部 IP / 域名?*
- *根据我们的 CTI(网络威胁情报),其中是否有已知的恶意内容?*
- *哪些内部主机连接了恶意指标,以及是如何连接的?*
PCAPGraph 的存在是为了在**几分钟内(而非几小时)**回答这些问题——将捕获文件转化为你可以点击浏览的图表,用它们真实的域名标记目标地址,并直接在你正在查看的节点上对照威胁情报(离线黑名单)和 **VirusTotal** 检查指标。
## 目前功能
- **可下钻图表。** 画布初始仅显示你的**内部主机**(以及内部↔内部的横向移动边缘)。点击主机会将其展开为它的**应用/协议框**(Web、DNS、SSH、NTP、SMB/RPC、RDP、Push/FCM、ICMP、未知等)以及一个 **🌍 国家/地区**框。点击应用框可显示该协议的**目标主机**;点击目标地址可查看详情。
- **域名标签。** 提取 **TLS SNI** 和 **HTTP Host**(并对观察到的 DNS 进行反向映射),使得目标地址显示为 `www.example.com` 而不是纯 IP。
- **反向查询 (🔎)。** 已经有指标了?输入一个恶意 IP 或域名,PCAPGraph 会找到**每一个连接过它的内部主机**(完整的会话表,按协议 / 端口 / 字节细分),并在图表上以**红色**绘制出源→目标的路径。
- **查找恶意 IoCs (🛡)。** 一键检查捕获中的*所有*公共 IP 和域名是否在 **VirusTotal** 中有记录,并高亮显示图表中**最恶意的**那些。(优先确认——见下文。)
- **点击即查 VirusTotal。** 点击任何外部 IP/域名即可查看其检测计数(有多少引擎将其标记为恶意/可疑)。可选 API key。
- **地理 / 国家/地区丰富化。** 点击公共 IP 可查看其国家/地区 / ASN / 组织(通过 ip-api.com 获取),并在“国家/地区”框中按国家对主机的外部目标地址进行分组。
- **离线威胁情报匹配。** 将 IP / 域名 / JA3 与本地黑名单(abuse.ch Feodo/SSLBL/URLhaus,Tor 出口节点)进行匹配——完全离线。匹配到的节点会变为**红色并带有 ☠**。
- **视觉提示,始终开启。** 威胁情报命中 = 红色 ☠,信标目标 = ⏱ 琥珀色(在详情面板中包含信标时间线迷你图),横向移动边缘 = 琥珀色。点击节点可对其进行**聚光灯**显示(其他内容变暗)。边缘和目标行上会显示端口号。
- **布局与导出。** 力导向或树状(从左到右)布局;**⬇ 导出**可将每个主机 → 应用 → 目标地址导出为 CSV。
## 快速开始
PCAPGraph 是一款 Python 3.8+ 应用。创建虚拟环境,安装依赖,运行服务器,然后在浏览器中打开它。
**Linux / macOS:**
```
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python app.py
# 打开 http://127.0.0.1:5000
```
**Windows (PowerShell):**
```
python -m venv venv
.\venv\Scripts\Activate.ps1
pip install -r requirements.txt
python app.py
# 打开 http://127.0.0.1:5000
```
然后**拖放**(或点击选择)一个 `.pcap` / `.pcapng` / `.cap` 文件。
操作完成后,运行 `deactivate` 退出虚拟环境。
### 典型的分诊流程
1. 拖入捕获文件。图表显示你的内部主机。
2. 点击主机 → 按协议查看它的行为。打开 **🌍 国家/地区** 查看其流量在地理位置上的去向;打开 **Web/DNS/…** 查看实际的目标地址。
3. 点击 **🛡 查找恶意 IoCs** 扫描所有内容是否在 VirusTotal 中留有记录,并让最严重的违规者亮起——或者,如果你已经从 CTI 获得了一个指标,将其粘贴到 **🔎 反向查询** 中,看看环境中的谁接触过它。
4. 点击任何可疑目标地址,查看 VirusTotal 检测数、国家/ASN,以及涉及的确切端口 / 数据量。
## 图表是如何构建的
该图表是**渐进式下钻**的,因此即使是一个繁忙的捕获文件也能保持可读性:
- **顶层:** 仅显示内部主机,以及**内部 ↔ 内部**边缘(横向移动 / 常规可见性,当通过 SMB/RDP/WinRM 等协议时绘制为琥珀色)。
- **主机 → 应用:** 点击主机会为其使用的每个应用/协议生成一个框,按端口 + TLS SNI / HTTP Host / JA3 进行分类。
- **应用 → 目标地址:** 点击应用框会显示其目标主机,并进行分页处理(一次显示 20 个,外加一个“+N 更多”节点),这样高频的协议就不会淹没画布。
- **主机 → 🌍 国家/地区 → 目标地址:** 相同外部目标地址的另一种分组方式,按国家/地区分组。
目标地址根据风险(☠ 威胁情报,⏱ 信标)进行着色,点击任何节点都会打开详情面板;点击空白处返回捕获概述。
解析器不会绘制数据包——它将每个 TCP/UDP 会话的两个方向合并为一个**会话**(五元组),因此内存随唯一会话的数量而非文件大小扩展。
## IP 丰富化 (ip-api.com)
点击公共 IP 可查看其**国家、ASN、组织和反向 DNS**,数据来源于 **ip-api.com**(无需 API key)。这受页眉中的**在线查询**开关控制(**默认开启**),因为它会将 IP 发送给第三方——如果调查必须保持在完全本地,请将其关闭。
每个主机的 **🌍 国家/地区**框使用 ip-api.com 的*批量*端点,因此对拥有数十个目标地址的主机进行地理定位只需一次快速请求。内部 / RFC1918 地址永远不会被丰富化。
## VirusTotal 集成(可选)
点击外部 IP 或域名,其面板会显示 **VirusTotal 检测计数**——将其标记为恶意/可疑的引擎数、引擎总数、信誉度,以及指向完整 VirusTotal 报告的链接。
这需要(免费的)VirusTotal API key,但它**完全是可选的**:
- **未配置 key** → 面板显示 *"VirusTotal API token not added"*,且**绝不会向 VirusTotal 发送任何请求。**
- **已配置 key** → 当你点击 IP/域名时,会自动获取检测结果。
要添加 key,请复制示例配置并填写(`config.ini` 已被 gitignored,因此你的 key 永远不会被提交——请保持 `.example` 为空白):
```
cp config.ini.example config.ini
# 编辑 config.ini 并在 [virustotal] 下设置 api_key
```
```
[virustotal]
api_key =
timeout = 8
scan_max = 40
```
在 获取免费 key。`VIRUSTOTAL_API_KEY` 环境变量同样有效,并且优先级高于配置文件。
### 查找恶意 IoCs(批量扫描)
**🛡 查找恶意 IoCs** 按钮可在一个过程中检查捕获中的*所有*公共 IP 和域名是否在 VirusTotal 中有记录,并高亮显示图表中**前 5 名恶意**指标(源→应用→目标路径变红),同时在侧面板提供检测总结以及哪些内部主机联系过它们。
由于这可能会触发大量 API 调用,因此首先会弹出一个**注意**对话框,准确告诉你将发送多少个指标。为了尊重免费层级,它最多扫描 `scan_max` 个指标(默认为 **40**,可配置);已检查的指标会被缓存,因此重新运行速度很快,并能填补任何受速率限制的空缺。在免费层级下(约 4 次查询/分钟),大型扫描可能需要几分钟——对于更大的捕获文件,请调高 `scan_max` 或使用更高级别的 VirusTotal 套餐。
## 离线威胁情报
PCAPGraph 将 IP、域名和 JA3 哈希与**本地黑名单文件**进行匹配——完全离线,匹配时不进行任何外部查询。在有网络连接时填充这些情报源:
```
./download_feeds.sh # abuse.ch Feodo / SSLBL / URLhaus + Tor exit nodes → ./threatintel
```
匹配到的目标地址在图表和面板中会变为**红色并带有 ☠**。如果 `./threatintel` 为空,此功能会优雅降级。
## 配置
大多数设置是环境变量;API key 存放在 `config.ini` 中(见上文)。
| 变量 | 默认值 | 含义 |
|---|---|---|
| `MAX_UPLOAD_MB` | `500` | 最大上传大小;超出此限制的文件会被干净利落地拒绝 |
| `MAX_PACKETS` | `5000000` | 解析达到此数量的数据包后停止(会有提示,绝不静默处理) |
| `PARSE_TIMEOUT` | `120` | 解析单个捕获文件的最大耗时(秒) |
| `THREATINTEL_DIR` | `./threatintel` | 存放离线黑名单源文件的文件夹 (`*.txt`) |
| `VIRUSTOTAL_API_KEY` | _(未设置)_ | VirusTotal key —— 启用检测(或通过 `config.ini` 设置) |
| `VT_SCAN_MAX` | `40` | 每次“查找恶意 IoCs”扫描的最大指标数(或通过 `config.ini` 设置) |
对于超过限制的捕获文件,请在上传前**预先切片**:
```
editcap -c 1000000 big.pcapng chunk.pcapng # split by packet count
tshark -r big.pcapng -Y "ip.addr==10.1.5.0/24" -w focused.pcap # filter to a subnet
```
## 路线图 —— 计划中的威胁狩猎检测
近期的优先事项是打造一个**重新设计的、低误报率的检测面**,以取代已禁用的发现面板,专为**端点恶意软件分诊**进行调优。计划中 / 期望添加的检测:
**需要强化并重新启用的核心检测**
- **隧道传输** —— DNS 隧道传输(长/编码的域名,大量的 TXT 记录,高子域名基数),ICMP 隧道传输(超大/稳定的 ICMP 负载),以及非标准端口的协议隧道传输。
- **C2 信标** —— 具有抖动容忍度的周期性检测,但带有**已知正常的白名单**(推送/遥测/NTP,主要的云 ASN),因此像 FCM 这样的良性服务不再触发它。
- **数据渗出** —— 到单一目标的出站占比较大的字节比例和数据量,加上基于 DNS 和 HTTP 的渗出,根据目标信誉进行评分。
**值得添加的建议**
- **CTI / 已知正常上下文层** —— 根据 ASN/组织(Google,Cloudflare,Microsoft,Apple,Akamai,AWS,Fastly)对目标地址进行分类以抑制误报,并引入更多 CTI 源(新注册域名列表,威胁源,AbuseIPDB)。
- **置信度评分 + 两个层级** —— 将高置信度的 **发现** 列表与 **信息性** 列表分开,以便分析师能看到噪音而不被其惊扰。
- **JA3 / JA3S 恶意软件家族匹配** 对应指纹集。
- **加密流量启发式分析** —— 自签名/异常证书,SNI↔DNS 不匹配,罕见的 TLS 参数。
- **低慢速 / 长连接** 检测和 **信标聚类**。
- **时间轴 / 时间滑块** 用于回放发生联系的时间,以及一个 **“展开所有标记路径”** 按钮,可自动展示通往恶意节点的每一条路径。
- **反向枢纽**(外部 → 哪些内部主机),**目标节点上的 GeoIP 标记**,以及 **IPv6 支持**。
## 注意事项与局限性
- **解析器:** 基于 Scapy 的 `RawPcapReader` 的流式原始头部解析(无逐包解析)——纯 Python 实现,不依赖 Wireshark/tshark,速度快(每秒数万个数据包)。内存随唯一会话的数量扩展,而非文件大小。
- TCP/UDP 会话的双向被合并为一个**会话**,其中知名/较低的端口被视为服务端。
- **目前仅支持 IPv4** —— IPv6 会被跳过。多播 / 广播 / 未指定地址(例如 SSDP `239.255.255.250`)会作为噪音被过滤掉。
支持的链路类型:Ethernet、Linux cooked (SLL)、原始 IPv4 以及 null/loopback。
- 上传的捕获**文件**在解析后即被删除;它永远不会被存储在磁盘上。最近一次上传解析出的会话表会保留在**内存中**(以便反向查询可以扫描每一个流而无需重新上传);它会在下一次上传时被替换,并在服务器停止时消失。
- **本地工具:** 运行在 `127.0.0.1`,单用户,未针对多用户或公共部署进行安全加固。
标签:IP 地址批量处理, 威胁情报, 安全运营, 库, 应急响应, 开发者工具, 扫描框架, 网络流量分析, 逆向工具