【驱动开发】Windows过滤平台(WFP,Windows Filtering Platform)

news2024/11/22 23:21:56

文章目录

  • Windows的发展历程
  • TDI简介
  • WFP简介
    • 用户态基础过滤引擎(BFE)
    • 内核态过滤引擎(KMFE)
      • 垫片(Shim)
      • 分层(Layer)
      • 子层(Sub Layer)
      • 过滤器(Filter)
      • 呼出接口(Callout)
      • 呼出端口的回调函数(classifyFn、notifyFn、flowDeleteFn)
  • 通过WFP API实现网络数据包过滤

Windows的发展历程

正题开始之前,先总结一下Windows的发展历程。

  • Windows1.0、2.0、3.0、3.1、3.2:16位。
  • Windows9x:包括Windows 95Windows 98Windows Me
  • WindowsNT系列:包括Windows NT 3.1Windows NT 3.1Windows NT 4.0Windows 2000Windows XPWindows Server 2003Windows VistaWindows Server 2008Windows 7Windows Server 2012Windows 8Windows 10,这些版本都源于Windows NT 内核。

比较常见的几个版本的顺序:
Windows 2000
Windows XP
Windows Vista
Windows 7
Windows 8
Windows10

TDI简介

TDI:Transport Driver Interface,传输层接口。TDI在Windows Vista之后就不再支持了,之后的版本中被WFP取代。
socket可以指定某种方式开始传输用户的数据(比如TCP或UDP),这就是传输层。
传输层的特点是:用户只需要关心实际需要传输的用户数据,而不用担心数据实际的发送次数、如何封装、如何确定发送正确性、出错何重发等。

WFP简介

Windows过滤平台(Windows Filter Platform),是从Vista系统后新增的一套系统API和服务,为网络数据包过滤提供架构支撑。
WFP框架是分层结构,可以在不同分层中进行过滤重定向修改网络数据包。
通过WFP框架,开发者可以在其上轻松实现防火墙、入侵检测系统、网络监视程序以及流量控制程序等。
WFP框架包含用户态API和内核态API。它只是一个提供各层网络数据包过滤的框架,自身并不是防火墙,也不存在任何过滤逻辑。

WFP框架主要分为两大层次模块:
在这里插入图片描述

用户态基础过滤引擎(BFE)

基础过滤引擎:BFE,Base Filtering Enging。
BFE 对上提供C管理API以及RPC接口,封装在fwpuclnt.dll中,供用户态程序调用;对下和KMFE交互,受其控制。

内核态过滤引擎(KMFE)

内核态过滤引擎:KMFE,Kernel Mode Filtering Enging,是整个WFP框架的核心。
其内部被划分为多个分层,不同分层代表着网络协议栈特定的层,在每个分层中可以存在子层和过滤器。KMFE负责检查网络数据包是否命中过滤器的规则(Rule),对于命中的过滤器,会执行这些过滤器指定的动作(Action)。

问题一:网络数据包从哪来?
答:KMFE需要和系统网络协议栈(如TCP/IP协议栈)交互,通过一种称为垫片(Shim)的内核模块从网络协议栈中获取网络数据。
垫片被插入到网络协议栈各个层中,包括:

  • 数据流分层垫片:对应 流/报文 数据分层(IPv4/IPv6)
  • ALE网络连接管理:对应 发送/接收 ALE分层(IPv4/IPv6)
  • 传输分层垫片(TCP/UDP):对应 发送/接收 传输分层(IPv4/IPv6)
  • 网络分层垫片(IPv4/IPv6):对应 发送/接收 IP分层(IPv4/IPv6)

不同层次的垫片获取到的网络数据不同,垫片获取到数据后,通过KMFE提供的Classify API,把数据传送到WFP的相应分层(Layer)中。

垫片(Shim)

垫片是一种特殊的内核模块,被安插在系统网络协议栈(如TCP/IP协议栈)的不同层(栈)中,主要作用有:

  1. 获取网络协议栈的数据。
    被安插在传输层,可以获取TCP/UDP等协议数据;
    被安插在网络层,可以获取IP协议等数据。
    Shim获取到数据后,会通过KMFE提供的分类API,把数据传递到相应的WFP分层中。
  2. 把KMFE的过滤结果反馈给网络协议栈。
    比如KMFE需要拦截某一类网络数据,通过分类API把过滤结果通知垫片,由于垫片被安插在网络协议栈中,所以垫片可以在网络协议栈中直接拦截网络数据包。

总结:垫片负责WFP的数据来源以及执行数据拦截/放行的最终动作,属于网络协议栈和WFP框架之间的通信桥梁。但垫片对开发者来说是透明的,无须过多关注。

分层(Layer)

KMFE内部被划分成不同的分层,每一个分层代表了系统网络协议栈的一个特定的层,接收待定的数据。
分层是一个容器,里面包含了零个或多个过滤器,此外还可能包含一个或多个子层

分层标识:
每个分层都有一个唯一的值来标识,在内核态,使用64位的LUID来标识一个子层;在用户态,使用128位GUID来标识一个分层。
这两种分层标识存在部分对应关系,一般来说,
把内核态用到的分层标识称为运行时过滤分层标识
把用户态使用到的分层标识称为管理过滤分层标识
常见的运行时过滤分层标识:.
FWPM_LAYER_ALE_AUTH_CONNECT_V4:连接IPv4
FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4:接收IPv4
FWPM_LAYER_ALE_AUTH_LISTEN_V4:监听IPv4
常见的管理过滤分层标识:
FWPM_LAYER_INBOUND_IPPACKET_V4:接收IPv4网络数据包层
FWPM_LAYER_INBOUND_IPPACKET_V6:接收IPv6网络数据包层
FWPM_LAYER_OUTBOUND_IPPACKET_V4:发送IPv4网络数据包层
FWPM_LAYER_OUTBOUND_IPPACKET_V6:发送IPv6网络数据包层

子层(Sub Layer)

子层是分层内更小的一个划分,一个分层可能被划分成多个子层,并且这种划分是由开发者控制的。
划分子层时需要给新子层分配一个权重(Weight),权重的值越,表明优先级越
当有相应的网络数据到达分层时,WFP会按照分层内的子层优先级顺序传递网络数据,子层的权重值越大,越早获取到数据。

typedef struct FWPM_SUBLAYER0_ {
  GUID               subLayerKey;	// 子层标识
  FWPM_DISPLAY_DATA0 displayData;	// 显示数据
  UINT32             flags;			// 特性,如FWPM_SUBLAYER_FLAG_PERSISTENT
  GUID               *providerKey;
  FWP_BYTE_BLOB      providerData;
  UINT16             weight;		// 权重,值越大,优先级越高
} FWPM_SUBLAYER0;
typedef struct FWPM_DISPLAY_DATA0_ {
	WCHAR* name;		// 对象名字
	WCHAR* description;	// 对象描述
}FWPM_DISPLAY_DATA0;

过滤器(Filter)

过滤器存在于WFP的分层中,WFP内置了一部分过滤器供开发者使用,开发者也可以添加自己的过滤器。
过滤器里保存了网络数据包的拦截规则(Rule)和处理动作(Action),Rule指明了需要过滤哪些网络数据包,当Rule被命中时,就会执行指定的Action。

一般来说,过滤器中的动作会表明是放行(Permit)还是拦截(Block)网络数据包。在实际情况中,KMFE的分层中可能会存在多个子层以及多个过滤器,对于一次网络事件而言,可能同时命中多个过滤器的规则,而这些命中规则的过滤器可能指定了不同的过滤动作,为了计算出最终的过滤动作,WFP引入了过滤仲裁器(Fileter Arbitration)模块,过滤仲裁器计算出最终的过滤动作后交给KMFE,KMFE最终将过滤结果反馈给垫片。

过滤器可以关联分层和子层,以及呼出接口。
在需要对网络数据包进行复杂的分析和处理的情况下,过滤器一般需要关联一个呼出接口,当过滤器的规则被命中时,WFP会直接执行与改过滤器关联的呼出接口内的回调函数。

typedef struct FWPM_FILTER0_ {
  GUID                   filterKey;		// 过滤器标识,若FwpmFilterAdd0中初始化为0,则BFE将生成一个
  FWPM_DISPLAY_DATA0     displayData;	// 显示数据
  UINT32                 flags;			// 特性
  GUID                   *providerKey;
  FWP_BYTE_BLOB          providerData;
  GUID                   layerKey;		// 过滤器所在的分层标识
  GUID                   subLayerKey;	// 过滤器所在的子层标识
  FWP_VALUE0             weight;		// 权重
  UINT32                 numFilterConditions;	// 过滤条件数
  FWPM_FILTER_CONDITION0 *filterCondition;		// 过滤条件
  FWPM_ACTION0           action;		// 操作
  union {
    UINT64 rawContext;
    GUID   providerContextKey;
  };
  GUID                   *reserved;
  UINT64                 filterId;
  FWP_VALUE0             effectiveWeight;
} FWPM_FILTER0;

typedef struct FWPM_ACTION0_ {
  FWP_ACTION_TYPE type;	// 操作类型,如FWP_ACTION_BLOCK(阻止流量)、FWP_ACTION_PERMIT(允许流量)
  union {
    GUID filterType;	// 过滤类型
    GUID calloutKey;	// 呼出接口标识
  };
} FWPM_ACTION0;

呼出接口(Callout)

呼出接口由一系列的回调函数组成,当网络数据包命中某过滤器的规则且该过滤器关联了呼出接口时,就会调用该呼出接口的回调函数。
Callout除了包含回调函数外,还包含一个GUID值,用来唯一地标识一个呼出接口。
一般来说,不同的呼出接口的回调函数实现不同的功能,系统内置了一部分呼出接口可以供开发者使用,开发者也可以向系统注册自己的呼出接口来完成特定的逻辑。

typedef struct FWPS_CALLOUT1_ {
	GUID calloutKey;		// 呼出接口标识
	UINT32 flags;			// 特性,可设为0
	FWPS_CALLOUT_CLASSIFY_FN1 classifyFn;
	FWPS_CALLOUT_NOTIFY_FN1 nptifyFn;
	FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN0 flowDeleteFn;
}FWPS_CALLOUT1

呼出端口的回调函数(classifyFn、notifyFn、flowDeleteFn)

  • classifyFn:过滤器的规则被命中时被调用,可以在回调函数中获取网络数据包的相关信息,具体信息取决于过滤器所在的分层,还可以对网络数据包设置允许/拦截操作,。
  • notifyFn:过滤器被添加到过滤引擎中或者从过滤引擎中移除时被调用。
  • flowDeleteFn:当一个网络数据流要被终止时被调用。
void FwpsCalloutClassifyFn1(
  [in]           const FWPS_INCOMING_VALUES0 *inFixedValues,	// 被过滤层中每个数据字段的值
  [in]           const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,	// 被过滤层中每个元数据字段的值
  [in, out]      void *layerData,	// 指向被过滤层中原始数据的结构指针,可能为NULL
  [in, optional] const void *classifyContext,	// 可选,表示和呼出接口驱动关联的上下文
  [in]           const FWPS_FILTER1 *filter,	// 过滤器指针
  [in]           UINT64 flowContext,	// 和流句柄关联的上下文
  [in, out]      FWPS_CLASSIFY_OUT0 *classifyOut	// 该函数对该网络数据包的过滤结果
);
typedef struct FWPS_CLASSIFY_OUT0_ {
  FWP_ACTION_TYPE actionType;	// 操作类型
  UINT64          outContext;
  UINT64          filterId;
  UINT32          rights;
  UINT32          flags;
  UINT32          reserved;
} FWPS_CLASSIFY_OUT0;

NTSTATUS FwpsCalloutNotifyFn1(
  [in] FWPS_CALLOUT_NOTIFY_TYPE notifyType,	// 通知类型, FWPS_CALLOUT_NOTIFY_ADD_FILTER / FWPS_CALLOUT_NOTIFY_DELETE_FILTER / FWPS_CALLOUT_NOTIFY_TYPE_MAX
  [in] const GUID *filterKey,	// 过滤器标识
  [in] FWPS_FILTER1 *filter		// 过滤器指针
);
void FwpsCalloutFlowDeleteNotifyFn0(
  [in] UINT16 layerId,		// 分层标识
  [in] UINT32 calloutId,	// 呼出接口ID
  [in] UINT64 flowContext	// 关联的上下文指针
);

通过WFP API实现网络数据包过滤

  • 调用FwpmEngineOpen0打开过滤引擎的会话,获得引擎句柄;使用结束后调用FwpmEngineClose0关闭。
  • 调用FwpmTransactionBegin0 在当前会话中开始事务;使用结束后使用pfnFwpmTransactionAbort0终止事务。
  • 定义一个或多个呼出接口(自实现回调函数),然后调用用FwpsCalloutRegister0向过滤引擎注册呼出接口;使用结束后调用FwpsCalloutUnregisterById0FwpsCalloutUnregisterByKey0卸载。
  • 调用FwpmCalloutAdd0向过滤引擎中添加呼出接口;使用结束后调用FwpmCalloutDeleteById0移除。
  • 初始化过滤器并关联呼出接口,调用FwpmFilterAdd0向过滤引擎中添加过滤器;移除过滤器使用FwpmFilterDeleteById0FwpmFilterDeleteByKey0
  • 调用FwpmTransactionCommit0 在当前会话中提交当前事务。
  • 关闭句柄以及终止会话事务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/417504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【微信小程序-原生开发】实用教程20 - 生成海报(实战范例为生成活动海报,内含生成指定页面的小程序二维码,保存图片到手机,canvas 系列教程)

可在系列教程的基础上继续开发,也可以单独使用 【微信小程序-原生开发】系列教程 效果预览 代码实现 点击触发生成海报 在活动详情页,指定点击某图标/按钮,触发跳转到生成海报的页面 pages\components\party\detail\index.js getPoster() …

OpenTex 企业内容管理平台

OpenText 企业内容管理平台 将内容服务与领先应用程序集成,弥合内容孤岛、加快信息流并扩大治理 什么是内容服务集成? 内容服务集成通过将内容管理平台与处于流程核心的独立应用程序和系统连接起来,支持并扩展了 ECM 的传统优势。 最好的内…

【通过Cpython3.9源码看看python字符串对象的创建】

CPython源码解析之PyUnicode_New函数实现 简介 PyUnicode_New是Python源码中用于创建Unicode字符串对象的函数,定义在UnicodeObject.c文件中。该函数接受一个长度参数size和最大字符值参数maxchar(根据传入的最大字符值 maxchar 确定新创建的字符串对象所需的存储…

百度工程师的软件质量与测试随笔

作者 | 百度移动生态质效工程师们 导读 在降本增效、以chatGPT为代表的大模型技术横空出世的背景下,对软件质量和软件测试的领域也带来了巨大冲击,也使得软件质量工作者开始变得焦虑,主要体现在:公司对软件质量从业者的不重视加剧…

SQL Server的执行计划(Execution Plans)

执行计划一、背景二、显示和保存执行计划三、显示估计的执行计划四、显示实际执行计划五、以 XML 格式保存执行计划六、比较和分析执行计划6.1、比较执行计划6.2、分析实际执行计划总结一、背景 为了能够执行查询,SQL Server 数据库引擎必须分析该语句,…

21100颗星的Locust性能测试工具到底有多牛!

一句话:用普通的Python编写可扩展的负载测试,就够了,懂得自然懂! Locust是一个易于使用、可编写脚本和可扩展的性能测试工具。你在常规的Python代码中定义你的用户的行为,而不是受制于一个UI或领域特定的语言&#xff…

HTB-Obscurity

HTB-Obscurity信息收集8080端口立足www-data -> robertrobert -> rootsudo 注入hash捕获信息收集 8080端口 ”如果攻击者不知道你在使用什么软件,你就不会被黑客攻击!“,目标对web的指纹做了某些处理。 “‘SuperSecureServer.py’ in the secre…

【从零开始学Skynet】基础篇(六):MySql数据库安装操作

游戏服务端的另一项重要功能是保存玩家数据,Skynet提供了操作MySQL数据库、MongoDB数据库的模块。1、数据库安装 首先安装Mysql服务器,打开终端输入如下指令: sudo apt-get install mysql-server 按下回车,输入密码后开始安装&a…

秒杀架构(二) -- nginx实现限流

限流(Rate Limitting)是服务降级的一种方式,通过限制系统的输入和输出流量以达到保护系统的目的。比如我们的网站暴露在公网环境中,除了用户的正常访问,网络爬虫、恶意攻击或者大促等突发流量都可能都会对系统造成压力…

OpenCV按指定大小分割图像并保存详细讲解

这几天在忙着整理自己的数据集,使用工业级相机拍了好多高清照片,但是模型训练的时候需要使用512*512像素点大小的图像,而且我的模型设计的时候就已经规定好了训练样本大小。 那就分割呗,把拍的照片按512*512分割一小块一小块的&am…

easyx

普通的画线图什么的 首先我们需要安装一个easyx的图形库&#xff0c;然后把头文件搞出来 #include <stdio.h> #include <easyx.h>//easyx画线啥啥的图形库 #include <graphics.h> #include <math.h> #include <conio.h>//键盘操作的头文件 设…

2023年mathorcupD题航空安全风险分析和飞行技术评估思路分析

2023年mathorcupD题航空安全风险分析和飞行技术评估思路分析 飞行安全是民航运输业赖以生存和发展的基础。随着我国民航业的快 速发展&#xff0c;针对飞行安全问题的研究显得越来越重要。2022 年 3 月 21 日&#xff0c;“3.21” 空难的发生终结了中国民航安全飞行 1 亿零 59…

Android中级——性能优化

性能优化布局优化UI渲染机制避免Overdraw优化布局层级利用<include\>重用Layout使用<ViewStub\>实现View的延迟加载Hierarchy View内存优化获取内存信息ProfilerTraceViewMAT&#xff08;Memory Analyzer Tool&#xff09;dumpsys布局优化 UI渲染机制 画面流畅需…

透过Gartner最新报告,认识“超级边缘”

当下&#xff0c;酝酿能量的超级边缘。最近&#xff0c;我们在谈视频化狂飙、谈AIGC颠覆、谈算力动能不足&#xff0c;很少谈及边缘。但“边缘”恰恰与这一切相关&#xff0c;且越发密不可分&#xff0c;它是未来技术发展的极大影响因子。 “到2025年&#xff0c;超过70%的组织…

Segment Anything Model

论文翻译&#xff1a; 图1&#xff1a;我们旨在通过引入三个相互关联的组件来构建分割的基础模型&#xff1a;即时分割任务、支持数据注释并通过即时工程将零样本传输到一系列任务的分割模型&#xff08;SAM&#xff09;&#xff0c;以及用于收集SA-1B的数据引擎&#xff0c;SA…

MappingGenerator PRO 2023.3 Visual Studio 2019-2022

您的私人编码助手 MappingGenerator 最初是作为 AutoMapper 的设计时替代品创建的。现在它正在演变为编码助手&#xff0c;您可以将最平凡的编码任务委派给它&#xff1a; 生成映射生成显式转换实施克隆生成投影表达式脚手架方法调用脚手架对象创建清理方法调用方便ILogger的使…

探讨Hive是否转为MapReduce程序

目录 前提条件 数据准备 探讨HQL是否转为MapReduce程序执行 1.设置hive.fetch.task.conversionnone 2.设置hive.fetch.task.conversionminimal 3.设置hive.fetch.task.conversionmore 前提条件 Linux环境下安装好Hive&#xff0c;这里测试使用版本为&#xff1a;Hive2.3.…

【结构型模式】适配者模式

文章目录优秀借鉴1、简介2、结构3、实现方式3.1、案例引入3.2、类适配器3.3、对象适配器3.4、接口适配器4、区别对比5、适配者模式优缺点6、应用场景优秀借鉴 黑马程序员Java设计模式详解-适配器模式概述适配器设计模式&#xff08;封装器模式&#xff09;一文彻底弄懂适配器模…

页眉怎么添加【节】,设置不同章节不同页眉

文章目录前言添加【节】&#xff0c;设置不同内容总结前言 大家写文档或者论文的时候可能会需要&#xff1a;不同章节页眉展示不同的内容 然而&#xff0c;在双击页眉进行编辑的时候却发现几个章节的页眉一起被修改了&#xff1a; 会出现文章与页眉不同步的情况&#xff0c…

idea使用Junit

文章目录 idea使用JunitJunit配置常用注解常用于测试的断言方法后续idea使用Junit 对项目使用Junit主要有两个步骤: 添加Junit依赖,即添加Junit jar包使用JunitJunit配置 方法一:idea自带的快捷方法 对要测试的类的方法,在该类中,右键鼠标呼出菜单,选择Generate,快捷…