首页
社区
课程
招聘
[求助]关于通过hook实现文件隐藏 防删除的问题
发表于: 2010-5-12 15:10 6446

[求助]关于通过hook实现文件隐藏 防删除的问题

2010-5-12 15:10
6446
在驱动程序里面,通过hook ZwQueryDirectoryFile()来实现的隐藏文件, 可以实现隐藏了,但是有一点小的问题,下面是hook ZwQueryDirectoryFile()过后的过程函数HookZwQueryDirectoryFile(),我把要hook的文件名放在链表里面,而链表的内容是通过外面的程序传给驱动程序的 具体的代码可以看附件,下面是链表和hook函数


#define dprintf if (DBG) DbgPrint
#define nprintf DbgPrint

//定义FILE_INFORMATION_CLASS的第3号结构:_FILE_BOTH_DIR_INFORMATION,这个结构是ZwQueryDirectoryFile必须参数。
typedef struct _FILE_BOTH_DIR_INFORMATION
{
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    CCHAR ShortNameLength;
    WCHAR ShortName[12];
    WCHAR FileName[1];
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;

//定义链表
typedef struct FileProtectLink
{
	UNICODE_STRING fileName;   //只是文件名如:abc.txt
	UNICODE_STRING allName;    //全路径如:c:\aaaa\abc.txt
	UNICODE_STRING nameWithoutDiskName; //除去盘符的路径 如 \aaaa\abc.txt
	UNICODE_STRING passWord;   //连接密码 
	struct FileProtectLink *next;     //指到下一个结点
} FileProtectLink, *PFileProtectLink;

FileProtectLink fileProtectLinkHand;   //申请的全局链表指针变量

//hook函数过程
NTSTATUS HookZwQueryDirectoryFile(
    IN HANDLE hFile,
    IN HANDLE hEvent OPTIONAL,
    IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
    IN PVOID IoApcContext OPTIONAL,
    OUT PIO_STATUS_BLOCK pIoStatusBlock,
    OUT PVOID FileInformationBuffer,
    IN ULONG FileInformationBufferLength,
    IN FILE_INFORMATION_CLASS FileInfoClass,
    IN BOOLEAN bReturnOnlyOneEntry,
    IN PUNICODE_STRING PathMask OPTIONAL,
    IN BOOLEAN bRestartQuery)
{
    NTSTATUS rc = STATUS_SUCCESS;
    UNICODE_STRING uniFileName;
    PCWSTR pProcPath = NULL;

    // 执行真正的 ZwQueryDirectoryFile 函数
    rc = OriginalZwQueryDirectoryFile(
        hFile, 
        hEvent, 
        IoApcRoutine,
        IoApcContext,
        pIoStatusBlock,
        FileInformationBuffer,
        FileInformationBufferLength,
        FileInfoClass,
        bReturnOnlyOneEntry,
        PathMask,
        bRestartQuery);

    // 如果执行成功,而且 FILE_INFORMATION_CLASS 的值为 FileBothDirectoryInformation,我们就进行处理,过滤
    if (NT_SUCCESS(rc) && FileInfoClass == FileBothDirectoryInformation)
    {
		PFileProtectLink pLink = fileProtectLinkHand.next;
		while( pLink != NULL)
		{
			// 把执行结果赋给 pFileInfo
			PFILE_BOTH_DIR_INFORMATION pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer;
			PFILE_BOTH_DIR_INFORMATION pLastFileInfo = NULL;
			BOOLEAN bLastOne = FALSE;
        
			// 循环检查
			do
			{
				bLastOne = !pFileInfo->NextEntryOffset;
				RtlInitUnicodeString(&uniFileName, pFileInfo->FileName);
				
				dprintf("pFileInfo %d %d %wZ\n", (int)pFileInfo, (int)pFileInfo->NextEntryOffset, &uniFileName);

							

				// 开始进行比较,如果找到了就隐藏这个文件或者目录
				if (RtlCompareMemory(uniFileName.Buffer, pLink->fileName.Buffer, pLink->fileName.Length) == pLink->fileName.Length)
				{
					if (bLastOne)
					{
						dprintf("bLastOne %wZ\n", &uniFileName);
						if (pFileInfo == (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer)
						{

							rc = STATUS_NO_MORE_FILES;    // 隐藏文件或者目录;
						}
						else
							pLastFileInfo->NextEntryOffset = 0;
						
						break;
					}
					else    // 指针往后移动
					{
						int iPos = (ULONG)pFileInfo - (ULONG)FileInformationBuffer;
						int iLeft = (ULONG)FileInformationBufferLength - iPos - pFileInfo->NextEntryOffset;
						RtlCopyMemory((PVOID)pFileInfo, (PVOID)((PCHAR)pFileInfo + pFileInfo->NextEntryOffset), (ULONG)iLeft);
						
                                                dprintf("enter bLastOne else and  iPos is %d  iLeft is %d  is %ld\n",iPos,iLeft,(ULONG)FileInformationBufferLength);
                                                continue;
					}
				}
				pLastFileInfo = pFileInfo;
				pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)pFileInfo + pFileInfo->NextEntryOffset);
			} while (!bLastOne);

			pLink = pLink->next;
		}
    }

    return rc;
}



问题:如果链表里面fileName的值是111.txt那么在C盘根目录下有这个文件的话就全部隐藏了
他是会执行rc = STATUS_NO_MORE_FILES;这条语句引起的,下面是我的分析。

分析:
通过调试 我发现  HOOK函数也是要枚举所有当前目录下的文件的,然后而且文件名都是在内核里面用的大写字母来比较的,所以即使我们建立的文件名是小写字母的,也会被转换为大写字母来比较,但只是比较的时候是这样,文件名本身不会被改变。也就是说假设C盘根目录下面有这几个文件(当然这是举例,不是实际情况) 123.txt, aaa.txt,nina.txt,CONFIG.SYS,CAD.EXE; 那么 系统会自动创立一个链表(其实不是链表,因为和链表的情况很相似,一个文件接一个文件的,所以我把他说成链表,便于理解),把我们这几个文件根据文件名链起来,分别是123.txt->aaa.txt->CAD.EXE->CONFIG.SYS->nina.txt ,是根据文件名来的  数字的永远都是在开头,如果我们在这个文件夹里面新建立一个文件a.txt 那么这个文件会自动插入上面的那个文件链表里面 结果就是:123.txt->a.txt->aaa.txt->CAD.EXE->CONFIG.SYS->nina.txt

通过调试 发现  程序只要不把上面那个链表的第一个文件隐藏 隐藏其他的都正常运行

整个隐藏的原理其实就是调整了这个文件链,通过hook那个函数的下面这几行 把链表里面信息改了

     int iPos = ((ULONG)pFileInfo) - (ULONG)FileInformationBuffer;
     int iLeft = (DWORD)FileInformationBufferLength - iPos - pFileInfo->NextEntryOffset;
     RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft );
     continue;

也就是说如果本来目录下的文件链表是:
123.txt->a.txt->aaa.txt->CAD.EXE->CONFIG.SYS->nina.txt   
那么 我要隐藏a.txt 我就通过上面那几句,找准位置后把链表改为:
123.txt->aaa.txt->aaa.txt->CAD.EXE->CONFIG.SYS->nina.txt
也就是把要隐藏节点的后面一个节点放到当前节点上面来 那么在函数返回后 用户就不会发现有a.txt这个文件了  

至于我们遇到的问题 为什么会全部隐藏  因为我们隐藏的是第一文件 而且pFileInfo->NextEntryOffset==0 所以他执行了rc= STATUS_NO_MORE_FILES所以 只要返回这个rc 就返回这个目录里面没有文件的tag,所以就全部看不到了 实现了一次性全部隐藏,根据我们的要求,根本不需要这里的对rc的改变,所以我把包括if(bLastOne)在内里面的东西全部注释起来了, 在上面的if语句里面,只要判断出名字相匹配了,就直接运行else里面的东西,不用去判断if(bLastOne),程序照样运行,只是不能隐藏第一个文件而已~~~~~~~~~

最后至于为什么不能隐藏链表的第一个文件?因为通过dbgview看到,第一个文件的pFileInfo->NextEntryOffset为0,(这个我也不知道为什么) 而且传进来的参数FileInformationBufferLength在枚举第一个文件的时候的值是616  而在第二个的时候就变成了4096 以后都是4096  而且整个过程没有看到它在哪点赋值过, 就是调用一次 然后居然在没有任何赋值的情况下自己被改变了?? 难道是在这里使用了多线程而又没有做同步?

还有就是如果隐藏第一个文件那么由于pFileInfo->NextEntryOffset==0 那么在RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft );的时候,拷贝内存的目的地和起始地都是同一个地方,可能这个就是不能实现隐藏的原因。不知道为什么RtlCopyMemory的第二个参数(PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset为什么要转换为char *类型??不懂?

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 192
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
自己顶一下 ~~~
2010-5-14 06:16
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢楼主分享
2010-5-14 07:48
0
雪    币: 192
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
自己再顶一下
2010-5-15 22:10
0
雪    币: 192
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
再顶下~~~~
2010-5-18 18:02
0
雪    币: 192
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
再顶一下~~
2010-5-20 18:03
0
游客
登录 | 注册 方可回帖
返回
//