在门店运维中,电脑频繁出现弹窗、卡死或被小游戏占用是常见问题。这些异常通常由病毒、恶意驱动或流氓软件导致。常规做法是通过TeamViewer、向日葵等远程工具手动清理,但门店需要安装远程软件并提供连接码,沟通成本高,且无法主动发现异常。本文结合古茗技术团队的实际经验,分享一套从远程控制到自动监控、再到主动拦截的Windows管控方案,涉及注册表扫描、IObit Unlocker强删、AppLocker策略、MinHook API挂钩以及SSDT Hook等核心技术。
一、一键远程:摆脱门店配合
传统远程依赖门店提供连接码,效率低下。除了购买企业版远程软件(如TeamViewer批量部署包)或开源方案外,团队自研了一款输入门店编码即可一键远控的小工具。具体实现涉及公司内部接口,但核心思路是:通过云端下发加密凭证,本机后台持续监听远控指令,配合Windows服务自动建立RDP或VNC连接。这可以大幅降低门店操作门槛。
二、被动转主动:监控门店软件列表
为尽早发现异常,需要从注册表拉取已安装程序列表并上报云端。核心代码示例(C#):- public static List<IAppData> getAllSoftWare()
- {
- List<IAppData> appDataList = new List<IAppData>();
- RegistryKey Key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
- if (Key != null)
- {
- foreach (RegistryKey SubKey in Key.GetSubKeyNames())
- {
- // 读取DisplayName,排除SystemComponent为1的项
- string SoftwareName = SubKey.GetValue("DisplayName", "").ToString();
- if (!string.IsNullOrEmpty(SoftwareName) && SubKey.GetValue("SystemComponent", "0").ToString() != "1")
- {
- var data = new IAppData();
- data.DisplayName = SoftwareName;
- // 填充其他字段
- appDataList.Add(data);
- }
- }
- }
- return appDataList;
- }
复制代码 此方法获取的程序列表与控制面板“程序和功能”一致,可识别大多数需要安装的软件。但对于绿色免安装程序,注册表无法扫描。替代方案是监控进程列表(但进程可被隐藏,如SSDT Hook技术)或扫描文件系统并匹配特征码(类似杀毒软件)。团队目前暂未处理免安装场景,因为门店需求主要针对常见安装型流氓软件。
三、自动删除异常软件:IObit Unlocker + 命令行强删
获取软件列表后,若发现已知的恶意软件,需要自动删除。两个障碍:1)进程占用的文件无法直接删除;2)杀毒软件或病毒自身设置了权限保护,阻止删除和注册表修改。
解决方案是使用IObit Unlocker命令行模式强制删除:- runCmd('IObitUnlocker.exe /Delete "文件的绝对路径"')
复制代码 但该命令会弹出确认对话框。为避免用户看到弹窗,可以在启动后立即杀掉IObitUnlocker进程:- if (/*删除成功或超时*/)
- {
- Process[] processes = Process.GetProcessesByName("IObitUnlocker");
- foreach (Process process in processes)
- {
- process.Kill(false);
- }
- }
复制代码 此外,安装IObit Unlocker时也有界面。团队将安装后的目录直接压缩上传云端,再下发解压到门店电脑,跳过安装过程(也可使用/silent参数静默安装但程序会自动启动界面)。此方法可静默解除文件占用并删除。
四、拦截软件安装:从策略组到API Hook
删除了异常软件,门店仍可能重新下载安装。必须从源头拦截。
1. 利用AppLocker策略组
Windows自带的AppLocker可通过gpedit.msc配置规则。支持三种策略:
- 发布者:根据数字签名(仅MSI/MSP文件)
- 路径:拦截指定文件夹或可执行文件,可设置例外
- 文件哈希:根据文件哈希值精确拦截
例如:将整个文件夹设为拒绝执行,再将常用软件(如浏览器、收银程序)路径添加至允许列表。配置后,双击被拦截的文件会弹出系统拒绝访问提示。
也可用PowerShell命令自动化配置:- Import-Module AppLocker
- Get-AppLockerPolicy
- Set-AppLockerPolicy -Policy $policy -Merge
复制代码 缺点:1)提示文字无法自定义,对门店用户不友好;2)Win10/11家庭版默认不开启AppLocker,需通过组策略编辑器手动启用。
2. 使用MinHook实现CreateProcess拦截
更彻底的方案是挂钩Windows API。程序通过CreateProcess创建进程,可HOOK该API,在调用前判断是否放行。使用MinHook库实现(C++):- #include <MinHook.h>
- typedef BOOL(WINAPI* myCreateProcessW)(
- _In_opt_ LPCWSTR lpApplicationName,
- _Inout_opt_ LPWSTR lpCommandLine,
- _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
- _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
- _In_ BOOL bInheritHandles,
- _In_ DWORD dwCreationFlags,
- _In_opt_ LPVOID lpEnvironment,
- _In_opt_ LPCWSTR lpCurrentDirectory,
- _In_ LPSTARTUPINFOW lpStartupInfo,
- _Out_ LPPROCESS_INFORMATION lpProcessInformation
- );
- myCreateProcessW fpCreateProcessW = NULL;
- BOOL WINAPI HookedCreateProcessW(/*参数同上*/)
- {
- if (/*判断需要拦截*/) {
- return TRUE; // 阻止创建
- }
- return fpCreateProcessW(/*原始参数*/);
- }
- BOOL Hook() {
- MH_Initialize();
- MH_CreateHookApiEx(L"kernel32", "CreateProcessW", &HookedCreateProcessW, &fpCreateProcessW);
- MH_EnableHook(MH_ALL_HOOKS);
- return TRUE;
- }
复制代码 此代码编译为DLL,需要全局注入。
DLL全局注入方式:
- 注册表注入:在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows下,将AppInit_DLLs设为DLL路径,LoadAppInit_Dlls设为1。原理:程序加载user32.dll时会加载该注册表指定的DLL。限制:64位电脑只能注入64位进程;少数系统进程无法注入。但explorer.exe、cmd、powershell等主流进程均可注入,可拦截桌面双击和cmd启动的安装程序。
- SetWindowsHookEx:通过消息钩子注入,但32/64位不互通,且只能注入注册了窗口类的程序(Windows Forms可以,WPF不行)。
- SSDT Hook:内核层HOOK NtCreateProcessEx,可实现全局拦截(包括进程内部CreateProcess)。团队未完全实现,但指出杀毒软件常用此技术,可参考“SSDT 进程保护”。
对于门店场景,大部分异常软件来自用户双击安装包(由explorer.exe发起),注册表注入即可覆盖。若想拦截更复杂的链式安装(如A程序调用B程序),需要内核HOOK。
五、拦截浏览器并引导至软件管理
门店常通过浏览器搜索下载软件,容易被误导安装流氓软件。可以拦截浏览器进程,同时提供一个受控的软件安装界面。
拦截方法:
1. 使用WMI事件监听进程创建,检测到浏览器进程即结束。C#示例:- public static void preventBrowser()
- {
- var queryString = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'";
- var query = new EventQuery(queryString);
- using (var watcher = new ManagementEventWatcher(query))
- {
- watcher.EventArrived += OnProcessStarted;
- watcher.Start();
- Console.ReadLine();
- }
- }
- private static void OnProcessStarted(object sender, EventArrivedEventArgs e)
- {
- var process = e.NewEvent.Properties["TargetInstance"].Value as ManagementBaseObject;
- if (process != null)
- {
- // 等待进程信息初始化
- for (int i = 0; i < 60; i++)
- {
- if (process.Properties.Count <= 0) Thread.Sleep(50);
- else break;
- }
- string processName = process["Name"].ToString();
- string processPath = process.Properties["ExecutablePath"]?.Value?.ToString();
- if (isBrowser(processName, processPath, process.Properties["CommandLine"]?.Value?.ToString()))
- {
- try
- {
- int pid = int.Parse(process.Properties["ProcessId"].Value.ToString());
- Process.GetProcessById(pid).Kill();
- }
- catch { }
- }
- }
- }
复制代码 说明:WMI轮询间隔(WITHIN 5)导致5秒延迟,且进程信息初始化有额外等待,因此对快速执行的静默安装可能失效,但手动双击浏览器足够拦截。同时需禁用浏览器的自动更新任务,以免误拦更新进程:- Global.RunCmd("schtasks /change /tn "SogouExplorer Updater Task" /disable");
- Global.RunCmd("reg add "HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Mozilla\\Firefox" /v DisableAppUpdate /t REG_DWORD /d 1 /f");
复制代码
2. 拦截后弹窗引导门店使用内部软件商店,统一下载经过审核的安装包。商店程序通过Simple Process.Start执行安装包,并轮询进程是否存在:- Process process = new Process();
- process.StartInfo.FileName = exePath;
- process.StartInfo.UseShellExecute = false;
- process.Start();
- while (true)
- {
- Thread.Sleep(3000);
- Process[] localByName = Process.GetProcessesByName(exeName);
- if (localByName.Length == 0)
- {
- Log("安装完成 " + exeName);
- break;
- }
- }
复制代码 注意:门店用户可能直接结束商店程序,导致管控失效。可像杀毒软件一样使用SSDT Hook Hook NtTerminateProcess保护自身进程,但团队最终选择更彻底的桌面管控。
六、桌面管控:完全改变用户认知
最根本的解决方案是替换Windows桌面,呈现一套仅包含收银功能的虚拟界面。功能包括:程序快捷方式、网络设置、关机/音量控制等,完全屏蔽开始菜单、任务栏和传统桌面。用户只能操作点单、收银流程,无法安装或运行无关软件。此方案可彻底杜绝误操作,但实现细节较多,团队将在后续文章中分享。
总结
本文从门店电脑频繁中病毒的痛点出发,逐步演进:先通过一键远程提升处理效率,再通过注册表监控发现异常软件,用IObit Unlocker自动删除,利用AppLocker和API Hook拦截软件安装,最后以WMI事件拦截浏览器并引导至官方软件商店。整套方案显著降低异常软件感染率,并增强了对门店收银机的可控性。对于需要类似场景(如公共终端、企业内网)的开发者,这些技术手段有很高的参考价值。 |