Windows 流氓软件删了又活:srvhost.exe、服务、计划任务的一份彻底清除手册

2026-10-22 · AI智工坊 · 远程运维实录

一台只能 SSH 登录的 Windows 机器,装了一堆"系统清理、大文件清理、DLL 修复、壁纸"类的免费工具。用户的原话是:"卸载了,重启又回来了,删了文件夹也自己长出来。"

这类软件不是普通的"卸载不干净",它是一套互相保护的常驻组件:一个伪装成系统进程的守护、一个同名 Windows 服务、一个登录时重建的计划任务,外加内核驱动。你用控制面板卸载,它只删掉外壳;你用资源管理器删目录,它下次登录重建。下面是我们在一台无显示器节点上把这类软件清干净的全过程与判据,命令可以直接复用。

一、先认清对手:srvhost.exe 不是 svchost.exe

第一个要建立的概念:Windows 真正的系统宿主进程叫 svchost.exe(c 在前),而这类软件投放的守护进程叫 srvhost.exe。两个名字只差两个字母的顺序,任务管理器里一眼扫过去几乎一样,这是刻意的。

所以侦察第一步就是把它的真身捞出来,而不是靠肉眼看进程名:

wmic process where "name='srvhost.exe'" get ProcessId,ExecutablePath,CommandLine

输出里的 ExecutablePath 会直接落到 C:\Program Files (x86)\ 下某个厂商目录。拿到这个路径,整条链就有锚点了。

我们遇到的这批家族有共同特征,看到这些目录名基本可以直接判定:

目录 / 进程名伪装身份实际行为
DupsClean / LargeFileClean重复文件、大文件清理常驻扫描磁盘,弹窗诱导付费
DllFix / DllFixTrayDLL 修复工具托盘常驻,劫持 shell 扩展
WinClean / WinOptimize / WinEase / EasyClean系统优化自启 + 计划任务重建
WhaleMemory内存优化反复释放内存,实际拖慢系统
HaloWallPaper动态壁纸注入 explorer 渲染
GamingBlast / LdsSurfAssistant / TinyDL / qbblink游戏加速、上网助手、下载器互装互保,装一个带一串

它们共享同一套骨架:每个产品一个 srvhost.exe 守护 + 一个同名服务 + 一个登录触发的计划任务,删掉其中一个,另外两个会把它拉起来。所以清除必须按"进程 → 服务 → 注册表 → 目录 → 计划任务 → 重启验证"的顺序整体做,中途停手等于没做。

二、远程执行的第一道坑:编码

目标机没有图形界面,卸载程序弹窗会卡死 SSH 通道,所以只能命令行硬删。用 paramiko 跑命令时,第一件要定的事是解码方式:

stdout.read().decode('gbk', 'ignore')

中文版 Windows 的控制台输出是 GBK 代码页,用 UTF-8 解出来是乱码,而乱码会让你误判"命令没输出"——我们第一轮就是这么把一条成功的 sc delete 当成失败的。

还有两个同源的坑:

三、删服务:传服务名,不要传注册表路径

这是最容易翻车的一步。正确写法是:

sc delete dllfixSvc

错误写法是:

sc delete "HKLM\SYSTEM\CurrentControlSet\Services\dllfixSvc"

后者会返回 1060(指定的服务不存在) 或 123,看起来像"服务本来就没有",实际上是参数形态错了。sc 只认 ServiceName,也就是注册表 Services 下面那一层的键名。

批量捞服务名的办法是按 ImagePath 反查:

reg query "HKLM\System\CurrentControlSet\Services" /s /v ImagePath | findstr /i "DupsClean LargeFileClean DllFix WinClean WhaleMemory HaloWallPaper WinOptimize WinEase EasyClean GamingBlast LdsSurfAssistant TinyDL qbblink 360"

内核驱动型的(TYPE 1 KERNEL_DRIVER,如 wpsedrv、winoptdrv)同样用 sc delete,但要注意下一节说的文件释放问题。

一个必须记住的判据:服务删掉之后,内存里可能还加载着它的 DLL 或驱动。sc delete 只是把服务注册项标了删除,没重启之前文件是被锁的,你删目录会得到"拒绝访问"。这不是权限问题,是加载问题——先重启,再删文件,顺序反了会白折腾半小时。

四、计划任务:删 XML 不够,必须连 TaskCache 一起删

很多教程教你删 C:\Windows\System32\Tasks\ 下的任务文件,删完 schtasks /query 里确实看不到了。但重启之后它又出现——因为任务调度器真正的索引在注册表里:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache

正确顺序是先尝试正规删除,失败再动注册表:

schtasks /delete /tn "SoftLandingXXX" /f

如果报 access denied(这类任务常以 SYSTEM 身份注册),就直接三件套一起下:

reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{guid}" /f
reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\SoftLandingXXX" /f
rmdir /s /q "C:\Windows\System32\Tasks\SoftLandingXXX"

找 {guid} 的办法是先按 URI 反查:

reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks" /s /v URI | findstr /i "softland"

枚举所有第三方任务的办法是抓 schtasks /query /fo LIST 里的"任务名:",把含 \Microsoft\ 的行全过滤掉——剩下的就是第三方。这一步能立刻看出"谁在登录时把东西拉起来"。

五、删目录:三种锁,三种解法

同一句 rmdir,在三种情况下会有三种完全不同的失败姿态,对症才对:

症状根因解法
"拒绝访问"进程占用,或 DLL 仍被加载先 taskkill,服务删后先重启再删
"找不到路径"(但目录明明在)路径超过 260 字符(Electron 类应用 node_modules 深层嵌套)robocopy 空目录 目标 /mir /r:0 /w:0 清空后再 rmdir
takeown + icacls 之后仍删不掉软件写了 DENY ACLPowerShell Remove-Item -LiteralPath ... -Recurse -Force

超长路径那条尤其反直觉:rmdir 报"系统找不到指定的路径",你会以为路径拼错了,其实是 API 长度上限。用 robocopy 做镜像清空是绕过它最稳的一招:

robocopy "C:\temp\empty" "C:\Program Files (x86)\SomeVendor\deep\path" /mir /r:0 /w:0

还有一种情况是 explorer 的 shell 扩展(常见 context.dll)锁着目录,这时可以 taskkill /f /im explorer.exe 后立刻删——explorer 会自动重启,删除窗口期足够完成。

六、重启也要讲方法:用 SYSTEM 开机任务抢在它之前

最彻底的清法是"在流氓进程启动之前把目录删掉"。做法是上传一个纯 ASCII 的清理批处理,注册成 SYSTEM 权限的开机任务,然后重启:

schtasks /create /tn cleanupX /ru SYSTEM /rl highest /sc onstart /tr "C:\temp\cleanupX.bat" /f
shutdown /r /t 5 /f

/sc onstart 的任务在用户登录之前执行,此时没有任何用户级自启项在跑,目录无锁,删得干干净净。批处理末尾可以顺手删掉自己和这个任务。

远程连接会因为重启中断,重连要写成循环:间隔 8~10 秒重试,最多二十几次。别用一次 connect 就下结论说"机器挂了"。

七、别误伤:三个真实存在的"看起来像流氓"的东西

清理脚本最容易造成的二次伤害,是把系统组件当流氓删了。我们实际踩到三个:

1. 关键词 dups 会命中 ReFsDedupSvc

这是 Windows ReFS 的去重服务,系统自带。删了它,ReFS 卷的相关功能会异常。恢复命令:

sc create ReFsDedupSvc binPath= "%SystemRoot%\System32\ReFsDedupSvc.exe" type= own start= demand obj= LocalSystem

教训是:批量删除前,命中列表必须逐条人工确认,不能"关键词命中即删除"。

2. SoftLanding 类的任务删了还会回来,而且无害

如果某任务的动作是"COM 处理程序",且它的 CLSID 在 HKCR 下没有注册,同时每次登录都会被系统重建——这通常是 Windows 自带的消费者功能任务,不是流氓。删它只会让你在"删了又复活"的错觉里多绕一圈。

3. 拼多多的 PddCoreService 不是严格意义的 PUP

它是真实购物 App 的后台服务(含 PCDN 上传),不是流氓软件。想停它的带宽占用可以 sc delete,但 App 文件还在,用户重装就回来。这类要跟用户说清楚,别打包进"清除战果"里充数。

八、重启后验证:六条判据,一条不过就不算清完

要验的项命令合格标准
守护进程tasklist /fi "imagename eq srvhost.exe"无结果
流氓服务sc query <名> / reg query Services1060 不存在
流氓目录if exist "C:\Program Files (x86)\厂商" echo ALIVE无输出
第三方向导任务schtasks /query /fo LIST只剩含 \Microsoft\ 的
机器级自启reg query "HKLM\...\Run"仅剩系统/本职项
用户级自启逐个 HKU\<SID>\...\Run无拼音/怪名项

补一条经验:验证要在重启后做,不能在当天做。计划任务重建、驱动重新加载都发生在开机阶段,当天的"干净"是假象。我们的做法是清理完重启,等 10 分钟再连回去,把上面六项全跑一遍,输出留档。

九、这套流程的可迁移部分

把上面所有细节剥掉,剩下四条是可以直接搬到任何一台 Windows 上的方法:

  1. 按"保护链"拆,不按"文件"删。进程、服务、任务、驱动是四个互相拉起的东西,必须一次全断,断一半等于没断。
  2. 能重启解决的,不要硬删。文件被锁八成是因为加载中,重启的代价远小于修 ACL。
  3. 每一条删除都要有"重启后仍不存在"的证据。当天的 if exist 为假,不构成结论。
  4. 批量删除必须有白名单复核。ReFsDedupSvc 这种误伤,恢复成本比清理成本高得多。

如果这台机器还要长期跑业务(比如当渲染节点、客服机),清完之后顺手把 Run 键收敛到"系统必需 + 本职服务"两项,比事后反复清理省事得多。

常见问题

用控制面板卸载了,为什么重启后软件又回来了?

因为卸载器只删外壳。这类软件的守护进程(srvhost.exe)、同名服务、登录触发的计划任务是三条独立的复活路径,只要有一条还在,其余会被重新拉起。必须按进程→服务→注册表→目录→计划任务的顺序整体清除,并在重启后验证。

sc delete 报 1060「指定的服务不存在」,是服务本来就没有吗?

不一定。如果你传的是完整注册表路径(HKLM\...\Services\Foo)而不是服务名 Foo,sc 就会报 1060 或 123。先确认参数形态,再判断服务是否真的不存在。

计划任务删了 XML,重启又出现怎么办?

任务调度器的索引在注册表 TaskCache 下。删了 C:\Windows\System32\Tasks\ 里的 XML 之后,还要删 TaskCache\Tasks\{guid} 与 TaskCache\Tree\<任务名> 两处,否则会被重建。

删目录报「拒绝访问」,takeown 之后也不行?

两种可能:一是服务虽已删除但 DLL 仍被加载,需要重启释放;二是软件写了 DENY 类型的 ACL。前者重启即可,后者用 PowerShell 的 Remove-Item -LiteralPath ... -Recurse -Force 最稳。

目录明明存在,rmdir 却说「找不到路径」?

路径超过 260 字符了。用 robocopy "空目录" "目标目录" /mir /r:0 /w:0 把目标清空,再用 rmdir 删空壳,可以绕开长度限制。

清理时把 ReFsDedupSvc 删了怎么办?

用 sc create ReFsDedupSvc binPath= "%SystemRoot%\System32\ReFsDedupSvc.exe" type= own start= demand obj= LocalSystem 可以恢复。根因是关键词 dups 同时命中了流氓软件名和这个系统服务,批量删除前必须逐条人工确认。