转载:http://blog.csdn.net/heyabo/article/details/8721611

转载:http://www.cnblogs.com/ljinshuan/archive/2012/03/15/2397743.html

一、建立通信端口

在DriverEntry函数里创建一个安全性叙述子。

函数FltBuildDefaultSecurityDescriptor是用来申请一个安全叙述子(简单点就是给使用通信端口的用户申请个权限,这里可以看到申请的权限是FLT_PORT_ALL_ACCESS,意思就是:用户层的程序连接到设置了这个权限级别的通信端口后,可以获得所有操作权限)。函数InitializeObejectAttributes就是用来给我们要创建的对象(名称是:MINISPY_PORT_NAME)设置一些属性值。

FltCreateCommunicationPort就是给这个端口定义所需要的三个函数,同时注册这个端口(注册了才能用)。这里注册的三个函数分别是:

MiniConnect用户层和内核层建立连接的时候会调用该函数

MiniDisconnect用户层和内核层断开连接的时候会调用该函数

MiniMessage用户层和内核层进行通讯的时候会调用

当然,既然称他们为回调函数,那他们就不是我们用户层的程序去调用的,工作原理是这样的,我们在用户层通过两个api:FilterConnectCommunicationPort和FilterSendMessage来发出请求,然后通讯端口会根据我们的请求自己去调用这三个函数完成具体的工作。其中前者对应NPMiniConnect,后者对应NPMiniMessage。

完成上面三个回调函数后,内核中的通讯代码已经准备好了。

#define MINISPY_PORT_NAME                                L"\\MiniPort"  //通信端口名字

PFLT_PORT     gServerPort;//服务端口
PFLT_PORT gClientPort;//客户端口 // Defines the commands between the utility and the filter
typedef enum _MINI_COMMAND {
ENUM_PASS = ,
ENUM_BLOCK
} MINI_COMMAND; // Defines the command structure between the utility and the filter.
typedef struct _COMMAND_MESSAGE {
MINI_COMMAND Command;
} COMMAND_MESSAGE, *PCOMMAND_MESSAGE;
NTSTATUS
DriverEntry (
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
PSECURITY_DESCRIPTOR sd;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString; UNREFERENCED_PARAMETER( RegistryPath ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("MiniFilter!DriverEntry: Entered\n") ); //
// Register with FltMgr to tell it our callback routines
// status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&gFilterHandle ); FLT_ASSERT( NT_SUCCESS( status ) ); if (NT_SUCCESS( status )) { //
// Start filtering i/o
// status = FltStartFiltering( gFilterHandle ); if (!NT_SUCCESS( status )) { FltUnregisterFilter( gFilterHandle );
}
} //产生一个安全性叙述子
status=FltBuildDefaultSecurityDescriptor(&sd,FLT_PORT_ALL_ACCESS);
RtlInitUnicodeString( &uniString, MINISPY_PORT_NAME ); //初始化对象属性
InitializeObjectAttributes( &oa,
&uniString,
OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
NULL,
sd ); //内核建立通信端口
status = FltCreateCommunicationPort(gFilterHandle,&gServerPort,&oa,NULL,MiniConnect,MiniDisconnect,MiniMessage,);
FltFreeSecurityDescriptor( sd ); return status;
}
//用户态和内核态建立连接
NTSTATUS
MiniConnect(
__in PFLT_PORT ClientPort,
__in PVOID ServerPortCookie,
__in_bcount(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
)
{
DbgPrint("[mini-filter] NPMiniConnect");
PAGED_CODE(); UNREFERENCED_PARAMETER( ServerPortCookie );
UNREFERENCED_PARAMETER( ConnectionContext );
UNREFERENCED_PARAMETER( SizeOfContext);
UNREFERENCED_PARAMETER( ConnectionCookie ); ASSERT( gClientPort == NULL );
gClientPort = ClientPort;
return STATUS_SUCCESS;
} //用户态和内核断开连接
VOID
MiniDisconnect(
__in_opt PVOID ConnectionCookie
)
{
PAGED_CODE();
UNREFERENCED_PARAMETER( ConnectionCookie );
DbgPrint("[mini-filter] NPMiniDisconnect"); // Close our handle
FltCloseClientPort( gFilterHandle, &gClientPort );
} //用户态和内核态传送数据
NTSTATUS
MiniMessage (
__in PVOID ConnectionCookie,
__in_bcount_opt(InputBufferSize) PVOID InputBuffer,
__in ULONG InputBufferSize,
__out_bcount_part_opt(OutputBufferSize,*ReturnOutputBufferLength) PVOID OutputBuffer,
__in ULONG OutputBufferSize,
__out PULONG ReturnOutputBufferLength
)
{
MINI_COMMAND command;
NTSTATUS status; PAGED_CODE(); UNREFERENCED_PARAMETER( ConnectionCookie );
UNREFERENCED_PARAMETER( OutputBufferSize );
UNREFERENCED_PARAMETER( OutputBuffer ); DbgPrint("[mini-filter] NPMiniMessage"); if ((InputBuffer != NULL) &&
(InputBufferSize >= (FIELD_OFFSET(COMMAND_MESSAGE,Command) +
sizeof(MINI_COMMAND)))) { try {
// Probe and capture input message: the message is raw user mode
// buffer, so need to protect with exception handler
command = ((PCOMMAND_MESSAGE) InputBuffer)->Command; } except( EXCEPTION_EXECUTE_HANDLER ) { return GetExceptionCode();
} switch (command) {
//释放规则
case ENUM_PASS:
{
DbgPrint("[mini-filter] ENUM_PASS");
gCommand = ENUM_PASS;
status = STATUS_SUCCESS;
break;
}
//阻擋規則
case ENUM_BLOCK:
{
DbgPrint("[mini-filter] ENUM_BLOCK");
gCommand = ENUM_BLOCK;
status = STATUS_SUCCESS;
break;
} default:
DbgPrint("[mini-filter] default");
status = STATUS_INVALID_PARAMETER;
break;
}
} else { status = STATUS_INVALID_PARAMETER;
} return status;
}

二、应用层通过DLL使用通信端口

在用户态编写应用程序时,开发者可以编写一个简单的动态链接库(DLL)来提供与内核中的MiniFilter内核驱动程序通信的功能。

动态库

.h

#ifndef _MINIFILTER_H_
#define _MINIFILTER_H_ #include <windows.h>
#include <stdio.h>
#include <FltUser.h>
#pragma comment(lib, "fltLib.lib") extern HANDLE g_hPort;
#define MIN_PORT_NAME L"\\MiniPort" #ifdef MINI_EXPORTS
#define MINI_API _declspec(dllexport)
#else
#define MINI_API _declspec(dllexport)
#endif // NPMINI_EXPORTS extern "C" MINI_API int InitialCommuicationPort(void);
extern "C" MINI_API int NPSendMessage(PVOID InputBuffer); typedef enum _MINI_COMMAND {
ENUM_PASS = ,
ENUM_BLOCK
}MIN_COMMAND; typedef struct _COMAND_MESSAGE
{
MIN_COMMAND Command;
} COMMAND_MESSAGE,*PCOMMAND_MESSAGE; #endif

.cpp

#include "stdafx.h"
#include "MiniFilter_dll.h" //初始化句柄
HANDLE g_hPort = INVALID_HANDLE_VALUE; int InitialCommuicationPort(void)
{
DWORD hResult = FilterConnectCommunicationPort(MIN_PORT_NAME,,NULL,,NULL,&g_hPort);
printf("进入了通信端口初始化\n");
if (hResult != S_OK)
{
return hResult;
printf("通信端口初始化不成功\n");
}
printf("通信端口初始化成功\n");
return ;
} int NPSendMessage(PVOID InputBuffer)
{
DWORD bytesReturned = ;
DWORD hResult = ;
PCOMMAND_MESSAGE command_message = (PCOMMAND_MESSAGE)InputBuffer; printf("进入发送消息\n");
hResult = FilterSendMessage(g_hPort,command_message,sizeof(command_message),NULL,NULL,&bytesReturned); if (hResult != S_OK)
{
return hResult;
}
return ;
}

为了在任意目标机器上使用,此动态库以静态链接C/C++运行时库

三、用户程序调用

在此是显示调用动态库

.h

#include <windows.h>
#include <vector>
#include <string> using namespace std; HANDLE g_hPort = INVALID_HANDLE_VALUE; typedef enum _MINI_COMMAND {
ENUM_PASS = ,
ENUM_BLOCK
}MIN_COMMAND; typedef struct _COMAND_MESSAGE
{
MIN_COMMAND Command;
}COMMAND_MESSAGE,*PCOMMAND_MESSAGE; class CApp
{
public:
CApp();
virtual ~CApp(); int Init(); void Message(COMMAND_MESSAGE data); private: HINSTANCE m_hModule; bool LoadminifilterDll();
};

.cpp

#include "App.h"
#include <iostream>
using namespace std; typedef int (*pSendMessage)(PVOID pInBufffer);
typedef int (*pInitiaCommunicationPort)(); CApp::CApp()
{
m_hModule = NULL; LoadminifilterDll();
} CApp::~CApp()
{
if (m_hModule)
{
FreeLibrary(m_hModule);
}
} bool CApp::LoadminifilterDll()
{
printf("进入了LoadminifilterDll,此函数是为了Minifilter_dll.dll中的NPSendMessage\n");
m_hModule = LoadLibrary(L"MiniFilter_dll.dll"); if (m_hModule != NULL)
{
pInitiaCommunicationPort pInit = (pInitiaCommunicationPort)GetProcAddress(m_hModule,"InitialCommuicationPort"); if (!pInit) {
printf("调用了pInit ,但是失败了\n");
return false;
}
pInit();
printf("调用了pInit ,并链接成功了\n");
return true;
} printf("获得MiniFilter_dll.dll的句柄失败\n");
return false;
} void CApp::Message(COMMAND_MESSAGE data)
{
if (m_hModule == NULL)
{
if (LoadminifilterDll() == false)
{
return ;
}
} printf("发送数据\n"); //根据符号名得到函数地址
pSendMessage send = (pSendMessage)GetProcAddress(m_hModule,"NPSendMessage"); send(&data);
} void main()
{
CApp app;
char input;
while (true)
{
cout << "Enter 'a' for PASS MODE, 'b' for BLOCKMODE or 'q' to EXIT" << endl;
cin >> input;
if (input=='a' || input=='A')
{
COMMAND_MESSAGE data;
data.Command =ENUM_PASS;
printf("上一句是 data.Command = ENUM_PASS;\n");
app.Message(data);
printf("==>NOTEPAD.EXE PASS MODE\n");
}
else if (input=='b' || input=='B')
{
COMMAND_MESSAGE data;
data.Command = ENUM_BLOCK;
app.Message(data);
printf("==>NOTEPAD.EXE BLOCK MODE\n");
}
else if (input== 'q' || input=='Q')
{
printf("EXIT\n");
break;
}
else
{
printf("Wrong Parameter!!!\n");
}
}
system("pause");
}

DLL是以静态链接运行时库的,所以用户程序也要以静态链接运行时库。

四、

驱动装好后,以管理员权限在cmd下net start MiniFilter开启服务

UseMiniFilter.exe 和 MiniFilter_dll.dll放在同一目录下

以管理员权限打开UseMiniFilter.exe

输入字符 b (阻止打开)

打开一个txt

通信成功了!!!!

[内核驱动] miniFilter 内核层与应用程序通信的更多相关文章

  1. 向Windows内核驱动传递用户层定义的事件Event,并响应内核层的通知

    完整的程序在下载:http://download.csdn.net/detail/dijkstar/7913249 用户层创建的事件Event是一个Handle句柄,和内核中的创建的内核模式下的KEV ...

  2. Linux驱动之内核自带的S3C2440的LCD驱动分析

    先来看一下应用程序是怎么操作屏幕的:Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出FrameBuffer这个设备来供用户 ...

  3. linux内核驱动模型

    linux内核驱动模型,以2.6.32内核为例.(一边写一边看的,有点乱.) 1.以内核对象为基础.用kobject表示,相当于其它对象的基类,是构建linux驱动模型的关键.具有相同类型的内核对象构 ...

  4. Unix/Linux环境C编程新手教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

    1. openSUSE是一款优秀的linux. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaXRjYXN0Y3Bw/font/5a6L5L2T/font ...

  5. Unix/Linux环境C编程入门教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

    1. openSUSE是一款优秀的linux. 2.选择默认虚拟机 3.选择稍后安装操作系统 4.选择linux  opensuse 5. 选择默认虚拟机名称 6.设置处理器为双核. 7.内存设置为2 ...

  6. 【引用】Linux 内核驱动--多点触摸接口

    本文转载自James<Linux 内核驱动--多点触摸接口>   译自:linux-2.6.31.14\Documentation\input\multi-touch-protocol.t ...

  7. Linux内核驱动开发之KGDB原理介绍及kgdboe方式配置

    接博文<Linux内核驱动开发之KGDB单步调试内核(kgdboc方式)>.上篇博文中,仅简单介绍使用串口的Kgbd的流程(kgdboc方式),本文将重点介绍KGDB调试Linux内核的原 ...

  8. linux内核驱动——从helloworld开始

    学习编程第一个都是学习hello world程序,学习内核驱动自然也不例外,我也是!本文整理了网上的一些资料以及加上自己的一些心得体会,希望对初学者有帮助,可别小看这个简单的hello world,本 ...

  9. 内核开发知识第二讲,编写Kerner 程序中注意的问题.

    一丶函数多线程的安全问题 什么是函数多线程安全. 简单来说就是 ,一个函数在调用过程中.还没有返回的时候.再次被其他线程调用了.但是函数执行的结果是可靠的.就可以了说这个函数是安全的. 比如我们在用户 ...

随机推荐

  1. Bukkit编程之动态向yml文件中添加属性

    yaml = new Yaml(); String goods = args[0]; String goodsNum = args[1]; YamlConfiguration yc = new Yam ...

  2. Docker中mysql修改配置导致无法启动的docker容器

    宿主机中查找my.cnf文件 # find / -name my.cnf |grep '/etc/mysql/my.cnf' 找到: /data/docker/overlay2/dfc2ddbed53 ...

  3. 记无法用被动方式登录远程linux主机的原因

    [环境]: linux主机:华为企业云 ftp服务端:vsftpd 客户端:ftp命令行工具,安卓端ES文件浏览器 [现象]: 在ES文件浏览器中,使用被动方式没法连接,使用主动方式可以连接,但是没法 ...

  4. python 正则基本方法

    2017-04-11 学习python,免不了应对爬虫,初学爬虫最难理解的就是正则表达式. 比如我们要爬去网页上的某些内容,就像下面这种形式: <p>safdsf</p>< ...

  5. Django admin模块无法调用css样式文件

    在使用Django Admin开发时,发现admin模块css样式文件丢失,无法调用,使火狐浏览器提示: 此 URL 的资源不是文本: http://127.0.0.1:8000/statics/ad ...

  6. qDeleteAll 之后必须清空容器

    [1]qDeleteAll应用示例 qDeleteAll源码如下: template <typename ForwardIterator> Q_OUTOFLINE_TEMPLATE voi ...

  7. win10 在任务栏添加 desktop 快捷图标

    http://www.xitongcheng.com/jiaocheng/win10_article_11980.html [Shell] Command= IconFile=explorer.exe ...

  8. 邮件服务器hMailServer管理工具hMailServer Administrator汉化(转)

    //实现:邮件服务器hMailServer管理工具hMailServer Administrator的汉化 //环境: Windows Server 2008 R2 hMailServer Admin ...

  9. ClassThree__HomeWork

    作业一 使用类的静态字段和构造函数,可以跟踪某个类所创建对象的个数.请写一个类,在任何时候都可以向它查询“你已经创建了多少个对象?”. 代码 public class TestOne {       ...

  10. 20165316 实验四 Android程序设计

    20165316 孙勖哲 第四次实验 Android 程序设计1 参考 http://www.cnblogs.com/rocedu/p/6371315.html#SECANDROID, 安装 Andr ...