当前位置: 首页 > 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.0)
  • Detours库:从微软官方GitHub仓库获取最新版本(建议4.0.1以上)

提示:Detours Express版对非商业用途免费,但功能完整。若需要商业使用,需购买专业版授权。

2.2 项目配置关键步骤

  1. 创建新的C++控制台应用程序项目
  2. 配置项目属性:
    • 平台工具集:Visual Studio 2022 (v143)
    • C++语言标准:ISO C++17标准 (/std:c++17)
  3. 添加Detours库引用:
# 使用vcpkg安装Detours(推荐) vcpkg install detours:x64-windows
  1. 配置附加包含目录和库目录:
配置项路径示例
包含目录$(VCPKG_ROOT)\installed\x64-windows\include
库目录$(VCPKG_ROOT)\installed\x64-windows\lib

2.3 基础代码框架

建立项目的基本结构,包含以下核心文件:

AntiShutdown/ ├── AntiShutdown.cpp # 主程序入口 ├── HookManager.h # 挂钩管理类 ├── Utils.cpp # 辅助功能函数 └── resource.h # 资源定义

3. 核心拦截机制实现

3.1 多层级API拦截策略

现代Windows系统关机流程涉及多个关键API,我们需要建立分层防御:

  1. 用户界面层:拦截WM_QUERYENDSESSION消息
  2. 系统调用层:挂钩ExitWindowsExInitiateShutdown
  3. 内核通信层:监控NtShutdownSystem调用
// 多API拦截示例 void InstallAllHooks() { HMODULE hUser32 = GetModuleHandle(L"user32.dll"); HMODULE hAdvapi32 = GetModuleHandle(L"advapi32.dll"); // 挂钩用户态API DetourAttach(&(PVOID&)TrueExitWindowsEx, GetProcAddress(hUser32, "ExitWindowsEx")); DetourAttach(&(PVOID&)TrueInitiateShutdown, GetProcAddress(hAdvapi32, "InitiateShutdownW")); // 挂钩未公开API需要特殊处理 PVOID pNtShutdown = GetProcAddress(GetModuleHandle(L"ntdll.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启用保护chkEnable
ComboBox保护级别cmbLevel
Edit白名单进程edtWhitelist
Button保存配置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::vector<std::wstring> whitelist = { L"trustedinstaller.exe", L"wuauclt.exe", L"msiexec.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(L"ShutdownLog.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 xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Product Id="*" Name="防误关机工具" Language="2052" Version="1.0.0" Manufacturer="YourCompany"> <Package InstallerVersion="200" Compressed="yes"/> <Feature Id="MainFeature" Title="主程序" Level="1"> <ComponentRef Id="MainEXE"/> <ComponentRef Id="ShortcutDesktop"/> </Feature> </Product> <Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="ProgramFilesFolder"> <Directory Id="INSTALLFOLDER" Name="AntiShutdown"/> </Directory> </Directory> </Wix>

6.2 自动启动配置

通过注册表实现开机自启:

void SetAutoStart(bool enable) { HKEY hKey; RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\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, L"AntiShutdown", 0, REG_SZ, (BYTE*)path, (wcslen(path)+1)*sizeof(WCHAR)); } else { RegDeleteValue(hKey, L"AntiShutdown"); } RegCloseKey(hKey); }

7. 实际测试与性能优化

7.1 测试用例设计

全面的测试方案确保工具可靠性:

测试场景预期结果测试方法
开始菜单关机被拦截点击开始→电源→关机
Alt+F4关机被拦截桌面按Alt+F4选择关机
命令行关机被拦截运行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, L"AntiShutdownPerf", &props); }

测试数据显示,API挂钩带来的性能影响可以忽略不计(<0.1% CPU占用率)。

8. 进阶开发方向

对于有更高需求的开发者,可以考虑以下扩展:

  1. 驱动级保护:通过WDF开发内核驱动实现更深层次的保护
  2. 远程管理:添加HTTP接口实现局域网内的远程状态监控
  3. 云同步:将配置和日志同步到云端实现多设备统一管理
  4. 机器学习:分析用户行为模式智能调整保护策略
// 简单的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版本后微软引入了新的关机流程,导致传统挂钩方法失效。经过反复测试,最终通过组合使用SetWindowsHookExWH_CALLWNDPROC钩子解决了这个问题。这也提醒我们,系统工具开发必须紧跟Windows版本更新,持续维护才能保证兼容性。

http://www.jsqmd.com/news/850788/

相关文章:

  • ThinkPad双风扇终极控制:TPFanControl2完全使用指南
  • 武汉新鹏源环保工程:硚口有实力的油烟管道安装公司 - LYL仔仔
  • 从CPU视角看Cache:深入理解Offset、Index、Tag如何协同工作提升程序性能
  • 分期乐购物额度变现最全指南,详细教程一看就会! - 团团收购物卡回收
  • 哈工大NLP期末考后复盘:从HMM到Transformer,这些知识点你掌握了吗?
  • 2026保山市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一修哥修缮
  • BBDown终极指南:高效下载B站视频的专业工具
  • 从‘失效’到‘复活’:深入剖析空间平滑MUSIC算法在雷达/声呐DOA估计中的实战应用
  • 5分钟快速上手:VideoDownloadHelper视频下载助手完整教程
  • 技术驱动商业重构:追觅16万转高速马达如何跨界降维,引爆传统赛道?
  • 手把手教你用Spark MLlib实现电影推荐系统(基于物品/用户协同过滤)
  • 2026 成都手表回收门店推荐:上门鉴定,实体老店名列前茅 - 奢侈品回收测评
  • 1000元携程礼品卡回收能换多少钱 - 购物卡回收找京尔回收
  • 量子同态加密技术:BNSF与MLWE的核心原理与应用
  • P3543 POI 2012 WYR-Leveling Ground Sol
  • 5分钟打造专属AI歌手:Retrieval-based-Voice-Conversion-WebUI语音克隆完整指南
  • 2026白山市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一修哥修缮
  • 2026 郑州装修公司口碑 TOP5 权威榜单(附核心优势与避坑指南) - 速递信息
  • 采购高低温交变试验箱前必看:如何判断厂家的综合实力? - 品牌推荐大师1
  • 保姆级教程:用国内镜像源5分钟搞定Spacy和en_core_web_lg模型下载安装
  • 别再死记硬背公式了!用Python和PyTorch手把手拆解Diffusion Model的前向加噪与反向去噪
  • 2026毕节市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一修哥修缮
  • 2026霸州市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一修哥修缮
  • 长期使用Taotoken的Token Plan套餐带来的月度成本节省感受
  • 从MIT-BIH到CPSC-2018:手把手教你用Python预处理不同格式的ECG公开数据
  • 五金冲压件厂家技术甄别:从工艺到交付的硬核参考 - 奔跑123
  • 【审计专栏-监督监管】【信息科学与工程学】计算机科学与自动化——第一百五十篇 招投标领域中的应用数学05
  • 做Java的都在看!Erupt 让老系统 AI 改造省到离谱
  • iOS照片去背景怎么操作?2026苹果手机去背景方法实测
  • 2026阿里市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一修哥修缮