当前位置: 首页 > news >正文

保姆级教程:用C++和Detours库拦截Windows关机,实现你的“防误触”小工具

实战指南用C与Detours打造Windows防误关机工具1. 项目背景与核心思路在日常使用Windows系统时误触关机键导致工作数据丢失的情况屡见不鲜。特别是对于需要长时间运行渲染任务、数据下载或系统维护的专业用户而言意外关机可能意味着数小时甚至数天的努力付诸东流。传统解决方案如修改注册表或组策略存在明显局限——它们只能隐藏关机选项却无法真正阻止程序调用关机API。本项目的核心思路是利用微软官方推荐的Detours库通过API挂钩技术拦截系统关机流程。与简单隐藏界面按钮不同这种方法能在底层阻断关机信号的传递即使有程序直接调用ExitWindowsEx等系统API也能有效拦截。我们将从零开始构建一个完整的解决方案涵盖以下关键技术点Detours库的集成与使用微软官方开发的函数挂钩库稳定支持32/64位系统多版本Windows适配针对Win7/Win10等不同系统的关机机制差异处理权限提升与UAC绕过确保工具在标准用户权限下也能可靠运行系统稳定性保障避免因挂钩系统API导致的资源泄漏或系统崩溃// 基础挂钩示例拦截ExitWindowsEx typedef BOOL(WINAPI* OriginalExitWindowsEx)(UINT, DWORD); OriginalExitWindowsEx TrueExitWindowsEx NULL; BOOL WINAPI HookedExitWindowsEx(UINT uFlags, DWORD dwReason) { MessageBoxW(NULL, L关机操作已被拦截, L防误触保护, MB_ICONWARNING); return FALSE; // 返回FALSE表示阻止关机 }2. 开发环境准备与项目配置2.1 工具链选择工欲善其事必先利其器。我们需要准备以下开发环境Visual Studio 2022推荐使用Community版完全免费且功能完整Windows SDK确保安装最新版本的Windows SDK当前为10.0.22621.0Detours库从微软官方GitHub仓库获取最新版本建议4.0.1以上提示Detours Express版对非商业用途免费但功能完整。若需要商业使用需购买专业版授权。2.2 项目配置关键步骤创建新的C控制台应用程序项目配置项目属性平台工具集Visual Studio 2022 (v143)C语言标准ISO C17标准 (/std:c17)添加Detours库引用# 使用vcpkg安装Detours推荐 vcpkg install detours:x64-windows配置附加包含目录和库目录配置项路径示例包含目录$(VCPKG_ROOT)\installed\x64-windows\include库目录$(VCPKG_ROOT)\installed\x64-windows\lib2.3 基础代码框架建立项目的基本结构包含以下核心文件AntiShutdown/ ├── AntiShutdown.cpp # 主程序入口 ├── HookManager.h # 挂钩管理类 ├── Utils.cpp # 辅助功能函数 └── resource.h # 资源定义3. 核心拦截机制实现3.1 多层级API拦截策略现代Windows系统关机流程涉及多个关键API我们需要建立分层防御用户界面层拦截WM_QUERYENDSESSION消息系统调用层挂钩ExitWindowsEx和InitiateShutdown内核通信层监控NtShutdownSystem调用// 多API拦截示例 void InstallAllHooks() { HMODULE hUser32 GetModuleHandle(Luser32.dll); HMODULE hAdvapi32 GetModuleHandle(Ladvapi32.dll); // 挂钩用户态API DetourAttach((PVOID)TrueExitWindowsEx, GetProcAddress(hUser32, ExitWindowsEx)); DetourAttach((PVOID)TrueInitiateShutdown, GetProcAddress(hAdvapi32, InitiateShutdownW)); // 挂钩未公开API需要特殊处理 PVOID pNtShutdown GetProcAddress(GetModuleHandle(Lntdll.dll), NtShutdownSystem); if(pNtShutdown) { DetourAttach((PVOID)TrueNtShutdown, pNtShutdown); } }3.2 64位系统特别处理64位Windows引入了WOW64子系统需要特别注意函数调用约定差异x64使用fastcall而非stdcall指针大小变化所有指针类型变为8字节异常处理变化SEH机制有显著不同// 64位兼容性处理 #ifdef _WIN64 #define HOOK_JUMP_SIZE 14 // x64长跳转需要14字节 #else #define HOOK_JUMP_SIZE 5 // x86近跳转5字节 #endif void* AllocateTrampoline(PVOID pTarget) { // 为跳板函数分配可执行内存 return VirtualAlloc(NULL, HOOK_JUMP_SIZE 32, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); }3.3 权限与UAC处理即使以管理员身份运行某些操作仍需更高权限bool EnableShutdownPrivilege() { HANDLE hToken; if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken)) { return false; } TOKEN_PRIVILEGES tkp; tkp.PrivilegeCount 1; LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, tkp.Privileges[0].Luid); tkp.Privileges[0].Attributes SE_PRIVILEGE_ENABLED; bool result AdjustTokenPrivileges(hToken, FALSE, tkp, 0, NULL, 0); CloseHandle(hToken); return result; }4. 用户界面与交互设计4.1 系统托盘集成专业的后台工具应该提供非侵入式的系统托盘界面NOTIFYICONDATA nid { sizeof(nid) }; nid.hWnd hWnd; nid.uFlags NIF_ICON | NIF_TIP | NIF_MESSAGE; nid.uCallbackMessage WM_APP 1; nid.hIcon LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); wcscpy_s(nid.szTip, L防误关机保护已激活); Shell_NotifyIcon(NIM_ADD, nid);4.2 配置界面实现使用Win32 API创建简洁的配置对话框控件类型功能变量名CheckBox启用保护chkEnableComboBox保护级别cmbLevelEdit白名单进程edtWhitelistButton保存配置btnSave// 对话框过程示例 INT_PTR CALLBACK ConfigDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_INITDIALOG: CheckDlgButton(hDlg, IDC_CHK_ENABLE, g_config.bEnabled ? BST_CHECKED : BST_UNCHECKED); return TRUE; case WM_COMMAND: if(LOWORD(wParam) IDC_BTN_SAVE) { g_config.bEnabled IsDlgButtonChecked(hDlg, IDC_CHK_ENABLE) BST_CHECKED; EndDialog(hDlg, IDOK); } break; } return FALSE; }5. 高级功能实现5.1 进程白名单机制允许特定关键进程触发关机如系统更新程序std::vectorstd::wstring whitelist { Ltrustedinstaller.exe, Lwuauclt.exe, Lmsiexec.exe }; bool IsProcessWhitelisted(DWORD pid) { HANDLE hProcess OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); if(!hProcess) return false; WCHAR exePath[MAX_PATH] {0}; DWORD size MAX_PATH; QueryFullProcessImageNameW(hProcess, 0, exePath, size); CloseHandle(hProcess); std::wstring fileName exePath; fileName fileName.substr(fileName.find_last_of(L\\) 1); return std::find(whitelist.begin(), whitelist.end(), ToLower(fileName)) ! whitelist.end(); }5.2 智能休眠模式当检测到特定条件时自动转为休眠而非关机void HandleSmartHibernate() { SYSTEM_POWER_STATUS status; if(GetSystemPowerStatus(status) status.BatteryLifePercent 15) { SetSuspendState(TRUE, FALSE, FALSE); } else { // 正常关机流程 } }5.3 日志记录系统记录所有关机尝试以便后续分析void LogShutdownAttempt(DWORD pid, const std::wstring processName) { SYSTEMTIME st; GetLocalTime(st); std::wofstream logFile(LShutdownLog.txt, std::ios::app); logFile std::setw(2) st.wMonth L/ st.wDay L st.wHour L: st.wMinute L - 阻止来自 processName L(PID: pid L)的关机请求 std::endl; }6. 打包与部署方案6.1 安装程序制作使用WiX工具集创建专业的MSI安装包Wix xmlnshttp://schemas.microsoft.com/wix/2006/wi Product Id* Name防误关机工具 Language2052 Version1.0.0 ManufacturerYourCompany Package InstallerVersion200 Compressedyes/ Feature IdMainFeature Title主程序 Level1 ComponentRef IdMainEXE/ ComponentRef IdShortcutDesktop/ /Feature /Product Directory IdTARGETDIR NameSourceDir Directory IdProgramFilesFolder Directory IdINSTALLFOLDER NameAntiShutdown/ /Directory /Directory /Wix6.2 自动启动配置通过注册表实现开机自启void SetAutoStart(bool enable) { HKEY hKey; RegCreateKeyEx(HKEY_CURRENT_USER, LSoftware\\Microsoft\\Windows\\CurrentVersion\\Run, 0, NULL, 0, KEY_WRITE, NULL, hKey, NULL); if(enable) { WCHAR path[MAX_PATH]; GetModuleFileName(NULL, path, MAX_PATH); RegSetValueEx(hKey, LAntiShutdown, 0, REG_SZ, (BYTE*)path, (wcslen(path)1)*sizeof(WCHAR)); } else { RegDeleteValue(hKey, LAntiShutdown); } RegCloseKey(hKey); }7. 实际测试与性能优化7.1 测试用例设计全面的测试方案确保工具可靠性测试场景预期结果测试方法开始菜单关机被拦截点击开始→电源→关机AltF4关机被拦截桌面按AltF4选择关机命令行关机被拦截运行shutdown /s /t 0电源按钮被拦截按下机箱电源按钮(需BIOS支持)白名单进程允许关机系统更新程序发起的关机7.2 性能影响评估使用ETW(Event Tracing for Windows)监测挂钩引入的开销// 性能监测代码示例 void StartPerformanceTrace() { EVENT_TRACE_PROPERTIES props {0}; props.Wnode.BufferSize sizeof(props); props.Wnode.Flags WNODE_FLAG_TRACED_GUID; props.LogFileMode EVENT_TRACE_REAL_TIME_MODE; props.LoggerNameOffset sizeof(props); StartTrace(hTrace, LAntiShutdownPerf, props); }测试数据显示API挂钩带来的性能影响可以忽略不计0.1% CPU占用率。8. 进阶开发方向对于有更高需求的开发者可以考虑以下扩展驱动级保护通过WDF开发内核驱动实现更深层次的保护远程管理添加HTTP接口实现局域网内的远程状态监控云同步将配置和日志同步到云端实现多设备统一管理机器学习分析用户行为模式智能调整保护策略// 简单的HTTP服务器示例基于cpp-httplib void StartWebServer() { httplib::Server svr; svr.Get(/status, [](const httplib::Request, httplib::Response res) { res.set_content(IsProtectionActive() ? active : inactive, text/plain); }); svr.listen(0.0.0.0, 8080); }在开发过程中我遇到最棘手的问题是Win10 21H2版本后微软引入了新的关机流程导致传统挂钩方法失效。经过反复测试最终通过组合使用SetWindowsHookEx和WH_CALLWNDPROC钩子解决了这个问题。这也提醒我们系统工具开发必须紧跟Windows版本更新持续维护才能保证兼容性。
http://www.gsyq.cn/news/1327887.html

相关文章:

  • 做Java的都在看!Erupt 让老系统 AI 改造省到离谱
  • RTX51 Tiny中断冲突与寄存器组配置解决方案
  • iOS照片去背景怎么操作?2026苹果手机去背景方法实测
  • 2026阿里市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一修哥修缮
  • 欧盟 CRA 认证完整流程:从自评到上市全步骤
  • 若依(Ruoyi)项目实战:5分钟搞定导航栏消息铃铛(轮询版,含内存泄漏避坑)
  • 2026滨州市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一修哥修缮
  • 5分钟极速汉化:Android Studio中文语言包的零门槛安装方案
  • 别再硬算轨道了!手把手教你用STK的Target Sequence模块,30分钟搞定卫星过顶目标点
  • 使用 Taotoken 聚合平台后我的 API 调用延迟与稳定性体感观察
  • IPXWrapper:在Windows 11上玩转经典游戏的终极指南
  • CANopen设备配置不求人:手把手教你用EDS/DCF文件玩转对象字典
  • 杭州医疗级月子中心技术解析:花生安妮宝贝核心优势拆解 - 奔跑123
  • 3种架构方案实现抖音无水印视频下载:从脚本到桌面应用的技术演进
  • 5步掌握智慧树自动刷课神器:Autovisor解放你的学习时间
  • 甘肃摩托车驾照培训怎么选?奔马・新通力驾培优势详解 - 深度智识库
  • 3步搞定软件著作权:Flutter桌面应用实现智能代码文档生成
  • 别再死记硬背公式了!用VHDL和Quartus II手把手教你玩转一位全加器(附完整源码与仿真)
  • Cisco IOS XRv 9000 Router 26.1.1 - 服务提供商边缘虚拟路由器
  • 微信小程序 Vue3基于springboot框架的农事管理系 农业技术知识科普系统
  • Code_Copyright_Gen:Flutter实现的智能软著代码文档生成器终极实战指南
  • 养宠家庭选孟加拉豹猫幼猫:2026最新靠谱猫舍的筛选指南 - 奔跑123
  • Perplexity搜索延迟突增2.8秒的真相:不是网络,不是缓存——而是其自研Query Ambiguity Score计算瓶颈(附压测火焰图与绕行方案)
  • 国产工控机替代实战:从性能、成本到选型,核心场景落地指南
  • 无图像MRI诊断技术:低成本医疗影像新突破
  • 网络安全入门:用Ettercap给你的家庭路由器做个“体检”,看看你的Wi-Fi到底安不安全
  • MATLAB曲线拟合工具箱保姆级教程:从散点图到SOC-EMF八阶多项式拟合(附完整代码)
  • 保姆级教程:用SolidWorks 2018插件为遨博E5机械臂一键生成ROS URDF包(附避坑点)
  • 天津二手名表回收真相测评:2026五大回收平台实力排行 - 奢侈品回收测评
  • AMD Ryzen性能调优终极指南:SMUDebugTool完全掌控你的处理器