基于DKOM的Windows驱动进程隐藏方案详解

发布时间:2026/10/28 9:17:36
基于DKOM的Windows驱动进程隐藏方案详解 简介C进程隐藏与驱动级隐藏的完整工程包面向系统安全分析、恶意软件防御与逆向工程场景帮助中高级开发者理解并复现进程不被任务管理器、进程枚举或驱动扫描发现的实现原理。工程包包含用户态隐藏源码、驱动交互骨架、Visual Studio解决方案、inf驱动配置和编译好的可执行程序支持打开工程直接编译调试配合说明文档与流程示意图可完整梳理从系统钩子安装、注册表项修改到SetProcessPriorityClass等API调用再到驱动层干扰EnumProcesses/OpenProcess枚举的关键环节。全部33个文件以tlog构建日志、vcxproj工程配置、C/C源文件、pdb符号及exe程序为主压缩包仅588KB并保留Win7Debug、x64等目标平台构建内容便于按环境选择参考。目前已有1465人下载学习可借此深入用户态与内核态双重隐藏技术的代码实现对研究反检测思路、开发安全工具或准备相关实验均有实际帮助。1. 用 C 做进程隐藏为什么要以驱动为核心在 Windows 环境下用 C 做进程隐藏常见思路是改任务管理器枚举结果但用户态方案一个重大限制就是不稳定——目标进程一重启就失效权限不够时连注入都做不进去。真正能稳定隐藏进程的做法是走驱动在系统内核层直接操作进程对象链表。这个资源的定位很明确它是一套完整的 C 驱动隐藏进程方案包含驱动源码和应用层管理工具核心作用是让指定进程从任务管理器等依赖系统进程链表枚举的工具中消失但进程本身仍在运行。适合谁用做安全研究、恶意样本行为分析、反外挂对抗验证的同学以及想搞懂 EPROCESS 链和内核对象操作的 C 开发者。普通应用层程序员不建议碰这个它需要你至少了解 Windows 驱动编写的基本流程。这套方案不是把进程杀掉也不是把线程挂起来而是让系统自己都不把它当成一个“活动进程”这才是它作为完结篇的价值所在。2. 先看懂层级用户态与内核态隐藏进程的原理差在哪2.1 用户态隐藏为什么只能算“半吊子”任务是让某个进程从任务管理器里消失。任务管理器枚举进程核心走的是NtQuerySystemInformation这个 API拿到系统进程信息。用户态方案的做法是向目标进程注入 DLLHook 掉这个 API把返回结果里指定进程的记录删掉。听起来简单但坑很多目标进程如果有保护机制注入直接失败即使注入成功Hook 过程自身也可能被检测到进程创建子进程之后子进程又出现在列表里你还要递归去隐藏。更麻烦的是如果你隐藏的是自己DLL 一卸载就露馅保持注入又容易被杀毒软件盯上。这套资源不会选这条路。从标题里的“驱动隐藏进程”也能看出来作者把重心放在内核层。原因很直接内核态做隐藏不是“欺骗”某一层 API而是直接修改内核进程链表本身。这属于底层数据操作稳定性比用户态 Hook 高一个数量级。2.2 内核态隐藏进程的几条路线内核态隐藏进程常见路数有三条SSDT Hook、直接内核对象操作DKOMDirect Kernel Object Manipulation、以及 MiniFilter 文件系统过滤。第三条一般用于隐藏文件隐藏进程不是主场。SSDT Hook 在 x86 下可以把NtQuerySystemInformation的调用结果改掉但 64 位系统有 PatchGuard动 SSDT 表很容易触发蓝屏。剩下最常用的一条就是 DKOM。Windows 内核里每个进程都对应一个EPROCESS结构体里面有一对指针ActiveProcessLinks把所有活动进程串成了一个双向链表。任务管理器枚举进程本质是遍历这个链表。DKOM 的核心思路很简单把目标进程的ActiveProcessLinks节点从链表里解下来系统在遍历时自然就看不到它了。这个操作不涉及函数调用拦截纯数据结构操作干净、直接、稳定。2.3 这套源码走的路径DKOM 断链这个资源包选择的方案就是 DKOM。驱动加载后应用层工具把要隐藏的进程 PID 传给驱动驱动通过PsLookupProcessByProcessId找到目标进程的EPROCESS拿到ActiveProcessLinks节点在自旋锁保护下把节点从链表摘除。恢复时再把节点插回原位置。它的护城河在哪一是不依赖 Windows API 版本系统更新不太容易影响链表结构的基本操作二是隐藏效果覆盖所有调用系统枚举接口的工具。当然边界也要说清楚Process Explorer 这类更底层的工具直接读EPROCESS而不是遍历链表所以对它是藏不住的——这不是源码的问题是隐藏原理本身决定的。3. 把驱动项目跑起来环境搭建与编译步骤3.1 环境准备Visual Studio、WDK 与测试签名这套源码面向 Windows 10/11 x64 环境。应用层工具是 C 写的需要 VC 运行库支持建议直接装 Microsoft Visual C 2015-2022 Redistributable (x64)不然工具起来瞬间报“缺少 VCRUNTIME140.dll”之类的错误。驱动部分需要 Visual Studio 2019 或 2022配套安装 Windows Driver KitWDK。驱动编译前先把测试机强烈建议用虚拟机别拿主力机直接试的驱动签名策略切到测试模式。x64 系统的驱动加载要求签名自编译的驱动没有正式签名必须在测试模式下允许加载bcdedit /set testsigning on执行完重启桌面右下角出现“测试模式”水印就没问题。注意如果机器开启了 Secure Bootbcdedit这步会失败需要先到 BIOS 里关掉 Secure Boot或者干脆用虚拟机并在虚拟机设置里关闭安全启动。这一步算是最容易翻车的地方很多人驱动编译好了死活加载不上回头查基本都是签名问题。3.2 编译入口打开解决方案资源把HideProcess完结篇.zip解压后目录结构大致是这样根目录下有解决方案文件.slnDriver子目录是内核驱动工程Client子目录是应用层 C 管理工具工程。用 Visual Studio 打开.sln在“解决方案配置”里把平台切换到x64两个项目分别右键“生成”。编译顺序上有讲究先编译驱动工程生成.sys文件再编译客户端工程生成.exe。如果直接 F7 全部生成偶尔会遇到客户端工程引用了驱动头文件但路径没配对的情况分开编译反而能更快定位问题。编译完成后x64/Release目录下会有hideproc.sys和HideClient.exe。我一般会先把这两个文件复制到同一个干净目录里隔离出来后面加载和调用都从这个目录走避免路径混乱导致驱动服务指向错误。3.3 加载驱动从创建服务到调用管理工具驱动文件不能像 exe 那样双击运行需要先注册成内核服务再启动它。这里用管理员命令行执行sc create hideproc type kernel binPath C:\test\hideproc.sys sc start hideproc第一条命令注册服务type kernel表示这是一个内核驱动binPath一定要写成磁盘绝对路径。第二条命令启动驱动。如果这里收到“服务已标记为删除”或错误 577八成是驱动签名或路径问题检查测试签名是否开启、路径是否存在、文件名是否带全.sys后缀。驱动启动成功后对应的设备会被创建出来。接下来用管理工具命令行控制隐藏和恢复。假设要隐藏 PID 为 12345 的进程HideClient.exe hide 12345这条命令通过DeviceIoControl把 PID 传给驱动驱动执行链表的摘除操作。如果操作成功任务管理器里立刻看不到 12345 这个进程了但回到进程列表用tasklist确认它仍然存在。想恢复显示运行HideClient.exe restore 12345驱动收到命令后会把节点插回链表进程重新出现在任务管理器里。这里有一个行为细节hide命令不会杀进程只是隐藏真正要结束进程得先restore再用任务管理器或taskkill处理。没恢复就想结束进程系统可能都找不到这个进程的资源退不干净。4. 核心代码与参数驱动隐藏进程的关键实现4.1 驱动入口与设备分发驱动侧的核心入口是DriverEntry所有对象的初始化和分发函数都从这里开始。代码骨架大致如下NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath) { UNICODE_STRING deviceName RTL_CONSTANT_STRING(L\\Device\\HideProcess); UNICODE_STRING symLink RTL_CONSTANT_STRING(L\\??\\HideProc); PDEVICE_OBJECT pDeviceObj NULL; IoCreateDevice(pDriverObj, 0, deviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, pDeviceObj); IoCreateSymbolicLink(symLink, deviceName); pDriverObj-MajorFunction[IRP_MJ_CREATE] DispatchCreate; pDriverObj-MajorFunction[IRP_MJ_CLOSE] DispatchClose; pDriverObj-MajorFunction[IRP_MJ_DEVICE_CONTROL] DispatchIoctl; pDriverObj-DriverUnload DriverUnload; return STATUS_SUCCESS; }关键点在两个地方IoCreateDevice创建设备对象IoCreateSymbolicLink创建应用层可访问的符号链接\??\HideProc。应用层之后的CreateFile打开的就是这个链接它对应\\.\HideProc路径。FILE_DEVICE_UNKNOWN表示设备类型不匹配任何标准设备这是自定义的通用类型。4.2 应用层传参IOCTL 通信协议客户端的核心逻辑是打开设备句柄通过DeviceIoControl把 PID 传给驱动。关键流程如下HANDLE hDevice CreateFileW(L\\\\.\\HideProc, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDevice INVALID_HANDLE_VALUE) { // 常见原因: 驱动未启动, 或符号链接未创建 return -1; } DWORD pid 12345; DWORD bytesReturned 0; BOOL ok DeviceIoControl(hDevice, IOCTL_HIDE_PROCESS, pid, sizeof(pid), NULL, 0, bytesReturned, NULL); CloseHandle(hDevice);IOCTL_HIDE_PROCESS是一个自定义的 IOCTL 码在驱动的公共头文件里统一定义#define IOCTL_HIDE_PROCESS \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_RESTORE_PROCESS \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)METHOD_BUFFERED是关键——它指明输入输出都通过系统缓冲区传递不直接映射用户内存这在内核访问用户态指针时能省去大量安全检查的麻烦。IOCTL码的功能号用了0x801和0x802这个没有硬性规定同一个驱动里保持唯一即可。4.3 驱动处理从 PID 到 EPROCESS 的隐藏逻辑驱动侧收到 IOCTL 后的核心处理逻辑是查找 EPROCESS 并执行链表解链。这里只列出隐藏操作的关键片段完整实现细节需要看资源包里的driver/hideproc.cNTSTATUS HideProcessById(ULONG pid) { PEPROCESS targetProc NULL; PLIST_ENTRY pLink NULL; // 按 PID 查找进程对象, 找不到返回 STATUS_NOT_FOUND NTSTATUS status PsLookupProcessByProcessId((HANDLE)pid, targetProc); if (!NT_SUCCESS(status)) { return status; } // 获取目标进程的 ActiveProcessLinks 节点地址 pLink (PLIST_ENTRY)((ULONG_PTR)targetProc ActiveProcessLinksOffset); // 摘除节点前必须拿锁, 防止系统枚举链表时并发冲突 KeAcquireSpinLock(g_hideLock, oldIrql); RemoveEntryList(pLink); KeReleaseSpinLock(g_hideLock, oldIrql); ObDereferenceObject(targetProc); return STATUS_SUCCESS; }有个非常容易被忽略的点ActiveProcessLinks在EPROCESS中的偏移不是写死的常数不同 Windows 版本里偏移位置不一样。资源包里窗口了一大块ActiveProcessLinksOffset的初始化逻辑这是兼容多系统版本的地基自己写代码时不要硬编码偏移一定要通过版本判断动态计算。摘除节点要放在自旋锁保护范围里否则系统刚好在遍历链表时看到节点指针断裂直接蓝屏CRITICAL_PROCESS_DIED这是最常见的 DRIVER 翻车现场。恢复过程是对称操作把保存的BLINK和FLINK重新接回链表。需要注意解链时保存原节点指针的位置需要额外存储资源包里用一个全局数组按 PID 做了映射就是为了恢复时能找到原链表位置。4.4 关键参数速查驱动和客户端之间有几个参数需要关注参数值说明设备名\Device\HideProcess驱动内部设备对象名符号链接\??\HideProc应用层访问入口功能码 1IOCTL_HIDE_PROCESS功能号 0x801功能码 2IOCTL_RESTORE_PROCESS功能号 0x802进程名长度上限由客户端命令行限制建议不要超过 256 字节IOCTL 缓冲方式METHOD_BUFFERED系统缓冲区传递客户端命令行支持hide、restore和list三个子命令其中list用来查看当前正在被隐藏的 PID 列表。这个列表的实际数据存在驱动侧客户端只是查询读数不是本地保存所以就算客户端重启隐藏状态仍然在。5. 常见问题与避坑驱动隐藏进程的五个翻车现场5.1 驱动加载失败错误 577 与“测试模式未开启”现象sc start hideproc返回错误 577或系统日志显示“驱动程序无法加载”。原因x64 系统要求内核驱动携带有效数字签名。自编译的驱动没有签名如果系统没进入测试模式加载直接被拒。还有一个隐蔽的原因Secure Boot 开启时即使bcdedit /set testsigning on显示成功重启后测试模式会被安全启动策略强制关闭驱动照样加载不了。解决确认主板 BIOS/虚拟机设置里关掉 Secure Boot然后在管理员命令行执行bcdedit /set testsigning on重启后确认桌面右下角有“测试模式”水印再尝试加载。这个顺序不能反过来先改 BCD 再关 Secure Boot 会导致测试模式配置被重置。5.2 加载后瞬间蓝屏CRITICAL_PROCESS_DIED现象驱动启动后几秒内系统蓝屏重启后事件查看器记录0x109。原因摘除链表节点时没拿自旋锁或锁的粒度不对。RemoveEntryList是修改全局进程链表系统随时可能在遍历它两个操作同时进行会导致链表指针错乱。另一种常见情况是传入的 PID 恰好是系统关键进程如System、smss.exe摘掉后系统自己的管理流程断路。解决严格遵守“操作前KeAcquireSpinLock操作后KeReleaseSpinLock”的结构并且在代码里过滤掉 PID 小于等于 4 的进程和PsInitialSystemProcess指向的进程。这个过滤条件在资源包的驱动里已经内置自己魔改时注意别顺手删掉。5.3 隐藏后杀毒软件报驱动异常现象360、Defender 或火绒弹出风险提示说检测到内核级自启动服务。原因加载内核驱动本质上就是在做最敏感的系统操作任何杀毒软件对未经签名的新驱动都会有反应。这不是代码“有问题”而是行为特征触发安全检查。解决资源包属于研究用途建议只在离线虚拟机里操作别放 live 系统跑。非要本机调试的话把编译产物目录加入白名单或者临时关闭实时保护验证完立刻恢复。5.4 进程隐藏后没法结束任务管理器看不到神仙也难杀现象执行 hide 之后taskkill /pid 12345返回“进程不存在”。原因进程从活动链表摘掉之后常规进程管理接口根本遍历不到它。taskkill按 PID 找进程的方式依赖活动进程表隐藏后它自然查不到。很多人踩坑在还没 restore 就尝试结束进程结果进程挂着结束不了造成资源残留。解决先执行restore 12345恢复链表节点再执行taskkill。编码习惯上我把 hide 和 kill 的操作拆分成了两条独立命令行绝不在没恢复的情况下强杀进程。如果你需要“隐藏后自己退出”正确做法是先恢复再退不要尝试隐藏状态下自杀。5.5 设备句柄打不开\\.\HideProc不存在现象客户端启动报CreateFile failed: 2。原因驱动服务没起来或者符号链接创建失败。符号链接创建失败在驱动卸载不干净时最容易发生——上次驱动没有IoDeleteSymbolicLink再次加载时链接被占用IoCreateSymbolicLink返回冲突。解决先sc stop hideprocsc delete hideproc清掉旧服务然后检查设备管理器和注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下有没有残留的hideproc项删掉再重新sc create。这算是驱动开发的常见套路服务没删干净就重新加载各种玄学报错就来了。6. 验证隐藏效果与进阶用法不只是“看不见”这么简单驱动加载并执行隐藏后怎么确认它真的生效了我习惯做三件套对照验证。第一件打开任务管理器确认目标进程消失第二件开一个管理员终端跑wmic process where processid12345 get name,processid能查到说明进程还在系统中运行隐藏只是让它从枚举接口消失第三件用 System Informer原 Process Explorer看一眼它能显示隐藏进程这部分写进资源包的验证文档里当边界说明。三者对比后你对这套方案的能力边界会非常直观。进阶用法上资源包自带一个值得改动的点客户端默认是手动传 PID但实际场景里进程名往往比 PID 更稳定。你可以把HideClient.exe hide pid扩展成先查进程名拿 PID 再隐藏的两段式调用这样就算目标 PID 变了只要进程名没变就能重新定位它。另一个实用调整是把恢复操作设计成热键触发省去每次都要开终端打命令的麻烦。有一点必须提醒进程隐藏解决的是“枚举可见性”解决不了“根因可查性”进程的句柄表、网络连接、内存页都还在用 R3 的 TCPView 能看到它的网络连接用 Windows 内核调试器能直接扫 EPROCESS 列表。研究内核对抗时记住这个边界你就知道它该在什么场合用。那以后我每次做驱动类项目验证完隐藏都会强制走一遍恢复流程再卸载驱动防止残留悬挂节点污染内核链表。这个项目帮我把核心里程碑式的链条操作彻底搞透希望你也能在安全研究路上用它省点时间少浇几锅蓝屏。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询