应用层读取wfp防火墙阻断记录

news2025/1/23 10:25:26

前言

之前的文档中,描写了如何对WFP防火墙进行操作[链接在此],这篇文档中,描述如何获取WFP防火墙进行阻断的操作记录。

需要注意的坑点

  • 使用FWPM_NET_EVENT_TYPE获取防火墙日志时,需要注意,只有丢弃和内核丢弃,以及几个错误信息是所有操作系统都可用,其它类型无法应用到所有操作系统。所以我们一般不会使用FWPM_NET_EVENT_TYPE来获取防火墙的放行日志。如果有需要读取放行日志的话,可以查询安全日志5156的方式进行(下次专门写文档来描述常用的三种读取方式)。
  • 使用主动读取的方式,在极个别系统上可能存在少量内存泄露(在保障所有内存都按照MSDN的要求释放的基础上,24小时有几十K的级别,没有仔细进行过日志条数的量化。有明白的也请指教)
  • 订阅的方式仅支持win7/2008 R2以上操作系统,建议使用loadlibrary动态加载,避免模块在vista或2008(SP2)操作系统上整体运行失败。

读取阻断日志(方案一:主动读取)

阻断日志即防火墙返回FWP_ACTION_BLOCK动作的记录信息,读取流程大体上分为:创建枚举句柄、执行枚举、释放枚举句柄简单的三步。

创建枚举句柄

DWORD FwpmNetEventCreateEnumHandle0( 
                            HANDLE engineHandle, 
                            const FWPM_NET_EVENT_ENUM_TEMPLATE0 *enumTemplate, 
                            HANDLE *enumHandle 
                            );
  • 输入参数:
    • engineHandle:防火墙句柄,前一章提到过,使用FwpmEngineOpen0打开
    • enumTemplate:枚举的限制条件,常用的是枚举起止时间,也可以设置网络条件以供筛选。
    • enumHandle:输出函数,用于输出枚举句柄
  • 输出参数:
    • 成功返回0,错误时返回WFP Error Codes

执行枚举操作

DWORD FwpmNetEventEnum0( 
                        HANDLE engineHandle, 
                        HANDLE enumHandle, 
                        UINT32 numEntriesRequested, 
                        FWPM_NET_EVENT0 ***entries, 
                        UINT32 *numEntriesReturned 
                        );
  • 输入参数:
    • engineHandle:防火墙句柄,FwpmEngineOpen0打开
    • enumHandle:枚举句柄,由上一步创建
    • numEnteiesRequested:本次想要枚举的最大数量,如果想要一次性返回所有,可以传-1(0xffffffff)
    • entries:用于输出事件数组,需要使用FwpmFreeMemory0释放
    • numEntriesReturned:用于输出事件数目,用于枚举entries
  • 输出参数:
    • 成功返回0,错误时返回WFP Error Codes

释放枚举句柄

DWORD FwpmNetEventDestroyEnumHandle0( 
                            HANDLE engineHandle, 
                            HANDLE enumHandle 
                            );
  • 输入参数:
    • 没啥好说的,两个句柄,参照上面
  • 输出参数:
    • 同上

相关函数1:启用防火墙事件采集

默认防火墙事件采集就是处于开启状态,因此不调用这个函数在大多数系统上可以正常进行事件读取。但是也发现过某些系统需要调用后才可以进行事件读取,建议还是增加此函数的调用

DWORD FwpmEngineSetOption0( 
                HANDLE engineHandle, 
                FWPM_ENGINE_OPTION option, 
                const FWP_VALUE0 *newValue 
                );
  • 输入参数
    • engineHandle:防火墙句柄,由FwpmEngineOpen0打开
    • 需要设置的参数,这个地方可以设置的类型还是蛮多的,可以参考
    • 设置参数对应的值,当option为FWPM_ENGINE_COLLECT_NET_EVENTS时,newValue为1则代表启用。
  • 输出参数
    • 成功返回ERROR_SUCCESS, 失败返回 WFP Error Codes

参考代码

void enumDemoCode()
{
	FWPM_SESSION0 session = { 0 };
	ZeroMemory(&session, sizeof(session));
	session.displayData.name = demoSession;
	session.txnWaitTimeoutInMSec = INFINITE;
	session.flags = FWPM_SESSION_FLAG_DYNAMIC;

	HANDLE hEngine = NULL;
	DWORD dwResult = FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &session, &hEngine);
	if (dwResult != ERROR_SUCCESS || hEngine == NULL)
	{
		std::cout << "FwpmEngineOpen0 Failed. ec:" << GetLastError() << std::endl;
		return;
	}

	FWP_VALUE0 inValue = {FWP_EMPTY};
	inValue.type = FWP_UINT32;
	inValue.uint32 = 1;
	FwpmEngineSetOption0(hEngine, FWPM_ENGINE_COLLECT_NET_EVENTS, &inValue);

	FWPM_NET_EVENT_ENUM_TEMPLATE0 enumTemplate = {0};

	SYSTEMTIME nowSystemTime;
	ZeroMemory(&nowSystemTime, sizeof(nowSystemTime));
	GetLocalTime(&nowSystemTime);

	FILETIME nowFileTime;
	ZeroMemory(&nowFileTime, sizeof(nowFileTime));
	if (SystemTimeToFileTime(&nowSystemTime, &nowFileTime))
	{
		enumTemplate.endTime.dwLowDateTime = nowFileTime.dwLowDateTime;
		enumTemplate.endTime.dwHighDateTime = nowFileTime.dwHighDateTime;
	}
	enumTemplate.startTime.dwHighDateTime = 0;
	enumTemplate.startTime.dwLowDateTime = 0;
	enumTemplate.numFilterConditions = 0;

	HANDLE hEnumHandle = NULL;
	dwResult = FwpmNetEventCreateEnumHandle0(hEngine, &enumTemplate, &hEnumHandle);
	if (dwResult != ERROR_SUCCESS || hEnumHandle == NULL)
	{
		std::cout << "Create Enum Handle Failed, ec:" << GetLastError() << std::endl;
		FwpmEngineClose0(hEngine);
		hEngine = NULL;
		return;
	}

	FWPM_NET_EVENT0** netEvents = NULL;
	UINT32 uEventNumber = 0;
	dwResult = FwpmNetEventEnum0(hEngine, hEnumHandle, INFINITE, &netEvents, &uEventNumber);
	if (uEventNumber > 0)
	{
		for (int eventPos = 0; eventPos < uEventNumber; eventPos++)
		{
			FWPM_NET_EVENT0* sigEvent = netEvents[eventPos];
			if (sigEvent->type != FWPM_NET_EVENT_TYPE_CLASSIFY_DROP)
			{
				continue;
			}

			if (sigEvent->header.ipVersion == FWP_IP_VERSION_V4)
			{
				std::wstring wstrLocalIp = ip2str(sigEvent->header.localAddrV4);
				std::wstring wstrRemoteIp = ip2str(sigEvent->header.remoteAddrV4);

				std::wstring wstrProtocol;
				switch (sigEvent->header.ipProtocol)
				{
				case 1:
					wstrProtocol = L"ICMP";
					break;
				case 6:
					wstrProtocol = L"TCP";
					break;
				case 17:
					wstrProtocol = L"UDP";
					break;
				default:
					wstrProtocol = L"Other:";
					wstrProtocol.append(std::to_wstring(sigEvent->header.ipProtocol));
					break;
				}

				std::wcout << wstrLocalIp << "[" << sigEvent->header.localPort << "] ==> " << wstrRemoteIp << "[" << sigEvent->header.remotePort << "] protocol:" << wstrProtocol << std::endl;
			}
		}
	}
       if (netEvents)
       {
              FwpmFreeMemory0((void**)&netEvents);
              netEvents = NULL;
       }

	if (hEnumHandle)
	{
		FwpmNetEventDestroyEnumHandle0(hEngine, hEnumHandle);
		hEnumHandle = NULL;
	}
	if (hEngine)
	{
		FwpmEngineClose0(hEngine);
		hEngine = NULL;
	}

	return;
}

执行结果
在这里插入图片描述

读取阻断日志(方案二:事件订阅)

使用事件订阅的方式在防火墙中读取日志,只需要开启和取消事件订阅即可

启动事件订阅

DWORD FwpmNetEventSubscribe0( 
                        HANDLE engineHandle, 
                        const FWPM_NET_EVENT_SUBSCRIPTION0 *subscription,
                        FWPM_NET_EVENT_CALLBACK0 callback, 
                        void *context, 
                        HANDLE *eventsHandle 
                    );
  • 输入参数
    • engineHandle:防火墙句柄,由FwpmEngineOpen0打开
    • subscription:需要订阅的通知类型
    • callback:订阅的回调
    • context:自定义指针,原封不动传递导callback函数
    • eventsHandle:订阅句柄,在FwpmNetEventUnsubscribe0中取消订阅
  • 输出参数
    • 成功返回ERROR_SUCCESS, 失败返回 WFP Error Codes

取消事件订阅

DWORD FwpmNetEventUnsubscribe0( 
                        HANDLE engineHandle, 
                        HANDLE eventsHandle 
                    );
  • 输入参数
    • engineHandle:防火墙句柄,由FwpmEngineOpen0打开
    • eventsHandle:订阅句柄,由FwpmNetEventSubscribe0返回
  • 输出参数
    • 成功返回ERROR_SUCCESS, 失败返回 WFP Error Codes

回调函数定义

void CALLBACK FuncFwpmNetEventCallback0(
                PVOID FwContext, 
                FWPM_NET_EVENT1* FwEvent
                )
  • 输入参数
    • FwContext:自定义指针,FwpmNetEventSubscribe0函数的context指针
    • FwEvent:订阅的事件
  • 输出参数

参考代码

void CALLBACK FuncFwpmNetEventCallback0(_Inout_ PVOID FwContext, _In_ const FWPM_NET_EVENT1* FwEvent)
{
	if (FwEvent == NULL)
	{
		return;
	}

	if (FwEvent->header.ipVersion == FWP_IP_VERSION_V4)
	{
		std::wstring wstrLocalIp = ip2str(FwEvent->header.localAddrV4);
		std::wstring wstrRemoteIp = ip2str(FwEvent->header.remoteAddrV4);

		std::wstring wstrProtocol;
		switch (FwEvent->header.ipProtocol)
		{
		case 1:
			wstrProtocol = L"ICMP";
			break;
		case 6:
			wstrProtocol = L"TCP";
			break;
		case 17:
			wstrProtocol = L"UDP";
			break;
		default:
			wstrProtocol = L"Other:";
			wstrProtocol.append(std::to_wstring(FwEvent->header.ipProtocol));
			break;
		}

		std::wcout << wstrLocalIp << "[" << FwEvent->header.localPort << "] ==> " << wstrRemoteIp << "[" << FwEvent->header.remotePort << "] protocol:" << wstrProtocol << std::endl;
	}
	return;
}


void subscribeEvents()
{
	FWPM_SESSION0 session = { 0 };
	ZeroMemory(&session, sizeof(session));
	session.displayData.name = demoSession;
	session.txnWaitTimeoutInMSec = INFINITE;
	session.flags = FWPM_SESSION_FLAG_DYNAMIC;

	HANDLE hEngine = NULL;
	DWORD dwResult = FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &session, &hEngine);
	if (dwResult != ERROR_SUCCESS || hEngine == NULL)
	{
		std::cout << "FwpmEngineOpen0 Failed. ec:" << GetLastError() << std::endl;
		return;
	}

	FWP_VALUE0 inValue = { FWP_EMPTY };
	inValue.type = FWP_UINT32;
	inValue.uint32 = 1;
	FwpmEngineSetOption0(hEngine, FWPM_ENGINE_COLLECT_NET_EVENTS, &inValue);

	HANDLE hSubScribeHandle = NULL;
	FWPM_NET_EVENT_ENUM_TEMPLATE0 eventTemplate = { 0 };
	eventTemplate.numFilterConditions = 0;

	FWPM_NET_EVENT_SUBSCRIPTION0 subscription = { 0 };
	subscription.enumTemplate = &eventTemplate;
	subscription.sessionKey = session.sessionKey;
	FwpmNetEventSubscribe0(hEngine, &subscription, FuncFwpmNetEventCallback0, NULL, &hSubScribeHandle);

	std::cout << "Event Subscribe Started....." << std::endl;
	getchar();

	FwpmNetEventUnsubscribe0(hEngine, hSubScribeHandle);

	if (hEngine)
	{
		FwpmEngineClose0(hEngine);
		hEngine = NULL;
	}
}

运行效果
在这里插入图片描述

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

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

相关文章

指定CUDA版本失败的解决方案

新电脑安装的WIN11系统&#xff0c;因为CUDA只有11和12目前能装到WIN11上&#xff0c;所以就装了一个CUDA 11.7。但是编译PBRT失败&#xff0c;所以无奈之下又装了CUDA 12。 但是因为我有的代码需要CUDA 11里的函数&#xff0c;这些函数在CUDA12里被彻底删除了&#xff0c;但是…

CentOS7的journalctl日志查看方法

多台服务器间免密登录|免密拷贝 Cenos7 搭建Minio集群部署服务器(一) Cenos7 搭建Minio集群Nginx统一访问入口|反向动态代理(二) Spring Boot 与Minio整合实现文件上传与下载(三) CentOS7的journalctl日志查看方法 MySQL8.xx一主两从复制安装与配置 1、概述 日志管理工…

下单接口调优实战,性能提高10倍

目录 概述 用到的工具和环境 工具 环境 找瓶颈 总结 概述 最近公司的下单接口有些慢&#xff0c;老板担心无法支撑双11&#xff0c;想让我优化一把&#xff0c;但是前提是不允许大改&#xff0c;因为下单接口太复杂了&#xff0c;如果改动太大&#xff0c;怕有风险。另外…

【Django】Task1安装python环境及运行项目

【Django】Task1安装python环境及运行项目 写在最前 8月份Datawhale组队学习&#xff0c;在这个群除我佬的时代&#xff0c;写一下blog记录学习过程。 参考资源&#xff1a; 学习项目github&#xff1a;https://github.com/Joe-2002/sweettalk-django4.2 队长博客&#xff1a…

使用K8s的一些经验和体会

Java应用程序的奇怪案例 ​在微服务和容器化方面&#xff0c;工程师倾向于避免使用 Java&#xff0c;这主要是由于 Java 臭名昭著的内存管理。但是&#xff0c;现在情况发生了改变&#xff0c;过去几年来 Java 的容器兼容性得到了改善。毕竟&#xff0c;大量的系统&#xff08…

RocketMQ部署 Linux方式和Docker方式

一、Linux部署 准备一台Linux机器&#xff0c;部署单master rocketmq节点 系统ip角色模式CENTOS10.4.7.126Nameserver,brokerMaster 1. 配置JDK rocketmq运行需要依赖jdk&#xff0c;安装步骤略。 2. 下载和配置 从官网下载安装包 https://rocketmq.apache.org/zh/downlo…

三.net core 自动化发布到docker (创建一个dotnet工程发布)

创建Jenkins-create a job 输入名称&#xff08;建议不要带“”这类的字符&#xff09;&#xff0c;选择自由风格的类型&#xff08;红框标注的&#xff09;&#xff0c;点击确定 用于测试,下面选项基本没有选择-配置代码地址 选择执行shell #!/bin/bash # 获取短版本号 GITHA…

会一点stm32,只后是做嵌入式Linux还是转JAVA?

选择嵌入式Linux还是转向JAVA&#xff0c;取决于你的兴趣、职业规划和就业市场的需求。以下是一些考虑因素&#xff1a;兴趣和擅长&#xff1a;首先&#xff0c;你应该考虑自己对嵌入式Linux和JAVA的兴趣和擅长程度。如果你对嵌入式系统、硬件交互和底层编程更感兴趣&#xff0…

echart 3d立体颜色渐变柱状图

如果可以实现记得点赞分享&#xff0c;谢谢老铁&#xff5e; 1.需求描述 根据业务需求将不同的法律法规&#xff0c;展示不同的3d立体渐变柱状图。 2.先看下效果图 3. 确定三面的颜色&#xff0c;这里我是自定义的颜色 // 右面生成颜色const rightColorArr ref(["#79D…

【图像融合】融合算法综述(持续更新)

按时间顺序&#xff0c;综述近5年的融合算法。重点分析了最近两年的work&#xff0c;欢迎留言探讨 文章目录 前言1.SSR-Laplacian Image Fusion&#xff08;2017&#xff09;2、FusionGAN&#xff08;2019&#xff09;3、MBNet&#xff08;2020&#xff09;4、DIDFuse&#xff…

【闪击Linux系列P10】操作系统管理的算珠——进程の详解

​ 前言 大家好吖&#xff0c;欢迎来到 YY 滴 Linux系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过Linux的老铁&#xff0c;从操作系统层面向大家介绍进程&#xff1a; 主要内容含&#xff1a; 欢迎订阅 YY滴Linux专栏&#xff01;更多干货持续更新&#xff0…

AIGC绘画:基于Stable Diffusion进行AI绘图

文章目录 AIGC深度学习模型绘画系统stable diffusion简介stable diffusion应用现状在线网站云端部署本地部署Stable Diffusion AIGC深度学习模型绘画系统 stable diffusion简介 Stable Diffusion是2022年发布的深度学习文本到图像生成模型&#xff0c;它主要用于根据文本的描述…

MySQL — 索引

文章目录 索引索引结构 — B树与B树B树B树 聚簇索引与非聚簇索引聚簇索引非聚簇索引优缺点 覆盖索引与回表联合索引索引覆盖最左前缀匹配 索引 索引是对数据库表中一列或多列的值进行排序的一种结构。MySQL索引的建立对于MySQL的高效运行是很重要的&#xff0c;索引可以大大提…

图像去雨-雨线清除-图像处理-(计算机作业附代码)

背景 多年来&#xff0c;图像去雨已经被广泛研究&#xff0c;使用传统方法和基于学习的方法。然而&#xff0c;传统方法如高斯混合模型和字典学习方法耗时&#xff0c;并且无法很好地处理受到严重雨滴影响的图像块。 算法 通过考虑雨滴条状特性和角度分布&#xff0c;这个问…

2023+HuggingGPT: Solving AI Tasks with ChatGPT and itsFriends in Hugging Face

摘要&#xff1a; 语言是llm(例如ChatGPT)连接众多AI模型(例如hugs Face)的接口&#xff0c;用于解决复杂的AI任务。在这个概念中&#xff0c;llms作为一个控制器&#xff0c;管理和组织专家模型的合作。LLM首先根据用户请求规划任务列表&#xff0c;然后为每个任务分配专家模…

3D- vista:预训练的3D视觉和文本对齐Transformer

论文&#xff1a;https://arxiv.org/abs/2308.04352 代码: GitHub - 3d-vista/3D-VisTA: Official implementation of ICCV 2023 paper "3D-VisTA: Pre-trained Transformer for 3D Vision and Text Alignment" 摘要 三维视觉语言基础(3D- vl)是一个新兴领域&…

JDBC封装与设计模式

什么是 DAO &#xff1f; Data Access Object(数据存取对象) 位于业务逻辑和持久化数据之间实现对持久化数据的访问 DAO起着转换器的作用&#xff0c;将数据在实体类和数据库记录之间进行转换。 ----------------------------------------------------- DAO模式的组成部分 …

【动画】p60动画蓝图、播放蒙太奇、打包

p60动画蓝图、播放蒙太奇、打包 p60动画蓝图、播放蒙太奇、打包添加动画动画蓝图使模型使用动画蓝图奔跑跳舞蒙太奇 移动打断蒙太奇打包退出游戏 p60动画蓝图、播放蒙太奇、打包 添加动画 右键内容浏览器-》动画-》混合空间1D-》选择新的角色的骨骼 如下图在资产详情修改参数…

【TypeScript】基础类型

安装 Node.js 环境 https://nodejs.org/en 终端中可以查到版本号即安装成功。 然后&#xff0c;终端执行npm i typescript -g安装 TypeScript 。 查到版本号即安装成功。 字符串类型 let str:string "Hello"; console.log(str);终端中先执行tsc --init&#xf…

机器学习:特征工程之特征预处理

目录 特征预处理 1、简述 2、内容 3、归一化 3.1、鲁棒性 3.2、存在的问题 4、标准化 ⭐所属专栏&#xff1a;人工智能 文中提到的代码如有需要可以私信我发给你&#x1f60a; 特征预处理 1、简述 什么是特征预处理&#xff1a;scikit-learn的解释&#xff1a; provide…