如何解决驱动发送IRP删除需管理员权限EXE文件时的挂起问题
问题原因及解决方案
核心原因
不是Windows限制驱动删除带管理员权限的EXE文件,你在IoCallDriver处挂起主要是两个层面的问题:
- 文件层面:需要管理员权限运行的EXE(尤其是安装包类程序),大概率被Windows Defender、UAC相关系统组件、第三方安全软件持有读写/独占句柄,文件系统收到删除IRP后会将IRP pending,直到所有相关句柄被释放,表现为调用
IoCallDriver时卡住。 - 代码层面:你现有实现存在多个逻辑漏洞,会直接导致IRP处理异常、等待逻辑失效。
现有代码的漏洞修复
- 栈内存越界风险:你将栈上的
FILE_DISPOSITION_INFORMATION变量地址直接赋值给irp->AssociatedIrp.SystemBuffer,如果IRP被文件系统pending,当前函数返回后栈内存会被回收覆盖,文件系统后续访问该内存时会产生不可预期的错误,必须改用非分页池内存存储该结构体,在IRP完成例程中释放内存。 - FILE_OBJECT权限校验缺失:你传入的
PFILE_OBJECT file_object必须是打开时就申请了DELETE访问权限的,否则删除IRP会直接被文件系统拒绝或pending。 - 等待逻辑错误:你调用
KeWaitForSingleObject时将Alertable参数设为true,如果有内核APC插入会提前返回,你没有判断等待返回值,无法确定是IRP完成触发了事件还是等待被打断,也没有处理等待超时后的IRP取消逻辑,会导致IRP泄露、永远挂起。 - 完成例程逻辑校验:你需要确认
io_complete完成例程中正确调用了KeSetEvent触发传入的事件,且完成例程最终返回STATUS_SUCCESS而非STATUS_MORE_PROCESSING_REQUIRED,否则事件永远不会被触发。
优化解决方案
- 优先选用内核原生接口删除文件:不需要手动拼IRP,直接调用
ZwDeleteFile内核函数,传入正确构造的OBJECT_ATTRIBUTES即可,内核态调用该接口默认使用KernelMode权限,稳定性远高于自行构造IRP。 - 强制删除被占用的文件:如果确定要强制删除被占用的文件,可改用
FileDispositionInformationEx配置删除参数,设置FLAG_DISPOSITION_FORCE_DELETE、FLAG_DISPOSITION_IGNORE_READONLY_ATTRIBUTE标记,不需要等待所有句柄释放,文件会在最后一个持有句柄关闭后自动删除。 - 预处理占用句柄:如果需要即时删除,可以先枚举系统中所有持有该文件句柄的进程,调用
ZwClose强制关闭对应句柄后再执行删除操作。
内容的提问来源于stack exchange,提问作者SuperBerry
相关产品推荐
相关产品推荐

