static FLT_POSTOP_CALLBACK_STATUS FileCreateFilterPostCallback ( PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID CompletionContext, FLT_POST_OPERATION_FLAGS Flags ) { FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING; KLOCK_QUEUE_HANDLE hMutex = { 0 }; PFLT_FILE_NAME_INFORMATION fileInfo = NULL; RU32 pid = 0; RU64 ts = 0; RU32 createOptions = 0; RU32 createDispositions = 0; _fileContext* context = NULL; UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( CompletionContext ); UNREFERENCED_PARAMETER( Flags ); // We only care about user mode for now. if( UserMode != Data->RequestorMode || STATUS_SUCCESS != Data->IoStatus.Status ) { return status; } if( FILE_CREATED == Data->IoStatus.Information ) { pid = (RU32)FltGetRequestorProcessId( Data ); ts = rpal_time_getLocal(); if( !NT_SUCCESS( FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP, &fileInfo ) ) ) { rpal_debug_kernel( "Failed to get file name info" ); fileInfo = NULL; } else { //rpal_debug_kernel( "NEW: %wZ", fileInfo->Name ); } if( NULL != ( context = _getOrSetContext( Data ) ) ) { context->isNew = TRUE; FltReleaseContext( (PFLT_CONTEXT)context ); } KeAcquireInStackQueuedSpinLock( &g_collector_2_mutex, &hMutex ); g_files[ g_nextFile ].pid = pid; g_files[ g_nextFile ].ts = ts; g_files[ g_nextFile ].uid = KERNEL_ACQ_NO_USER_ID; g_files[ g_nextFile ].action = KERNEL_ACQ_FILE_ACTION_ADDED; if( NULL != fileInfo ) { copyUnicodeStringToBuffer( &fileInfo->Name, g_files[ g_nextFile ].path ); FltReleaseFileNameInformation( fileInfo ); } g_nextFile++; if( g_nextFile == _NUM_BUFFERED_FILES ) { g_nextFile = 0; } KeReleaseInStackQueuedSpinLock( &hMutex ); } createOptions = Data->Iopb->Parameters.Create.Options & 0x00FFFFFF; createDispositions = ( Data->Iopb->Parameters.Create.Options & 0xFF000000 ) >> 24; if( IS_FLAG_ENABLED( createOptions, FILE_DELETE_ON_CLOSE ) ) { if( NULL != ( context = _getOrSetContext( Data ) ) ) { context->isDelete = TRUE; FltReleaseContext( (PFLT_CONTEXT)context ); } } return status; }
static FLT_POSTOP_CALLBACK_STATUS FileSetInfoFilterPostCallback ( PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID CompletionContext, FLT_POST_OPERATION_FLAGS Flags ) { FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING; KLOCK_QUEUE_HANDLE hMutex = { 0 }; PFLT_FILE_NAME_INFORMATION fileInfoSrc = NULL; PFLT_FILE_NAME_INFORMATION fileInfoDst = NULL; RU32 pid = 0; RU64 ts = 0; RU32 createOptions = 0; RU32 createDispositions = 0; PFILE_RENAME_INFORMATION renameInfo = NULL; _fileContext* context = NULL; UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( CompletionContext ); UNREFERENCED_PARAMETER( Flags ); // We only care about user mode for now. if( UserMode != Data->RequestorMode || STATUS_SUCCESS != Data->IoStatus.Status ) { return status; } if( FileRenameInformation == Data->Iopb->Parameters.SetFileInformation.FileInformationClass ) { if( NULL != ( fileInfoSrc = (PFLT_FILE_NAME_INFORMATION)CompletionContext ) ) { //rpal_debug_kernel( "MOVE OLD: %wZ", fileInfoSrc->Name ); } else { rpal_debug_kernel( "Failed to get src file name info" ); } renameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer; if( !NT_SUCCESS( FltGetDestinationFileNameInformation( FltObjects->Instance, FltObjects->FileObject, renameInfo->RootDirectory, renameInfo->FileName, renameInfo->FileNameLength, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP, &fileInfoDst ) ) ) { rpal_debug_kernel( "Failed to get dst file name info" ); } else { //rpal_debug_kernel( "MOVE TO: %wZ", fileInfoDst->Name ); } pid = (RU32)FltGetRequestorProcessId( Data ); ts = rpal_time_getLocal(); createOptions = Data->Iopb->Parameters.Create.Options & 0x00FFFFFF; createDispositions = ( Data->Iopb->Parameters.Create.Options & 0xFF000000 ) >> 24; KeAcquireInStackQueuedSpinLock( &g_collector_2_mutex, &hMutex ); g_files[ g_nextFile ].pid = pid; g_files[ g_nextFile ].ts = ts; g_files[ g_nextFile ].uid = KERNEL_ACQ_NO_USER_ID; // For compability with the user mode API we report file moves // as two different operations. // First we report the old file name. g_files[ g_nextFile ].action = KERNEL_ACQ_FILE_ACTION_RENAME_OLD; if( NULL != fileInfoSrc ) { copyUnicodeStringToBuffer( &fileInfoSrc->Name, g_files[ g_nextFile ].path ); FltReleaseFileNameInformation( fileInfoSrc ); } g_nextFile++; if( g_nextFile == _NUM_BUFFERED_FILES ) { g_nextFile = 0; } // Now report the new file name. g_files[ g_nextFile ].action = KERNEL_ACQ_FILE_ACTION_RENAME_NEW; if( NULL != fileInfoDst ) { copyUnicodeStringToBuffer( &fileInfoDst->Name, g_files[ g_nextFile ].path ); FltReleaseFileNameInformation( fileInfoDst ); } g_nextFile++; if( g_nextFile == _NUM_BUFFERED_FILES ) { g_nextFile = 0; } KeReleaseInStackQueuedSpinLock( &hMutex ); } else if( FileDispositionInformationEx == Data->Iopb->Parameters.SetFileInformation.FileInformationClass ||
FLT_PREOP_CALLBACK_STATUS FLTAPI FilterPreCreate( FLT_CALLBACK_DATA* Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext ) { NTSTATUS status; FLT_FILE_NAME_INFORMATION *nameInformation; UNICODE_STRING *fullPath; status = FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInformation ); if (status == STATUS_SUCCESS) { status = FltParseFileNameInformation(nameInformation); if (status == STATUS_SUCCESS) { FLT_FILE_LIST_ENTRY *file = FltFileList; fullPath = &nameInformation->Name; if ((Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & FILE_EXECUTE) //Execute && (nameInformation->FinalComponent.Length == 16 //d3d8.dll/d3d9.dll || nameInformation->FinalComponent.Length == 18)) //d3d10.dll/d3d11.dll { if (wcsncmp(L"d3d8.dll", nameInformation->FinalComponent.Buffer, 8) == 0 || wcsncmp(L"d3d9.dll", nameInformation->FinalComponent.Buffer, 8) == 0 || wcsncmp(L"d3d10.dll", nameInformation->FinalComponent.Buffer, 9) == 0 || wcsncmp(L"d3d11.dll", nameInformation->FinalComponent.Buffer, 9) == 0) { PROCESSID processId; DEVICE_EXTENSION *deviceExtension; processId = FltGetRequestorProcessId(Data); deviceExtension = g_DeviceObject->DeviceExtension; deviceExtension->imageEvent.processID = processId; KeSetEvent(PushGpuAccelerationEvent, 0, FALSE); KeClearEvent(PushGpuAccelerationEvent); DbgPrint("[PUSH] %u loaded %wZ\n", processId, fullPath); } } while (file != 0) { if (fullPath->Length == file->NameLength && wcsncmp(file->Name, fullPath->Buffer, file->NameLength / sizeof(WCHAR)) == 0) { UNICODE_STRING newName; UNICODE_STRING redirect; UNICODE_STRING *currentName; UINT16 newNameSize; WCHAR *buffer; //DbgPrint("[PUSH] %ws matches %wZ", file->Name, fullPath); RtlInitUnicodeString(&newName, PUSH_RAMDISK_DEVICE_NAME L"\\"); // Calculate the size of the name newNameSize = newName.Length + nameInformation->FinalComponent.Length; redirect.Length = newName.Length; redirect.MaximumLength = newNameSize; redirect.Buffer = ExAllocatePool(NonPagedPool, newNameSize); // Copy ramdisk device name into buffer RtlCopyMemory(redirect.Buffer, newName.Buffer, newName.Length); // Append original file name //RtlAppendUnicodeStringToString(&redirect, &nameInformation->FinalComponent); buffer = &redirect.Buffer[redirect.Length / sizeof(WCHAR)]; RtlMoveMemory( buffer, nameInformation->FinalComponent.Buffer, nameInformation->FinalComponent.Length ); redirect.Length += nameInformation->FinalComponent.Length; currentName = &Data->Iopb->TargetFileObject->FileName; // Throw away the current file name ExFreePool(currentName->Buffer); currentName->Length = 0; currentName->MaximumLength = redirect.MaximumLength; currentName->Buffer = ExAllocatePool(NonPagedPool, redirect.MaximumLength); // Copy new path to buffer RtlCopyUnicodeString(currentName, &redirect); // Be nice and give back what was given to us ExFreePool(redirect.Buffer); Data->IoStatus.Information = IO_REPARSE; Data->IoStatus.Status = STATUS_REPARSE; Data->Iopb->TargetFileObject->RelatedFileObject = NULL; FltSetCallbackDataDirty(Data); return FLT_PREOP_COMPLETE; } file = file->NextEntry; } } } return FLT_PREOP_SUCCESS_NO_CALLBACK; }