查出是谁改了这个 Windows 设置

Windows 记录了值,从不记录作者。功能更新突然不再推送、休眠从电源菜单里消失——你手里只剩一个别人写下的值,却无处问「谁干的」。whodunit 就是来回答这个问题的。

单个静态二进制 · 免安装 · 只读不写入 · MIT · 需要管理员权限的只有「改回去」,不是「查出来」

它回答的不是「有没有问题」

体检工具告诉你机器不健康,优化工具把它改成不健康。两者都不告诉你第三个问题:到底是谁动的手。

体检工具会告诉你

「检测到策略阻止了功能更新,建议删除注册表键 DisableWindowsUpdateAccess。」

whodunit 会告诉你

「这个值是 Winhance 写的——它自己的变更日志里就记着这一条,时间 2026-10-04 11:10。这是它当时的原话。」

为什么现有工具解决不了

工具它做什么为什么不够
Process Monitor实时抓注册表写入必须在改动之前就开着——你之所以在读这页,正是因为它没开
Regshot快照比对只说「什么变了」,不说「谁变的」,还得先有改动前的快照
RegRipper取证向注册表解析面向调查人员的磁盘镜像,不是坐在机器前的人
winutil / Sophia / privacy.sexy应用各种优化它们往往就是「肇事者」,而不是解释者

一次真正的点名

下面是一次完整归真的输出(英文版,中英文可切换)。注意 A 级证据不是宣传话术——它引用了凶手自己的日志原文。

$ whodunit why "26H2 not offered" -lang en ## [DETECTED] wufb-feature-update-blocked **Feature updates are blocked by policy (26H2 will not install)** - observed: DisableWindowsUpdateAccess=1 - subject: HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate - attributed to: Winhance (evidence A, tool_fingerprint) | grade | source | what it proves | |-------|--------------------|-------------------------------------------------| | A | tool_fingerprint | Winhance's own change history names this setting | | C | registry_lastwrite | the key was last written at 2026-10-04 11:10:19 | | D | event_audit | no write audit available for this value | Details: - A / tool_fingerprint — Winhance's own change history names this setting Found C:\ProgramData\Winhance\Logs\ChangeHistory.txt. Its change history records this setting, so the tool itself confirms it made the change: [SET] HKLM\SOFTWARE\Policies\...\DisableWindowsUpdateAccess Revert (printed only; whodunit does not run these): 1. reg delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /v DisableWindowsUpdateAccess /f

这段输出可以在任何机器上复现:demo/ 目录带了一套夹具(假注册表快照 + 一份真实风格的变更日志),不需要真的装过 Winhance。CI 里每次提交都跑一遍,一旦报告里不再出现 evidence A,构建就失败。

证据分级:等级就是承诺

每一条证据都带等级,等级说了它到底能证明什么。多数机器上没有可查的变更日志,所以多数归因落在 B 或 C——分级体系的存在就是为了让这件事诚实。

等级含义典型来源
A施动者被自己的记录点名工具自身的变更日志(真实读取)
B强线索:工具在机器上,且确实会改这类设置安装痕迹、指纹库
C只有时间——知道什么时候,不知道谁注册表键的 FILETIME
D只有状态——连时间都拿不到没有源能回答
最强证据只有 C 级时,报告写的是 unknown actor(凶手未知)。不会把猜测升格成事实——这是整个项目的立身之本。A 级要求凶手自己的日志里有一行点名了这个设置;日志存在、但提的是别的设置,那还是 B 级:存在不等于认罪。

下载

单个静态二进制,无安装器、无数据文件。下载后建议核对 SHA256(每个包里都带 .sha256)。

每个包里有两个 exe:whodunit.exe 是命令行(给脚本用), whodunit-gui.exe 双击就在浏览器里打开报告。两个都不需要安装。

只发布 Windows 版本——whodunit 排查的就是 Windows 机器。 (CI 里会交叉编译 Linux,那是为了保证代码不被写坏,不是给你下载的。)

用法

# 列出内置规则 $ whodunit rules # 跑一遍所有规则,报出命中的 $ whodunit scan # 按症状归因 $ whodunit why "26H2 not offered" # 机器可读 / 换成英文报告 $ whodunit why "hibernate gone" -lang en -json

退出码:0 没命中,1 有命中,2 用法或运行错误——可以塞进脚本和登录任务。

常见问题

它会改我的机器吗?

不会。它只读。报告末尾会打印「改回去」的命令,但从不执行——要不要跑,你自己决定。

需要管理员权限吗?

查不需要。读注册表、读策略、读工具日志都用普通用户权限就能做。只有真正执行回滚命令时才需要管理员。

为什么大多数时候只能查到 C 级?

因为 Windows 默认不记录注册表写入,多数机器也没有留下可查的变更日志。这时最诚实的结果就是「这个键在某某时间被写过,凶手未知」。宁可说不知道,也不编一个。

我用的优化工具不在指纹库里怎么办?

内置认得 Winhance、ShutUp10 等 6 个。不在库里的工具点不出名字——但加一个只是改 YAML 的事,见仓库里的 internal/sources/fingerprints/tools.yaml,欢迎 PR。规则同样:加一个检查 = 加一个 YAML 文件,不用写 Go 代码。

删掉键之后过一会儿又回来了?

那说明有 MDM 或计划任务在持续下发。动手前先看证据链里 policy_origin 那一条,它会区分「直接写注册表」「本地 GPO」和「MDM 下发」。

GUI 版是真正的窗口程序吗?

它双击就打开一个真正的窗口——不过那个窗口是你的浏览器。原生控件库要么需要 cgo、要么要拖进一大堆依赖,那就毁掉了「单文件静态二进制」这个前提。所以 GUI 是本机回环服务(只监听 127.0.0.1)+ 编译进去的页面,关掉窗口就停。