BlueTeamCoolTeam/feintnet
GitHub: BlueTeamCoolTeam/feintnet
一个单二进制、跨平台、分层自适应的伪网络分析工具,用于在恶意软件动态分析中模拟网络环境并捕获 C2 通信与 IOC。
Stars: 0 | Forks: 0
```
███████╗███████╗██╗███╗ ██╗████████╗███╗ ██╗███████╗████████╗
██╔════╝██╔════╝██║████╗ ██║╚══██╔══╝████╗ ██║██╔════╝╚══██╔══╝
█████╗ █████╗ ██║██╔██╗ ██║ ██║ ██╔██╗ ██║█████╗ ██║
██╔══╝ ██╔══╝ ██║██║╚██╗██║ ██║ ██║╚██╗██║██╔══╝ ██║
██║ ███████╗██║██║ ╚████║ ██║ ██║ ╚████║███████╗ ██║
╚═╝ ╚══════╝╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝
blueteam.cool · driverless where FakeNet-NG can't go, driver-backed where it can
```
`feintnet` 是一个单二进制文件的伪网络环境,用于动态恶意软件分析。它将分析环境转变为了一个逼真的人造互联网——包含 DNS sinkhole、协议响应器、被动连接记录器和 TLS 拦截——使得引爆的样本能够进行解析、连接并暴露其 C2,同时将其接触到的所有内容捕获到结构化日志和 IOC 报告中。
它是**分层能力**的:feintnet 会根据主机的支持程度运行,并且*会自适应而不是直接失败*。
- 在 **x86-64 Windows** 上,它使用**驱动程序** (WinDivert) 来透明地转移所有出站流量。
- 在 **Linux** 上,它使用原生的**无驱动内核**路径(nftables `REDIRECT`)。
- 在两者都不可用的地方——**ARM64、模拟的 Windows、macOS**——它会**回退到 DNS 漏斗模式**:较弱,但仍然可用。
这是一个几乎可以在任何环境下工作的工具——无论是 ARM 还是 x64,Windows 还是 Linux——它会降级到可用的层级继续工作,而不是拒绝运行。
## 为什么会有这个工具
我构建 feintnet 是因为在 ARM / 模拟的 Windows 环境上分析恶意软件时,经常遇到 **WinDivert 驱动程序失败**的问题,在这种情况下 [FakeNet-NG](https://github.com/mandiant/flare-fakenet-ng) 的内核驱动程序根本无法加载。FakeNet-NG 非常出色,也是这里的直接灵感来源——但它依赖于驱动程序:当驱动程序不受支持时,你就会陷入困境。在尝试了太多次变通方法之后,我想要一个工作方式*类似于* FakeNet-NG,但能够**灵活适应主机能力**的工具——这样当最强的拦截功能不可用时,它会降级到较弱但仍然可用的层级并继续捕获,而不是完全无法工作。这个概念和 SingleHost 方法归功于 FakeNet-NG(FLARE / Mandiant)。
## 工作原理
feintnet 是一个**同主机工具**,使用方式类似于 FakeNet-NG 的 SingleHost 模式:**你在分析 VM 上运行 feintnet,然后在同一台 VM 上引爆样本。** feintnet 绑定所有接口并在本地捕获样本的流量——这正是它的连接记录器能够将连接归属于特定 **PID 和进程名**的原因。这里没有第二台机器,也不需要配置网关。
一旦启动,feintnet 就会扮演样本期望互联网扮演的所有角色:
- **DNS sinkhole** —— 每次查询都会解析为 feintnet 的 IP,因此样本会连接回 feintnet。OS 连接检查名称(NCSI / 强制门户)也会解析到 feintnet,因此如果一个样本依赖于名称解析或 TCP 连接,它就会相信自己处于联网状态。注意:feintnet **不会**重现 Microsoft 精确的 NCSI 响应(`connecttest.txt` 正文或 `dns.msftncsi.com` 标记 IP),因此 Windows *自身*的网络指示器可能仍然显示“无网络连接”——这通常对样本无关紧要,但值得了解。
- **协议响应器** —— HTTP 和 TLS,以及*服务端先发言*的协议 SMTP、FTP、POP3、IMAP 和 IRC,每个协议都会向样本发送问候并保持对话,以便样本进行信标通信或数据渗透。HTTP 请求正文和 SMTP DATA payload 会作为 artifacts 保存。
- **TLS 指纹识别** —— SNI、**JA3** 和 **JA4** 是根据 ClientHello 计算出来的(即使没有 MITM)。开启 MITM 后,feintnet 会使用由会话 CA 生成的针对特定主机的证书来终止 TLS,从而将 HTTPS 解密为完整的 HTTP 事件。
- **被动连接记录器** —— 读取本地 OS 连接表,以捕获 feintnet 从未绑定监听器的流量(在非寻常端口上的硬编码 IP C2),并附带有源 PID 和进程信息。
- **IOC 报告** —— 每次运行都会生成一份人类可读的 `summary.md` 以及原始的 `events.jsonl`。
## 能力 × 平台
feintnet 可以在以下所有平台上运行;不同的是拦截的*强度*。被动捕获在任何地方都可以工作;透明层级和修改主机的功能是因平台而异的部分。
| 能力 | Windows x64 | Windows ARM64 | Linux x64 / ARM64 | macOS |
|---|:--:|:--:|:--:|:--:|
| 被动捕获(sinkhole、响应器、JA3/JA4、IOC 报告) | ✅ | ✅ | ✅ | ✅ |
| 透明重定向 —— 捕获硬编码 IP / 无 DNS 的 C2 | ✅ WinDivert | ➖ DNS 漏斗 | ✅ nftables | ➖ DNS 漏斗 |
| DNS 重指向 (`--set-dns`) | ✅ | ✅ | ✅ | ❌ |
| MITM + 自动信任 CA (`--mitm --trust-ca` / `--auto`) | ✅ | ✅ | ✅ | ❌ |
| 带 PID / 进程的 connlog | ✅ | ✅ | ✅ | ❌ |
| 数据包捕获 (`--pcap`, pcapng) | ✅ | ❌ | ❌ *(计划中)* | ❌ |
- ✅ 可用 · ➖ 不可用,**自动回退到 DNS 漏斗** · ❌ 未实现
- **WinDivert 透明层级**需要 **x86-64 + 管理员权限**,并且需要在 `feintnet.exe` 旁边放置附带的 `WinDivert.dll` 和 `WinDivert64.sys`;**Windows ARM64 / 模拟的 Windows** 没有 x64 驱动程序,因此它会回退到 DNS 漏斗。
- 在 **macOS** 上,feintnet 是**仅被动模式**的——透明层级、DNS 重指向、CA 信任和 connlog 未实现;它仍然会对 DNS 进行 sinkhole 处理,并捕获所有通过名称访问的内容。
- **`--transparent`** 在无法实现该功能的主机上会报硬错误;**`--auto`** 在相同主机上会回退到 DNS 漏斗并**发出强烈警告**(通过 stderr 和横幅提示)告知请求了更强的层级但被拒绝,以及原因。
## 拦截层级
单纯的 `feintnet run` 是**完全被动**的——它只负责监听和记录日志,从不触碰主机的网络。为了也能捕获那些忽略 DNS 或硬编码了 C2 IP:port 的流量,feintnet 会在以下三个层级之一对主机进行修改:
| 层级 | 标志 | 功能 | 还能捕获 |
|---|---|---|---|
| 0 (默认) | *(无)* | 仅监听;被动记录看到的内容 | 通过 feintnet 的 DNS 进行解析或连接到已服务端口的样本 |
| 1 | `--set-dns` | 将主机的 DNS 解析器重定向到 feintnet | 通过自定义解析器进行普通 DNS 查询的样本 |
| 2 | `--transparent` | 将**所有**出站流量转移到 feintnet | 硬编码 IP 的 C2、任意端口、无 DNS 的恶意软件 |
`--auto` 是一键配置:它会探测主机,启用可用的最强层级,开启 MITM,并将会话 CA 安装到主机信任存储中——所有操作都需要经过明确的确认。每一次更改在应用之前都会被**记录在日志中**,并且在退出时、在下一次运行的自愈过程中,或者崩溃后通过 `feintnet revert` 恢复原状。
## 安装
从 **[Releases](https://github.com/BlueTeamCoolTeam/feintnet/releases)** 页面下载适用于您平台的压缩包并解压。该二进制文件是静态编译的(`CGO_ENABLED=0`)——无需安装任何其他内容。
| 平台 | 压缩包 |
|---|---|
| Windows x86-64 | `feintnet__windows_amd64.zip` |
| Windows ARM64 | `feintnet__windows_arm64.zip` |
| Linux x86-64 | `feintnet__linux_amd64.tar.gz` |
| Linux ARM64 | `feintnet__linux_arm64.tar.gz` |
**Windows 压缩包在 `feintnet.exe` 旁捆绑了 `WinDivert.dll` + `WinDivert64.sys`**,因此透明层级在 x86-64 上可以开箱即用。复制后,请清除 Web 标记:`Unblock-File .\feintnet.exe`。
或者从源码构建 (Go 1.22+):
```
go build -o feintnet .
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o feintnet.exe . # cross-compile
```
## 快速开始
工作流程在单台 VM 上始终相同:**打快照 → 隔离网络 → 启动 feintnet → 在同一台 VM 上引爆样本 → 阅读报告 → 恢复快照。**
```
# Windows x86-64,提权的 PowerShell — 最强等级 + MITM + CA 安装,一条命令:
.\feintnet.exe run --auto --dir .\feintnet-runs
```
```
# Linux,root:
sudo ./feintnet run --auto --dir ./feintnet-runs
```
在 `sudo` 下,feintnet 会将会话输出交还给调用用户(通过 `SUDO_UID`/`SUDO_GID`),因此 `feintnet-runs/` 在运行结束后无需 root 权限即可保持可读和可删除状态。
`--auto` 会打印出它将要进行的更改,并要求您输入 `yes`(使用 `--yes` 跳过)。在 x86-64 Windows 机器上,横幅会报告 WinDivert 层级:
```
── feintnet ─────────────────────────────
Interception : transparent(windivert)
Sink IP : 172.16.43.10
Session dir : feintnet-runs\20260706T041530Z
Listeners : 14 up, 0 failed to bind
Ports : 14 TCP served, DNS sinkhole on :53
TLS : mitm=true trust-ca=true
DNS repoint : false
revert journal armed — changes revert on exit / `feintnet revert`
───────────────────────────────────────
```
引爆样本,让它进行信标通信,然后按 Ctrl-C(或使用 `--duration`)。所有内容都保存在 `feintnet-runs//` 中。
## 实用示例
每个实用示例都包含一个问题、对应的命令以及您应该期望看到的输出。
### 1. 捕获硬编码 C2 IP:port 的样本
透明层级会转移*所有*出站流量,因此即使是不使用 DNS 的 C2 也会落到 feintnet 上,从而恢复真实的目的地。通过使用 curl 访问一个未被绑定的 IP 来验证它——这正是硬编码 C2 的样子:
```
curl --max-time 3 http://203.0.113.9:4444/beacon -o /dev/null || true
grep '"type":"conn"' "$(ls -dt ./feintnet-runs/*/ | head -1)events.jsonl"
```
```
{"type":"conn","state":"redirected","dst_ip":"203.0.113.9","dst_port":4444,"src":"10.0.0.5:51234"}
```
`dst_ip:dst_port` 是样本*实际*拨号的地址,从重定向中恢复——而不是 feintnet 的通用捕获端口。
### 2. 阅读 IOC 报告
每次运行都会生成 `summary.md`(人类可读)和 `summary.json`(用于脚本处理):
```
cat "$(ls -dt ./feintnet-runs/*/ | head -1)summary.md"
```
```
# feintnet 会话 IOC 总结
## C2 端点
- `203.0.113.9:4444` [pid 4812 sample.exe]
## 域名
- `payload.evil.example`
## TLS SNIs
- `c2.evil.example`
## JA3
- `9dfdf48f402c78a2cffc0ab68f9c914c`
## JA4
- `t13d2012h1_2b729b4bf6f3_36bf25f296df`
## URLs
- `http://127.0.0.1:8080/gate`
- `https://c2.evil.example`
## Artifacts
- `artifacts/http_8080_1783319313842742200.body`
```
**C2 endpoints** 部分会在透明层级和 connlog 处于活动状态时,将每个真实的 `ip:port` 与所属的 PID/进程相关联。即使关闭了 MITM,也会从 ClientHello 计算出 JA3/JA4。
### 3. 获取数据包捕获 (Windows x86-64)
`--pcap` 会写入一个 `capture.pcapng`,其中包含**原始和被转移的帧,并为每个数据包标注了 PID/进程**。它只在 **WinDivert 透明层级** (x86-64 Windows) 上才会产生输出——Linux nftables 路径是 socket 级别的,因此没有可写入的原始帧,feintnet 会在横幅中说明这一点,而不是写入一个空文件。
```
.\feintnet.exe run --auto --pcap --dir .\feintnet-runs
```
横幅会增加一行 PCAP 信息,并且 `feintnet-runs\\capture.pcapng` 可以在 Wireshark 中打开。
### 4. 解密 HTTPS (MITM)
feintnet 会生成一个**临时会话 CA**(每次运行都是全新的,密钥从不写入磁盘),并使用 `--trust-ca`/`--auto` 将其证书安装到**此 VM 的**信任存储区中,以便同主机上的样本信任生成的叶证书。它会在退出时 / 执行 `feintnet revert` 时再次被移除。
```
.\feintnet.exe run --mitm --trust-ca --dir .\feintnet-runs
```
经过验证的 HTTPS 客户端的流量现在会被解密为完整的 `http` 事件(方法、路径、正文 artifact),而不仅仅是一个 `sni` 指纹。
### 5. 消除噪音 —— 只显示样本的 C2
在真实的机器上,OS 和后台应用程序会建立自己的连接。通过配置文件,让 feintnet 只关注您引爆的进程,并屏蔽已知的良性 endpoint:
```
# focus.yaml
ioc:
process: sample.exe # only surface C2 from this process in the headline
suppress:
domains: [update.contoso.com] # hide known-benign endpoints
processes: [MsMpEng.exe]
```
```
./feintnet run --auto --config focus.yaml
```
被屏蔽的 endpoint 仍然会出现在 `events.jsonl` 和一个 `## Suppressed (benign)` 部分——没有任何内容被丢弃,只是移出了 C2 标题。
### 6. 让 DNS 失败或重塑 DNS
默认情况下会对所有内容进行 sinkhole。要让样本认为 DNS 已死,或者选择性地进行 sinkhole:
```
# dns.yaml
dns:
default: nxdomain # everything → NXDOMAIN...
rules:
- {match: "*.evil.example", action: sink} # ...except these, which resolve to the sink
```
```
./feintnet run --config dns.yaml
```
操作包括 `sink` 和 `nxdomain`;规则匹配精确名称或 `*.suffix` 通配符。
### 7. 在 Windows 上安全首次运行 —— 限定重定向范围
透明层级会重新路由**所有**出站流量;糟糕的首次运行可能会在 feintnet 退出前卡死 VM 的网络。在您的第一次尝试中,使用环境变量将 WinDivert 限定在一个测试端口(无需重新编译),确认重有效,然后再扩大范围:
```
$env:FEINTNET_WINDIVERT_FILTER = "outbound and ip and tcp.DstPort == 4444"
.\feintnet.exe run --transparent --yes --dir .\feintnet-runs
```
只有发往端口 4444 的流量会被转移;其他一切正常流动。取消设置该变量即可扩大范围。
### 8. 无需 admin/root 权限进行测试
仅绑定高位端口,因此不需要任何特权:
```
./feintnet init --out feintnet.yaml # writes a starter config
# 编辑端口,例如:ports: {tcp: [8080, 8443], udp: [5353]}
./feintnet run --config feintnet.yaml
```
将客户端指向高位端口:`curl http://127.0.0.1:8080/` 和 `dig -p 5353 @127.0.0.1 x.example`。
### 9. Headless 运行 / 管道传输给 jq
`--no-console` 会静默控制台镜像,使 `events.jsonl` 保持机器可读的纯净,而 `--duration` 会自动停止运行:
```
./feintnet run --auto --no-console --duration 60s --dir ./feintnet-runs
```
真实的事件行(每行一个 JSON 对象):
```
{"type":"http","method":"POST","path":"/gate","host":"127.0.0.1:8080","body_file":"artifacts/http_8080_1783319313842742200.body","body_sha256":"9847fbfd0aa37053585773f709feb6a6223ae2836f2f913d91985bbec7b8113d","ts":"2026-07-06T06:28:33.84Z"}
{"type":"sni","sni":"c2.evil.example","ja3":"9dfdf48f402c78a2cffc0ab68f9c914c","ja4":"t13d2012h1_2b729b4bf6f3_36bf25f296df","port":8443,"ts":"2026-07-06T06:28:33.90Z"}
```
然后,例如:`jq -r 'select(.type=="sni") | .ja4' events.jsonl`。
### 10. 在崩溃后恢复
每一次修改(DNS、重定向、信任存储)在应用*之前*都会被记录到日志中,因此强行终止永远不会让 VM 处于被接管的状态:
```
sudo ./feintnet revert # undoes any pending changes, then deletes the journal
```
相同的自愈过程也会在下一次 `feintnet run --auto` 开始时自动运行。
## 选项参考
`feintnet run` 标志:
| 标志 | 效果 |
|---|---|
| `--auto` | 最强可用层级 + MITM + trust-ca,一条命令搞定(会修改系统) |
| `--set-dns` | 层级 1:重新指向主机 DNS 解析器(会修改系统) |
| `--transparent` | 层级 2:转移所有出站流量(会修改系统) |
| `--mitm` | 使用针对特定主机的叶证书终止 TLS(解密 HTTPS) |
| `--trust-ca` | 将会话 CA 安装到主机信任存储区,仅限 VM 使用(会修改系统) |
| `--pcap` | 写入 `capture.pcapng` —— 仅限 WinDivert (Windows x64) 层级 |
| `--yes` | 跳过修改类标志所需的确认提示 |
| `--ports "80,443,1-1024"` | 覆盖已服务的 TCP 端口集(`all`、列表或范围) |
| `--sink-ip ` | DNS sinkhole 回答时使用的 IP(默认:主机主要 IP) |
| `--dir ` | 会话输出目录(默认 `./feintnet-runs`) |
| `--duration 60s` | 运行这么长时间后退出(默认:直到按 Ctrl-C) |
| `--no-console` | 禁止控制台镜像;仅写入 JSONL |
| `--config ` | 加载 YAML 配置(见上文实用示例) |
其他命令:`feintnet init`(写入一个入门的 `feintnet.yaml`),`feintnet revert`(撤销崩溃运行带来的更改)。环境变量:`FEINTNET_WINDIVERT_FILTER` 用于限定 Windows 重定向范围(实用示例 7)。
**默认服务端口**(使用 `--ports` / 配置覆盖):TCP `53, 80, 443, 8080, 8443, 25, 587, 21, 110, 143, 993, 995, 1080, 6667`(14 个端口)以及 UDP `53` 上的 DNS。
## 它做不到的事情(目前)
坦诚的局限性,让您了解边界在哪里:
- **FTP 数据通道**不被捕获——STOR/RETR 文件名和控制命令会被记录,但文件字节数不会(PASV/PORT 被拒绝)。
- **没有 SOCKS 响应器**——端口 1080 被服务,但 SOCKS 握手只会作为原始字节被记录,而不会进行交互。
- **IMAPS / POP3S 只进行指纹识别,不进行解密**——您可以在 993/995 上获取 SNI/JA3/JA4,但 MITM 只会将解密后的流量重新分发给 HTTP 响应器,因此加密的 IMAP/POP3 不会被重放。
- **DNS 透传**(将名称中继到真实的上游)尚未连接——请使用 `sink` / `nxdomain` / 规则。
- **PCAP 仅限 Windows x86-64** (WinDivert);Linux nftables 后端尚无数据包捕获功能。
- **macOS 是纯被动的**——没有透明层级、DNS 重指向、CA 信任或 connlog。
## 配置
大多数运行不需要配置。`feintnet init` 会写入一个您可以编辑的入门文件;每个字段都是可选的,并会覆盖默认值。常见键:`ports.{tcp,udp}`, `sink_ip`, `dns.{default,rules,ncsi_decoy}`, `tls.{mitm}`, `responders.http.{status,body,capture_bodies}`, `intercept.{mode,ports,icmp}`, `ioc.{process,suppress,suppress_file}`, `pcap.{enabled,file,include_original,annotate}`, `logging.{jsonl,console,dir}`。
## 安全
- 永远只在**位于仅主机网络上的、一次性的、打过快照的 VM 内**运行修改类标志(`--auto`、`--transparent`、`--set-dns`、`--trust-ca`),并且**在每次运行后恢复快照。**
- 永远只在**该 VM 内部**信任 feintnet 会话 CA。绝对不要在您的工作站上信任它。
- 在仅主机的实验环境中,允许 client→feintnet 的流量并拒绝其他一切流量——这种隔离就是对活体样本的遏制。
- 透明层级会重新路由**所有**出站流量;一次糟糕的运行可能会在 feintnet 退出前卡死 VM 的网络(退出时会解除转移)。限定您首次 Windows 运行的范围(实用示例 7),并将快照作为您的一键撤销手段。
## 第三方组件
Windows 透明层级使用了由 Basil 开发的 **WinDivert**(`WinDivert.dll`、`WinDivert64.sys`),捆绑在 Windows 压缩包中。WinDivert 采用 **LGPLv3 / GPLv2** 双重许可——请参阅 [`WINDIVERT-LICENSE`](WINDIVERT-LICENSE) 和 [`NOTICE`](NOTICE)。
## 许可证
Apache License 2.0 —— 请参阅 [LICENSE](LICENSE)。
## 作者 / 致谢
由 **blueteam.cool** 构建。灵感来自 [FakeNet-NG](https://github.com/mandiant/flare-fakenet-ng)
(FLARE / Mandiant)。
- 网站:
- X / Twitter:
在 AI 协助下构建。
标签:DAST, DNS劫持, EVTX分析, IP 地址批量处理, TLS解密, 威胁情报, 开发者工具, 恶意软件分析, 日志审计, 网络仿真