編寫驅(qū)動(dòng)攔截NT的API完成隱藏文件目錄
發(fā)表時(shí)間:2024-02-14 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]目前NT下有很多種隱藏文件和目錄的方法,其中最簡(jiǎn)單的一種是給文件和文件夾加上系統(tǒng)屬性和隱藏屬性,操作系統(tǒng)就會(huì)不在顯示了,而且查找也找不到了,但是這種方法一點(diǎn)都不徹底,沒有可用性!下面我們來介紹用NT驅(qū)動(dòng)程序來攔截NTAPI來實(shí)現(xiàn)徹底隱藏文件和目錄的目的。NT下有一個(gè)文件NTDLL.DLL,大部分N...
目前NT下有很多種隱藏文件和目錄的方法,其中最簡(jiǎn)單的一種是給文件和文件夾加上系統(tǒng)屬性和隱藏屬性,操作系統(tǒng)就會(huì)不在顯示了,而且查找也找不到了,但是這種方法一點(diǎn)都不徹底,沒有可用性!下面我們來介紹用NT驅(qū)動(dòng)程序來攔截NTAPI來實(shí)現(xiàn)徹底隱藏文件和目錄的目的。NT下有一個(gè)文件NTDLL.DLL,大部分NTAPI都是在這個(gè)庫中封裝的。其中實(shí)現(xiàn)查找文件和目錄的API接口是ZwQueryDirectoryFile,所以我們只要攔截這個(gè)API的話,文件和目錄就可以完全隱藏了!下面來一步不實(shí)現(xiàn)(準(zhǔn)備工作:到NTDDK中找一個(gè)WDM驅(qū)動(dòng)程序模型,也就是最簡(jiǎn)單的驅(qū)動(dòng)程序了):
1.定義FILE_INFORMATION_CLASS的第3號(hào)結(jié)構(gòu):_FILE_BOTH_DIR_INFORMATION,這個(gè)結(jié)構(gòu)是ZwQueryDirectoryFile必須參數(shù)。
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 pIoStatusBlock,
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);
//定義一個(gè)原函數(shù)指針
REALZWQUERYSYSTEMINFORMATION RealZwQuerySystemInformation;
3.定義替換API函數(shù)的原型:
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.在DriverEntry(驅(qū)動(dòng)入口)函數(shù)中加入如下申明:
//保存真正的ZwQueryDirectoryFile函數(shù)地址
RealZwQueryDirectoryFile=(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile));
//把自定義的替換函數(shù)指針指向真正的ZwQueryDirectoryFile函數(shù)
(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile))=HookZwQueryDirectoryFile;
5.在DriverUnload(驅(qū)動(dòng)卸載函數(shù))函數(shù)中加入恢復(fù)代碼:
//恢復(fù)原來的函數(shù)指針
(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile))=RealZwQueryDirectoryFile;
6.現(xiàn)在準(zhǔn)備工作做好了,函數(shù)指針都已經(jīng)設(shè)置轉(zhuǎn)向了,剩下的是實(shí)現(xiàn)這個(gè)我們自定義的替換函數(shù)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,HideDirFile;
UNICODE_STRING uniFileName;
//初始化要過慮的文件名這里是debug.exe
RtlInitAnsiString(&HideDirFile,"DBGVIEW.EXE");
// 執(zhí)行真正的ZwQueryDirectoryFile函數(shù)
rc = ((REALZWQUERYDIRECTORYFILE)(RealZwQueryDirectoryFile))(
hFile,
hEvent,
IoApcRoutine,
IoApcContext,
pIoStatusBlock,
FileInformationBuffer,
FileInformationBufferLength,
FileInfoClass,
bReturnOnlyOneEntry,
PathMask,
bRestartQuery);
/*如果執(zhí)行成功(而且FILE_INFORMATION_CLASS的值為FileBothDirectoryInformation,我們就進(jìn)行處理,過濾*/
if(NT_SUCCESS(rc)&& (FileInfoClass == FileBothDirectoryInformation))
{
PFILE_BOTH_DIR_INFORMATION pFileInfo;
PFILE_BOTH_DIR_INFORMATION pLastFileInfo;
BOOL bLastOne;
//把執(zhí)行結(jié)果賦給pFileInfo
pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer;
pLastFileInfo = NULL;
//循環(huán)檢查
do
{
bLastOne = !( pFileInfo->NextEntryOffset );
RtlInitUnicodeString(&uniFileName,pFileInfo->FileName);
RtlUnicodeStringToAnsiString(&ansiFileName,&uniFileName,TRUE);
RtlUnicodeStringToAnsiString(&ansiDirName,&uniFileName,TRUE);
RtlUpperString(&ansiFileName,&ansiDirName);
//打印結(jié)果,用debugview可以查看打印結(jié)果
DbgPrint("ansiFileName :%s\n",ansiFileName.Buffer);
DbgPrint("HideDirFile :%s\n",HideDirFile.Buffer);
// 開始進(jìn)行比較,如果找到了就隱藏這個(gè)文件或者目錄
if( RtlCompareMemory(ansiFileName.Buffer,HideDirFile.Buffer,HideDirFile.Length ) == HideDirFile.Length)
{
DbgPrint("This is HideDirFile!\n");
if(bLastOne)
{
if(pFileInfo == (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer )
{
rc = 0x80000006; //隱藏文件或者目錄;
}
else
{
pLastFileInfo->NextEntryOffset = 0;
}
break;
}
else //指針往后移動(dòng)
{
int iPos = ((ULONG)pFileInfo) - (ULONG)FileInformationBuffer;
int iLeft = (DWORD)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);
}
本代碼在開發(fā)機(jī)器(WINXP+SP1+XPDDK)上測(cè)試通過!