应用层的代码如下:
/*
名字:minifilter通讯之简单示例.之所以说简单是因为没有列举异步,多线程等全面和安全的用法.
个人感觉FilterSendMessage就像DeviceIoControl,可以发送和接受信息.
但是要自定义格式结构,驱动收到了再解析.
FilterGetMessage和FilterReplyMessage可能需要多线程或者异步等措施,这里不列举了,只是简单列举一下调用:
//FILTER_MESSAGE_HEADER MessageBuffer;
//hResult = FilterGetMessage(port, &MessageBuffer, sizeof (FILTER_MESSAGE_HEADER), 0);
//if (IS_ERROR( hResult )) {
// OutputDebugString(L"FilterGetMessage fail!\n");
//} else {
// OutputDebugString(L"FilterGetMessage ok!\n");
//}
//FILTER_REPLY_HEADER ReplyBuffer;
//hResult = FilterReplyMessage(port, &ReplyBuffer,sizeof(FILTER_REPLY_HEADER));
//if (IS_ERROR( hResult )) {
// OutputDebugString(L"FilterReplyMessage fail!\n");
//} else {
// OutputDebugString(L"FilterReplyMessage ok!\n");
//}
不足之处,敬请指出.
made by correy
made at 2013.11.13
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
效果如下(包括驱动打印的消息):
用户发来的信息是:test
[1124] FilterSendMessage ok!
[1124] 从内核发来的信息是:
[1124] to user client
[1124]
*/
#include <windows.h>
//这两个文件在VS中没有,在WDK中有.
//如果要用VS编译要拷贝相应的文件到相应的目录或者改变目录的设置等.
#include <fltuser.h>
#pragma comment(lib, "fltLib.lib")
int _tmain(int argc, _TCHAR* argv[])
{
MessageBox(0,L"请附加调试器",L"调试专用",0);//如果是远程调试的话,这行特别有用.
HANDLE port = INVALID_HANDLE_VALUE;
HRESULT hResult = S_OK;
hResult = FilterConnectCommunicationPort( L"\\CommunicationPort", 0, NULL, 0, NULL, &port );
if (IS_ERROR( hResult )) {
OutputDebugString(L"FilterConnectCommunicationPort fail!\n");
return hResult;
}
wchar_t InBuffer[] = L"test";
wchar_t OutBuffer[MAX_PATH] = {0};
DWORD bytesReturned = 0;
hResult = FilterSendMessage(port, InBuffer, lstrlen(InBuffer), OutBuffer, sizeof(OutBuffer), &bytesReturned);
if (IS_ERROR( hResult )) {
OutputDebugString(L"FilterSendMessage fail!\n");
CloseHandle( port );
return hResult;
} else {
OutputDebugString(L"FilterSendMessage ok!\n");
}
OutputDebugString(L"从内核发来的信息是:");
OutputDebugString(OutBuffer);
OutputDebugString(L"\n");
CloseHandle( port );
return 0;
}
驱动的代码如下:
/*
内核中没有:FltGetMessage,FltReplyMessage函数.
个人认为:MessageNotifyCallback有FltGetMessage,FltReplyMessage,FltSendMessage这三个函数的功能.
所以在MessageNotifyCallback里面调用这些函数是不对的,得到一些意想不到的效果.建议不要这样做.
FltGetMessage除了在MessageNotifyCallback里面,大多的地方都可以调用,但是用户层最好开启线程处理函数.
FltGetMessage函数调用示例代码如下:
//{
// wchar_t SenderBuffer[] = L"SenderBuffer";
// wchar_t ReplyBuffer[] = L"ReplyBuffer";
// ULONG replyLength = sizeof(ReplyBuffer);
//
// status = FltSendMessage( gFilterHandle, &g_ClientPort, SenderBuffer, sizeof(SenderBuffer), ReplyBuffer, &replyLength, NULL);
// if (STATUS_SUCCESS == status) {
// DbgPrint( "send message to user-mode\n");
// } else {
// DbgPrint( "couldn't send message to user-mode to scan file, status 0x%X\n", status );
// }
//}
*/
#include <fltKernel.h>
PFLT_FILTER gFilterHandle;
PFLT_PORT g_ServerPort;
PFLT_PORT g_ClientPort;
NTSTATUS MessageNotifyCallback (
IN PVOID PortCookie,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength,//用户可以接受的数据的最大长度.
OUT PULONG ReturnOutputBufferLength)
/*
这里要注意:1.数据地址的对齐.
2.文档建议使用:try/except处理.
3.如果是64位的驱动要考虑32位的EXE发来的请求.
*/
{
NTSTATUS status = 0;
wchar_t buffer[] = L"to user client";//
PAGED_CODE();
UNREFERENCED_PARAMETER(PortCookie);
//打印用户发来的信息
KdPrint(("用户发来的信息是:%ls\n",InputBuffer));
//返回用户一些信息.
*ReturnOutputBufferLength = sizeof(buffer);
RtlCopyMemory(OutputBuffer,buffer,* ReturnOutputBufferLength);
/*
minispy在这里用FilterSendMessage获取信息的,对就是FilterSendMessage.
这里某个类型里面获取信息,这些信息是在各种操作时(IRP的MJ_)加入链表的.
注意链表的操作一定要同步,支持多线程.
然后用户的一个线程在不停的获取这些信息.
*/
return status;
}
VOID DisconnectNotifyCallback (_In_opt_ PVOID ConnectionCookie)
{
PAGED_CODE();
UNREFERENCED_PARAMETER(ConnectionCookie);
FltCloseClientPort(gFilterHandle, &g_ClientPort);//应该加判断,如果ConnectionCookie == 我们的值就执行这行.
}
NTSTATUS ConnectNotifyCallback (IN PFLT_PORT ClientPort, IN PVOID ServerPortCookie, IN PVOID ConnectionContext, IN ULONG SizeOfContext, OUT PVOID * ConnectionPortCookie)
{
PAGED_CODE();
UNREFERENCED_PARAMETER( ServerPortCookie );
UNREFERENCED_PARAMETER( ConnectionContext );
UNREFERENCED_PARAMETER( SizeOfContext);
UNREFERENCED_PARAMETER( ConnectionPortCookie);
//可以加以判断,禁止非法的连接,从而给予保护.
g_ClientPort = ClientPort;//保存以供以后使用.
return STATUS_SUCCESS;
}
#pragma PAGEDCODE
NTSTATUS PtInstanceQueryTeardown (__in PCFLT_RELATED_OBJECTS FltObjects,__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
return STATUS_SUCCESS;
}
#pragma PAGEDCODE//#pragma alloc_text(PAGE, PtUnload)
NTSTATUS PtUnload (__in FLT_FILTER_UNLOAD_FLAGS Flags)
{
FltCloseCommunicationPort(g_ServerPort);//没有这一行是停止不了驱动的,查询也是永远等待中.
FltUnregisterFilter( gFilterHandle );
return STATUS_SUCCESS;
}
CONST FLT_REGISTRATION FilterRegistration = {
sizeof( FLT_REGISTRATION ), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags
NULL, // Context
NULL, // Operation callbacks
PtUnload, // MiniFilterUnload
NULL, // InstanceSetup
PtInstanceQueryTeardown, // InstanceQueryTeardown
NULL, // InstanceTeardownStart
NULL, // InstanceTeardownComplete
NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL // NormalizeNameComponent
};
DRIVER_INITIALIZE DriverEntry;
#pragma alloc_text(INIT, DriverEntry)//#pragma INITCODE
NTSTATUS DriverEntry (_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
PSECURITY_DESCRIPTOR sd;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
UNREFERENCED_PARAMETER(RegistryPath);
KdBreakPoint();
__try
{
status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle);
if (!NT_SUCCESS(status)) //;
{
__leave;
}
status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS);
if (!NT_SUCCESS( status )) {
__leave;
}
RtlInitUnicodeString(&uniString, L"\\CommunicationPort");
InitializeObjectAttributes( &oa, &uniString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, sd);
status = FltCreateCommunicationPort(gFilterHandle, &g_ServerPort, &oa, NULL, ConnectNotifyCallback, DisconnectNotifyCallback, MessageNotifyCallback, 1);
FltFreeSecurityDescriptor( sd );
if (!NT_SUCCESS( status )) {
__leave;
}
status = FltStartFiltering(gFilterHandle);//这个结果在下面判断.
} __finally {
if (!NT_SUCCESS( status ) )
{
if (NULL != g_ServerPort) {
FltCloseCommunicationPort(g_ServerPort);
}
if (NULL != gFilterHandle) {
FltUnregisterFilter(gFilterHandle);
}
}
}
return status;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课