想必大家都有无法通 explorer.exe 删除的文件吧。一些病毒和木马等都会保护自己的
文件,而一些软件在卸载的时候也会留下dll 等文件,残留的DLL文件无法用 explorer.exe
来删除,只有在重启才可以删除残留的 DLL 文件,因为 dll 在 explorer 中加载了,卸载的
时候没有 free。强删文件的软件有很多。如 unlockme,超级巡警,360 等等。这些软件是
怎么实现强删文件的呢?今天带给大家几种强删与防删的技术:句柄占坑,hardlink,直接
下发 IRP 等方法。
要实现文件的强删,就必须要知道文件防删的原理,毕竟攻与防是对立也是统一的。
文件无法删除有以下几种情况:
1:文件被占坑,如以 file_share_read 权限打开文件,这样其他程序在句柄被关闭前就无
法删除该文件。另一种是建立了hardlink硬链接。这种方法很隐蔽很强大,后面介绍。
2:HOOK 了 FSD 中的分发函数,SSDT HOOK 了相关的 ZwDeletefile和 ZwSetInfromation 函
数。
3:文件是PE 文件且被加载了,即打开了Section.
先分析第一种:
一句代码就能实现防删:
[code]
hfile=CreateFile(TEXT("C:\\my.txt"),
GENERIC_WRITE | GENERIC_READ,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
[/code]
文件句柄在关闭前,普通的方法是删除不了my,txt。
试图在 explorer中右键删除:

因为文件系统在删除文件的时候,会检查该文件是否被其他程序打开,若打开,则无法删除。
要删除句柄保护的文件,可以枚举系统中所有进程的句柄,若发现是 my.txt 的句柄,关闭
之,然后在explorer中删除my.txt。
具体实现方法:
用户层:在用户层获取系统所有句柄,将句柄信息传入驱动层验证。若返回1,则关闭该句
柄。(附件中的queryhandle工程)
驱动层:根据用户层传入的数据获取该文件对象的绝对路径,并且与my.txt的绝对路径比较。
符合返回1,否则返回0.(附件中的duphandle工程)
用ZwQuerySystemInfromation这个未公开的函数,并设置SystemInformationClass
为SystemHandleInformation可以获得系统所有的句柄。具体代码如下:
[code]
p=malloc(sizeof(SYSTEM_HANDLE_INFORMATION)); //申请缓冲区
n=length=sizeof(SYSTEM_HANDLE_INFORMATION);
/*调用系统服务获取系统所有句柄,保存在缓冲区中*/
while(ZwQuerySystemInformation(SystemHandleInformation,p,n,&length)==ST
ATUS_INFO_LENGTH_MISMATCH)
{
n=n*2;
free(p);
p=malloc(n);
}
[/code]
缓冲区中前4个字节保存系统的句柄总数,之后的数据是SYSTEM_HANDLE_INFORMATION结构的
数组。
SYSTEM_HANDLE_INFORMATION结构体定义如下:
[code]
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG Processid;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
}SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
[/code]
ObjectTypeNumber域是句柄类型,文件句柄的ObjectTypeNumber值是0x1c(xp sp3系统)。
Object域是个指针,对于文件句柄来讲,指向文件在内核中的file_object结构体。
接着要获取文件句柄对应的文件名了(绝对路径),在R3中ZwQueryObject系统服务可以获取
文件对象的绝对路径,但是该函数有时候会死锁(因为Pipe管道也是文件对象,而
ZwQueryObject在获取PIPE对象的路径时候会死锁),所以我直接在R0中自己获取绝对路径。
用户层的代码就到这里了。
内核层代码的主要功能就是获取文件的绝对路径,并与my.txt的绝对路径比较。
下面说几点注意:
1. 获取绝对路径,可以调用object_type_initializer结构中的QueryNameProcedure指向
的函数(即IopQueryName)获得(object_header->type.QueryNameProcedure) 。该函数返
回的是NT格式的路径,即\device\harddiskvolumex\xxx类型。但是my.txt的路径是dos格式
的(c:\my.txt),如何将dos格式路径转换成nt格式路径呢?有人会说将盘符C换成 |