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】。文章转载请联系作者。
评论