編寫驅動攔截NT的API實現隱藏檔案目錄 (轉)

gugu99發表於2007-08-17
編寫驅動攔截NT的API實現隱藏檔案目錄 (轉)[@more@]

  目前NT下有很多種隱藏和目錄的方法,其中最簡單的一種是給檔案和資料夾加上屬性和隱藏屬性,就會不在顯示了,而且查詢也找不到了,但是這種方法一點都不徹底,沒有可用性!下面我們來介紹用NT來攔截NT來實現徹底隱藏檔案和目錄的目的。NT下有一個檔案NTDLL.DLL,大部分NTAPI都是在這個庫中封裝的。其中實現查詢檔案和目錄的API介面是ZwQueryDirectoryFile,所以我們只要攔截這個API的話,檔案和目錄就可以完全隱藏了!下面來一步不實現(準備工作:到NTDDK中找一個WDM驅動程式模型,也就是最簡單的驅動程式了):

  1.定義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;

 

2.先申明ZwQueryDirectoryFile,然後定義ZwQueryDirectoryFile的原型:

extern NTSYSAPI NTSTATUS NTAPI ZwQueryDirectoryFile(
 IN HANDLE hFile,
 IN HANDLE hEvent OPTIONAL,
 IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
 IN PVOID IoApcContext OPTIONAL,
 OUT PIO_STATUS_BLOCK pIoStatlock,
 OUT PVOID FileInformationBuffer,
 IN ULONG FileInformationBufferLength,
 IN FILE_INFORMATION_CLASS FileInfoClass,
 IN BOOLEAN bReturnOnlyOneEntry,
 IN PUNICODE_STRING PathMask OPTIONAL,
 IN BOOLEAN bRestartQuery);

//定義ZwQueryDirectoryFile的原型

typedef NTSTATUS (*REALZWQUERYDIRECTORYFILE)(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);

//定義一個原指標
REALZWQUERYSYSTEMINFORMATION RealZwQuerySystemInformation;

3.定義替換API函式的原型:

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);

4.在Entry(驅動入口)函式中加入如下申明:

//儲存真正的ZwQueryDirectoryFile函式地址

RealZwQueryDirectoryFile=(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile));

//把自定義的替換函式指標指向真正的ZwQueryDirectoryFile函式

(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile))=HookZwQueryDirectoryFile;

5.在DriverUnload(驅動解除安裝函式)函式中加入恢復程式碼:

//恢復原來的函式指標

(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile))=RealZwQueryDirectoryFile;

6.現在準備工作做好了,函式指標都已經設定轉向了,剩下的是實現這個我們自定義的替換函式HookZwQueryDirectoryFile,程式碼如下:

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;
 ULONG CR0VALUE;
 
 ANSI_STRING ansiFileName,ansiDirName,HDirFile;
 UNICODE_STRING uniFileName;
 
 //初始化要過慮的檔名這裡是de.exe
 RtlInitAnsiString(&HideDirFile,"GVIEW.EXE"); 
 
 // 真正的ZwQueryDirectoryFile函式
 rc = ((REALZWQUERYDIRECTORYFILE)(RealZwQueryDirectoryFile))(
 hFile,
 hEvent,
 IoApcRoutine,
 IoApcContext,
 pIoStatusBlock,
 FileInformationBuffer,
 FileInformationBufferLength,
 FileInfoClass,
 bReturnOnlyOneEntry,
 PathMask,
 bRestartQuery);
  /*如果執行成功(而且FILE_INFORMATION_CLASS的值為FileBothDirectoryInformation,我們就進行處理,過濾*/
  if(NT_SUCCESS(rc)&& (FileInfoClass == FileBothDirectoryInformation))
 {
 PFILE_BOTH_DIR_INFORMATION pFileInfo;
 PFILE_BOTH_DIR_INFORMATION pLastFileInfo;
 BOOL bLastOne;
 //把執行結果賦給pFileInfo 
 pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer; 
 pLastFileInfo = NULL;
 //迴圈檢查
 do
 {
 bLastOne = !( pFileInfo->NextEntryOffset );
 RtlInitUnicodeString(&uniFileName,pFileInfo->FileName);
 RtlUnicodeStringToAnsiString(&ansiFileName,&uniFileName,TRUE);
 RtlUnicodeStringToAnsiString(&ansiDirName,&uniFileName,TRUE);
 RtlUpperString(&ansiFileName,&ansiDirName);
 //列印結果,用debugview可以檢視列印結果
 DbgPrint("ansiFileName :%s ",ansiFileName.Buffer);
 DbgPrint("HideDirFile :%s ",HideDirFile.Buffer);
 
 // 開始進行比較,如果找到了就隱藏這個檔案或者目錄
 if( RtlCompareMemory(ansiFileName.Buffer,HideDirFile.Buffer,HideDirFile.Length ) == HideDirFile.Length)
 {
 DbgPrint("This is HideDirFile! ");
 if(bLastOne)
 {
 if(pFileInfo == (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer )
 {
 rc = 0x80000006; //隱藏檔案或者目錄;
 }
 else
 {
 pLastFileInfo->NextEntryOffset = 0;
 }
 break;
 }
 else //指標往後移動
 {
 int iP= ((ULONG)pFileInfo) - (ULONG)FileInformationBuffer;
 int iLeft = (D)FileInformationBufferLength - iPos - pFileInfo->NextEntryOffset;
 RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft );
 continue;
 }
 }
 pLastFileInfo = pFileInfo;
 pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((char *)pFileInfo + pFileInfo->NextEntryOffset);
 
 }while(!bLastOne);
 RtlFreeAnsiString(&ansiDirName);
 RtlFreeAnsiString(&ansiFileName);
 }
 return(rc);
}

本程式碼在開發機器(+SP1+XPDDK)上測試透過!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-963553/,如需轉載,請註明出處,否則將追究法律責任。

相關文章