看门狗线程一挂就失效是因为它是被保护进程内启动的单点线程,易被SuspendThread/TerminateThread终止或patch入口/sleep调用;双进程互保通过独立进程、命名对象通信、互相监控与重启来提升可靠性。

看门狗线程为什么一挂就失效?
因为单点看门狗本质是「被保护进程自己启动的线程」,逆向者用 SuspendThread 或 TerminateThread 直接干掉它,甚至 patch 线程入口或 sleep 调用,整个检测逻辑就形同虚设。Windows 下线程级防护没有内核支持根本不可靠,必须跳出「单进程内保」思维。
双进程互保的核心:用独立进程做 watchdog
主进程(业务逻辑)和 watchdog 进程(纯检测)彼此独立运行,通过命名对象(如 Event、Mutex)通信,不共享内存、不共用句柄。关键点在于:谁先死,另一个就拉响警报并尝试复活对方。
- watchdog 进程持续调用
OpenProcess检查主进程是否存在,若GetExitCodeProcess返回STILL_ACTIVE异常(比如句柄无效),说明主进程已被强杀或崩溃 - 主进程同样用
OpenProcess反向检查 watchdog 进程;一旦发现 watchdog 失联,立即调用CreateProcess重启它(注意传入完整路径,避免路径劫持) - 双方都设置
CREATE_NO_WINDOW和DETACHED_PROCESS,防止窗口暴露或控制台依赖
防挂起的关键:别让 watchdog 进程能被轻易枚举和操作
逆向者常靠 EnumProcesses + OpenProcess 找到 watchdog 并下手。要增加干扰成本:
- watchdog 进程名不要硬编码为
"watchdog.exe",改用无意义字符串(如"svchostmgr.exe"),但需确保主进程启动时用真实路径 + 参数传递,避免误启系统同名进程 - 启动 watchdog 后,主进程立即调用
CloseHandle关闭其PROCESS_INFORMATION.hProcess和.hThread,断开自身对它的句柄引用——这样即使主进程被 dump,也拿不到 watchdog 的有效句柄 - watchdog 进程自身调用
SetThreadPriority设为THREAD_PRIORITY_HIGHEST(非必需但可提升响应及时性),并避免任何 Sleep(0) 或长时间阻塞,防止被调度器“忽略”
实际部署时最容易被绕过的三个细节
很多实现卡在最后一步:看似双进程,实则一戳就穿。
- 没校验签名或完整性:攻击者直接替换 watchdog.exe 文件。应在主进程中用
WinVerifyTrust校验 watchdog 文件的代码签名,失败则拒绝启动 - IPC 同步对象未设安全描述符:
CreateEvent或CreateMutex默认允许任意进程 open,攻击者可提前创建同名对象抢占。必须传入自定义SECURITY_ATTRIBUTES,限制仅本用户 SID 可访问 - watchdog 进程未隐藏自身窗口句柄:哪怕无窗体,仍可能被
FindWindow或EnumWindows扫出。启动后立即调用ShowWindow(GetConsoleWindow(), SW_HIDE)(如有控制台),并确保不注册任何窗口类
双进程互保不是银弹,它只抬高了直接挂起的门槛。真正难防的是内存 patch 或 DLL 注入后修改进程间通信逻辑——那已进入反调试/反注入范畴,需要更底层的对抗手段。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











