DCART.c (357 lines of code) (raw):

#include <fltKernel.h> #include <dontuse.h> #include <suppress.h> #include <ntstrsafe.h> #pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers") PFLT_FILTER gFilterHandle; ULONG_PTR OperationStatusCtx = 1; DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath); NTSTATUS DriverUnload( _In_ FLT_FILTER_UNLOAD_FLAGS Flags); NTSTATUS InstanceSetup( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_SETUP_FLAGS Flags, _In_ DEVICE_TYPE VolumeDeviceType, _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType); VOID InstanceTeardownStart( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags); VOID InstanceTeardownComplete( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags); NTSTATUS InstanceQueryTeardown( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags); VOID OperationStatusCallback( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ PFLT_IO_PARAMETER_BLOCK ParameterSnapshot, _In_ NTSTATUS OperationStatus, _In_ PVOID RequesterContext); FLT_POSTOP_CALLBACK_STATUS PostOperation( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_opt_ PVOID CompletionContext, _In_ FLT_POST_OPERATION_FLAGS Flags); BOOLEAN DoRequestOperationStatus( _In_ PFLT_CALLBACK_DATA Data); #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) #pragma alloc_text(PAGE, DriverUnload) #pragma alloc_text(PAGE, InstanceQueryTeardown) #pragma alloc_text(PAGE, InstanceSetup) #pragma alloc_text(PAGE, InstanceTeardownStart) #pragma alloc_text(PAGE, InstanceTeardownComplete) #endif FLT_PREOP_CALLBACK_STATUS PreWrite( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Flt_CompletionContext_Outptr_ PVOID *CompletionContext) { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); NTSTATUS status; PFLT_FILE_NAME_INFORMATION pNameInfo = NULL; status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &pNameInfo); if (NT_SUCCESS(status)) { status = FltParseFileNameInformation(pNameInfo); if (NT_SUCCESS(status)) { ANSI_STRING aFileName; RtlUnicodeStringToAnsiString(&aFileName, &(pNameInfo->Name), TRUE); ULONG processId = FltGetRequestorProcessId(Data); UNICODE_STRING uDriverLogName; RtlInitUnicodeString(&uDriverLogName, L"\\Device\\HarddiskVolume2\\driver_log\\driver_log.dcart"); UNICODE_STRING uPythonLogName; RtlInitUnicodeString(&uPythonLogName, L"\\Device\\HarddiskVolume2\\python_log\\python_log.dcart"); LONG driverLogRetVal = RtlCompareUnicodeString(&(pNameInfo->Name), &uDriverLogName, TRUE); LONG pythonLogRetVal = RtlCompareUnicodeString(&(pNameInfo->Name), &uPythonLogName, TRUE); // this is to avoid filtering the writes created by this driver and the corresponding user space python process if ((4 != processId) && (0 != driverLogRetVal) && (0 != pythonLogRetVal)) { DbgPrint("WRITE | PID: %u | FileName = %s\n", processId, aFileName.Buffer); UNICODE_STRING uName; OBJECT_ATTRIBUTES objAttr; RtlInitUnicodeString(&uName, L"\\DosDevices\\C:\\driver_log\\driver_log.dcart"); InitializeObjectAttributes(&objAttr, &uName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); HANDLE handle; NTSTATUS ntstatus; IO_STATUS_BLOCK ioStatusBlock; if (PASSIVE_LEVEL != KeGetCurrentIrql()) { return STATUS_INVALID_DEVICE_STATE; } ntstatus = ZwCreateFile(&handle, FILE_APPEND_DATA, &objAttr, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); CHAR write_buffer[512]; size_t uLength; if (NT_SUCCESS(ntstatus)) { ntstatus = RtlStringCbPrintfA(write_buffer, sizeof(write_buffer), "WRITE|%u|%s\n", processId, aFileName.Buffer); RtlStringCbLengthA(write_buffer, sizeof(write_buffer), &uLength); LARGE_INTEGER ByteOffset; ByteOffset.HighPart = -1; ByteOffset.LowPart = FILE_WRITE_TO_END_OF_FILE; ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock, write_buffer, (ULONG)uLength, &ByteOffset, NULL); ZwClose(handle); } RtlFreeAnsiString(&aFileName); } } FltReleaseFileNameInformation(pNameInfo); } if (DoRequestOperationStatus(Data)) { status = FltRequestOperationStatusCallback(Data, OperationStatusCallback, (PVOID)(++OperationStatusCtx)); if (!NT_SUCCESS(status)) { DbgPrint("DCART!PreWrite: FltRequestOperationStatusCallback Failed, status=%08x\n", status); } } return FLT_PREOP_SUCCESS_WITH_CALLBACK; } FLT_PREOP_CALLBACK_STATUS PreSetInfo( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Flt_CompletionContext_Outptr_ PVOID *CompletionContext) { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); NTSTATUS status; PFLT_FILE_NAME_INFORMATION pNameInfo; PFILE_RENAME_INFORMATION pRenameInfo; ULONG processId = FltGetRequestorProcessId(Data); switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass) { case FileRenameInformation: FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED, &pNameInfo); FltReleaseFileNameInformation(pNameInfo); pRenameInfo = Data->Iopb->Parameters.SetFileInformation.InfoBuffer; ANSI_STRING aOldFileName; RtlUnicodeStringToAnsiString(&aOldFileName, &(pNameInfo->Name), TRUE); UNICODE_STRING uNewFileName; RtlInitUnicodeString(&uNewFileName, (PCWSTR)(&(pRenameInfo->FileName))); ANSI_STRING aNewFileName; RtlUnicodeStringToAnsiString(&aNewFileName, &uNewFileName, TRUE); UNICODE_STRING uDriverLogName; RtlInitUnicodeString(&uDriverLogName, L"\\Device\\HarddiskVolume2\\driver_log\\driver_log.dcart"); LONG driverLogRetVal = RtlCompareUnicodeString(&(pNameInfo->Name), &uDriverLogName, TRUE); if ((4 != processId) && (0 != driverLogRetVal)) { DbgPrint("RENAME | PID: %u | %s => %s\n", processId, aOldFileName.Buffer, aNewFileName.Buffer); UNICODE_STRING uName; OBJECT_ATTRIBUTES objAttr; RtlInitUnicodeString(&uName, L"\\DosDevices\\C:\\driver_log\\driver_log.dcart"); InitializeObjectAttributes(&objAttr, &uName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); HANDLE handle; NTSTATUS ntstatus; IO_STATUS_BLOCK ioStatusBlock; if (PASSIVE_LEVEL != KeGetCurrentIrql()) { return STATUS_INVALID_DEVICE_STATE; } ntstatus = ZwCreateFile(&handle, FILE_APPEND_DATA, &objAttr, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); CHAR write_buffer[512]; size_t uLength; if (NT_SUCCESS(ntstatus)) { ntstatus = RtlStringCbPrintfA(write_buffer, sizeof(write_buffer), "RENAME|%u|%s|%s\n", processId, aOldFileName.Buffer, aNewFileName.Buffer); RtlStringCbLengthA(write_buffer, sizeof(write_buffer), &uLength); LARGE_INTEGER ByteOffset; ByteOffset.HighPart = -1; ByteOffset.LowPart = FILE_WRITE_TO_END_OF_FILE; ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock, write_buffer, (ULONG)uLength, &ByteOffset, NULL); ZwClose(handle); } RtlFreeAnsiString(&aOldFileName); RtlFreeAnsiString(&aNewFileName); } break; default: break; } if (DoRequestOperationStatus(Data)) { status = FltRequestOperationStatusCallback(Data, OperationStatusCallback, (PVOID)(++OperationStatusCtx)); if (!NT_SUCCESS(status)) { DbgPrint("DCART!PreSetInfo: FltRequestOperationStatusCallback Failed, status=%08x\n", status); } } return FLT_PREOP_SUCCESS_WITH_CALLBACK; } // only registering two callbacks to handle write and setinfo (rename) CONST FLT_OPERATION_REGISTRATION Callbacks[] = { {IRP_MJ_WRITE, 0, PreWrite, PostOperation}, {IRP_MJ_SET_INFORMATION, 0, PreSetInfo, PostOperation}, {IRP_MJ_OPERATION_END} }; CONST FLT_REGISTRATION FilterRegistration = { sizeof(FLT_REGISTRATION), // Size FLT_REGISTRATION_VERSION, // Version 0, // Flags NULL, // Context Callbacks, // Operation callbacks DriverUnload, // MiniFilterUnload InstanceSetup, // InstanceSetup InstanceQueryTeardown, // InstanceQueryTeardown InstanceTeardownStart, // InstanceTeardownStart InstanceTeardownComplete, // InstanceTeardownComplete NULL, // GenerateFileName NULL, // GenerateDestinationFileName NULL // NormalizeNameComponent }; NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); NTSTATUS status; DbgPrint("DCART!DriverEntry\n"); status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle); if (!NT_SUCCESS(status)) { return status; } if (NT_SUCCESS(status)) { status = FltStartFiltering(gFilterHandle); if (NT_SUCCESS(status)) { return status; } } FltUnregisterFilter(gFilterHandle); return status; } NTSTATUS DriverUnload( _In_ FLT_FILTER_UNLOAD_FLAGS Flags) { UNREFERENCED_PARAMETER(Flags); PAGED_CODE(); DbgPrint("DCART!DriverUnload\n"); FltUnregisterFilter(gFilterHandle); return STATUS_SUCCESS; } NTSTATUS InstanceSetup( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_SETUP_FLAGS Flags, _In_ DEVICE_TYPE VolumeDeviceType, _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType) { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(Flags); UNREFERENCED_PARAMETER(VolumeDeviceType); UNREFERENCED_PARAMETER(VolumeFilesystemType); PAGED_CODE(); DbgPrint("DCART!InstanceSetup\n"); return STATUS_SUCCESS; } NTSTATUS InstanceQueryTeardown( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags) { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(Flags); PAGED_CODE(); DbgPrint("DCART!InstanceQueryTeardown\n"); return STATUS_SUCCESS; } VOID InstanceTeardownStart( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags) { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(Flags); PAGED_CODE(); DbgPrint("DCART!InstanceTeardownStart\n"); } VOID InstanceTeardownComplete( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags) { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(Flags); PAGED_CODE(); DbgPrint("DCART!InstanceTeardownComplete\n"); } VOID OperationStatusCallback( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ PFLT_IO_PARAMETER_BLOCK ParameterSnapshot, _In_ NTSTATUS OperationStatus, _In_ PVOID RequesterContext) { UNREFERENCED_PARAMETER(FltObjects); DbgPrint("DCART!OperationStatusCallback: Status=%08x ctx=%p IrpMj=%02x.%02x \"%s\"\n", OperationStatus, RequesterContext, ParameterSnapshot->MajorFunction, ParameterSnapshot->MinorFunction, FltGetIrpName(ParameterSnapshot->MajorFunction)); } FLT_POSTOP_CALLBACK_STATUS PostOperation( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_opt_ PVOID CompletionContext, _In_ FLT_POST_OPERATION_FLAGS Flags) { UNREFERENCED_PARAMETER(Data); UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); UNREFERENCED_PARAMETER(Flags); return FLT_POSTOP_FINISHED_PROCESSING; } BOOLEAN DoRequestOperationStatus( _In_ PFLT_CALLBACK_DATA Data) { PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb; // return boolean state based on which operations we are interested in return (BOOLEAN) // check for oplock operations (((iopb->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) && ((iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK) || (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK) || (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_1) || (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2))) || // check for directy change notification ((iopb->MajorFunction == IRP_MJ_DIRECTORY_CONTROL) && (iopb->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)) ); }