向计算机提问
一种语言,既用于窗口的搜索框,也用于 bws list --query。单独一个词会在名称、显示名称、账户和启动路径中搜索。加上字段则缩小范围。共有 21 个字段,相同的文本在工具的两部分中含义相同。
六个能回答实际问题的查询
应该在运行却没有运行的内容
start:auto !status:running
大多数人写的第一个查询,也是 services.msc 完全无法回答的查询。
文件已丢失的服务
file:missing
指向磁盘上不存在的可执行文件的条目。通常是卸载后遗留了注册信息。
未签名,去掉会话噪声
signed:no peruser:no
按用户的服务族会为每个会话生成一个副本,让列表里充满近似重复的条目。这个查询询问的是其余的部分。
已禁用却仍在运行
mismatch:running
配置与状态不一致:一个被服务管理器设为永不启动的条目,却仍在运行。
任何请求调试权限的内容
privilege:SeDebugPrivilege
一种让进程能够打开任何其他进程的特权。值得知道哪些服务请求了它。
工具无法读取的内容
account:?
此会话无法读取其账户的条目。这是 services.msc 连问都问不出的问题。
如何书写查询
检索词
- 检索词以空格分隔,并且必须全部匹配:没有
and关键字,因为它不可能有别的含义。 - 同一个字段写两次是唯一的例外:
status:running status:stopped表示二者之一,因为勾选两个筛选项时写出的就是这个。对数字的两个边界仍然会缩小范围:pid:>1000 pid:<2000就是二者之间的范围。 - 检索词前的
!表示取反:!status:running。在带有setlocal EnableDelayedExpansion的批处理文件中,cmd 会悄无声息地吃掉这个!,查询便在不知不觉中变成了别的意思:在那里请在引号内写成^!。 - 字段内的逗号表示或:
start:manual,disabled。 - 引号可以保护含有空格或冒号的内容:
account:"NT SERVICE\McmSvc"。 - 原样粘贴的路径,例如
C:\Windows\System32\svchost.exe,会被当作搜索内容,而不是被当作名为 C 的字段。
文本如何匹配
name:spool匹配任何包含它的内容:这是默认行为,因为这是人们对搜索框的预期。name:=spooler是精确匹配。name:spool*支持通配符*和?。name:/^Sql.*/是正则表达式,在斜杠内按正则表达式的写法书写:\?、\\和逗号在那里是什么意思就是什么意思。一个永远不闭合的斜杠是错误:要搜索斜杠本身,请写成\/或使用引号。- 大小写会被忽略,包括 ASCII 之外的字符:波兰语或希腊语的显示名称,无论怎么输入都能匹配。
每个字段都接受的三个词
any- 有值,无论是什么none- 确实没有值,该条目没有值?- 工具无法读取这个字段,或者没有读取它,而这是services.msc连问都问不出的问题
输错的值会报错,而不是返回空结果。status:runing 会回答 Did you mean running?,并以代码 2 结束。空列表看起来就像一个答案,而“没有任何匹配”与“你输错了”之间的差别,就是一台干净的计算机与一次什么也没证明的审计之间的差别。在命令行中,任何不会缩小范围的查询同样会被拒绝,所以脚本不会因为一个拼写错误而对整台计算机进行操作。
更多示例
每一个在窗口的搜索框中和在 bws list --query 之后的效果都一样,而且每一个在写到这里之前都在真实的 Windows 上运行过。能找到什么取决于计算机:对于关于故障的问题,空结果正是你想要的答案。
状态与启动类型
| 查询 | 找到的内容 |
|---|---|
status:stopPending, | 卡在停止或启动中:管理单元显示、永远不会结束的等待。 |
start:auto status:stopped trigger:none | 设为自动启动、已停止,且不在等待触发器:重启之后值得一读的简短列表。 |
start:delayed | 自动,比其他自动条目稍晚启动。 |
start:manual, | 启动时没有任何内容会启动它却在运行:有东西请求了它、触发器启动了它,或者有人启动了它。 |
账户
| 查询 | 找到的内容 |
|---|---|
account:localsystem !publisher:microsoft | 以最强的账户 LocalSystem 运行,且来自 Microsoft 没有签名的文件。关于发布者的查询会自行读取签名,所以需要几秒钟。 |
!account:localsystem, | 在其他任何账户下运行的服务:虚拟账户、托管账户,或某个人自己的账户。 |
account:"NT SERVICE" | 服务自己的虚拟账户。引号把这些词放在一起,因为中间有空格。 |
文件与签名
| 查询 | 找到的内容 |
|---|---|
signed:notSigned, | 没有签名,Windows 不信任的证书链,或签名之后被更改的文件。 |
signed:trusted !publisher:microsoft | 已签名、受信任,且不是 Microsoft:其他公司放在这台计算机上的软件。 |
type:driver start:boot, | 在 Windows 启动时加载、而 Windows 不信任其签名的驱动程序。在健康的计算机上应为零。 |
!path:C:\Windows type:ownProcess | 有独立进程、其文件位于 Windows 文件夹之外的服务。 |
path:\AppData\ | 从某人的用户配置文件内部启动:最不应该出现服务的地方。 |
path:\System32\\ type:ownProcess | 空格前的反斜杠会让空格成为词的一部分,所以当后面还有其他检索词时,以反斜杠结尾的路径要写两个反斜杠。在查询末尾,一个就够了。 |
触发器与依赖关系
| 查询 | 找到的内容 |
|---|---|
trigger:device status:stopped | 等待设备到达,因此是有原因的已停止。 |
trigger:network | 当请求到达某个网络端点(端口、命名管道或 RPC 接口)时启动。 |
trigger:stop | 触发器不仅可以启动、也可以停止的条目。 |
dependson:Winmgmt | 需要 WMI 才能运行的条目。 |
requiredby:Spooler | Print Spooler 运行所需要的一切,以及这些内容又依次需要的一切。 |
特权与进程
| 查询 | 找到的内容 |
|---|---|
privilege:SeTcbPrivilege | 请求以操作系统的一部分身份运行。 |
privilege:SeImpersonatePrivilege !account:localsystem | 在 LocalSystem 之外的账户下运行时,可以代表客户端执行操作。 |
sidtype:unrestricted | 其进程中带有自己的服务 SID,因此权限可以单独指名它。sidtype:restricted 询问的是其进程同时还受写入限制的那些。 |
type:sharedProcess status:running | 与其他服务一起运行在共享的 svchost 内。 |
memory:>200MB | 占用超过 200 MB 的进程。查询询问内存时,会自动读取内存。 |
pid:1000-2000 | 位于进程 ID 在 1000 到 2000 之间的进程中。 |
名称与文本
| 查询 | 找到的内容 |
|---|---|
spool | 单独一个词,在名称、显示名称、账户和启动路径中搜索。 |
name:=wuauserv | 恰好是这个名称,而不是仅仅包含它的内容。 |
name:win* | 以 win 开头的名称,用通配符书写。 |
name:/svc$/ | 以 svc 结尾的名称,用正则表达式书写。 |
description:none | 完全没有描述,大多数驱动程序都是这样。 |
description:? | Windows 无法提供的描述,通常是因为它指向一个不存在的语言文件。 |
peruser:template | Windows 为每个已登录会话复制的按用户模板。 |
每个字段
由程序本身生成,因此这张表不会与工具接受的内容脱节。没有取值列表的字段接受文本、数字或大小:第三列会说明是哪一种。
| 字段 | 询问的内容 | 取值 |
|---|---|---|
name | 服务名称,即 Windows 用来识别它的那个名称 | 文本 |
display | 显示名称,按这台 Windows 的写法 | 文本 |
description | 条目对自身的描述 | 文本 |
type | 这是哪一类条目 | driver, kernelDriver, fileSystemDriver, ownProcess, sharedProcess, unknown |
peruser | 它是否属于 Windows 为每个会话生成副本的按用户服务族之一 | yes, no, template, instance |
status | 它此刻在做什么 | running, stopped, paused, pending, startPending, stopPending, pausePending, continuePending, unknown |
start | 服务管理器在下次启动时如何处理它 | automatic, auto, delayed, manual, disabled, boot, system, unknown |
account | 它运行所用的账户,按服务管理器的写法 | 文本,例如 localsystem |
pid | 它所在的进程 | 数字:1234、>1000、100-200 |
trigger | 启动或停止它的条件 | device, ip, domain, firewall, policy, network, custom, state, aggregate, unknown, start, stop |
path | 服务管理器启动的命令行 | 文本 |
file | 它所运行的文件是否在磁盘上 | present, missing |
signed | Windows 对文件签名的判断,不检查吊销 | yes, no, trusted, notSigned, untrustedRoot, expired, revoked, tampered, unknown |
publisher | 谁给文件签的名,只有受信任的签名才能证明 | 文本 |
privilege | 条目请求的一项特权 | 文本,例如 SeDebugPrivilege |
dependson | 它需要什么 | 服务名称 |
requiredby | 它停止时什么会出问题 | 服务名称 |
sidtype | 服务 SID 类型 | unrestricted, restricted, unknown |
sddl | 安全描述符,以文本形式表示 | 文本 |
memory | 它的进程正在使用什么 | 带单位的大小:500MB、>1GB、100MB-1GB |
mismatch | 相互矛盾的配置与状态 | stopped, running |
两件值得知道的事
有些字段开销很大,查询它们会自动开启读取
在整台计算机上读取签名需要几秒钟,而内存是一项测量而不是一项设置,所以除非被要求,否则都不会为列表读取它们。提到其中任何一项的查询会自动开启这项读取:你不必在 signed:no 之外再记着加 --signatures。在窗口中,关于签名的查询会说明在签名到达之前答案并不完整,而不是展示一份较短的列表、仿佛那就是答案。
基于无法读取内容得出的结果会明说
如果条目是依据此会话无法读取的字段来判断的,结果会带有一行说明有多少个,因为这样的结果可能缺少条目,或者包含了不该有的条目。这与整个工具遵守的规则相同:读取失败会在答案中可见,绝不会被吞掉。如果发布者仅由证书声称,也会得到同样的处理:在任何非 trusted 的判定旁边,名称会显示为 not verified,而 publisher: 会在单独一行中把该条目计为不确定,所以 !publisher:microsoft 会保留某个在签名后被人更改过的 Microsoft 文件。