博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[内核驱动] miniFilter 内核层与应用程序通信
阅读量:4563 次
发布时间:2019-06-08

本文共 9337 字,大约阅读时间需要 31 分钟。

转载:

转载:

一、建立通信端口

在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 filtertypedef enum _MINI_COMMAND {    ENUM_PASS = 0,    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;

 

NTSTATUSDriverEntry (    _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,1);    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 
#include
#include
#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_EXPORTSextern "C" MINI_API int InitialCommuicationPort(void);extern "C" MINI_API int NPSendMessage(PVOID InputBuffer);typedef enum _MINI_COMMAND { ENUM_PASS = 0, 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,0,NULL,0,NULL,&g_hPort);    printf("进入了通信端口初始化\n");    if (hResult != S_OK)    {        return hResult;        printf("通信端口初始化不成功\n");    }    printf("通信端口初始化成功\n");    return 0;}int  NPSendMessage(PVOID InputBuffer){    DWORD bytesReturned = 0;    DWORD hResult = 0;    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 0;}

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

 

三、用户程序调用

在此是显示调用动态库

.h

#include 
#include
#include
using namespace std;HANDLE g_hPort = INVALID_HANDLE_VALUE;typedef enum _MINI_COMMAND { ENUM_PASS = 0, 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 
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

 

 

通信成功了!!!!

 

转载于:https://www.cnblogs.com/chechen/p/7777029.html

你可能感兴趣的文章
面向对象(五)
查看>>
android平台下使用点九PNG技术
查看>>
Python学习3,列表
查看>>
最长回文子串
查看>>
JAVA基础-JDBC(一)
查看>>
js中for和while运行速度比较
查看>>
简单理解什么是递归(阶乘演示)
查看>>
http协议
查看>>
js倒计时,页面刷新时,不会从头计时
查看>>
洛谷1156垃圾陷阱
查看>>
python ==》 递归
查看>>
简单网络请求封装
查看>>
django —— MVT模型
查看>>
oracle 静默安装
查看>>
Python3基础(2)模块、数据类型及运算、进制、列表、元组、字符串操作、字典...
查看>>
服务器上centos 7 配置静态IP
查看>>
C# unsafe模式内存操作深入探索
查看>>
Redis拾遗(一)
查看>>
js字符串转换为Json对象的三种写法
查看>>
Is it possible to display icons in a PopupMenu?
查看>>