C 语言驱动开发之内核解锁与强删文件

在某些时候我们的系统中会出现一些无法被正常删除的文件,如果想要强制删除则需要在驱动层面对其进行解锁后才可删掉,而所谓的解锁其实就是释放掉文件描述符(句柄表)占用,文件解锁的核心原理是通过调用ObSetHandleAttributes函数将特定句柄设置为可关闭状态,然后在调用ZwClose将其文件关闭,强制删除则是通过ObReferenceObjectByHandle在对象上提供相应的权限后直接调用ZwDeleteFile将其删除,虽此类代码较为普遍,但作为揭秘 ARK 工具来说也必须要将其分析并讲解一下。
 
 首先封装lyshark.h通用头文件,并定义好我们所需要的结构体,以及特定未导出函数的声明,此处的定义部分是微软官方的规范,如果不懂结构具体含义可自行去微软官方查阅参考资料。
接下来将具体分析如何解锁指定文件的句柄表,强制解锁文件句柄表,大体步骤如下所示。
- 1.首先调用 - ZwQuerySystemInformation的 16 功能号- SystemHandleInformation来枚举系统里的句柄。
- 2.通过 - ZwOpenProcess()打开拥有此句柄的进程,通过- ZwDuplicateObject创建一个新的句柄,并把此句柄复制到自己的进程内。
- 3.通过调用 - ZwQueryObject并传入- ObjectNameInformation查询到句柄的名称,并将其放入到- pNameInfo变量内。
- 4.循环这个过程并在每次循环中通过 - strstr()判断是否是我们需要关闭的文件名,如果是则调用- ForceCloseHandle强制解除占用。
- 5.此时会进入到 - ForceCloseHandle流程内,通过- KeStackAttachProcess附加到进程内,并调用- ObSetHandleAttributes将句柄设置为可关闭状态。
- 6.最后调用 - ZwClose关闭句柄占用,并- KeUnstackDetachProcess脱离该进程。
实现代码流程非常容易理解,此类功能也没有其他别的写法了一般也就这种,但是还是需要注意这些内置函数的参数传递,这其中ZwQuerySystemInformation()一般用于查询系统进程等信息居多,但通过对SystemInformationClass变量传入不同的参数可实现对不同结构的枚举工作,具体的定义可去查阅微软定义规范;
函数ZwDuplicateObject(),该函数例程用于创建一个句柄,该句柄是指定源句柄的副本,此函数的具体声明部分如下;
函数ZwQueryObject()其可以返回特定的一个对象参数,此函数尤为注意第二个参数,当下我们传入的是ObjectNameInformation则代表需要取出对象名称,而如果使用ObjectTypeInformation则是返回对象类型,该函数微软定义如下所示;
而对于ForceCloseHandle函数中,需要注意的只有一个ObSetHandleAttributes该函数微软并没有格式化文档,但是也并不影响我们使用它,如下最需要注意的是PreviousMode变量,该变量如果传入KernelMode则是内核模式,传入UserMode则代表用户模式,为了权限最大化此处需要写入KernelMode模式;
实现文件解锁,该驱动程序不仅可用于解锁应用层程序,也可用于解锁驱动,如下代码中我们解锁pagefile.sys程序的句柄占用;
编译并运行这段驱动程序,则会将pagefile.sys内核文件进行解锁,输出效果如下所示;
 
 聊完了文件解锁功能,接下来将继续探讨如何实现强制删除文件的功能,文件强制删除的关键在于ObReferenceObjectByHandle函数,该函数可在对象句柄上提供访问验证,并授予访问权限返回指向对象的正文的相应指针,当有了指定的权限以后则可以直接调用ZwDeleteFile()将文件强制删除。
在调用初始化句柄前提之下需要先调用KeGetCurrentIrql()函数,该函数返回当前IRQL级别,那么什么是 IRQL 呢?
Windows 中系统中断请求(IRQ)可分为两种,一种外部中断(硬件中断),一种是软件中断(INT3),微软将中断的概念进行了扩展,提出了中断请求级别(IRQL)的概念,其中就规定了 32 个中断请求级别。
- 其中 0-2 级为软中断,顺序由小到大分别是:PASSIVE_LEVEL,APC_LEVEL,DISPATCH_LEVEL 
- 其中 27-31 为硬中断,顺序由小到大分别是:PROFILE_LEVEL,CLOCK1_LEVEL,CLOCK2_LEVEL,IPI_LEVEL,POWER_LEVEL,HIGH_LEVEL 
我们的代码中开头部分KeGetCurrentIrql() > PASSIVE_LEVEL则是在判断当前的级别不大于 0 级,也就是说必须要大于 0 才可以继续执行。
好开始步入正题,函数ObReferenceObjectByHandle需要传入一个文件句柄,而此句柄需要通过IoCreateFileSpecifyDeviceObjectHint对其进行初始化,文件系统筛选器驱动程序使用IoCreateFileSpecifyDeviceObjectHint函数创建,该函数的微软完整定义如下所示;
当调用IoCreateFileSpecifyDeviceObjectHint()函数完成初始化并创建设备后,则下一步就是调用ObReferenceObjectByHandle()并传入初始化好的设备句柄到Handle参数上,
通过调用如上两个函数将权限设置好以后,我们再手动将ImageSectionObject也就是映像节对象填充为 0,然后再将DeleteAccess删除权限位打开,最后调用ZwDeleteFile()函数即可实现强制删除文件的效果,其核心代码如下所示;
编译并运行如上程序,则会分别将c://lyshark.exe以及驱动程序自身删除,并输出如下图所示的提示信息;
 
 欢迎加入我的粉丝群,领取更多的福利哟!
 
 版权声明: 本文为 InfoQ 作者【向阳逐梦】的原创文章。
原文链接:【http://xie.infoq.cn/article/e1dd113ab5492ce944bcf8442】。文章转载请联系作者。












 
    
评论