FltSendMessage.
Below is the code I had been using before I began reading into workitems.
#include <fltkernel.h>
#include <dontuse.h>
#include <suppress.h>
#include <ntddk.h>
#include <ntifs.h>
#pragma warning(disable:4995)
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#pragma warning(default:4995)
const PWSTR DriverName = L"\fdriver";
typedef struct _DRV_MESSAGE_SEND
{
DWORD dwUniqueMessageId;
BOOLEAN fCreate, fRead, fWrite, fExecute;
DWORD dwProcId;
WCHAR wzChildFileName[1024];
} DRV_MESSAGE_SEND, *PDRV_MESSAGE_SEND;
typedef struct _DRV_MESSAGE_RECV { BOOLEAN fAccess; } DRV_MESSAGE_RECV, *PDRV_MESSAGE_RECV;
typedef struct _DRV_TIMER_MESSAGE_RECV { DWORD dwUniqueMessageId; } DRV_TIMER_MESSAGE_RECV, *PDRV_TIMER_MESSAGE_RECV;
typedef struct _STREAM_HANDLE_CONTEXT { BOOLEAN fRequired; } STREAM_HANDLE_CONTEXT, *PSTREAM_HANDLE_CONTEXT;
typedef struct _CREATE_PARAMS { WCHAR wString[0]; } CREATE_PARAMS, *PCREATE_PARAMS;
typedef struct _MAIN_SERVICE_DATA
{
HANDLE ThreadHandle;
PDRIVER_OBJECT pDriverObject;
PFLT_FILTER pFltFilter;
PFLT_PORT pFltServicePort;
PFLT_PORT pFltClientPort;
PEPROCESS pEprocess;
} MAIN_SERVICE_DATA, *PMAIN_SERVICE_DATA;
MAIN_SERVICE_DATA MainServiceData;
typedef struct _TIMER_SERVICE_DATA
{
DWORD dwLastUniqueMessageId;
DWORD dwUniqueMessageId;
KDPC KTimerDpc;
KTIMER KTimer;
} TIMER_SERVICE_DATA, PTIMER_SERVICE_DATA;
TIMER_SERVICE_DATA TimerServiceData;
NTSTATUS DriverEntry (PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath);
NTSTATUS DriverUnload (FLT_FILTER_UNLOAD_FLAGS FltFilterUnloadFlags);
NTSTATUS DriverInstanceSetup (PCFLT_RELATED_OBJECTS PcFltRelatedObjects, FLT_INSTANCE_SETUP_FLAGS FltInstanceSetupFlags, DEVICE_TYPE DeviceType, FLT_FILESYSTEM_TYPE FltFileSystemType);
NTSTATUS DriverQueryTearDown (PCFLT_RELATED_OBJECTS PcFltRelatedObjects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS FltInstanceQueryTearDownFlags);
FLT_PREOP_CALLBACK_STATUS PreCreate (PFLT_CALLBACK_DATA pFltCallbackData, PCFLT_RELATED_OBJECTS PcFltRelatedObjects, PVOID pContext);
FLT_PREOP_CALLBACK_STATUS SendFileToService(PFLT_CALLBACK_DATA pFltCallbackData, PCFLT_RELATED_OBJECTS PcFltRelatedObjects, PVOID pContext, BOOLEAN fCreate, BOOLEAN fRead, BOOLEAN fWrite);
NTSTATUS ClientServiceConnect (PFLT_PORT pFltClientPort, PVOID pCookie, PVOID pContext, ULONG uContextSize, PVOID pConnCookie);
VOID ClientServiceDisconnect (PVOID pConnCookie);
NTSTATUS ClientServiceMessages (PVOID pCookie, PVOID pIBuffer, ULONG InputLength, PVOID pOBuffer, ULONG OutputLength, PULONG ReturnBufferLength);
NTSTATUS TimerCreate();
VOID TimerDestory();
KDEFERRED_ROUTINE TimerClientServiceDpc;
VOID TimerClientServiceDpc(struct _KDPC kDpc, PVOID pContext, PVOID pArgu1, PVOID pArgu2);
const FLT_OPERATION_REGISTRATION FltOperationRegistrationCallbacks[] = { {IRP_MJ_CREATE, 0, PreCreate, NULL }, {IRP_MJ_OPERATION_END} };
const FLT_CONTEXT_REGISTRATION FltContextRegistration[] = { { FLT_STREAMHANDLE_CONTEXT, 0, NULL, sizeof(STREAM_HANDLE_CONTEXT), ‘corp’ }, {FLT_CONTEXT_END}};
const FLT_REGISTRATION FltRegistration = { sizeof(FLT_REGISTRATION), FLT_REGISTRATION_VERSION, 0, FltContextRegistration, FltOperationRegistrationCallbacks, DriverUnload, DriverInstanceSetup, DriverQueryTearDown, NULL, NULL, NULL, NULL, NULL };
NTSTATUS DriverEntry (PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING wzString;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
NTSTATUS NtStatus;
NtStatus = FltRegisterFilter(pDriverObject, &FltRegistration, &MainServiceData.pFltFilter);
if(NtStatus != STATUS_SUCCESS) return NtStatus;
NtStatus = FltBuildDefaultSecurityDescriptor(&pSecurityDescriptor, FLT_PORT_ALL_ACCESS);
if(NtStatus != STATUS_SUCCESS) { FltUnregisterFilter(MainServiceData.pFltFilter); return NtStatus; }
RtlInitUnicodeString(&wzString, DriverName);
InitializeObjectAttributes(&ObjectAttributes, &wzString, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, pSecurityDescriptor);
NtStatus = FltCreateCommunicationPort(MainServiceData.pFltFilter, &MainServiceData.pFltServicePort, &ObjectAttributes, NULL, ClientServiceConnect, ClientServiceDisconnect, ClientServiceMessages, 1); FltFreeSecurityDescriptor(pSecurityDescriptor);
if(NtStatus != STATUS_SUCCESS) { FltUnregisterFilter(MainServiceData.pFltFilter); return NtStatus; }
NtStatus = FltStartFiltering(MainServiceData.pFltFilter);
if(NtStatus != STATUS_SUCCESS) { FltCloseCommunicationPort(MainServiceData.pFltServicePort); FltUnregisterFilter(MainServiceData.pFltFilter); return NtStatus; }
return STATUS_SUCCESS;
}
NTSTATUS DriverUnload (FLT_FILTER_UNLOAD_FLAGS FltFilterUnloadFlags)
{
FltCloseCommunicationPort(MainServiceData.pFltServicePort);
FltUnregisterFilter(MainServiceData.pFltFilter);
return STATUS_SUCCESS;
}
NTSTATUS DriverInstanceSetup (PCFLT_RELATED_OBJECTS PcFltRelatedObjects, FLT_INSTANCE_SETUP_FLAGS FltInstanceSetupFlags, DEVICE_TYPE DeviceType, FLT_FILESYSTEM_TYPE FltFileSystemType)
{
ASSERT(FltObjects->Filter == MainServiceData.pFltFilter);
if(DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) return STATUS_FLT_DO_NOT_ATTACH;
return STATUS_SUCCESS;
}
NTSTATUS DriverQueryTearDown (PCFLT_RELATED_OBJECTS PcFltRelatedObjects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS FltInstanceQueryTearDownFlags)
{
return STATUS_SUCCESS;
}
FLT_PREOP_CALLBACK_STATUS PreCreate (PFLT_CALLBACK_DATA pFltCallbackData, PCFLT_RELATED_OBJECTS PcFltRelatedObjects, PVOID pContext)
{
return SendFileToService(pFltCallbackData, PcFltRelatedObjects, pContext, TRUE, FALSE, FALSE);
}
FLT_PREOP_CALLBACK_STATUS SendFileToService(PFLT_CALLBACK_DATA pFltCallbackData, PCFLT_RELATED_OBJECTS PcFltRelatedObjects, PVOID pContext, BOOLEAN fCreate, BOOLEAN fRead, BOOLEAN fWrite)
{
PFLT_FILE_NAME_INFORMATION pFltFileNameInformation;
NTSTATUS NtStatus;
PDRV_MESSAGE_SEND pDrvMessageSend;
ULONG ReplyLength;
if(PsIsSystemThread(pFltCallbackData->Thread)) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if(IoThreadToProcess(pFltCallbackData->Thread) == MainServiceData.pEprocess) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if(!NT_SUCCESS(pFltCallbackData->IoStatus.Status) || pFltCallbackData->IoStatus.Status == STATUS_REPARSE) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if(MainServiceData.pFltClientPort == NULL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
NtStatus = FltGetFileNameInformation(pFltCallbackData, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &pFltFileNameInformation);
if(NtStatus != STATUS_SUCCESS) return FLT_PREOP_SUCCESS_NO_CALLBACK;
pDrvMessageSend = ExAllocatePoolWithTag(NonPagedPool, sizeof(DRV_MESSAGE_SEND), ‘corp’);
if(pDrvMessageSend == NULL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
FltParseFileNameInformation(pFltFileNameInformation);
pDrvMessageSend->dwUniqueMessageId = 2201;
pDrvMessageSend->fCreate = fCreate;
pDrvMessageSend->fRead = fRead;
pDrvMessageSend->fWrite = fWrite;
pDrvMessageSend->fExecute = FALSE;
pDrvMessageSend->dwProcId = (DWORD) PsGetProcessId(IoThreadToProcess(pFltCallbackData->Thread));
RtlStringCbCopyUnicodeString(pDrvMessageSend->wzChildFileName, 1024, &pFltFileNameInformation->Name);
ReplyLength = sizeof(DRV_MESSAGE_SEND);
NtStatus = FltSendMessage(MainServiceData.pFltFilter, &MainServiceData.pFltClientPort, pDrvMessageSend, sizeof(DRV_MESSAGE_SEND), pDrvMessageSend, &ReplyLength, NULL);
if(NtStatus != STATUS_SUCCESS) NtStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
else
{
if(((PDRV_MESSAGE_RECV)pDrvMessageSend)->fAccess) NtStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
else NtStatus = STATUS_UNSUCCESSFUL;
}
ExFreePoolWithTag(pDrvMessageSend, ‘corp’);
return NtStatus;
}
NTSTATUS ClientServiceConnect (PFLT_PORT pFltClientPort, PVOID pCookie, PVOID pContext, ULONG uContextSize, PVOID pConnCookie)
{
NTSTATUS NtStatus;
DbgPrint(“ClientServiceConnect Called.\n”);
ASSERT(MainServiceData.pFltClientPort == NULL);
ASSERT(MainServiceData.pEprocess == NULL);
MainServiceData.pEprocess = PsGetCurrentProcess();
MainServiceData.pFltClientPort = pFltClientPort;
TimerCreate();
return STATUS_SUCCESS;
}
VOID ClientServiceDisconnect (PVOID pConnCookie)
{
DbgPrint(“ClientServiceDisconnect Called.\n”);
FltCloseClientPort(MainServiceData.pFltFilter, &MainServiceData.pFltClientPort);
MainServiceData.pEprocess = NULL;
TimerDestory();
}
NTSTATUS ClientServiceMessages (PVOID pCookie, PVOID pIBuffer, ULONG InputLength, PVOID pOBuffer, ULONG OutputLength, PULONG ReturnBufferLength)
{
NTSTATUS NtStatus;
DWORD dwUniqueMessageId;
if(pIBuffer != NULL && InputLength >= FIELD_OFFSET(DRV_TIMER_MESSAGE_RECV, dwUniqueMessageId) + sizeof(DWORD))
{
try
{
TimerServiceData.dwLastUniqueMessageId = (DWORD) ((PDRV_TIMER_MESSAGE_RECV) pIBuffer)->dwUniqueMessageId;
DbgPrint(“Message Incoming. [dwLastUniqueMessageId=‘%d’]\n”, TimerServiceData.dwLastUniqueMessageId);
} except (EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); }
} else return STATUS_INVALID_PARAMETER;
return STATUS_SUCCESS;
}
NTSTATUS TimerCreate()
{
LARGE_INTEGER liTimerInterrupt;
NTSTATUS NtStatus;
pDrvTimerMessageSend = ExAllocatePoolWithTag(NonPagedPool, sizeof(DRV_MESSAGE_SEND), ‘corp’);
if(pDrvTimerMessageSend == NULL) return STATUS_UNSUCCESSFUL;
TimerServiceData.dwLastUniqueMessageId = 0;
TimerServiceData.dwUniqueMessageId = 0;
KeInitializeDpc(&TimerServiceData.KTimerDpc, (PKDEFERRED_ROUTINE)TimerClientServiceDpc, NULL);
KeInitializeTimerEx(&TimerServiceData.KTimer, SynchronizationTimer);
liTimerInterrupt.QuadPart = -(LONGLONG)31010001000;
NtStatus = KeSetTimer(&TimerServiceData.KTimer, liTimerInterrupt, &TimerServiceData.KTimerDpc);
if(NtStatus != STATUS_SUCCESS) { DbgPrint(“KeSetTImerEx unfortunately failed.\n”); return NtStatus; }
DbgPrint(“TimerCreate fortunately succeed.\n”);
return STATUS_SUCCESS;
}
VOID TimerDestory()
{
KeCancelTimer(&TimerServiceData.KTimer);
ExFreePoolWithTag(pDrvTimerMessageSend, ‘corp’);
return;
}
VOID TimerClientServiceDpc(PKDPC kDpc, PVOID pContext, PVOID pArgu1, PVOID pArgu2)
{
LARGE_INTEGER liTimerInterrupt;
NTSTATUS NtStatus;
ULONG ReplyLength;
DbgPrint(“Sending Client Ping Request.\n”);
liTimerInterrupt.QuadPart = -(LONGLONG)41010001000;
if(TimerServiceData.dwLastUniqueMessageId != TimerServiceData.dwUniqueMessageId)
{
DbgPrint(“Pong request failed.\n”);
//FltCloseClientPort(MainServiceData.pFltFilter, &MainServiceData.pFltClientPort);
} else DbgPrint(“Pong request succeed. [TimerServiceData.dwLastUniqueMessageId=‘%d’]\n”, TimerServiceData.dwLastUniqueMessageId);
if(TimerServiceData.dwUniqueMessageId > 2200) TimerServiceData.dwUniqueMessageId = 0; else TimerServiceData.dwUniqueMessageId++;
pDrvTimerMessageSend->dwUniqueMessageId = TimerServiceData.dwUniqueMessageId;
NtStatus = FltSendMessage(MainServiceData.pFltFilter, &MainServiceData.pFltClientPort, pDrvTimerMessageSend, sizeof(DRV_MESSAGE_SEND), NULL, NULL, &liTimerInterrupt);
if(NtStatus != STATUS_SUCCESS)
{
DbgPrint(“FltSendMessage unfortunately failed.\n”);
}
NtStatus = KeSetTimer(&TimerServiceData.KTimer, liTimerInterrupt, &TimerServiceData.KTimerDpc);
if(NtStatus != STATUS_SUCCESS) { DbgPrint(“KeSetTImerEx unfortunately failed.\n”); return; }
return;
}</ntstrsafe.h></ntifs.h></ntddk.h></suppress.h></dontuse.h></fltkernel.h>