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

深入Winlogon:用C++和Detours库拦截Windows关机/重启的实战教程(含完整项目代码)

深入Winlogon:用C++和Detours库拦截Windows关机/重启的实战教程(含完整项目代码)

在Windows系统开发领域,掌握底层API拦截技术是进阶开发者的必备技能。本文将带领您从零开始构建一个完整的关机拦截工具,通过Detours库实现对ExitWindowsExInitiateShutdownW等关键API的挂钩,并提供可直接编译的Visual Studio项目代码。

1. Windows关机机制深度解析

Windows系统的关机流程是一个复杂的多进程协作过程。当用户触发关机操作时,系统会经历以下关键阶段:

  1. 用户界面层:Explorer.exe接收用户操作
  2. 会话管理层:Winlogon.exe协调关机流程
  3. 系统服务层:Wininit.exe执行最终关机操作

关键API调用链

// 用户层调用 ExitWindowsEx(dwFlags, dwReason); // 系统层调用 InitiateShutdownW(lpMachineName, lpMessage, dwGracePeriod, dwShutdownFlags, dwReason); // 内核层调用 NtShutdownSystem(dwAction);

不同Windows版本对关机流程的实现有显著差异:

Windows版本主要关机API会话隔离机制
Win7及之前ExitWindowsExSession 0隔离
Win8/8.1InitiateShutdownW增强型会话隔离
Win10/11RPC调用组合PPL进程保护

2. Detours库实战环境搭建

2.1 开发环境配置

  1. 安装Visual Studio 2019/2022(需勾选C++桌面开发组件)
  2. 通过NuGet安装Detours库:
Install-Package Detours -Version 4.0.1
  1. 创建Win32控制台应用程序项目,配置项目属性:
// 预处理器定义 WIN32_LEAN_AND_MEAN // 附加包含目录 $(SolutionDir)packages\Microsoft.Detours.4.0.1\lib\native\include // 附加库目录 $(SolutionDir)packages\Microsoft.Detours.4.0.1\lib\native\lib\x86

2.2 基础挂钩框架搭建

构建一个基本的DLL注入项目结构:

ShutdownInterceptor/ ├── ShutdownHook/ │ ├── ShutdownHook.cpp // 主挂钩逻辑 │ ├── ShutdownHook.def // 模块定义文件 │ └── ShutdownHook.vcxproj ├── Injector/ │ ├── Injector.cpp // DLL注入器 │ └── Injector.vcxproj └── ShutdownInterceptor.sln

关键代码结构

// 原始函数指针定义 typedef BOOL(WINAPI* TrueExitWindowsEx)(UINT, DWORD); // 钩子函数声明 BOOL WINAPI HookedExitWindowsEx(UINT uFlags, DWORD dwReason); // Detours事务管理 void StartHook(); void RemoveHook();

3. 核心API挂钩实现

3.1 ExitWindowsEx挂钩实现

针对Windows 7及以下系统的关键拦截代码:

BOOL WINAPI HookedExitWindowsEx(UINT uFlags, DWORD dwReason) { // 解析关机类型 const wchar_t* operation = L"未知操作"; switch(uFlags) { case EWX_LOGOFF: operation = L"注销"; break; case EWX_SHUTDOWN: operation = L"关机"; break; case EWX_REBOOT: operation = L"重启"; break; } // 显示拦截提示 MessageBoxW(NULL, L"系统关机操作已被拦截\n请保存工作后重试", L"关机拦截提示", MB_ICONWARNING | MB_OK); // 返回FALSE表示阻止关机 SetLastError(ERROR_CANCELLED); return FALSE; }

3.2 InitiateShutdownW挂钩实现

针对Windows 8/8.1系统的增强型拦截:

DWORD WINAPI HookedInitiateShutdownW( LPWSTR lpMachineName, LPWSTR lpMessage, DWORD dwGracePeriod, DWORD dwShutdownFlags, DWORD dwReason) { // 创建拦截日志 LogEvent(L"拦截到系统关机请求,标志位: 0x%X", dwShutdownFlags); // 终止LogonUI进程防止关机界面卡住 TerminateProcessByName(L"LogonUI.exe"); return ERROR_OPERATION_ABORTED; }

3.3 跨会话UI显示技术

由于Winlogon运行在Session 0隔离环境,常规MessageBox无法显示。需要使用WTSSendMessage实现跨会话弹窗:

void ShowSessionMessage(DWORD sessionId, const wchar_t* title, const wchar_t* message) { DWORD response; WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, sessionId, title, wcslen(title)*2, message, wcslen(message)*2, MB_ICONWARNING | MB_OK, 0, &response, TRUE); }

4. 高级技巧与系统适配

4.1 Windows版本检测与适配

enum WindowsVersion { WIN_UNSUPPORTED, WIN_7, WIN_8, WIN_10, WIN_11 }; WindowsVersion GetWindowsVersion() { OSVERSIONINFOEX osvi = { sizeof(OSVERSIONINFOEX) }; GetVersionEx((OSVERSIONINFO*)&osvi); if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) return WIN_7; if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) return WIN_8; if (osvi.dwMajorVersion == 10 && osvi.dwBuildNumber < 22000) return WIN_10; if (osvi.dwMajorVersion == 10 && osvi.dwBuildNumber >= 22000) return WIN_11; return WIN_UNSUPPORTED; }

4.2 PPL绕过技术(Win10/11)

对于受保护的Wininit进程,需要特殊处理:

bool BypassPPL(DWORD pid) { // 加载PPLKiller驱动 if (!LoadDriver("PPLKiller.sys")) { LogEvent(L"驱动加载失败"); return false; } // 通过IOCTL与驱动通信 HANDLE hDevice = CreateFile(L"\\\\.\\PPLKiller", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDevice == INVALID_HANDLE_VALUE) { LogEvent(L"设备打开失败: %d", GetLastError()); return false; } DWORD bytesReturned; PPL_KILL_REQUEST request = { pid }; DeviceIoControl(hDevice, IOCTL_PPL_KILL, &request, sizeof(request), NULL, 0, &bytesReturned, NULL); CloseHandle(hDevice); return true; }

5. 完整项目代码结构

项目包含以下关键组件:

  1. 核心挂钩模块

    • API拦截实现
    • 错误处理机制
    • 日志记录系统
  2. 注入器工具

    • 进程注入功能
    • 权限提升处理
    • 命令行接口
  3. 测试应用程序

    • 模拟关机操作
    • 验证拦截效果
    • 系统兼容性测试

关键代码文件说明

文件功能
ShutdownHook.cpp主挂钩逻辑实现
Injector.cppDLL注入工具实现
SessionUtils.cpp会话管理相关功能
PPLBypass.cppPPL绕过实现
ShutdownInterceptor.slnVisual Studio解决方案文件

6. 实战调试技巧

6.1 调试挂钩DLL

  1. 使用DebugView捕获内核模式输出
  2. 配置Visual Studio远程调试
  3. 使用Process Explorer验证DLL注入

6.2 常见问题解决

问题1:挂钩后系统不稳定

解决方案:确保在Detours事务中正确处理线程状态

问题2:拦截无效

检查目标进程是否正确注入,使用API Monitor验证调用

问题3:跨会话UI不显示

确认WTSSendMessage调用参数正确,检查会话ID

7. 安全与稳定性考量

  1. 错误处理最佳实践
void SafeHookOperation() { __try { // 敏感操作代码 StartHook(); } __except(EXCEPTION_EXECUTE_HANDLER) { LogEvent(L"挂钩操作异常: 0x%X", GetExceptionCode()); } }
  1. 资源清理规范

    • 确保所有句柄正确关闭
    • 在DLL_PROCESS_DETACH中移除挂钩
    • 释放分配的临时内存
  2. 系统兼容性检查表

检查项Win7Win10Win11
ExitWindowsEx挂钩
InitiateShutdownW挂钩
PPL绕过不需要需要需要
会话隔离增强增强

(✓完全支持 △部分支持 ✗不支持)

8. 扩展应用场景

基于本技术的衍生应用:

  1. 企业数据保护:防止员工意外关机导致数据丢失
  2. 工业控制系统:确保关键操作完成前不中断
  3. 安全软件:拦截恶意关机行为
  4. 自动化测试:模拟各种关机场景

性能优化建议

  • 最小化挂钩函数中的操作
  • 避免在挂钩中调用可能被挂钩的API
  • 使用异步方式处理复杂逻辑

9. 完整代码示例

以下是关键挂钩实现的完整代码片段:

// ShutdownHook.h #pragma once #include <windows.h> #include <detours.h> typedef BOOL(WINAPI* TrueExitWindowsEx)(UINT, DWORD); typedef DWORD(WINAPI* TrueInitiateShutdownW)(LPWSTR, LPWSTR, DWORD, DWORD, DWORD); extern TrueExitWindowsEx OriginalExitWindowsEx; extern TrueInitiateShutdownW OriginalInitiateShutdownW; BOOL WINAPI HookedExitWindowsEx(UINT uFlags, DWORD dwReason); DWORD WINAPI HookedInitiateShutdownW(LPWSTR lpMachineName, LPWSTR lpMessage, DWORD dwGracePeriod, DWORD dwShutdownFlags, DWORD dwReason); void InstallHooks(); void RemoveHooks();
// ShutdownHook.cpp #include "ShutdownHook.h" #include <WtsApi32.h> #pragma comment(lib, "WtsApi32.lib") TrueExitWindowsEx OriginalExitWindowsEx = nullptr; TrueInitiateShutdownW OriginalInitiateShutdownW = nullptr; BOOL WINAPI HookedExitWindowsEx(UINT uFlags, DWORD dwReason) { // 详细实现参考前文 return FALSE; } DWORD WINAPI HookedInitiateShutdownW(LPWSTR lpMachineName, LPWSTR lpMessage, DWORD dwGracePeriod, DWORD dwShutdownFlags, DWORD dwReason) { // 详细实现参考前文 return ERROR_OPERATION_ABORTED; } void InstallHooks() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); OriginalExitWindowsEx = (TrueExitWindowsEx)DetourFindFunction("user32.dll", "ExitWindowsEx"); OriginalInitiateShutdownW = (TrueInitiateShutdownW)DetourFindFunction("advapi32.dll", "InitiateShutdownW"); DetourAttach(&(PVOID&)OriginalExitWindowsEx, HookedExitWindowsEx); DetourAttach(&(PVOID&)OriginalInitiateShutdownW, HookedInitiateShutdownW); DetourTransactionCommit(); } void RemoveHooks() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)OriginalExitWindowsEx, HookedExitWindowsEx); DetourDetach(&(PVOID&)OriginalInitiateShutdownW, HookedInitiateShutdownW); DetourTransactionCommit(); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: InstallHooks(); break; case DLL_PROCESS_DETACH: RemoveHooks(); break; } return TRUE; }

10. 进阶开发建议

  1. 多层级拦截策略

    • 用户模式API挂钩
    • 内核模式过滤驱动
    • RPC调用拦截
  2. 智能拦截逻辑

bool ShouldBlockShutdown() { // 检查关键进程是否运行 if (IsProcessRunning(L"important_app.exe")) { return true; } // 检查网络传输状态 if (IsNetworkTransferActive()) { return true; } // 检查系统负载 if (GetSystemLoad() > 0.8) { return true; } return false; }
  1. 配置化管理
    • XML/JSON规则配置
    • 动态规则加载
    • 远程管理接口

在实际项目中,我们发现Windows 10 1809版本后对PPL的保护更加严格,需要结合多个技术点才能实现稳定拦截。建议开发者针对不同Windows版本编译不同的二进制,并在运行时动态选择挂钩策略。

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

相关文章:

  • Evident方法论:用观察、假设、测试构建可复现的数据科学工作流
  • 开屏广告变现平台排行:APP广告收益提升、APP广告素材合规、APP想接入广告、APP流量变现、SDK变现、开屏广告变现选择指南 - 优质品牌商家
  • STR9微控制器Flash编程方法与实践指南
  • 告别调参噩梦!用Ball k-means在Python里5分钟搞定百万级数据聚类
  • 多中心医学影像机器学习中ComBat数据协调的数据泄漏陷阱与解决方案
  • 荒野搜救无人机图像采集优化:提升CV/ML应用效能的五条核心原则
  • 【2026年阿里巴巴集团暑期实习- 5月23日-算法岗-第二题- 多约束条件下的元素匹配统计】(题目+思路+JavaC++Python解析+在线测试)
  • Windows/Mac/Linux全平台指南:永久设置HF_ENDPOINT加速镜像,告别HuggingFace下载超时
  • 2026年APP流量变现平台排行:开源广告SDK、微信小程序广告、聚合SDK广告、聚合广告联盟、APP变现、APP商业化变现选择指南 - 优质品牌商家
  • SQLMap HTTPS注入失败原因与Burp代理链路解析
  • 离散元法与机器学习融合优化催化剂连续浸渍工艺
  • 强化学习实战:用Python手搓Sarsa和Q-Learning,在悬崖漫步里看谁更“怂”
  • 用 Matrix Synapse 和 Element 搭建私有聊天服务器
  • 【2026年阿里巴巴集团暑期实习- 5月23日-算法岗-第三题- 寻找满足条件的最优子序列】(题目+思路+JavaC++Python解析+在线测试)
  • AI社交对话设计:如何避免商业场景中的期望违背与尴尬感
  • AI赋能公立高校:四大核心场景降本增效实践与挑战
  • ArcGIS新手别怕!用Union和字段计算器,5步搞定土地利用变化图斑分析
  • 对比直接使用原厂API体验Taotoken在路由容灾与稳定性上的差异
  • SqueezeBERT:用分组卷积思想加速Transformer,实现移动端4.3倍推理提速
  • 统计学习理论:从VC维到泛化误差,构建稳健CV系统的数学基石
  • 别再傻等下载了!手把手教你用wget离线部署sentence-transformers模型(以all-MiniLM-L6-v2为例)
  • 别再傻傻分不清了!TP53、7157、ENSG00000141510... 一文搞懂基因ID转换(附R代码与g:Profiler保姆级教程)
  • 告别ggrcs直方图!用singlercs函数为你的线性回归RCS曲线“瘦身美颜”
  • 人机协作视觉系统自适应:基准测试与概念漂移应对实战
  • 为什么92%的AI Agent项目卡在POC阶段?揭秘头部银行、药企、电网的6个月规模化上线方法论
  • 别再乱试了!这些看似“整蛊”的Windows批处理命令,分分钟让你的电脑报废
  • 从/dev/snd文件看起:手把手教你理解Linux ALSA声卡驱动的设备命名规则
  • 2026年评价高的谐波减速机/ATG减速机高口碑品牌推荐 - 品牌宣传支持者
  • 低代码Agent平台是怎样实现自动化流程编排的?深度拆解2026企业级智能体底层架构
  • 从‘盲人摸象’到‘心中有尺’:聊聊DOA估计里那个绕不开的CRLB到底怎么用