阅读:1798回复:1
【求助】关于通过hook实现文件隐藏的问题
在驱动程序里面,通过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 而且整个过程没有看到它在哪点赋值过, 就是调用一次 然后居然在没有任何赋值的情况下自己被改变了?? 难道是在这里使用了多线程而又没有做同步?[/COLOR] 还有就是如果隐藏第一个文件那么由于pFileInfo->NextEntryOffset==0 那么在RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft );的时候,拷贝内存的目的地和起始地都是同一个地方,可能这个就是不能实现隐藏的原因。 请问如果要隐藏第一个文件 该怎么解决~~~~ [/COLOR] |
|
沙发#
发布于:2011-09-13 11:34
|
|