edgecasehuman/procdrift

GitHub: edgecasehuman/procdrift

一款单文件、零依赖的 Windows 进程漂移检测器,通过路径级快照对比来回答「这台机器上现在多跑了哪些程序」。

Stars: 1 | Forks: 0

# ProcDrift [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/edgecasehuman/procdrift/actions/workflows/ci.yml) [![Security audit](https://static.pigsec.cn/wp-content/uploads/repos/cas/38/38ac485d5ebb6dda2e12861e191bded15d89d807729096383bf8e2e82dfa83fa.svg)](https://github.com/edgecasehuman/procdrift/actions/workflows/audit.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) 一个单一可执行文件的 Windows 进程监视器,旨在回答一个问题:**现在运行着哪些在这台机器处于已知良好状态时并未运行的程序?** Task Manager 告诉你正在运行什么。Autoruns 告诉你配置了哪些开机启动项。两者都没告诉你*变化*了什么。ProcDrift 会记录其能检测到的每个可执行文件路径的参考快照,然后将后续的每次扫描显示为与该快照的差异。 一个单一可执行文件,体积不到半兆:只有一个桌面窗口,没有控制台,无需安装。没有服务,没有驱动,没有遥测,没有网络访问,没有后台进程。关闭它之后,不会留下任何运行中的痕迹。 ## 它展示的内容 信任度和发现结果是分开的,因为它们回答的是不同的问题。 **Trust (信任度)** 是指该可执行文件相对于你的快照所处的状态: | Trust | 含义 | |---|---| | Protected | Windows 关键进程。ProcDrift 拒绝对其执行任何操作,因为结束它会导致机器停机。 | | Allowed | 其确切路径存在于你的参考快照中 | | Known | Windows 自带的程序,ProcDrift 可以描述它,但它不在你的快照中 | | Unclassified | 除了本次扫描观察到的情况外,对此一无所知 | `Protected` 声明的是 ProcDrift 会采取什么操作,而不是判断该进程是否为良性。 **Findings (发现)** 是指当前关于该进程的真实情况: | Finding | 含义 | |---|---| | New | 不存在于参考快照中 | | Different path | 该名称曾在不同的路径下被观察到 | | Starts automatically | 存在与该可执行文件完全对应的开机启动项 | | Parent ended | 启动它的父进程已不再运行 | | Restarting | 在两分钟内至少启动了三次 | | Peer outlier | 比同类的其他实例消耗更多资源 | | Many instances | 正在运行多个同类的实例 | | Known parent | 由快照中匹配的进程启动 | | Heavy CPU / memory / disk | 目前位列前五的资源消耗大户 | 值得采取行动的组合是 **New + Starts automatically**:某些不在你的基线中、但在重启后依然会存在的东西。ProcDrift 会将其排在最前面。 Findings 被表述为观察结果,而不是定性判断。这里没有任何内容会说“恶意”或“威胁”,因为进程监视器无法知晓这一点,而硬要这么说,正是这些工具让人们逐渐无视它们的原因。 ## Authenticode 选中一个进程会离线验证其签名:首先检查安全目录(这是大多数 Windows 系统二进制文件的签名方式 —— 仅检查内嵌签名会将一台干净的机器大部分报告为“未签名”),然后是内嵌签名。其结果会区分 **Unsigned**(完全没有签名)和 **Invalid**(存在签名但未通过验证),因为将这两者混为一谈会丢失唯一真正值得关注的案例。默认关闭了吊销检查,并且 URL 检索仅限于缓存,因此选中某一行永远不会因网络原因而阻塞。 ## 安装 从 [Releases] 下载 `ProcDrift.exe` 并运行。这就是安装的全部过程。 状态数据会被写入 `%LOCALAPPDATA%\ProcDrift\state.json`,并且仅在你回应首次运行提示、捕获快照或更改允许项之后才会写入。写入是原子操作。不会基于定时器进行任何写入。 ### 关于 SmartScreen 发布的二进制文件是未签名的。在特定构建版本积累足够信誉之前,Windows SmartScreen 会在首次运行时发出警告。如果你需要确定性,请根据发布说明验证其 SHA-256,或者直接从本仓库自行构建。 ProcDrift 绝不会要求你添加 Defender 排除项。如果一个工具提出此要求,它实际上是在要求你仅凭它的一面之词降低你自身的安全防护。 ## 使用说明 1. 在你认为干净的机器上运行它,然后选择 **Record all**。 2. 过段时间再回来查看。**Review** 过滤器会显示不匹配的项目。 3. **Allow** 会将特定的可执行文件路径标记为预期项。允许项是基于路径的,而不是基于名称,因此具有熟悉名称的不同二进制文件不会被盲目信任。 键盘快捷键:`F5` 刷新,`Ctrl+F` 或 `Ctrl+K` 搜索,`Ctrl+C` 复制选中行,`Enter` 查看详情,`Space` 切换挂起状态,`F2` 允许选中的路径,`Delete` 结束进程,`Escape` 清除搜索。点击列标题进行排序。 进程控制(挂起、恢复、结束、结束捕获的进程树)仅对选定的进程执行,并会重新检查进程身份,因此不会错误地操作被复用的 PID。 ## 设计约束 这些是有意为之的设计,而非缺失的功能: - 一个进程,一个窗口,每次可见刷新只进行一次进程枚举。 - 最小化时定时器会停止。 - 如果内核查询失败,屏幕上会保留最后的有效表格,而不是清空内容。 - 启动项索引只构建一次,而不是每次刷新都构建,因为它需要读取数百个注册表项。 - 签名验证在工作线程中运行,绝不在 UI 线程中运行。 没有历史数据库,没有图形化,没有在线查询,没有套接字普查,也没有定期的文件写入操作。 ## 构建 需要 rustup 和 Visual Studio Build Tools。编译器版本固定在 `rust-toolchain.toml` 中,并在首次执行 `cargo` 命令时自行安装。该 crate 也可以在 Rust 1.88 及更高版本上构建,这已由 CI 单独验证。 ``` cargo build --locked --release ``` 生成的二进制文件是 `target/release/ProcDrift.exe`,这就是完整的应用程序。 ``` cargo clippy --locked --all-targets -- -D warnings cargo test --locked ``` 某些测试会特意测试真实的运行环境:目录验证会针对真实的 `kernel32.dll` 进行检查,并且断言启动项索引不为空。这两者一旦失败都会产生明显的报错,而不是静默地返回无结果。 ## 安全性 该工具会结束和挂起进程,并报告 Authenticode 结果,因此其信任边界已在 [SECURITY.md](SECURITY.md) 中明确记录 —— 包括 `Trusted` 判定*不代表*什么,以及出于设计考虑默认关闭了吊销检查。请通过仓库的 Security 标签页私下报告漏洞,切勿作为公开 issue 提交。 ## 贡献 [CONTRIBUTING.md](CONTRIBUTING.md) 涵盖了构建过程、CI 强制执行的四道关卡,以及本项目刻意不做的事情列表。参与本项目受 [行为准则](CODE_OF_CONDUCT.md) 约束。 ## 许可证 MIT。详见 [LICENSE](LICENSE)。
标签:Rust, 可视化界面, 桌面应用, 端点可见性, 系统工具, 网络流量审计, 通知系统, 配置漂移