最近有个需求需要监控管道的链接,IRP_MJ_CREATE过滤不到管道的创建和链接。
注册的IRP_MJ_CREATE_NAMED_PIPE这个irp的回调也一直不被调用。
OSR上老外也提了类似的问题:
- https://community.osr.com/discussion/239743/can-a-minifilter-filter-a-non-file-devices-irps
- https://community.osr.com/discussion/171174
- https://community.osr.com/discussion/247489
最后一个OSR上的问题,老外提到了微软的minispy中的部分代码,这个代码是用在注册Filter的时候填写在 FLT_REGISTRATION结构中的flag,这个flag从Win8才开始支持!
后来也搜到了两篇文章,介绍了Win8的新特性,其中就提到了开始支持过滤命名管道和邮槽,也证明了上面老外提到的这件事。
- http://fsfilters.blogspot.com/2011/09/whats-new-in-win8-for-file-system.html
- http://fsfilters.blogspot.com/2014/01/getting-started-with-windows-file_23.html
下面是我写的minifilter代码,用来过滤创建或打开的管道名是wdy就把管道名和当前进程名字打印出来。
代码中注册了下面两个IRP的回调函数:
- IRP_MJ_CREATE
- IRP_MJ_CREATE_NAMED_PIPE
最终结果显示,当使用了FLTFL_REGISTRATION_SUPPORT_NPFS_MSFS
这个flag时,
IRP_MJ_CREATE
可以监控到打开管道
名为wdy的事件
IRP_MJ_CREATE_NAMED_PIPE
可以监控到创建管道
名为wdy的事件
这个验证结果和《Windows内核原理与实现》书中8.3节介绍的一样
当不使用FLTFL_REGISTRATION_SUPPORT_NPFS_MSFS
属性时,两个IRP都监控不到管道的创建和打开。
微软官方对这个属性的介绍:
- https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/fltkernel/ns-fltkernel-_flt_registration
记住,这个属性从Win8才开始支持。
#include <fltKernel.h>
#include <dontuse.h>
#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")
PFLT_FILTER gFilterHandle;
ULONG_PTR OperationStatusCtx = 1;
#define PTDBG_TRACE_ROUTINES 0x00000001
#define PTDBG_TRACE_OPERATION_STATUS 0x00000002
ULONG gTraceFlags = 0;
#define PT_DBG_PRINT( _dbgLevel, _string ) \
(FlagOn(gTraceFlags,(_dbgLevel)) ? \
DbgPrint _string : \
((int)0))
NTSTATUS FsFilter1Unload(FLT_FILTER_UNLOAD_FLAGS Flags)
{
UNREFERENCED_PARAMETER(Flags);
PAGED_CODE();
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("FsFilter1!FsFilter1Unload: Entered\n"));
FltUnregisterFilter(gFilterHandle);
return STATUS_SUCCESS;
}
extern NTSYSAPI PUCHAR NTAPI PsGetProcessImageFileName(PEPROCESS Process);
/*************************************************************************
MiniFilter callback routines.
*************************************************************************/
FLT_PREOP_CALLBACK_STATUS PreCreateOperation(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext)
{
NTSTATUS status;
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
PEPROCESS eProcess = NULL;
HANDLE pid = PsGetCurrentProcessId();
do
{
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
{
break;
}
if ((ULONG)pid == 4 || (ULONG)pid == 0)
{
break;
}
status = PsLookupProcessByProcessId(pid, &eProcess);
if (!NT_SUCCESS(status))
{
KdPrint(("Get PsLookupProcessByProcessId Failed\n")); break;
}
PUCHAR pszProcessName = NULL;
pszProcessName = PsGetProcessImageFileName(eProcess);
if (pszProcessName == NULL)
{
KdPrint(("Get PsGetProcessImageFileName Failed\n")); break;
}
if (strstr(pszProcessName, "Server.exe") || strstr(pszProcessName, "Client.exe"))
{
UNICODE_STRING usPipeName = { 0 };
FltParseFileName(&FltObjects->FileObject->FileName, NULL, NULL, &usPipeName);
UNICODE_STRING usTarget = { 0 };
RtlInitUnicodeString(&usTarget, L"wdy");
if (RtlEqualUnicodeString(&usTarget, &usPipeName, TRUE))
{
DbgPrint("[IRP_MJ_CREATE]=====> Process:%s Create Named Pipe:%wZ \n", pszProcessName, &usPipeName);
}
}
} while (0);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FLT_PREOP_CALLBACK_STATUS PreCreateNamedPipeOperation(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext)
{
NTSTATUS status;
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
PEPROCESS eProcess = NULL;
HANDLE pid = PsGetCurrentProcessId();
do
{
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
{
break;
}
if ((ULONG)pid == 4 || (ULONG)pid == 0)
{
break;
}
status = PsLookupProcessByProcessId(pid, &eProcess);
if (!NT_SUCCESS(status))
{
break;
}
PUCHAR pszProcessName = NULL;
pszProcessName = PsGetProcessImageFileName(eProcess);
if (pszProcessName == NULL)
{
break;
}
if (strstr(pszProcessName, "Server.exe") || strstr(pszProcessName, "Client.exe"))
{
UNICODE_STRING usPipeName = { 0 };
FltParseFileName(&FltObjects->FileObject->FileName, NULL, NULL, &usPipeName);
UNICODE_STRING usTarget = { 0 };
RtlInitUnicodeString(&usTarget,L"wdy");
if (RtlEqualUnicodeString(&usTarget, &usPipeName, TRUE))
{
DbgPrint("[IRP_MJ_CREATE_NAMED_PIPE]=====> Process:%s Create Named Pipe:%wZ \n", pszProcessName, &usPipeName);
}
}
} while (0);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
//
// operation registration
//
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{
{
IRP_MJ_CREATE,
0,
PreCreateOperation,
NULL
},
{
IRP_MJ_CREATE_NAMED_PIPE,
0,
PreCreateNamedPipeOperation,
NULL
},
{ IRP_MJ_OPERATION_END }
};
//
// This defines what we want to filter with FltMgr
//
CONST FLT_REGISTRATION FilterRegistration = {
sizeof( FLT_REGISTRATION ), // Size
FLT_REGISTRATION_VERSION, // Version
FLTFL_REGISTRATION_SUPPORT_NPFS_MSFS, // Flags 这里需要做个判断win8才开始支持这个Flag
NULL, // Context
Callbacks, // Operation callbacks
FsFilter1Unload, // MiniFilterUnload
NULL,// InstanceSetup
NULL,// InstanceQueryTeardown
NULL,// InstanceTeardownStart
NULL,// InstanceTeardownComplete
NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL // NormalizeNameComponent
};
/*************************************************************************
MiniFilter initialization and unload routines.
*************************************************************************/
NTSTATUS DriverEntry ( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )
{
NTSTATUS status;
UNREFERENCED_PARAMETER( RegistryPath );
PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,("FsFilter1!DriverEntry: Entered\n") );
status = FltRegisterFilter( DriverObject,&FilterRegistration,&gFilterHandle );
FLT_ASSERT( NT_SUCCESS( status ) );
if (NT_SUCCESS( status )) {
status = FltStartFiltering( gFilterHandle );
if (!NT_SUCCESS( status )) {
FltUnregisterFilter( gFilterHandle );
}
}
return status;
}