hook NtQueryDirectoryFile实现文件隐藏

一、NtQueryDirectoryFile函数功能(NT系列函数)

     NtQueryDirectoryFile函数:在一个给定的文件句柄,该函数返回该文件句柄指定目录下的不同文件的各种信息。

根据传入的文件句柄参数fileHandle,返回句柄所表示的目录中的不同文件的信息。

NTSTATUS ZwQueryDirectoryFile(
  _In_      HANDLE FileHandle,
  _In_opt_  HANDLE Event,
  _In_opt_  PIO_APC_ROUTINE ApcRoutine,
  _In_opt_  PVOID ApcContext,
  _Out_     PIO_STATUS_BLOCK IoStatusBlock,
  _Out_     PVOID FileInformation,
  _In_      ULONG Length,
  _In_      FILE_INFORMATION_CLASS FileInformationClass,
  _In_      BOOLEAN ReturnSingleEntry,
  _In_opt_  PUNICODE_STRING FileName,
  _In_      BOOLEAN RestartScan
);

   下面就简单说几个重要的参数:

   1.FileHandle [in]文件句柄

ZwCreateFile或者ZwOpenFile返回的句柄。

A handle returned by ZwCreateFile or ZwOpenFile for the file object that represents the directory for which information is being requested. The file object must have been opened for asynchronous I/O if the caller specifies a non-NULL value for Event or ApcRoutine.

   7.FileInformation [out]

FileInformation是一个指向一个缓冲区的指针。该缓冲区存储关于文件的信息。信息的结构由FileInformationClassparameter定义。就由最后一个参数FileInformationClass决定。所以要先判断这个参数的值是什么呀。

A pointer to a buffer that receives the desired information about the file. The structure of the information returned in the buffer is defined by the FileInformationClassparameter.

8.Length [in] 长度,代表缓冲区的size,以字节大小记录。

The size, in bytes, of the buffer pointed to by FileInformation. The caller should set this parameter according to the given FileInformationClass.

9.FileInformationClass [in]文件信息类

返回的关于在一个目录中的文件的信息类型。它的取值是下表中的一个。

The type of information to be returned about files in the directory. One of the following.

ValueMeaning

FileBothDirectoryInformation

Return a FILE_BOTH_DIR_INFORMATION structure for each file.

FileDirectoryInformation

Return a FILE_DIRECTORY_INFORMATION structure for each file.

FileFullDirectoryInformation

Return a FILE_FULL_DIR_INFORMATION structure for each file.

FileIdBothDirectoryInformation

Return a FILE_ID_BOTH_DIR_INFORMATION structure for each file.

FileIdFullDirectoryInformation

Return a FILE_ID_FULL_DIR_INFORMATION structure for each file.

FileNamesInformation

Return a FILE_NAMES_INFORMATION structure for each file.

FileObjectIdInformation

Return a FILE_OBJECTID_INFORMATION structure for each file. This information class is valid only for NTFS volumes on Windows 2000 and later versions of Windows.

FileReparsePointInformation

Return a single FILE_REPARSE_POINT_INFORMATION structure for the directory.

ReturnSingleEntry [in]

Set to TRUE if only a single entry should be returned, FALSE otherwise. If this parameter is TRUEZwQueryDirectoryFile returns only the first entry that is found.

FileName [in, optional]

An optional pointer to a caller-allocated Unicode string containing the name of a file (or multiple files, if wildcards are used) within the directory specified by FileHandle. This parameter is optional and can be NULL.

If FileName is not NULL, only files whose names match the FileName string are included in the directory scan. If FileName is NULL, all files are included.

The FileName is used as a search expression and is captured on the very first call to ZwQueryDirectoryFile for a given handle. Subsequent calls toZwQueryDirectoryFile will use the search expression set in the first call. The FileName parameter passed to subsequent calls will be ignored.

RestartScan [in]

Set to TRUE if the scan is to start at the first entry in the directory. Set to FALSE if resuming the scan from a previous call.

When the ZwQueryDirectoryFile routine is called for a particular handle, the RestartScan parameter is treated as if it were set to TRUE, regardless of its value. On subsequent ZwQueryDirectoryFile calls, the value of the RestartScan parameter is honored.

2.hook  NtQueryDirectoryFile()实现对文件的隐藏

  1 #include "ntddk.h"
  2  
  3 
  4 #pragma pack(1)
  5 typedef struct ServiceDescriptorEntry {
  6     unsigned int *ServiceTableBase;
  7     unsigned int *ServiceCounterTableBase;
  8     unsigned int NumberOfServices;
  9     unsigned char *ParamTableBase;
 10 } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
 11 
 12 typedef struct _FILE_BOTH_DIR_INFORMATION {
 13     ULONG           NextEntryOffset;
 14     ULONG           FileIndex;
 15     LARGE_INTEGER   CreationTime;
 16     LARGE_INTEGER   LastAccessTime;
 17     LARGE_INTEGER   LastWriteTime;
 18     LARGE_INTEGER   ChangeTime;
 19     LARGE_INTEGER   EndOfFile;
 20     LARGE_INTEGER   AllocationSize;
 21     ULONG           FileAttributes;
 22     ULONG           FileNameLength;
 23     ULONG           EaSize;
 24     CCHAR           ShortNameLength;
 25     WCHAR           ShortName[12];
 26     WCHAR           FileName[1];
 27 } FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
 28  
 29  
 30 // Our System Call Table
 31 PVOID* NewSystemCallTable;
 32  
 33 // Our Memory Descriptor List
 34 PMDL pMyMDL;
 35  
 36 #define HOOK_INDEX(function2hook) *(PULONG)((PUCHAR)function2hook+1)
 37  
 38 #define HOOK(functionName, newPointer2Function, oldPointer2Function )  
 39        oldPointer2Function = (PVOID) InterlockedExchange( (PLONG) &NewSystemCallTable[HOOK_INDEX(functionName)], (LONG) newPointer2Function)
 40  
 41 #define UNHOOK(functionName, oldPointer2Function)  
 42        InterlockedExchange( (PLONG) &NewSystemCallTable[HOOK_INDEX(functionName)], (LONG) oldPointer2Function)
 43  
 44 NTSYSAPI
 45 NTSTATUS
 46 NTAPI ZwQueryDirectoryFile(
 47   IN  HANDLE FileHandle,
 48   IN  HANDLE Event OPTIONAL,
 49   IN  PIO_APC_ROUTINE ApcRoutine OPTIONAL,
 50   IN  PVOID ApcContext OPTIONAL,
 51   OUT PIO_STATUS_BLOCK IoStatusBlock,
 52   OUT PVOID FileInformation,
 53   IN  ULONG Length,
 54   IN  FILE_INFORMATION_CLASS FileInformationClass,
 55   IN  BOOLEAN ReturnSingleEntry,
 56   IN  PUNICODE_STRING FileName OPTIONAL,
 57   IN  BOOLEAN RestartScan
 58   );
 59  
 60  
 61 typedef NTSTATUS (__stdcall*  ZWQUERYDIRECTORYFILE)(
 62   __in  HANDLE FileHandle,
 63   __in_opt  HANDLE Event OPTIONAL,
 64   __in_opt  PIO_APC_ROUTINE ApcRoutine OPTIONAL,
 65   __in_opt  PVOID ApcContext OPTIONAL,
 66   __out PIO_STATUS_BLOCK IoStatusBlock,
 67   __out PVOID FileInformation,
 68   __in  ULONG Length,
 69   __in  FILE_INFORMATION_CLASS FileInformationClass,
 70   __in  BOOLEAN ReturnSingleEntry,
 71   __in  PUNICODE_STRING FileName OPTIONAL,
 72   __in  BOOLEAN RestartScan
 73   );
 74 
 75 int  ZwQueryDirectoryFileIndex;//作为ZwQueryDirectoryFileIndex在ssdt索引地址中的相对路径。
 76 
 77  
 78 NTSTATUS  __stdcall NewNtQueryDirectoryFile(
 79   __in  HANDLE FileHandle,
 80   __in_opt  HANDLE Event ,
 81   __in_opt  PIO_APC_ROUTINE ApcRoutine,
 82   __in_opt  PVOID ApcContext OPTIONAL,
 83   __out PIO_STATUS_BLOCK IoStatusBlock,
 84   __out PVOID FileInformation,
 85   __in  ULONG Length,
 86   __in  FILE_INFORMATION_CLASS FileInformationClass,
 87   __in  BOOLEAN ReturnSingleEntry,
 88   __in  PUNICODE_STRING FileName,
 89   __in  BOOLEAN RestartScan
 90   )
 91 {
 92   NTSTATUS status;
 93   ANSI_STRING ansiFileName,ansiDirName,HideDirFile;
 94   UNICODE_STRING uniFileName;
 95   ZWQUERYDIRECTORYFILE OldZwQueryDirectoryFile;
 96   int 1;
 97   //测试C盘中的123.txt是否可以被隐藏。
 98   RtlInitAnsiString(&HideDirFile,"123.txt"); 
 99   KdPrint(("hide: NewZwQueryDirectoryFile called."));
100 
101   if(MmIsAddressValidEx(OriginalServiceDescriptorTable->ServiceTable[ZwQueryDirectoryFileIndex]))//判断函数的地址是否有效
102 {
103       OldZwQueryDirectoryFile=OriginalServiceDescriptorTable->ServiceTable[ZwQueryDirectoryFileIndex];
104 }
105 else
106       OldZwQueryDirectoryFile=KeServiceDescriptorTable->ServiceTable[ZwQueryDirectoryFileIndex];
107 
108  status = OldZwQueryDirectoryFile (
109                   FileHandle,
110                   Event,
111                   ApcRoutine,
112                   ApcContext,
113                   IoStatusBlock,
114                   FileInformation,
115                   Length,
116                   FileInformationClass,
117                   ReturnSingleEntry,
118                   FileName,
119                   RestartScan);
120  if()
121   //这部分是隐藏文件的核心部分
122     if(NT_SUCCESS(status)&&FileInformationClass==FileBothDirectoryInformation)
123   {
124     PFILE_BOTH_DIR_INFORMATION pFileInfo;
125     PFILE_BOTH_DIR_INFORMATION pLastFileInfo;
126     BOOLEAN bLastOne=FALSE;
127     pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformation; 
128     pLastFileInfo = NULL;
129     do
130     {
131 bLastOne = !( pFileInfo->NextEntryOffset );
132 RtlInitUnicodeString(&uniFileName,pFileInfo->FileName);   RtlUnicodeStringToAnsiString(&ansiFileName,&uniFileName,TRUE);
133 RtlUnicodeStringToAnsiString(&ansiDirName,&uniFileName,TRUE);
134 
135 if( RtlCompareMemory(ansiFileName.Buffer,HideDirFile.Buffer,HideDirFile.Length ) == HideDirFile.Length)
136       {
137           if(bLastOne) 
138           {
139               pLastFileInfo->NextEntryOffset = 0;
140               break;
141           } 
142           else //指针往后移动
143           {
144             int iPos = ((ULONG)pFileInfo) - (ULONG)FileInformation;
145             int iLeft = (DWORD)Length - iPos - pFileInfo->NextEntryOffset;
146             RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft );
147             continue;
148           }
149       }
150       pLastFileInfo = pFileInfo;
151       pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((char *)pFileInfo + pFileInfo->NextEntryOffset);
152     }while(!bLastOne);
153     RtlFreeAnsiString(&ansiDirName); 
154     RtlFreeAnsiString(&ansiFileName);
155   }
156 goto  _FunctionRet;
157 
158 _FunctionRet:
159 
160      return   status;
161
162 }
163  

其中,指针类型变量强化转换为ULONG型变量。

(ULONG)pFileInfo ;//即把地址转化为ULONG型变量。

 (ULONG) FileInformation;

那么int  iPos=((ULONG)pFileInfo)- (ULONG) FileInformation;

得到的就是地址偏移值。

 int  iLeft=(DWORD)Length-iPos-pFileInfo->NextEntryOffset;

3.上述代码,采用WDK编译。然后再整合到MFC开发的用户界面程序中。

4.在Vmware虚拟机中,操作系统是Windows XP,做测试。

5.发现在点击XX.exe之后,C盘中的123.txt就消失不见。说明对123.txt的文件隐藏成功。

原文地址:https://www.cnblogs.com/meihao1989/p/4097979.html